From 334d1b55376dfcd90cc4a6121fc587c35a80d4ed Mon Sep 17 00:00:00 2001 From: Edo Date: Fri, 16 Jun 2023 19:03:01 +0200 Subject: [PATCH 01/22] fix(git): fix git submodules --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 95e898f6..611fdd5d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -43,4 +43,4 @@ url = https://github.com/Tencent/rapidjson.git [submodule "deps/iw4-open-formats"] path = deps/iw4-open-formats - url = https://github.com/XLabsProject/iw4-open-formats.git + url = https://github.com/diamante0018/iw4-open-formats.git From b7aba4e97830fb8a77c7dd5e5acc1302845fe31d Mon Sep 17 00:00:00 2001 From: Diavolo Date: Fri, 16 Jun 2023 19:38:12 +0200 Subject: [PATCH 02/22] fix(github): fix CI --- .github/workflows/build.yml | 43 +------------------------------------ README.md | 9 ++------ 2 files changed, 3 insertions(+), 49 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 951fd023..e871fcdf 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -24,7 +24,7 @@ jobs: - Release steps: - name: Check out files - uses: actions/checkout@v3.5.2 + uses: actions/checkout@v3.5.3 with: submodules: true fetch-depth: 0 @@ -50,44 +50,3 @@ jobs: path: | build/bin/Win32/${{matrix.configuration}}/iw4x.dll build/bin/Win32/${{matrix.configuration}}/iw4x.pdb - - deploy: - name: Deploy artifacts - needs: build - runs-on: ubuntu-latest - if: github.event_name == 'push' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/develop') - steps: - - name: Setup main environment - if: github.ref == 'refs/heads/master' - run: echo "XLABS_MASTER_PATH=${{ secrets.XLABS_MASTER_SSH_PATH }}" >> $GITHUB_ENV - - - name: Setup develop environment - if: github.ref == 'refs/heads/develop' - run: echo "XLABS_MASTER_PATH=${{ secrets.XLABS_MASTER_SSH_PATH_DEV }}" >> $GITHUB_ENV - - - name: Download Release binaries - uses: actions/download-artifact@v3.0.2 - with: - name: Release binaries - - # Set up committer info and GPG key - - name: Install SSH key - uses: shimataro/ssh-key-action@v2.5.1 - with: - key: ${{ secrets.XLABS_MASTER_SSH_PRIVATE_KEY }} - known_hosts: 'just-a-placeholder-so-we-dont-get-errors' - - - name: Add known hosts - run: ssh-keyscan -H ${{ secrets.XLABS_MASTER_SSH_ADDRESS }} >> ~/.ssh/known_hosts - -# - name: Remove old data files -# run: ssh ${{ secrets.XLABS_MASTER_SSH_USER }}@${{ secrets.XLABS_MASTER_SSH_ADDRESS }} rm -rf ${{ env.XLABS_MASTER_PATH }}/iw4x/data/* - - - name: Upload iw4x binary - run: rsync -avz iw4x.dll ${{ secrets.XLABS_MASTER_SSH_USER }}@${{ secrets.XLABS_MASTER_SSH_ADDRESS }}:${{ env.XLABS_MASTER_PATH }}/iw4x/ - -# - name: Upload data files -# run: rsync -avz ./data/ ${{ secrets.XLABS_MASTER_SSH_USER }}@${{ secrets.XLABS_MASTER_SSH_ADDRESS }}:${{ env.XLABS_MASTER_PATH }}/iw4x/data/ - - - name: Publish changes - run: ssh ${{ secrets.XLABS_MASTER_SSH_USER }}@${{ secrets.XLABS_MASTER_SSH_ADDRESS }} ${{ secrets.XLABS_MASTER_SSH_CHANGE_PUBLISH_COMMAND }} diff --git a/README.md b/README.md index d7a32313..9b9e005c 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,5 @@ -![license](https://img.shields.io/github/license/IW4x/iw4x-client.svg) -![forks](https://img.shields.io/github/forks/IW4x/iw4x-client.svg) -![stars](https://img.shields.io/github/stars/IW4x/iw4x-client.svg) -![issues](https://img.shields.io/github/issues/IW4x/iw4x-client.svg) -[![build](https://github.com/XLabsProject/iw4x-client/workflows/Build/badge.svg)](https://github.com/XLabsProject/iw4x-client/actions) -[![discord](https://img.shields.io/endpoint?url=https://momo5502.com/iw4x/members-badge.php)](https://discord.gg/sKeVmR3) -[![patreon](https://img.shields.io/badge/patreon-support-blue.svg?logo=patreon)](https://www.patreon.com/xlabsproject) +![license](https://img.shields.io/github/license/diamante0018/iw4x-client.svg) +[![build](https://github.com/diamante0018/iw4x-client/workflows/Build/badge.svg)](https://github.com/diamante0018/iw4x-client/actions) # IW4x: Client From a6864ff7254c6ddd9907be89d8f4c36fb542f71b Mon Sep 17 00:00:00 2001 From: Diavolo Date: Fri, 16 Jun 2023 21:56:18 +0200 Subject: [PATCH 03/22] feature: /serverlist TCP endpoint --- .github/workflows/discord-notify.yml | 17 -- .github/workflows/draft-new-release.yml | 48 ------ .github/workflows/release.yml | 83 --------- src/Components/Modules/Download.cpp | 213 ++++++++++++++---------- src/Components/Modules/Download.hpp | 46 ++--- src/Components/Modules/Node.cpp | 6 +- src/Components/Modules/ServerList.cpp | 2 +- 7 files changed, 153 insertions(+), 262 deletions(-) delete mode 100644 .github/workflows/discord-notify.yml delete mode 100644 .github/workflows/draft-new-release.yml delete mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/discord-notify.yml b/.github/workflows/discord-notify.yml deleted file mode 100644 index d80352fb..00000000 --- a/.github/workflows/discord-notify.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: Notify Discord - -on: - push: - branches: - - "*" - issues: - -jobs: - notify: - runs-on: ubuntu-latest - if: github.repository_owner == 'XLabsProject' - steps: - - name: Send notification to Discord - uses: Ilshidur/action-discord@master - env: - DISCORD_WEBHOOK: ${{ secrets.DISCORD_CI_BOT_WEBHOOK }} diff --git a/.github/workflows/draft-new-release.yml b/.github/workflows/draft-new-release.yml deleted file mode 100644 index f3c13068..00000000 --- a/.github/workflows/draft-new-release.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: "Draft new release" - -on: - workflow_dispatch: - inputs: - version: - description: "The version you want to release." - required: true - -jobs: - draft-new-release: - name: "Draft a new release" - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3.5.2 - - - name: Normalize version - id: normalize_version - run: | - version="${{ github.event.inputs.version }}" - version="r${version#v}" - echo "::set-output name=version::$version" - - # Set up committer info and GPG key - - name: Import GPG key - id: import_gpg - uses: XLabsProject/ghaction-import-gpg@25d9d6ab99eb355c169c33c2306a72df85d9f516 - with: - git-commit-gpgsign: true - git-committer-email: "${{ secrets.XLABS_CI_EMAIL }}" - git-committer-name: "${{ secrets.XLABS_CI_NAME }}" - # git-push-gpgsign: true - git-tag-gpgsign: true - git-user-signingkey: true - gpg-private-key: ${{ secrets.XLABS_CI_GPG_PRIVATE_KEY }} - passphrase: ${{ secrets.XLABS_CI_GPG_PASSWORD }} - - - name: Create Pull Request - uses: repo-sync/pull-request@v2 - with: - github_token: ${{ secrets.XLABS_CI_GITHUB_TOKEN }} - source_branch: "develop" - destination_branch: "master" - pr_allow_empty: true - pr_body: | - This Pull Request is for the release of IW4x ${{ steps.normalize_version.outputs.version }} and was [automatically created by a workflow](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) triggered by @${{ github.actor }}. - pr_title: Release ${{ steps.normalize_version.outputs.version }} - pr_label: release diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index fb5e9814..00000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,83 +0,0 @@ -name: Release - -on: - pull_request: - branches: - - "master" - types: [closed] -jobs: - merge: - runs-on: ubuntu-latest - name: Merge Release - steps: - - name: Check out files - if: github.event.pull_request.merged - uses: actions/checkout@v3.5.2 - with: - submodules: false - lfs: false - - # Set up committer info and GPG key - - name: Import GPG key - if: github.event.pull_request.merged - id: import_gpg - uses: XLabsProject/ghaction-import-gpg@25d9d6ab99eb355c169c33c2306a72df85d9f516 - with: - git-commit-gpgsign: true - git-committer-email: "${{ secrets.XLABS_CI_EMAIL }}" - git-committer-name: "${{ secrets.XLABS_CI_NAME }}" - git-push-gpgsign: false - git-tag-gpgsign: true - git-user-signingkey: true - gpg-private-key: ${{ secrets.XLABS_CI_GPG_PRIVATE_KEY }} - passphrase: ${{ secrets.XLABS_CI_GPG_PASSWORD }} - - - name: Extract version from pull request - if: github.event.pull_request.merged - id: extract_version - run: | - title="${{ github.event.pull_request.title }}" - version="${title#Release }" - echo "::set-output name=version::$version" - - - name: Create annotated tag - if: github.event.pull_request.merged - run: | - git tag -a -m "${{ github.event.pull_request.title }}" \ - "${{ steps.extract_version.outputs.version }}" \ - "${{ github.event.pull_request.merge_commit_sha }}" - git push origin --tags - - - name: Create Pull Request - if: github.event.pull_request.merged - uses: repo-sync/pull-request@v2 - with: - github_token: ${{ secrets.XLABS_CI_GITHUB_TOKEN }} - source_branch: "master" - destination_branch: "develop" - pr_allow_empty: true - pr_body: | - This Pull Request merges the release of IW4x ${{ steps.extract_version.outputs.version }} and was [automatically created by a workflow](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) triggered by @${{ github.actor }}. - pr_title: Merge release ${{ steps.extract_version.outputs.version }} - pr_label: release - - - notify: - name: Notify Discord - runs-on: ubuntu-latest - if: | - github.repository_owner == 'XLabsProject' && ( - ( - github.event.pull_request.merged - ) || ( - github.event.push.ref == 'refs/heads/master' || - github.event.push.ref == 'refs/heads/develop' - ) - ) - steps: - - name: Post CI status notification to Discord - uses: sarisia/actions-status-discord@v1.7.1 - if: always() - with: - webhook: ${{ secrets.DISCORD_CI_BOT_WEBHOOK }} - title: "Build" diff --git a/src/Components/Modules/Download.cpp b/src/Components/Modules/Download.cpp index eee8c80d..282f6e86 100644 --- a/src/Components/Modules/Download.cpp +++ b/src/Components/Modules/Download.cpp @@ -5,6 +5,7 @@ #include "Download.hpp" #include "Events.hpp" #include "MapRotation.hpp" +#include "Node.hpp" #include "Party.hpp" #include "ServerInfo.hpp" @@ -40,7 +41,7 @@ namespace Components void Download::InitiateClientDownload(const std::string& mod, bool needPassword, bool map) { - if (CLDownload.running) return; + if (CLDownload.running_) return; Scheduler::Once([] { @@ -61,26 +62,26 @@ namespace Components return; } - CLDownload.hashedPassword = Utils::String::DumpHex(Utils::Cryptography::SHA256::Compute(password), ""); + CLDownload.hashedPassword_ = Utils::String::DumpHex(Utils::Cryptography::SHA256::Compute(password), ""); } - CLDownload.running = true; - CLDownload.isMap = map; - CLDownload.mod = mod; - CLDownload.terminateThread = false; - CLDownload.totalBytes = 0; - CLDownload.lastTimeStamp = 0; - CLDownload.downBytes = 0; - CLDownload.timeStampBytes = 0; - CLDownload.isPrivate = needPassword; - CLDownload.target = Party::Target(); - CLDownload.thread = std::thread(ModDownloader, &CLDownload); + CLDownload.running_ = true; + CLDownload.isMap_ = map; + CLDownload.mod_ = mod; + CLDownload.terminateThread_ = false; + CLDownload.totalBytes_ = 0; + CLDownload.lastTimeStamp_ = 0; + CLDownload.downBytes_ = 0; + CLDownload.timeStampBytes_ = 0; + CLDownload.isPrivate_ = needPassword; + CLDownload.target_ = Party::Target(); + CLDownload.thread_ = std::thread(ModDownloader, &CLDownload); } bool Download::ParseModList(ClientDownload* download, const std::string& list) { if (!download) return false; - download->files.clear(); + download->files_.clear(); nlohmann::json listData; try @@ -98,7 +99,7 @@ namespace Components return false; } - download->totalBytes = 0; + download->totalBytes_ = 0; const nlohmann::json::array_t listDataArray = listData; for (auto& file : listDataArray) @@ -118,8 +119,8 @@ namespace Components if (!fileEntry.name.empty()) { - download->files.push_back(fileEntry); - download->totalBytes += fileEntry.size; + download->files_.push_back(fileEntry); + download->totalBytes_ += fileEntry.size; } } catch (const nlohmann::json::exception& ex) @@ -134,12 +135,12 @@ namespace Components bool Download::DownloadFile(ClientDownload* download, unsigned int index) { - if (!download || download->files.size() <= index) return false; + if (!download || download->files_.size() <= index) return false; - auto file = download->files[index]; + auto file = download->files_[index]; - auto path = download->mod + "/" + file.name; - if (download->isMap) + auto path = download->mod_ + "/" + file.name; + if (download->isMap_) { path = "usermaps/" + path; } @@ -149,16 +150,16 @@ namespace Components auto data = Utils::IO::ReadFile(path); if (data.size() == file.size && Utils::String::DumpHex(Utils::Cryptography::SHA256::Compute(data), "") == file.hash) { - download->totalBytes += file.size; + download->totalBytes_ += file.size; return true; } } - auto host = "http://" + download->target.getString(); + auto host = "http://" + download->target_.getString(); auto fastHost = SV_wwwBaseUrl.get(); if (Utils::String::StartsWith(fastHost, "https://")) { - download->thread.detach(); + download->thread_.detach(); download->clear(); Scheduler::Once([] @@ -197,8 +198,8 @@ namespace Components } else { - url = host + "/file/" + (download->isMap ? "map/" : "") + file.name - + (download->isPrivate ? ("?password=" + download->hashedPassword) : ""); + url = host + "/file/" + (download->isMap_ ? "map/" : "") + file.name + + (download->isPrivate_ ? ("?password=" + download->hashedPassword_) : ""); } Logger::Print("Downloading from url {}\n", url); @@ -212,14 +213,14 @@ namespace Components Utils::String::Replace(url, " ", "%20"); - download->valid = true; + download->valid_ = true; fDownload.downloading = true; Utils::WebIO webIO; webIO.setProgressCallback([&fDownload, &webIO](std::size_t bytes, std::size_t) { - if(!fDownload.downloading || fDownload.download->terminateThread) + if(!fDownload.downloading || fDownload.download->terminateThread_) { webIO.cancelDownload(); return; @@ -234,14 +235,14 @@ namespace Components fDownload.downloading = false; - download->valid = false; + download->valid_ = false; if (fDownload.buffer.size() != file.size || Utils::Cryptography::SHA256::Compute(fDownload.buffer, true) != file.hash) { return false; } - if (download->isMap) Utils::IO::CreateDir("usermaps/" + download->mod); + if (download->isMap_) Utils::IO::CreateDir("usermaps/" + download->mod_); Utils::IO::WriteFile(path, fDownload.buffer); return true; @@ -251,16 +252,16 @@ namespace Components { if (!download) download = &CLDownload; - const auto host = "http://" + download->target.getString(); + const auto host = "http://" + download->target_.getString(); - const auto listUrl = host + (download->isMap ? "/map" : "/list") + (download->isPrivate ? ("?password=" + download->hashedPassword) : ""); + const auto listUrl = host + (download->isMap_ ? "/map" : "/list") + (download->isPrivate_ ? ("?password=" + download->hashedPassword_) : ""); const auto list = Utils::WebIO("IW4x", listUrl).setTimeout(5000)->get(); if (list.empty()) { - if (download->terminateThread) return; + if (download->terminateThread_) return; - download->thread.detach(); + download->thread_.detach(); download->clear(); Scheduler::Once([] @@ -272,13 +273,13 @@ namespace Components return; } - if (download->terminateThread) return; + if (download->terminateThread_) return; if (!ParseModList(download, list)) { - if (download->terminateThread) return; + if (download->terminateThread_) return; - download->thread.detach(); + download->thread_.detach(); download->clear(); Scheduler::Once([] @@ -290,21 +291,21 @@ namespace Components return; } - if (download->terminateThread) return; + if (download->terminateThread_) return; static std::string mod; - mod = download->mod; + mod = download->mod_; - for (std::size_t i = 0; i < download->files.size(); ++i) + for (std::size_t i = 0; i < download->files_.size(); ++i) { - if (download->terminateThread) return; + if (download->terminateThread_) return; if (!DownloadFile(download, i)) { - if (download->terminateThread) return; + if (download->terminateThread_) return; - mod = std::format("Failed to download file: {}!", download->files[i].name); - download->thread.detach(); + mod = std::format("Failed to download file: {}!", download->files_[i].name); + download->thread_.detach(); download->clear(); Scheduler::Once([] @@ -320,12 +321,12 @@ namespace Components } } - if (download->terminateThread) return; + if (download->terminateThread_) return; - download->thread.detach(); + download->thread_.detach(); download->clear(); - if (download->isMap) + if (download->isMap_) { Scheduler::Once([] { @@ -357,22 +358,22 @@ namespace Components void Download::DownloadProgress(FileDownload* fDownload, std::size_t bytes) { fDownload->receivedBytes += bytes; - fDownload->download->downBytes += bytes; - fDownload->download->timeStampBytes += bytes; + fDownload->download->downBytes_ += bytes; + fDownload->download->timeStampBytes_ += bytes; static volatile bool framePushed = false; if (!framePushed) { double progress = 0; - if (fDownload->download->totalBytes) + if (fDownload->download->totalBytes_) { - progress = (100.0 / fDownload->download->totalBytes) * fDownload->download->downBytes; + progress = (100.0 / fDownload->download->totalBytes_) * fDownload->download->downBytes_; } static std::uint32_t dlIndex, dlSize, dlProgress; dlIndex = fDownload->index + 1; - dlSize = fDownload->download->files.size(); + dlSize = fDownload->download->files_.size(); dlProgress = static_cast(progress); framePushed = true; @@ -383,18 +384,18 @@ namespace Components }, Scheduler::Pipeline::MAIN); } - auto delta = Game::Sys_Milliseconds() - fDownload->download->lastTimeStamp; + auto delta = Game::Sys_Milliseconds() - fDownload->download->lastTimeStamp_; if (delta > 300) { - const auto doFormat = fDownload->download->lastTimeStamp != 0; - fDownload->download->lastTimeStamp = Game::Sys_Milliseconds(); + const auto doFormat = fDownload->download->lastTimeStamp_ != 0; + fDownload->download->lastTimeStamp_ = Game::Sys_Milliseconds(); - const auto dataLeft = fDownload->download->totalBytes - fDownload->download->downBytes; + const auto dataLeft = fDownload->download->totalBytes_ - fDownload->download->downBytes_; int timeLeft = 0; - if (fDownload->download->timeStampBytes) + if (fDownload->download->timeStampBytes_) { - const double timeLeftD = ((1.0 * dataLeft) / fDownload->download->timeStampBytes) * delta; + const double timeLeftD = ((1.0 * dataLeft) / fDownload->download->timeStampBytes_) * delta; timeLeft = static_cast(timeLeftD); } @@ -404,7 +405,7 @@ namespace Components static int dlDelta, dlTimeLeft; dlTimeLeft = timeLeft; dlDelta = delta; - dlTsBytes = fDownload->download->timeStampBytes; + dlTsBytes = fDownload->download->timeStampBytes_; Scheduler::Once([] { @@ -413,7 +414,7 @@ namespace Components }, Scheduler::Pipeline::MAIN); } - fDownload->download->timeStampBytes = 0; + fDownload->download->timeStampBytes_ = 0; } } @@ -434,7 +435,7 @@ namespace Components MongooseLogBuffer.push_back(c); } - static std::string InfoHandler() + static std::optional InfoHandler([[maybe_unused]] mg_connection* c, [[maybe_unused]] const mg_http_message* hm) { const auto status = ServerInfo::GetInfo(); const auto host = ServerInfo::GetHostInfo(); @@ -480,10 +481,12 @@ namespace Components } info["players"] = players; - return nlohmann::json(info).dump(); + std::string out = nlohmann::json(info).dump(); + + return { out }; } - static std::string ListHandler() + static std::optional ListHandler([[maybe_unused]] mg_connection* c, [[maybe_unused]] const mg_http_message* hm) { static nlohmann::json jsonList; static std::filesystem::path fsGamePre; @@ -526,10 +529,12 @@ namespace Components jsonList = fileList; } - return jsonList.dump(); + std::string out = jsonList.dump(); + + return { out }; } - static std::string MapHandler() + static std::optional MapHandler([[maybe_unused]] mg_connection* c, [[maybe_unused]] const mg_http_message* hm) { static std::string mapNamePre; static nlohmann::json jsonList; @@ -570,10 +575,12 @@ namespace Components jsonList = fileList; } - return jsonList.dump(); + std::string out = jsonList.dump(); + + return { out }; } - static void FileHandler(mg_connection* c, const mg_http_message* hm) + static std::optional FileHandler(mg_connection* c, const mg_http_message* hm) { std::string url(hm->uri.ptr, hm->uri.len); @@ -602,7 +609,7 @@ namespace Components if ((!Maps::GetUserMap()->isValid() && !Party::IsInUserMapLobby()) || !isValidFile) { mg_http_reply(c, 403, "Content-Type: text/html\r\n", "%s", "403 - Forbidden"); - return; + return {}; } url = std::format("usermaps\\{}\\{}", mapName, url); @@ -612,7 +619,7 @@ namespace Components if ((!url.ends_with(".iwd") && url != "mod.ff") || url.find("_svr_") != std::string::npos) { mg_http_reply(c, 403, "Content-Type: text/html\r\n", "%s", "403 - Forbidden"); - return; + return {}; } } @@ -633,10 +640,44 @@ namespace Components mg_printf(c, "%s", "\r\n"); mg_send(c, file.data(), file.size()); } + + return {}; + } + + static std::optional ServerListHandler([[maybe_unused]] mg_connection* c, [[maybe_unused]] const mg_http_message* hm) + { + std::vector servers; + + const auto nodes = Node::GetNodes(); + for (const auto& node : nodes) + { + const auto address = node.address.getString(); + servers.emplace_back(address); + } + + nlohmann::json jsonList = servers; + std::string out = jsonList.dump(); + + return { out }; } static void EventHandler(mg_connection* c, const int ev, void* ev_data, [[maybe_unused]] void* fn_data) { + using callback = std::function(mg_connection*, const mg_http_message*)>; + + static const auto handlers = []() -> std::unordered_map + { + std::unordered_map f; + + f["/file"] = FileHandler; + f["/info"] = InfoHandler; + f["/list"] = ListHandler; + f["/map"] = MapHandler; + f["/serverlist"] = ServerListHandler; + + return f; + }(); + if (ev != MG_EV_HTTP_MSG) { return; @@ -645,26 +686,24 @@ namespace Components auto* hm = static_cast(ev_data); const std::string url(hm->uri.ptr, hm->uri.len); - if (url.starts_with("/info")) + auto handled = false; + for (auto i = handlers.begin(); i != handlers.end();) { - const auto reply = InfoHandler(); - mg_http_reply(c, 200, "Content-Type: application/json\r\n", "%s", reply.data()); + if (url.starts_with(i->first)) + { + if (const auto reply = i->second(c, hm)) + { + mg_http_reply(c, 200, "Content-Type: application/json\r\n", "%s", reply.value().data()); + } + + handled = true; + break; + } + + ++i; } - else if (url.starts_with("/list")) - { - const auto reply = ListHandler(); - mg_http_reply(c, 200, "Content-Type: application/json\r\n", "%s", reply.data()); - } - else if (url.starts_with("/map")) - { - const auto reply = MapHandler(); - mg_http_reply(c, 200, "Content-Type: application/json\r\n", "%s", reply.data()); - } - else if (url.starts_with("/file")) - { - FileHandler(c, hm); - } - else + + if (!handled) { mg_http_serve_opts opts = { .root_dir = "iw4x/html" }; // Serve local dir mg_http_serve_dir(c, hm, &opts); diff --git a/src/Components/Modules/Download.hpp b/src/Components/Modules/Download.hpp index fe8ab847..84ee7584 100644 --- a/src/Components/Modules/Download.hpp +++ b/src/Components/Modules/Download.hpp @@ -24,24 +24,24 @@ namespace Components class ClientDownload { public: - ClientDownload(bool _isMap = false) : running(false), valid(false), terminateThread(false), isMap(_isMap), totalBytes(0), downBytes(0), lastTimeStamp(0), timeStampBytes(0) {} + ClientDownload(bool isMap = false) : running_(false), valid_(false), terminateThread_(false), isMap_(isMap), totalBytes_(0), downBytes_(0), lastTimeStamp_(0), timeStampBytes_(0) {} ~ClientDownload() { this->clear(); } - bool running; - bool valid; - bool terminateThread; - bool isMap; - bool isPrivate; - Network::Address target; - std::string hashedPassword; - std::string mod; - std::thread thread; + bool running_; + bool valid_; + bool terminateThread_; + bool isMap_; + bool isPrivate_; + Network::Address target_; + std::string hashedPassword_; + std::string mod_; + std::thread thread_; - std::size_t totalBytes; - std::size_t downBytes; + std::size_t totalBytes_; + std::size_t downBytes_; - int lastTimeStamp; - std::size_t timeStampBytes; + int lastTimeStamp_; + std::size_t timeStampBytes_; class File { @@ -51,24 +51,24 @@ namespace Components std::size_t size; }; - std::vector files; + std::vector files_; void clear() { - this->terminateThread = true; + this->terminateThread_ = true; - if (this->thread.joinable()) + if (this->thread_.joinable()) { - this->thread.join(); + this->thread_.join(); } - this->running = false; - this->mod.clear(); - this->files.clear(); + this->running_ = false; + this->mod_.clear(); + this->files_.clear(); - if (this->valid) + if (this->valid_) { - this->valid = false; + this->valid_ = false; } } }; diff --git a/src/Components/Modules/Node.cpp b/src/Components/Modules/Node.cpp index 3fa2217a..b922e249 100644 --- a/src/Components/Modules/Node.cpp +++ b/src/Components/Modules/Node.cpp @@ -353,18 +353,18 @@ namespace Components Scheduler::OnGameInitialized(loadNodes, Scheduler::Pipeline::MAIN); - Command::Add("listnodes", [](const Command::Params*) + Command::Add("listNodes", [](const Command::Params*) { Logger::Print("Nodes: {}\n", Node::Nodes.size()); std::lock_guard _(Node::Mutex); - for (auto& node : Node::Nodes) + for (const auto& node : Node::Nodes) { Logger::Print("{}\t({})\n", node.address.getString(), node.isValid() ? "Valid" : "Invalid"); } }); - Command::Add("addnode", [](const Command::Params* params) + Command::Add("addNode", [](const Command::Params* params) { if (params->size() < 2) return; auto address = Network::Address{ params->get(1) }; diff --git a/src/Components/Modules/ServerList.cpp b/src/Components/Modules/ServerList.cpp index 06668ad3..1f5f58db 100644 --- a/src/Components/Modules/ServerList.cpp +++ b/src/Components/Modules/ServerList.cpp @@ -29,7 +29,7 @@ namespace Components Dvar::Var ServerList::NETServerQueryLimit; Dvar::Var ServerList::NETServerFrames; - bool ServerList::UseMasterServer = true; + bool ServerList::UseMasterServer = false; std::vector* ServerList::GetList() { From c85538eb239ddc57c6f7d9637e394183e47fa293 Mon Sep 17 00:00:00 2001 From: Diavolo Date: Sat, 17 Jun 2023 11:46:20 +0200 Subject: [PATCH 04/22] feature(nodes): migrate to JSON node list --- src/Components/Modules/Chat.cpp | 2 +- src/Components/Modules/Node.cpp | 188 ++++++++++++++++++++++---------- src/Components/Modules/Node.hpp | 4 +- 3 files changed, 132 insertions(+), 62 deletions(-) diff --git a/src/Components/Modules/Chat.cpp b/src/Components/Modules/Chat.cpp index 7e0b0290..fe659ec8 100644 --- a/src/Components/Modules/Chat.cpp +++ b/src/Components/Modules/Chat.cpp @@ -371,7 +371,7 @@ namespace Components MutedList.access([&](muteList& clients) { const nlohmann::json::array_t arr = list; - for (auto& entry : arr) + for (const auto& entry : arr) { if (entry.is_number_unsigned()) { diff --git a/src/Components/Modules/Node.cpp b/src/Components/Modules/Node.cpp index b922e249..7d55671f 100644 --- a/src/Components/Modules/Node.cpp +++ b/src/Components/Modules/Node.cpp @@ -48,7 +48,7 @@ namespace Components this->lastRequest->update(); Session::Send(this->address, "nodeListRequest"); - Node::SendList(this->address); + SendList(this->address); #ifdef NODE_SYSTEM_DEBUG Logger::Debug("Sent request to {}", this->address.getString()); #endif @@ -56,7 +56,6 @@ namespace Components void Node::Entry::reset() { - // this->lastResponse.reset(); // This would invalidate the node, but maybe we don't want that? this->lastRequest.reset(); } @@ -69,28 +68,54 @@ namespace Components for (auto i = 0; i < list.nodes_size(); ++i) { - const std::string& addr = list.nodes(i); - + const auto& addr = list.nodes(i); if (addr.size() == sizeof(sockaddr)) { - Node::Add(reinterpret_cast(const_cast(addr.data()))); + Add(reinterpret_cast(const_cast(addr.data()))); } } } void Node::LoadNodes() { - Proto::Node::List list; - std::string nodes = Utils::IO::ReadFile("players/nodes.dat"); - if (nodes.empty() || !list.ParseFromString(Utils::Compression::ZLib::Decompress(nodes))) return; - - for (int i = 0; i < list.nodes_size(); ++i) + std::string data; + if (!Utils::IO::ReadFile("players/nodes.json", &data) || data.empty()) { - const std::string& addr = list.nodes(i); + return; + } - if (addr.size() == sizeof(sockaddr)) + nlohmann::json nodes; + try + { + nodes = nlohmann::json::parse(data); + } + catch (const std::exception& ex) + { + Logger::PrintError(Game::CON_CHANNEL_ERROR, "JSON Parse Error: {}\n", ex.what()); + return; + } + + if (!nodes.contains("nodes")) + { + Logger::PrintError(Game::CON_CHANNEL_ERROR, "nodes.json contains invalid data\n"); + return; + } + + const auto& list = nodes["nodes"]; + if (!list.is_array()) + { + return; + } + + const nlohmann::json::array_t arr = list; + Logger::Print("Parsing {} nodes from nodes.json\n", arr.size()); + + for (const auto& entry : arr) + { + if (entry.is_string()) { - Node::Add(reinterpret_cast(const_cast(addr.data()))); + Network::Address address(entry.get()); + Add(address); } } } @@ -99,26 +124,29 @@ namespace Components { if (Dedicated::IsEnabled() && Dedicated::SVLanOnly.get()) return; + std::vector nodes; + static Utils::Time::Interval interval; if (!force && !interval.elapsed(1min)) return; interval.update(); - Proto::Node::List list; + Mutex.lock(); - Node::Mutex.lock(); - for (auto& node : Node::Nodes) + for (auto& node : Nodes) { - if (node.isValid()) + if (node.isValid() || force) { - std::string* str = list.add_nodes(); - - sockaddr addr = node.address.getSockAddr(); - str->append(reinterpret_cast(&addr), sizeof(addr)); + const auto address = node.address.getString(); + nodes.emplace_back(address); } } - Node::Mutex.unlock(); - Utils::IO::WriteFile("players/nodes.dat", Utils::Compression::ZLib::Compress(list.SerializeAsString())); + Mutex.unlock(); + + nlohmann::json out; + out["nodes"] = nodes; + + Utils::IO::WriteFile("players/nodes.json", out.dump()); } void Node::Add(Network::Address address) @@ -129,23 +157,23 @@ namespace Components if (!address.isValid()) return; - std::lock_guard _(Node::Mutex); - for (auto& session : Node::Nodes) + std::lock_guard _(Mutex); + for (auto& session : Nodes) { if (session.address == address) return; } - Node::Entry node; + Entry node; node.address = address; - Node::Nodes.push_back(node); + Nodes.push_back(node); } std::vector Node::GetNodes() { - std::lock_guard _(Node::Mutex); + std::lock_guard _(Mutex); - return Node::Nodes; + return Nodes; } void Node::RunFrame() @@ -165,7 +193,7 @@ namespace Components if (WasIngame) // our last frame we were in-game and now we aren't so touch all nodes { - for (auto i = Node::Nodes.begin(); i != Node::Nodes.end();++i) + for (auto i = Nodes.begin(); i != Nodes.end();++i) { // clearing the last request and response times makes the // dispatcher think its a new node and will force a refresh @@ -181,15 +209,15 @@ namespace Components if (!frameLimit.elapsed(std::chrono::milliseconds(interval))) return; frameLimit.update(); - std::lock_guard _(Node::Mutex); + std::lock_guard _(Mutex); Dvar::Var queryLimit("net_serverQueryLimit"); int sentRequests = 0; - for (auto i = Node::Nodes.begin(); i != Node::Nodes.end();) + for (auto i = Nodes.begin(); i != Nodes.end();) { if (i->isDead()) { - i = Node::Nodes.erase(i); + i = Nodes.erase(i); continue; } if (sentRequests < queryLimit.get() && i->requiresRequest()) @@ -204,10 +232,9 @@ namespace Components void Node::Synchronize() { - std::lock_guard _(Node::Mutex); - for (auto& node : Node::Nodes) + std::lock_guard _(Mutex); + for (auto& node : Nodes) { - //if (node.isValid()) // Comment out to simulate 'syncnodes' behaviour { node.reset(); } @@ -223,7 +250,7 @@ namespace Components Logger::Debug("Received response from {}", address.getString()); #endif - std::lock_guard _(Node::Mutex); + std::lock_guard _(Mutex); for (int i = 0; i < list.nodes_size(); ++i) { @@ -231,7 +258,7 @@ namespace Components if (addr.size() == sizeof(sockaddr)) { - Node::Add(reinterpret_cast(const_cast(addr.data()))); + Add(reinterpret_cast(const_cast(addr.data()))); } } @@ -251,7 +278,7 @@ namespace Components #endif } - for (auto& node : Node::Nodes) + for (auto& node : Nodes) { if (address == node.address) { @@ -263,35 +290,37 @@ namespace Components } } - Node::Entry entry; + Entry entry; entry.address = address; entry.data.protocol = list.protocol(); entry.lastResponse.emplace(Utils::Time::Point()); - Node::Nodes.push_back(entry); + Nodes.push_back(entry); } } void Node::SendList(const Network::Address& address) { - std::lock_guard _(Node::Mutex); + std::lock_guard _(Mutex); // need to keep the message size below 1404 bytes else recipient will just drop it std::vector nodeListReponseMessages; - for (std::size_t curNode = 0; curNode < Node::Nodes.size();) + for (std::size_t curNode = 0; curNode < Nodes.size();) { Proto::Node::List list; list.set_isnode(Dedicated::IsEnabled()); list.set_protocol(PROTOCOL); - list.set_port(Node::GetPort()); + list.set_port(GetPort()); for (std::size_t i = 0; i < NODE_MAX_NODES_TO_SEND;) { - if (curNode >= Node::Nodes.size()) + if (curNode >= Nodes.size()) + { break; + } - auto node = Node::Nodes.at(curNode++); + auto node = Nodes.at(curNode++); if (node.isValid()) { @@ -326,6 +355,44 @@ namespace Components return Network::GetPort(); } + void Node::Migrate() + { + Proto::Node::List list; + std::string nodes; + + if (!Utils::IO::ReadFile("players/nodes.dat", &nodes) || nodes.empty()) + { + return; + } + + if (!list.ParseFromString(Utils::Compression::ZLib::Decompress(nodes))) + { + return; + } + + std::vector data; + for (auto i = 0; i < list.nodes_size(); ++i) + { + const std::string& addr = list.nodes(i); + + if (addr.size() == sizeof(sockaddr)) + { + Network::Address address(reinterpret_cast(const_cast(addr.data()))); + data.emplace_back(address.getString()); + } + } + + nlohmann::json out; + out["nodes"] = data; + + if (!Utils::IO::FileExists("players/nodes.json")) + { + Utils::IO::WriteFile("players/nodes.json", out.dump()); + } + + Utils::IO::RemoveFile("players/nodes.dat"); + } + Node::Node() { if (ZoneBuilder::IsEnabled()) return; @@ -333,32 +400,33 @@ namespace Components Scheduler::Loop([] { - Node::StoreNodes(false); + StoreNodes(false); }, Scheduler::Pipeline::ASYNC); - Scheduler::Loop(Node::RunFrame, Scheduler::Pipeline::MAIN); + Scheduler::Loop(RunFrame, Scheduler::Pipeline::MAIN); - Session::Handle("nodeListResponse", Node::HandleResponse); + Session::Handle("nodeListResponse", HandleResponse); Session::Handle("nodeListRequest", [](const Network::Address& address, [[maybe_unused]] const std::string& data) { - Node::SendList(address); + SendList(address); }); // Load stored nodes auto loadNodes = [] { - Node::LoadNodePreset(); - Node::LoadNodes(); + Migrate(); + LoadNodePreset(); + LoadNodes(); }; Scheduler::OnGameInitialized(loadNodes, Scheduler::Pipeline::MAIN); Command::Add("listNodes", [](const Command::Params*) { - Logger::Print("Nodes: {}\n", Node::Nodes.size()); + Logger::Print("Nodes: {}\n", Nodes.size()); - std::lock_guard _(Node::Mutex); - for (const auto& node : Node::Nodes) + std::lock_guard _(Mutex); + for (const auto& node : Nodes) { Logger::Print("{}\t({})\n", node.address.getString(), node.isValid() ? "Valid" : "Invalid"); } @@ -370,15 +438,15 @@ namespace Components auto address = Network::Address{ params->get(1) }; if (address.isValid()) { - Node::Add(address); + Add(address); } }); } - Node::~Node() + void Node::preDestroy() { - std::lock_guard _(Node::Mutex); - Node::StoreNodes(true); - Node::Nodes.clear(); + std::lock_guard _(Mutex); + StoreNodes(true); + Nodes.clear(); } } diff --git a/src/Components/Modules/Node.hpp b/src/Components/Modules/Node.hpp index b585df3f..d76cdd20 100644 --- a/src/Components/Modules/Node.hpp +++ b/src/Components/Modules/Node.hpp @@ -34,7 +34,7 @@ namespace Components }; Node(); - ~Node(); + void preDestroy() override; static void Add(Network::Address address); static std::vector GetNodes(); @@ -55,5 +55,7 @@ namespace Components static void StoreNodes(bool force); static unsigned short GetPort(); + + static void Migrate(); }; } From 00f86cefe4e3fb36019ec77656f4ff2ff939aaeb Mon Sep 17 00:00:00 2001 From: Diavolo Date: Sat, 17 Jun 2023 19:30:33 +0200 Subject: [PATCH 05/22] deps: update mongoose --- .gitmodules | 2 +- deps/mongoose | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 611fdd5d..469c3e6a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -17,7 +17,7 @@ [submodule "deps/mongoose"] path = deps/mongoose url = https://github.com/cesanta/mongoose.git - branch = 7.9 + branch = 7.10 [submodule "deps/protobuf"] path = deps/protobuf url = https://github.com/google/protobuf.git diff --git a/deps/mongoose b/deps/mongoose index 4236405b..b3798161 160000 --- a/deps/mongoose +++ b/deps/mongoose @@ -1 +1 @@ -Subproject commit 4236405b90e051310aadda818e21c811e404b4d8 +Subproject commit b379816178abdcd59135aa32f990a4b3bbbfb54b From bc11a6cb390b59cceab86b5e022bb7ae7fc0d898 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 17 Jun 2023 17:33:41 +0000 Subject: [PATCH 06/22] Bump deps/iw4-open-formats from `477a3c2` to `5e17794` Bumps [deps/iw4-open-formats](https://github.com/diamante0018/iw4-open-formats) from `477a3c2` to `5e17794`. - [Commits](https://github.com/diamante0018/iw4-open-formats/compare/477a3c223b734a55c33ca330b84ea0fc0007673f...5e17794ed16351d3f77b72ff1ff8c52621e7b51d) --- updated-dependencies: - dependency-name: deps/iw4-open-formats dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/iw4-open-formats | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/iw4-open-formats b/deps/iw4-open-formats index 477a3c22..5e17794e 160000 --- a/deps/iw4-open-formats +++ b/deps/iw4-open-formats @@ -1 +1 @@ -Subproject commit 477a3c223b734a55c33ca330b84ea0fc0007673f +Subproject commit 5e17794ed16351d3f77b72ff1ff8c52621e7b51d From 7c05b151b7bc3224acb775f4243df147c1b55f97 Mon Sep 17 00:00:00 2001 From: Diavolo Date: Sun, 18 Jun 2023 11:37:02 +0200 Subject: [PATCH 07/22] maint(node): cleanup node system --- src/Components/Modules/News.hpp | 1 - src/Components/Modules/Node.cpp | 29 ++++++++++++--------------- src/Components/Modules/Node.hpp | 4 ++-- src/Components/Modules/ServerList.hpp | 10 ++++----- 4 files changed, 20 insertions(+), 24 deletions(-) diff --git a/src/Components/Modules/News.hpp b/src/Components/Modules/News.hpp index a69aa27d..9170dcf6 100644 --- a/src/Components/Modules/News.hpp +++ b/src/Components/Modules/News.hpp @@ -14,7 +14,6 @@ namespace Components static std::thread Thread; static bool Terminate; - static bool DownloadUpdater(); static const char* GetNewsText(); }; diff --git a/src/Components/Modules/Node.cpp b/src/Components/Modules/Node.cpp index 7d55671f..50b0c8fe 100644 --- a/src/Components/Modules/Node.cpp +++ b/src/Components/Modules/Node.cpp @@ -149,7 +149,7 @@ namespace Components Utils::IO::WriteFile("players/nodes.json", out.dump()); } - void Node::Add(Network::Address address) + void Node::Add(const Network::Address& address) { #ifndef DEBUG if (address.isLocal() || address.isSelf()) return; @@ -193,24 +193,23 @@ namespace Components if (WasIngame) // our last frame we were in-game and now we aren't so touch all nodes { - for (auto i = Nodes.begin(); i != Nodes.end();++i) + for (auto& entry : Nodes) { // clearing the last request and response times makes the // dispatcher think its a new node and will force a refresh - i->lastRequest.reset(); - i->lastResponse.reset(); + entry.lastRequest.reset(); + entry.lastResponse.reset(); } WasIngame = false; } static Utils::Time::Interval frameLimit; - int interval = static_cast(1000.0f / Dvar::Var("net_serverFrames").get()); + const auto interval = 1000 / ServerList::NETServerFrames.get(); if (!frameLimit.elapsed(std::chrono::milliseconds(interval))) return; frameLimit.update(); std::lock_guard _(Mutex); - Dvar::Var queryLimit("net_serverQueryLimit"); int sentRequests = 0; for (auto i = Nodes.begin(); i != Nodes.end();) @@ -220,7 +219,8 @@ namespace Components i = Nodes.erase(i); continue; } - if (sentRequests < queryLimit.get() && i->requiresRequest()) + + if (sentRequests < ServerList::NETServerQueryLimit.get() && i->requiresRequest()) { ++sentRequests; i->sendRequest(); @@ -241,7 +241,7 @@ namespace Components } } - void Node::HandleResponse(Network::Address address, const std::string& data) + void Node::HandleResponse(const Network::Address& address, const std::string& data) { Proto::Node::List list; if (!list.ParseFromString(data)) return; @@ -320,11 +320,11 @@ namespace Components break; } - auto node = Nodes.at(curNode++); + auto& node = Nodes.at(curNode++); if (node.isValid()) { - std::string* str = list.add_nodes(); + auto* str = list.add_nodes(); sockaddr addr = node.address.getSockAddr(); str->append(reinterpret_cast(&addr), sizeof(addr)); @@ -401,7 +401,7 @@ namespace Components Scheduler::Loop([] { StoreNodes(false); - }, Scheduler::Pipeline::ASYNC); + }, Scheduler::Pipeline::ASYNC, 5min); Scheduler::Loop(RunFrame, Scheduler::Pipeline::MAIN); @@ -411,15 +411,12 @@ namespace Components SendList(address); }); - // Load stored nodes - auto loadNodes = [] + Scheduler::OnGameInitialized([] { Migrate(); LoadNodePreset(); LoadNodes(); - }; - - Scheduler::OnGameInitialized(loadNodes, Scheduler::Pipeline::MAIN); + }, Scheduler::Pipeline::MAIN); Command::Add("listNodes", [](const Command::Params*) { diff --git a/src/Components/Modules/Node.hpp b/src/Components/Modules/Node.hpp index d76cdd20..d0943b43 100644 --- a/src/Components/Modules/Node.hpp +++ b/src/Components/Modules/Node.hpp @@ -36,7 +36,7 @@ namespace Components Node(); void preDestroy() override; - static void Add(Network::Address address); + static void Add(const Network::Address& address); static std::vector GetNodes(); static void RunFrame(); static void Synchronize(); @@ -46,7 +46,7 @@ namespace Components static std::vector Nodes; static bool WasIngame; - static void HandleResponse(Network::Address address, const std::string& data); + static void HandleResponse(const Network::Address& address, const std::string& data); static void SendList(const Network::Address& address); diff --git a/src/Components/Modules/ServerList.hpp b/src/Components/Modules/ServerList.hpp index a0ebfc28..a3820f14 100644 --- a/src/Components/Modules/ServerList.hpp +++ b/src/Components/Modules/ServerList.hpp @@ -54,6 +54,11 @@ namespace Components static bool GetMasterServer(const char* ip, int port, Game::netadr_t& address); static bool UseMasterServer; + static Dvar::Var UIServerSelected; + static Dvar::Var UIServerSelectedMap; + static Dvar::Var NETServerQueryLimit; + static Dvar::Var NETServerFrames; + private: enum class Column : int { @@ -150,11 +155,6 @@ namespace Components static std::vector VisibleList; - static Dvar::Var UIServerSelected; - static Dvar::Var UIServerSelectedMap; - static Dvar::Var NETServerQueryLimit; - static Dvar::Var NETServerFrames; - static bool IsServerListOpen(); }; } From 2ae991ccbf932a6c47da7ad718fdfdfce813c2bb Mon Sep 17 00:00:00 2001 From: Diavolo Date: Sun, 18 Jun 2023 14:59:37 +0200 Subject: [PATCH 08/22] maint: remove components I will never use --- .gitmodules | 3 - deps/iw4-open-formats | 1 - deps/premake/iw4-open-formats.lua | 44 - src/Components/Loader.cpp | 3 - src/Components/Loader.hpp | 1 - src/Components/Modules/AssetHandler.cpp | 180 +- src/Components/Modules/AssetHandler.hpp | 18 - .../Modules/AssetInterfaces/IComWorld.cpp | 71 - .../Modules/AssetInterfaces/IComWorld.hpp | 14 - .../Modules/AssetInterfaces/IFont_s.cpp | 291 --- .../Modules/AssetInterfaces/IFont_s.hpp | 14 - .../Modules/AssetInterfaces/IFxEffectDef.cpp | 456 ----- .../Modules/AssetInterfaces/IFxEffectDef.hpp | 22 - .../Modules/AssetInterfaces/IFxWorld.cpp | 218 -- .../Modules/AssetInterfaces/IFxWorld.hpp | 16 - .../Modules/AssetInterfaces/IGameWorldMp.cpp | 85 - .../Modules/AssetInterfaces/IGameWorldMp.hpp | 13 - .../Modules/AssetInterfaces/IGameWorldSp.cpp | 348 ---- .../Modules/AssetInterfaces/IGameWorldSp.hpp | 18 - .../Modules/AssetInterfaces/IGfxImage.cpp | 50 - .../Modules/AssetInterfaces/IGfxImage.hpp | 13 - .../Modules/AssetInterfaces/IGfxLightDef.cpp | 46 - .../Modules/AssetInterfaces/IGfxLightDef.hpp | 14 - .../Modules/AssetInterfaces/IGfxWorld.cpp | 945 --------- .../Modules/AssetInterfaces/IGfxWorld.hpp | 22 - .../Modules/AssetInterfaces/ILoadedSound.cpp | 42 - .../Modules/AssetInterfaces/ILoadedSound.hpp | 13 - .../AssetInterfaces/ILocalizeEntry.cpp | 131 -- .../AssetInterfaces/ILocalizeEntry.hpp | 16 - .../Modules/AssetInterfaces/IMapEnts.cpp | 98 - .../Modules/AssetInterfaces/IMapEnts.hpp | 14 - .../Modules/AssetInterfaces/IMaterial.cpp | 178 -- .../Modules/AssetInterfaces/IMaterial.hpp | 16 - .../AssetInterfaces/IMaterialPixelShader.cpp | 49 - .../AssetInterfaces/IMaterialPixelShader.hpp | 16 - .../AssetInterfaces/IMaterialTechniqueSet.cpp | 198 -- .../AssetInterfaces/IMaterialTechniqueSet.hpp | 19 - .../IMaterialVertexDeclaration.cpp | 45 - .../IMaterialVertexDeclaration.hpp | 16 - .../AssetInterfaces/IMaterialVertexShader.cpp | 50 - .../AssetInterfaces/IMaterialVertexShader.hpp | 16 - .../Modules/AssetInterfaces/IMenuList.cpp | 81 - .../Modules/AssetInterfaces/IMenuList.hpp | 14 - .../Modules/AssetInterfaces/IPhysCollmap.cpp | 136 -- .../Modules/AssetInterfaces/IPhysCollmap.hpp | 16 - .../Modules/AssetInterfaces/IPhysPreset.cpp | 41 - .../Modules/AssetInterfaces/IPhysPreset.hpp | 14 - .../Modules/AssetInterfaces/IRawFile.cpp | 46 - .../Modules/AssetInterfaces/IRawFile.hpp | 13 - .../Modules/AssetInterfaces/ISndCurve.cpp | 35 - .../Modules/AssetInterfaces/ISndCurve.hpp | 13 - .../Modules/AssetInterfaces/IStringTable.cpp | 52 - .../Modules/AssetInterfaces/IStringTable.hpp | 15 - .../AssetInterfaces/IStructuredDataDefSet.cpp | 152 -- .../AssetInterfaces/IStructuredDataDefSet.hpp | 15 - .../Modules/AssetInterfaces/ITracerDef.cpp | 45 - .../Modules/AssetInterfaces/ITracerDef.hpp | 14 - .../Modules/AssetInterfaces/IWeapon.cpp | 785 -------- .../Modules/AssetInterfaces/IWeapon.hpp | 17 - .../Modules/AssetInterfaces/IXAnimParts.cpp | 259 --- .../Modules/AssetInterfaces/IXAnimParts.hpp | 17 - .../Modules/AssetInterfaces/IXModel.cpp | 260 --- .../Modules/AssetInterfaces/IXModel.hpp | 14 - .../Modules/AssetInterfaces/IXModelSurfs.cpp | 167 -- .../Modules/AssetInterfaces/IXModelSurfs.hpp | 16 - .../Modules/AssetInterfaces/IclipMap_t.cpp | 585 ------ .../Modules/AssetInterfaces/IclipMap_t.hpp | 94 - .../Modules/AssetInterfaces/ImenuDef_t.cpp | 700 ------- .../Modules/AssetInterfaces/ImenuDef_t.hpp | 45 - .../AssetInterfaces/Isnd_alias_list_t.cpp | 226 --- .../AssetInterfaces/Isnd_alias_list_t.hpp | 17 - src/Components/Modules/Auth.cpp | 6 +- src/Components/Modules/Branding.cpp | 6 +- src/Components/Modules/Console.cpp | 4 +- src/Components/Modules/Dedicated.cpp | 4 +- src/Components/Modules/Discord.cpp | 2 +- src/Components/Modules/Dvar.cpp | 2 +- src/Components/Modules/FastFiles.cpp | 11 +- src/Components/Modules/FileSystem.cpp | 5 - src/Components/Modules/Friends.cpp | 4 +- src/Components/Modules/Gamepad.cpp | 5 - src/Components/Modules/IPCPipe.cpp | 2 +- src/Components/Modules/MapDump.cpp | 464 ----- src/Components/Modules/MapDump.hpp | 10 - src/Components/Modules/Maps.cpp | 2 +- src/Components/Modules/Menus.cpp | 5 - src/Components/Modules/ModelSurfs.cpp | 9 +- src/Components/Modules/News.cpp | 2 +- src/Components/Modules/Node.cpp | 1 - src/Components/Modules/Party.cpp | 2 +- src/Components/Modules/Singleton.cpp | 2 +- src/Components/Modules/StructuredData.cpp | 157 +- src/Components/Modules/Toast.cpp | 2 +- src/Components/Modules/ZoneBuilder.cpp | 1762 ----------------- src/Components/Modules/ZoneBuilder.hpp | 175 -- src/Components/Modules/Zones.cpp | 351 ---- src/Components/Modules/Zones.hpp | 12 - src/STDInclude.hpp | 6 + src/Steam/Interfaces/SteamUser.cpp | 6 +- src/Steam/Proxy.cpp | 6 +- 100 files changed, 42 insertions(+), 10710 deletions(-) delete mode 160000 deps/iw4-open-formats delete mode 100644 deps/premake/iw4-open-formats.lua delete mode 100644 src/Components/Modules/AssetInterfaces/IComWorld.cpp delete mode 100644 src/Components/Modules/AssetInterfaces/IComWorld.hpp delete mode 100644 src/Components/Modules/AssetInterfaces/IFont_s.cpp delete mode 100644 src/Components/Modules/AssetInterfaces/IFont_s.hpp delete mode 100644 src/Components/Modules/AssetInterfaces/IFxEffectDef.cpp delete mode 100644 src/Components/Modules/AssetInterfaces/IFxEffectDef.hpp delete mode 100644 src/Components/Modules/AssetInterfaces/IFxWorld.cpp delete mode 100644 src/Components/Modules/AssetInterfaces/IFxWorld.hpp delete mode 100644 src/Components/Modules/AssetInterfaces/IGameWorldMp.cpp delete mode 100644 src/Components/Modules/AssetInterfaces/IGameWorldMp.hpp delete mode 100644 src/Components/Modules/AssetInterfaces/IGameWorldSp.cpp delete mode 100644 src/Components/Modules/AssetInterfaces/IGameWorldSp.hpp delete mode 100644 src/Components/Modules/AssetInterfaces/IGfxImage.cpp delete mode 100644 src/Components/Modules/AssetInterfaces/IGfxImage.hpp delete mode 100644 src/Components/Modules/AssetInterfaces/IGfxLightDef.cpp delete mode 100644 src/Components/Modules/AssetInterfaces/IGfxLightDef.hpp delete mode 100644 src/Components/Modules/AssetInterfaces/IGfxWorld.cpp delete mode 100644 src/Components/Modules/AssetInterfaces/IGfxWorld.hpp delete mode 100644 src/Components/Modules/AssetInterfaces/ILoadedSound.cpp delete mode 100644 src/Components/Modules/AssetInterfaces/ILoadedSound.hpp delete mode 100644 src/Components/Modules/AssetInterfaces/ILocalizeEntry.cpp delete mode 100644 src/Components/Modules/AssetInterfaces/ILocalizeEntry.hpp delete mode 100644 src/Components/Modules/AssetInterfaces/IMapEnts.cpp delete mode 100644 src/Components/Modules/AssetInterfaces/IMapEnts.hpp delete mode 100644 src/Components/Modules/AssetInterfaces/IMaterial.cpp delete mode 100644 src/Components/Modules/AssetInterfaces/IMaterial.hpp delete mode 100644 src/Components/Modules/AssetInterfaces/IMaterialPixelShader.cpp delete mode 100644 src/Components/Modules/AssetInterfaces/IMaterialPixelShader.hpp delete mode 100644 src/Components/Modules/AssetInterfaces/IMaterialTechniqueSet.cpp delete mode 100644 src/Components/Modules/AssetInterfaces/IMaterialTechniqueSet.hpp delete mode 100644 src/Components/Modules/AssetInterfaces/IMaterialVertexDeclaration.cpp delete mode 100644 src/Components/Modules/AssetInterfaces/IMaterialVertexDeclaration.hpp delete mode 100644 src/Components/Modules/AssetInterfaces/IMaterialVertexShader.cpp delete mode 100644 src/Components/Modules/AssetInterfaces/IMaterialVertexShader.hpp delete mode 100644 src/Components/Modules/AssetInterfaces/IMenuList.cpp delete mode 100644 src/Components/Modules/AssetInterfaces/IMenuList.hpp delete mode 100644 src/Components/Modules/AssetInterfaces/IPhysCollmap.cpp delete mode 100644 src/Components/Modules/AssetInterfaces/IPhysCollmap.hpp delete mode 100644 src/Components/Modules/AssetInterfaces/IPhysPreset.cpp delete mode 100644 src/Components/Modules/AssetInterfaces/IPhysPreset.hpp delete mode 100644 src/Components/Modules/AssetInterfaces/IRawFile.cpp delete mode 100644 src/Components/Modules/AssetInterfaces/IRawFile.hpp delete mode 100644 src/Components/Modules/AssetInterfaces/ISndCurve.cpp delete mode 100644 src/Components/Modules/AssetInterfaces/ISndCurve.hpp delete mode 100644 src/Components/Modules/AssetInterfaces/IStringTable.cpp delete mode 100644 src/Components/Modules/AssetInterfaces/IStringTable.hpp delete mode 100644 src/Components/Modules/AssetInterfaces/IStructuredDataDefSet.cpp delete mode 100644 src/Components/Modules/AssetInterfaces/IStructuredDataDefSet.hpp delete mode 100644 src/Components/Modules/AssetInterfaces/ITracerDef.cpp delete mode 100644 src/Components/Modules/AssetInterfaces/ITracerDef.hpp delete mode 100644 src/Components/Modules/AssetInterfaces/IWeapon.cpp delete mode 100644 src/Components/Modules/AssetInterfaces/IWeapon.hpp delete mode 100644 src/Components/Modules/AssetInterfaces/IXAnimParts.cpp delete mode 100644 src/Components/Modules/AssetInterfaces/IXAnimParts.hpp delete mode 100644 src/Components/Modules/AssetInterfaces/IXModel.cpp delete mode 100644 src/Components/Modules/AssetInterfaces/IXModel.hpp delete mode 100644 src/Components/Modules/AssetInterfaces/IXModelSurfs.cpp delete mode 100644 src/Components/Modules/AssetInterfaces/IXModelSurfs.hpp delete mode 100644 src/Components/Modules/AssetInterfaces/IclipMap_t.cpp delete mode 100644 src/Components/Modules/AssetInterfaces/IclipMap_t.hpp delete mode 100644 src/Components/Modules/AssetInterfaces/ImenuDef_t.cpp delete mode 100644 src/Components/Modules/AssetInterfaces/ImenuDef_t.hpp delete mode 100644 src/Components/Modules/AssetInterfaces/Isnd_alias_list_t.cpp delete mode 100644 src/Components/Modules/AssetInterfaces/Isnd_alias_list_t.hpp delete mode 100644 src/Components/Modules/MapDump.cpp delete mode 100644 src/Components/Modules/MapDump.hpp delete mode 100644 src/Components/Modules/ZoneBuilder.cpp delete mode 100644 src/Components/Modules/ZoneBuilder.hpp diff --git a/.gitmodules b/.gitmodules index 469c3e6a..56289153 100644 --- a/.gitmodules +++ b/.gitmodules @@ -41,6 +41,3 @@ [submodule "deps/rapidjson"] path = deps/rapidjson url = https://github.com/Tencent/rapidjson.git -[submodule "deps/iw4-open-formats"] - path = deps/iw4-open-formats - url = https://github.com/diamante0018/iw4-open-formats.git diff --git a/deps/iw4-open-formats b/deps/iw4-open-formats deleted file mode 160000 index 5e17794e..00000000 --- a/deps/iw4-open-formats +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5e17794ed16351d3f77b72ff1ff8c52621e7b51d diff --git a/deps/premake/iw4-open-formats.lua b/deps/premake/iw4-open-formats.lua deleted file mode 100644 index 9b6751da..00000000 --- a/deps/premake/iw4-open-formats.lua +++ /dev/null @@ -1,44 +0,0 @@ -iw4_open_formats = { - source = path.join(dependencies.basePath, "iw4-open-formats"), -} - -function iw4_open_formats.import() - links "iw4-open-formats" - - iw4_open_formats.includes() -end - -function iw4_open_formats.includes() - includedirs { - path.join(iw4_open_formats.source, "include") - } -end - -function iw4_open_formats.project() - project "iw4-open-formats" - language "C++" - - iw4_open_formats.includes() - - pchheader "std_include.hpp" - pchsource (path.join(iw4_open_formats.source, "src/iw4-of/std_include.cpp")) - - files { - path.join(iw4_open_formats.source, "src/iw4-of/**.hpp"), - path.join(iw4_open_formats.source, "src/iw4-of/**.cpp"), - } - - includedirs { - path.join(iw4_open_formats.source, "src/iw4-of"), - path.join(iw4_open_formats.source, "include"), - } - - libtomcrypt.includes() - libtommath.includes() - rapidjson.includes() - zlib.includes() - - kind "StaticLib" -end - -table.insert(dependencies, iw4_open_formats) diff --git a/src/Components/Loader.cpp b/src/Components/Loader.cpp index fc09bb18..339b3dc9 100644 --- a/src/Components/Loader.cpp +++ b/src/Components/Loader.cpp @@ -28,7 +28,6 @@ #include "Modules/Gamepad.hpp" #include "Modules/IPCPipe.hpp" #include "Modules/Lean.hpp" -#include "Modules/MapDump.hpp" #include "Modules/MapRotation.hpp" #include "Modules/Materials.hpp" #include "Modules/ModList.hpp" @@ -107,7 +106,6 @@ namespace Components Register(new Network()); Register(new Logger()); Register(new UIScript()); - Register(new ZoneBuilder()); Register(new ArenaLength()); Register(new AssetHandler()); @@ -137,7 +135,6 @@ namespace Components Register(new Gamepad()); Register(new Lean()); Register(new Localization()); - Register(new MapDump()); Register(new MapRotation()); Register(new Maps()); Register(new Materials()); diff --git a/src/Components/Loader.hpp b/src/Components/Loader.hpp index 41c14b78..e9111590 100644 --- a/src/Components/Loader.hpp +++ b/src/Components/Loader.hpp @@ -69,7 +69,6 @@ namespace Components #include "Modules/Logger.hpp" #include "Modules/Singleton.hpp" #include "Modules/UIScript.hpp" -#include "Modules/ZoneBuilder.hpp" #include "Modules/AssetHandler.hpp" #include "Modules/Dedicated.hpp" diff --git a/src/Components/Modules/AssetHandler.cpp b/src/Components/Modules/AssetHandler.cpp index 5995d3c4..61bcd764 100644 --- a/src/Components/Modules/AssetHandler.cpp +++ b/src/Components/Modules/AssetHandler.cpp @@ -2,44 +2,10 @@ #include "FastFiles.hpp" #include "Weapon.hpp" -#include "AssetInterfaces/IFont_s.hpp" -#include "AssetInterfaces/IWeapon.hpp" -#include "AssetInterfaces/IXModel.hpp" -#include "AssetInterfaces/IFxWorld.hpp" -#include "AssetInterfaces/IMapEnts.hpp" -#include "AssetInterfaces/IRawFile.hpp" -#include "AssetInterfaces/IComWorld.hpp" -#include "AssetInterfaces/IGfxImage.hpp" -#include "AssetInterfaces/IGfxWorld.hpp" -#include "AssetInterfaces/IMaterial.hpp" -#include "AssetInterfaces/ISndCurve.hpp" -#include "AssetInterfaces/IMenuList.hpp" -#include "AssetInterfaces/IclipMap_t.hpp" -#include "AssetInterfaces/ImenuDef_t.hpp" -#include "AssetInterfaces/ITracerDef.hpp" -#include "AssetInterfaces/IPhysPreset.hpp" -#include "AssetInterfaces/IXAnimParts.hpp" -#include "AssetInterfaces/IFxEffectDef.hpp" -#include "AssetInterfaces/IGameWorldMp.hpp" -#include "AssetInterfaces/IGameWorldSp.hpp" -#include "AssetInterfaces/IGfxLightDef.hpp" -#include "AssetInterfaces/ILoadedSound.hpp" -#include "AssetInterfaces/IPhysCollmap.hpp" -#include "AssetInterfaces/IStringTable.hpp" -#include "AssetInterfaces/IXModelSurfs.hpp" -#include "AssetInterfaces/ILocalizeEntry.hpp" -#include "AssetInterfaces/Isnd_alias_list_t.hpp" -#include "AssetInterfaces/IMaterialPixelShader.hpp" -#include "AssetInterfaces/IMaterialTechniqueSet.hpp" -#include "AssetInterfaces/IMaterialVertexShader.hpp" -#include "AssetInterfaces/IStructuredDataDefSet.hpp" -#include "AssetInterfaces/IMaterialVertexDeclaration.hpp" - namespace Components { thread_local int AssetHandler::BypassState = 0; bool AssetHandler::ShouldSearchTempAssets = false; - std::map AssetHandler::AssetInterfaces; std::map> AssetHandler::TypeCallbacks; Utils::Signal AssetHandler::RestrictSignal; @@ -49,28 +15,6 @@ namespace Components std::map AssetHandler::TemporaryAssets[Game::ASSET_TYPE_COUNT]; - void AssetHandler::RegisterInterface(IAsset* iAsset) - { - if (!iAsset) return; - if (iAsset->getType() == Game::XAssetType::ASSET_TYPE_INVALID) - { - delete iAsset; - return; - } - - if (AssetHandler::AssetInterfaces.contains(iAsset->getType())) - { - Logger::Print("Duplicate asset interface: {}\n", Game::DB_GetXAssetTypeName(iAsset->getType())); - delete AssetHandler::AssetInterfaces[iAsset->getType()]; - } - else - { - Logger::Print("Asset interface registered: {}\n", Game::DB_GetXAssetTypeName(iAsset->getType())); - } - - AssetHandler::AssetInterfaces[iAsset->getType()] = iAsset; - } - void AssetHandler::ClearTemporaryAssets() { for (int i = 0; i < Game::ASSET_TYPE_COUNT; ++i) @@ -379,68 +323,6 @@ namespace Components offset->pointer = *static_cast(pointer); } - void AssetHandler::ZoneSave(Game::XAsset asset, ZoneBuilder::Zone* builder) - { - if (AssetHandler::AssetInterfaces.contains(asset.type)) - { - AssetHandler::AssetInterfaces[asset.type]->save(asset.header, builder); - } - else - { - Logger::Error(Game::ERR_FATAL, "No interface for type '{}'!", Game::DB_GetXAssetTypeName(asset.type)); - } - } - - void AssetHandler::ZoneMark(Game::XAsset asset, ZoneBuilder::Zone* builder) - { - if (AssetHandler::AssetInterfaces.contains(asset.type)) - { - AssetHandler::AssetInterfaces[asset.type]->mark(asset.header, builder); - } - else - { - Logger::Error(Game::ERR_FATAL, "No interface for type '{}'!", Game::DB_GetXAssetTypeName(asset.type)); - } - } - - Game::XAssetHeader AssetHandler::FindAssetForZone(Game::XAssetType type, const std::string& filename, ZoneBuilder::Zone* builder, bool isSubAsset) - { - ZoneBuilder::Zone::AssetRecursionMarker _(builder); - - Game::XAssetHeader header = { nullptr }; - if (type >= Game::ASSET_TYPE_COUNT) return header; - - auto tempPool = &AssetHandler::TemporaryAssets[type]; - auto entry = tempPool->find(filename); - if (entry != tempPool->end()) - { - return { entry->second }; - } - - if (AssetHandler::AssetInterfaces.contains(type)) - { - AssetHandler::AssetInterfaces[type]->load(&header, filename, builder); - - if (header.data) - { - Components::AssetHandler::StoreTemporaryAsset(type, header); - } - } - - if (!header.data && isSubAsset) - { - header = ZoneBuilder::GetEmptyAssetIfCommon(type, filename, builder); - } - - if (!header.data) - { - header = Game::DB_FindXAssetHeader(type, filename.data()); - if (header.data) Components::AssetHandler::StoreTemporaryAsset(type, header); // Might increase efficiency... - } - - return header; - } - Game::XAssetHeader AssetHandler::FindOriginalAsset(Game::XAssetType type, const char* filename) { AssetHandler::SetBypassState(true); @@ -484,7 +366,7 @@ namespace Components { AssertSize(Game::XAssetEntry, 16); - size_t size = (ZoneBuilder::IsEnabled() ? 1183968 : 789312); + constexpr std::size_t size = 789312; Game::XAssetEntry* entryPool = Utils::Memory::GetAllocator()->allocateArray(size); // Apply new size @@ -553,7 +435,7 @@ namespace Components Utils::Hook(0x5BB6EC, AssetHandler::StoreEmptyAssetStub, HOOK_CALL).install()->quick(); // Intercept missing asset messages - if (!ZoneBuilder::IsEnabled()) Utils::Hook(0x5BB3F2, AssetHandler::MissingAssetError, HOOK_CALL).install()->quick(); + Utils::Hook(0x5BB3F2, AssetHandler::MissingAssetError, HOOK_CALL).install()->quick(); // Log missing empty assets Scheduler::Loop([] @@ -578,77 +460,27 @@ namespace Components }); Game::ReallocateAssetPool(Game::ASSET_TYPE_GAMEWORLD_SP, 1); - Game::ReallocateAssetPool(Game::ASSET_TYPE_IMAGE, ZoneBuilder::IsEnabled() ? 14336 * 2 : 7168); + Game::ReallocateAssetPool(Game::ASSET_TYPE_IMAGE, 7168); Game::ReallocateAssetPool(Game::ASSET_TYPE_LOADED_SOUND, 2700 * 2); Game::ReallocateAssetPool(Game::ASSET_TYPE_FX, 1200 * 2); Game::ReallocateAssetPool(Game::ASSET_TYPE_LOCALIZE_ENTRY, 14000); Game::ReallocateAssetPool(Game::ASSET_TYPE_XANIMPARTS, 8192 * 2); Game::ReallocateAssetPool(Game::ASSET_TYPE_XMODEL, 5125 * 2); Game::ReallocateAssetPool(Game::ASSET_TYPE_PHYSPRESET, 128); - Game::ReallocateAssetPool(Game::ASSET_TYPE_PIXELSHADER, ZoneBuilder::IsEnabled() ? 0x4000 : 10000); - Game::ReallocateAssetPool(Game::ASSET_TYPE_VERTEXSHADER, ZoneBuilder::IsEnabled() ? 0x2000 : 3072); + Game::ReallocateAssetPool(Game::ASSET_TYPE_PIXELSHADER, 10000); + Game::ReallocateAssetPool(Game::ASSET_TYPE_VERTEXSHADER, 3072); Game::ReallocateAssetPool(Game::ASSET_TYPE_MATERIAL, 8192 * 2); - Game::ReallocateAssetPool(Game::ASSET_TYPE_VERTEXDECL, ZoneBuilder::IsEnabled() ? 0x400 : 196); + Game::ReallocateAssetPool(Game::ASSET_TYPE_VERTEXDECL, 196); Game::ReallocateAssetPool(Game::ASSET_TYPE_WEAPON, WEAPON_LIMIT); Game::ReallocateAssetPool(Game::ASSET_TYPE_STRINGTABLE, 800); Game::ReallocateAssetPool(Game::ASSET_TYPE_IMPACT_FX, 8); - - // Register asset interfaces - if (ZoneBuilder::IsEnabled()) - { - Game::ReallocateAssetPool(Game::ASSET_TYPE_MAP_ENTS, 10); - Game::ReallocateAssetPool(Game::ASSET_TYPE_XMODEL_SURFS, 8192 * 2); - Game::ReallocateAssetPool(Game::ASSET_TYPE_TECHNIQUE_SET, 0x2000); - Game::ReallocateAssetPool(Game::ASSET_TYPE_FONT, 32); - Game::ReallocateAssetPool(Game::ASSET_TYPE_RAWFILE, 2048); - Game::ReallocateAssetPool(Game::ASSET_TYPE_LEADERBOARD, 500); - - AssetHandler::RegisterInterface(new Assets::IFont_s()); - AssetHandler::RegisterInterface(new Assets::IWeapon()); - AssetHandler::RegisterInterface(new Assets::IXModel()); - AssetHandler::RegisterInterface(new Assets::IFxWorld()); - AssetHandler::RegisterInterface(new Assets::IMapEnts()); - AssetHandler::RegisterInterface(new Assets::IRawFile()); - AssetHandler::RegisterInterface(new Assets::IComWorld()); - AssetHandler::RegisterInterface(new Assets::IGfxImage()); - AssetHandler::RegisterInterface(new Assets::IGfxWorld()); - AssetHandler::RegisterInterface(new Assets::ISndCurve()); - AssetHandler::RegisterInterface(new Assets::IMaterial()); - AssetHandler::RegisterInterface(new Assets::IMenuList()); - AssetHandler::RegisterInterface(new Assets::IclipMap_t()); - AssetHandler::RegisterInterface(new Assets::ImenuDef_t()); - AssetHandler::RegisterInterface(new Assets::ITracerDef()); - AssetHandler::RegisterInterface(new Assets::IPhysPreset()); - AssetHandler::RegisterInterface(new Assets::IXAnimParts()); - AssetHandler::RegisterInterface(new Assets::IFxEffectDef()); - AssetHandler::RegisterInterface(new Assets::IGameWorldMp()); - AssetHandler::RegisterInterface(new Assets::IGameWorldSp()); - AssetHandler::RegisterInterface(new Assets::IGfxLightDef()); - AssetHandler::RegisterInterface(new Assets::ILoadedSound()); - AssetHandler::RegisterInterface(new Assets::IPhysCollmap()); - AssetHandler::RegisterInterface(new Assets::IStringTable()); - AssetHandler::RegisterInterface(new Assets::IXModelSurfs()); - AssetHandler::RegisterInterface(new Assets::ILocalizeEntry()); - AssetHandler::RegisterInterface(new Assets::Isnd_alias_list_t()); - AssetHandler::RegisterInterface(new Assets::IMaterialPixelShader()); - AssetHandler::RegisterInterface(new Assets::IMaterialTechniqueSet()); - AssetHandler::RegisterInterface(new Assets::IMaterialVertexShader()); - AssetHandler::RegisterInterface(new Assets::IStructuredDataDefSet()); - AssetHandler::RegisterInterface(new Assets::IMaterialVertexDeclaration()); - } } AssetHandler::~AssetHandler() { AssetHandler::ClearTemporaryAssets(); - for (auto i = AssetHandler::AssetInterfaces.begin(); i != AssetHandler::AssetInterfaces.end(); ++i) - { - delete i->second; - } - AssetHandler::Relocations.clear(); - AssetHandler::AssetInterfaces.clear(); AssetHandler::RestrictSignal.clear(); AssetHandler::TypeCallbacks.clear(); } diff --git a/src/Components/Modules/AssetHandler.hpp b/src/Components/Modules/AssetHandler.hpp index c965e58b..fb06a9d3 100644 --- a/src/Components/Modules/AssetHandler.hpp +++ b/src/Components/Modules/AssetHandler.hpp @@ -5,17 +5,6 @@ namespace Components class AssetHandler : public Component { public: - class IAsset - { - public: - virtual ~IAsset() {} - virtual Game::XAssetType getType() { return Game::XAssetType::ASSET_TYPE_INVALID; } - virtual void mark(Game::XAssetHeader /*header*/, ZoneBuilder::Zone* /*builder*/) {} - virtual void save(Game::XAssetHeader /*header*/, ZoneBuilder::Zone* /*builder*/) {} - virtual void dump(Game::XAssetHeader /*header*/) {} - virtual void load(Game::XAssetHeader* /*header*/, const std::string& /*name*/, ZoneBuilder::Zone* /*builder*/) {} - }; - typedef Game::XAssetHeader(Callback)(Game::XAssetType type, const std::string& name); typedef void(RestrictCallback)(Game::XAssetType type, Game::XAssetHeader asset, const std::string& name, bool* restrict); @@ -28,11 +17,7 @@ namespace Components static void ClearRelocations(); static void Relocate(void* start, void* to, DWORD size = 4); - static void ZoneSave(Game::XAsset asset, ZoneBuilder::Zone* builder); - static void ZoneMark(Game::XAsset asset, ZoneBuilder::Zone* builder); - static Game::XAssetHeader FindOriginalAsset(Game::XAssetType type, const char* filename); - static Game::XAssetHeader FindAssetForZone(Game::XAssetType type, const std::string& filename, ZoneBuilder::Zone* builder, bool isSubAsset = true); static void ClearTemporaryAssets(); static void StoreTemporaryAsset(Game::XAssetType type, Game::XAssetHeader asset); @@ -49,7 +34,6 @@ namespace Components static std::map TemporaryAssets[Game::XAssetType::ASSET_TYPE_COUNT]; - static std::map AssetInterfaces; static std::map> TypeCallbacks; static Utils::Signal RestrictSignal; @@ -57,8 +41,6 @@ namespace Components static std::vector> EmptyAssets; - static void RegisterInterface(IAsset* iAsset); - static Game::XAssetHeader FindAsset(Game::XAssetType type, const char* filename); static Game::XAssetHeader FindTemporaryAsset(Game::XAssetType type, const char* filename); static bool IsAssetEligible(Game::XAssetType type, Game::XAssetHeader* asset); diff --git a/src/Components/Modules/AssetInterfaces/IComWorld.cpp b/src/Components/Modules/AssetInterfaces/IComWorld.cpp deleted file mode 100644 index c6584170..00000000 --- a/src/Components/Modules/AssetInterfaces/IComWorld.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#include -#include "IComWorld.hpp" - -#define IW4X_COMMAP_VERSION 0 - -namespace Assets -{ - void IComWorld::load(Game::XAssetHeader* header, const std::string& _name, Components::ZoneBuilder::Zone* builder) - { - header->comWorld = builder->getIW4OfApi()->read(Game::XAssetType::ASSET_TYPE_COMWORLD, _name); - } - - void IComWorld::mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - Game::ComWorld* asset = header.comWorld; - - if (asset->primaryLights) - { - for (unsigned int i = 0; i < asset->primaryLightCount; ++i) - { - if (asset->primaryLights[i].defName) - { - builder->loadAssetByName(Game::XAssetType::ASSET_TYPE_LIGHT_DEF, asset->primaryLights[i].defName, false); - } - } - } - } - - void IComWorld::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::ComWorld, 16); - - Utils::Stream* buffer = builder->getBuffer(); - Game::ComWorld* asset = header.comWorld; - Game::ComWorld* dest = buffer->dest(); - buffer->save(asset); - - buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); - - if (asset->name) - { - buffer->saveString(builder->getAssetName(this->getType(), asset->name)); - Utils::Stream::ClearPointer(&dest->name); - } - - if (asset->primaryLights) - { - AssertSize(Game::ComPrimaryLight, 68); - buffer->align(Utils::Stream::ALIGN_4); - - Game::ComPrimaryLight* destLights = buffer->dest(); - buffer->saveArray(asset->primaryLights, asset->primaryLightCount); - - for (unsigned int i = 0; i < asset->primaryLightCount; ++i) - { - Game::ComPrimaryLight* destLight = &destLights[i]; - Game::ComPrimaryLight* light = &asset->primaryLights[i]; - - if (light->defName) - { - buffer->saveString(light->defName); - Utils::Stream::ClearPointer(&destLight->defName); - } - } - - Utils::Stream::ClearPointer(&dest->primaryLights); - } - - buffer->popBlock(); - } -} diff --git a/src/Components/Modules/AssetInterfaces/IComWorld.hpp b/src/Components/Modules/AssetInterfaces/IComWorld.hpp deleted file mode 100644 index 49048400..00000000 --- a/src/Components/Modules/AssetInterfaces/IComWorld.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -namespace Assets -{ - class IComWorld : public Components::AssetHandler::IAsset - { - public: - Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_COMWORLD; } - - void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override; - }; -} diff --git a/src/Components/Modules/AssetInterfaces/IFont_s.cpp b/src/Components/Modules/AssetInterfaces/IFont_s.cpp deleted file mode 100644 index 97fdc966..00000000 --- a/src/Components/Modules/AssetInterfaces/IFont_s.cpp +++ /dev/null @@ -1,291 +0,0 @@ -#include -#include "IFont_s.hpp" - -#define STB_TRUETYPE_IMPLEMENTATION -#include - -namespace Assets -{ - namespace - { - int PackFonts(const uint8_t* data, std::vector& charset, Game::Glyph* glyphs, float pixel_height, unsigned char* pixels, int pw, int ph, int yOffset) - { - stbtt_fontinfo f; - f.userdata = NULL; - - if (!stbtt_InitFont(&f, data, 0)) - return -1; - - std::memset(pixels, 0, pw * ph); - - int x = 1, y = 1, bottom_y = 1; - - float scale = stbtt_ScaleForPixelHeight(&f, pixel_height); - - int i = 0; - - for (auto& ch : charset) - { - int advance, lsb, x0, y0, x1, y1, gw, gh; - - int g = stbtt_FindGlyphIndex(&f, ch); - - stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb); - stbtt_GetGlyphBitmapBox(&f, g, scale, scale, &x0, &y0, &x1, &y1); - - gw = x1 - x0; - gh = y1 - y0; - - if (x + gw + 1 >= pw) - { - // Advance to next row - y = bottom_y; - x = 1; - } - - if (y + gh + 1 >= ph) - { - // Check if we have ran out of the room - return -i; - } - - stbtt_MakeGlyphBitmap(&f, pixels + x + y * pw, gw, gh, pw, scale, scale, g); - - auto& glyph = glyphs[i++]; - - glyph.letter = ch; - glyph.s0 = x / static_cast(pw); - glyph.s1 = (x + gw) / static_cast(pw); - glyph.t0 = y / static_cast(ph); - glyph.t1 = (y + gh) / static_cast(ph); - glyph.pixelWidth = static_cast(gw); - glyph.pixelHeight = static_cast(gh); - glyph.x0 = static_cast(x0); - glyph.y0 = static_cast(y0 + yOffset); - glyph.dx = static_cast(std::roundf(scale * advance)); - - // Advance to next col - x = x + gw + 1; - - // Expand bottom of current row if current glyph is bigger - if (y + gh + 1 > bottom_y) - { - bottom_y = y + gh + 1; - } - } - - return bottom_y; - } - } - - void IFont_s::mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - const auto* asset = header.font; - - if (asset->material) - { - builder->loadAsset(Game::ASSET_TYPE_MATERIAL, asset->material); - } - - if (asset->glowMaterial) - { - builder->loadAsset(Game::ASSET_TYPE_MATERIAL, asset->glowMaterial); - } - } - - void IFont_s::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) - { - Components::FileSystem::File fontDefFile(std::format("{}.json", name)); - Components::FileSystem::File fontFile(std::format("{}.ttf", name)); - - if (!fontDefFile.exists() || !fontFile.exists()) - { - return; - } - - nlohmann::json fontDef; - try - { - fontDef = nlohmann::json::parse(fontDefFile.getBuffer()); - } - catch (const nlohmann::json::parse_error& ex) - { - Components::Logger::Error(Game::ERR_FATAL, "JSON Parse Error: {}. Font {} is invalid\n", ex.what(), name); - return; - } - - auto w = fontDef["textureWidth"].get(); - auto h = fontDef["textureHeight"].get(); - - auto size = fontDef["size"].get(); - auto yOffset = fontDef["yOffset"].get(); - - auto* pixels = builder->getAllocator()->allocateArray(w * h); - - // Setup assets - const auto* texName = builder->getAllocator()->duplicateString(Utils::String::VA("if_%s", name.data() + 6 /* skip "fonts/" */)); - const auto* fontName = builder->getAllocator()->duplicateString(name); - const auto* glowMaterialName = builder->getAllocator()->duplicateString(Utils::String::VA("%s_glow", name.data())); - - auto* image = builder->getAllocator()->allocate(); - std::memcpy(image, Game::DB_FindXAssetHeader(Game::ASSET_TYPE_IMAGE, "gamefonts_pc").image, sizeof(Game::GfxImage)); - - image->name = texName; - - auto* material = builder->getAllocator()->allocate(); - std::memcpy(material, Game::DB_FindXAssetHeader(Game::ASSET_TYPE_MATERIAL, "fonts/gamefonts_pc").material, sizeof(Game::Material)); - - auto textureTable = builder->getAllocator()->allocate(); - std::memcpy(textureTable, material->textureTable, sizeof(Game::MaterialTextureDef)); - - material->textureTable = textureTable; - material->textureTable->u.image = image; - material->info.name = fontName; - - auto* glowMaterial = builder->getAllocator()->allocate(); - std::memcpy(glowMaterial, Game::DB_FindXAssetHeader(Game::ASSET_TYPE_MATERIAL, "fonts/gamefonts_pc_glow").material, sizeof(Game::Material)); - - glowMaterial->textureTable = material->textureTable; - glowMaterial->info.name = glowMaterialName; - - std::vector charset; - - if (fontDef["charset"].is_array()) - { - nlohmann::json::array_t charsetArray = fontDef["charset"]; - for (auto& ch : charsetArray) - { - charset.push_back(static_cast(ch.get())); - } - - // order matters - std::ranges::sort(charset); - - for (std::uint16_t i = 32; i < 128; i++) - { - if (std::ranges::find(charset, i) == charset.end()) - { - Components::Logger::Error(Game::ERR_FATAL, "Font {} missing codepoint {}", name.data(), i); - } - } - } - else - { - for (std::uint16_t i = 32; i < 128; i++) - { - charset.push_back(i); - } - } - - auto* font = builder->getAllocator()->allocate(); - - font->fontName = fontName; - font->pixelHeight = size; - font->material = material; - font->glowMaterial = glowMaterial; - font->glyphCount = static_cast(charset.size()); - font->glyphs = builder->getAllocator()->allocateArray(charset.size()); - - // Generate glyph data - int result = PackFonts(reinterpret_cast(fontFile.getBuffer().data()), charset, font->glyphs, static_cast(size), pixels, w, h, yOffset); - - if (result == -1) - { - Components::Logger::Error(Game::ERR_FATAL, "Truetype font {} is broken", name); - } - else if (result < 0) - { - Components::Logger::Error(Game::ERR_FATAL, "Texture size of font {} is not enough", name); - } - else if(h - result > size) - { - Components::Logger::Warning(Game::CON_CHANNEL_DONT_FILTER, "Texture of font {} have too much left over space: {}\n", name, h - result); - } - - header->font = font; - - // Save generated materials - Game::XAssetHeader tmpHeader; - - tmpHeader.image = image; - Components::AssetHandler::StoreTemporaryAsset(Game::ASSET_TYPE_IMAGE, tmpHeader); - - tmpHeader.material = material; - Components::AssetHandler::StoreTemporaryAsset(Game::ASSET_TYPE_MATERIAL, tmpHeader); - - tmpHeader.material = glowMaterial; - Components::AssetHandler::StoreTemporaryAsset(Game::ASSET_TYPE_MATERIAL, tmpHeader); - - // Save generated image - Utils::IO::CreateDir("userraw\\images"); - - int fileSize = w * h * 4; - int iwiHeaderSize = static_cast(sizeof(Game::GfxImageFileHeader)); - - Game::GfxImageFileHeader iwiHeader = - { - { 'I', 'W', 'i' }, - /* version */ - 8, - /* flags */ - 2, - /* format */ - Game::IMG_FORMAT_BITMAP_RGBA, - 0, - /* dimensions(x, y, z) */ - { static_cast(w), static_cast(h), 1 }, - /* fileSizeForPicmip (mipSize in bytes + sizeof(GfxImageFileHeader)) */ - { fileSize + iwiHeaderSize, fileSize, fileSize, fileSize } - }; - - std::string outIwi; - outIwi.resize(fileSize + sizeof(Game::GfxImageFileHeader)); - - std::memcpy(outIwi.data(), &iwiHeader, sizeof(Game::GfxImageFileHeader)); - - // Generate RGBA data - auto* rgbaPixels = outIwi.data() + sizeof(Game::GfxImageFileHeader); - - for (auto i = 0; i < w * h * 4; i += 4) - { - rgbaPixels[i + 0] = static_cast(255); - rgbaPixels[i + 1] = static_cast(255); - rgbaPixels[i + 2] = static_cast(255); - rgbaPixels[i + 3] = static_cast(pixels[i / 4]); - } - - Utils::IO::WriteFile(std::format("userraw\\images\\{}.iwi", texName), outIwi); - } - - void IFont_s::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::Font_s, 24); - AssertSize(Game::Glyph, 24); - - auto* buffer = builder->getBuffer(); - auto* asset = header.font; - auto* dest = buffer->dest(); - - buffer->save(asset); - - buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); - - if (asset->fontName) - { - buffer->saveString(asset->fontName); - Utils::Stream::ClearPointer(&dest->fontName); - } - - dest->material = builder->saveSubAsset(Game::ASSET_TYPE_MATERIAL, asset->material).material; - dest->glowMaterial = builder->saveSubAsset(Game::ASSET_TYPE_MATERIAL, asset->glowMaterial).material; - - if (asset->glyphs) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->glyphs, asset->glyphCount); - Utils::Stream::ClearPointer(&dest->glyphs); - } - - buffer->popBlock(); - } -} diff --git a/src/Components/Modules/AssetInterfaces/IFont_s.hpp b/src/Components/Modules/AssetInterfaces/IFont_s.hpp deleted file mode 100644 index 7596656d..00000000 --- a/src/Components/Modules/AssetInterfaces/IFont_s.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -namespace Assets -{ - class IFont_s : public Components::AssetHandler::IAsset - { - public: - Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_FONT; } - - void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override; - }; -} diff --git a/src/Components/Modules/AssetInterfaces/IFxEffectDef.cpp b/src/Components/Modules/AssetInterfaces/IFxEffectDef.cpp deleted file mode 100644 index 2066126c..00000000 --- a/src/Components/Modules/AssetInterfaces/IFxEffectDef.cpp +++ /dev/null @@ -1,456 +0,0 @@ -#include -#include "IFxEffectDef.hpp" - -namespace Assets -{ - void IFxEffectDef::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) - { - if (!header->data) this->loadEfx(header, name, builder); // Check if we have an editor fx - if (!header->data) this->loadFromIW4OF(header, name, builder); // Check if we need to import a new one into the game - if (!header->data /*&& !builder->isPrimaryAsset()*/) this->loadNative(header, name, builder); // Check if there is a native one - - assert(header->data); - } - - void IFxEffectDef::loadFromIW4OF(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) - { - header->fx = builder->getIW4OfApi()->read(Game::XAssetType::ASSET_TYPE_FX, name); - } - - void IFxEffectDef::loadEfx(Game::XAssetHeader* /*header*/, const std::string& name, Components::ZoneBuilder::Zone* /*builder*/) - { -#ifdef DEBUG - Components::FileSystem::File rawFx(Utils::String::VA("fx/%s.efx", name.data())); - if (rawFx.exists()) - { - const char* session = rawFx.getBuffer().data(); - Game::Com_BeginParseSession("fx"); - Game::Com_SetSpaceDelimited(0); - Game::Com_SetParseNegativeNumbers(1); - - const char* format = Game::Com_Parse(&session); - if (format != "iwfx"s) - { - Game::Com_EndParseSession(); - Components::Logger::Error(Game::ERR_FATAL, "Effect needs to be updated from the legacy format.\n"); - } - - int version = atoi(Game::Com_Parse(&session)); - if (version > 2) - { - Game::Com_EndParseSession(); - Components::Logger::Error(Game::ERR_FATAL, "Version {} is too high. I can only handle up to 2.\n", version); - } - - Utils::Memory::Allocator allocator; - Game::FxEditorEffectDef* efx = allocator.allocate(); - ZeroMemory(efx, sizeof(efx)); - - for (efx->elemCount = 0; ; ++efx->elemCount) - { - const char* value = Game::Com_Parse(&session); - if (!value) break; - if (*value != '{') - { - Components::Logger::Error(Game::ERR_FATAL, "Expected '{' to start a new segment, found '{}' instead.\n", value); - } - - if (efx->elemCount >= ARRAYSIZE(efx->elems)) - { - Components::Logger::Error(Game::ERR_FATAL, "Cannot have more than {} segments.\n", ARRAYSIZE(efx->elems)); - } - - Game::FxEditorElemDef* element = &efx->elems[efx->elemCount]; - // TODO: Initialize some stuff here - - while (true) - { - std::string newValue = Game::Com_Parse(&session); - if (newValue[0] != '}') break; - - for (int i = 0; i < FX_ELEM_FIELD_COUNT; ++i) - { - if (Game::s_elemFields[i].keyName == std::string(newValue)) - { - // TODO: Allow loading assets from raw! - if (Game::s_elemFields[i].handler(&session, element)) break; - Components::Logger::Error(Game::ERR_FATAL, "Failed to parse element {}!\n", newValue); - } - } - - if (!Game::Com_MatchToken(&session, ";", 1)) - { - Components::Logger::Error(Game::ERR_FATAL, "Expected token ';'\n"); - } - } - } - - Game::Com_EndParseSession(); - - // TODO: Convert editor fx to real fx - } -#else - (void)name; -#endif - } - - void IFxEffectDef::loadNative(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* /*builder*/) - { - header->fx = Components::AssetHandler::FindOriginalAsset(this->getType(), name.data()).fx; - } - - void IFxEffectDef::markFxElemVisuals(Game::FxElemVisuals* visuals, char elemType, Components::ZoneBuilder::Zone* builder) - { - switch (elemType) - { - case 7: - { - if (visuals->model) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_XMODEL, visuals->model); - } - - break; - } - - case 8: - case 9: - break; - - case 0xA: - { - if (visuals->soundName) - { - // Double "find call" but we have to because otherwise we'd crash on missing asset - // Sometimes Fx reference by name a sound that does not exist. IW oversight ? - // Never happens on iw3 but often happens on iw5, especially DLC maps. - if (Components::AssetHandler::FindAssetForZone(Game::XAssetType::ASSET_TYPE_SOUND, visuals->soundName, builder, false).data) - { - builder->loadAssetByName(Game::XAssetType::ASSET_TYPE_SOUND, visuals->soundName, false); - } - } - break; - } - - case 0xC: - { - if (visuals->effectDef.handle) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_FX, visuals->effectDef.handle, false); - } - - break; - } - - default: - { - if (visuals->material) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, visuals->material); - } - - break; - } - } - } - - void IFxEffectDef::mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - Game::FxEffectDef* asset = header.fx; - - for (int i = 0; i < (asset->elemDefCountEmission + asset->elemDefCountLooping + asset->elemDefCountOneShot); ++i) - { - Game::FxElemDef* elemDef = &asset->elemDefs[i]; - - { - if (elemDef->elemType == 11) - { - if (elemDef->visuals.markArray) - { - for (char j = 0; j < elemDef->visualCount; ++j) - { - if (elemDef->visuals.markArray[j].materials[0]) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, elemDef->visuals.markArray[j].materials[0]); - } - - if (elemDef->visuals.markArray[j].materials[1]) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, elemDef->visuals.markArray[j].materials[1]); - } - } - } - } - else if (elemDef->visualCount > 1) - { - if (elemDef->visuals.array) - { - for (char j = 0; j < elemDef->visualCount; ++j) - { - this->markFxElemVisuals(&elemDef->visuals.array[j], elemDef->elemType, builder); - } - } - } - else - { - this->markFxElemVisuals(&elemDef->visuals.instance, elemDef->elemType, builder); - } - } - - if (elemDef->effectOnImpact.handle) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_FX, elemDef->effectOnImpact.handle, false); - } - - if (elemDef->effectOnDeath.handle) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_FX, elemDef->effectOnDeath.handle, false); - } - - if (elemDef->effectEmitted.handle) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_FX, elemDef->effectEmitted.handle, false); - } - } - } - - void IFxEffectDef::saveFxElemVisuals(Game::FxElemVisuals* visuals, Game::FxElemVisuals* destVisuals, char elemType, Components::ZoneBuilder::Zone* builder) - { - Utils::Stream* buffer = builder->getBuffer(); - - switch (elemType) - { - case Game::FX_ELEM_TYPE_MODEL: - { - if (visuals->model) - { - destVisuals->model = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_XMODEL, visuals->model).model; - } - - break; - } - - case Game::FX_ELEM_TYPE_OMNI_LIGHT: - case Game::FX_ELEM_TYPE_SPOT_LIGHT: - break; - - case Game::FX_ELEM_TYPE_SOUND: - { - if (visuals->soundName) - { - buffer->saveString(visuals->soundName); - Utils::Stream::ClearPointer(&destVisuals->soundName); - } - - break; - } - - case Game::FX_ELEM_TYPE_RUNNER: - { - if (visuals->effectDef.handle) - { - buffer->saveString(visuals->effectDef.handle->name); - Utils::Stream::ClearPointer(&destVisuals->effectDef.handle); - } - - break; - } - - default: - { - if (visuals->material) - { - destVisuals->material = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, visuals->material).material; - } - - break; - } - } - } - - void IFxEffectDef::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::FxEffectDef, 32); - - Utils::Stream* buffer = builder->getBuffer(); - Game::FxEffectDef* asset = header.fx; - Game::FxEffectDef* dest = buffer->dest(); - buffer->save(asset); - - buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); - - if (asset->name) - { - buffer->saveString(builder->getAssetName(this->getType(), asset->name)); - Utils::Stream::ClearPointer(&dest->name); - } - - if (asset->elemDefs) - { - AssertSize(Game::FxElemDef, 252); - buffer->align(Utils::Stream::ALIGN_4); - - Game::FxElemDef* destElemDefs = buffer->dest(); - buffer->saveArray(asset->elemDefs, asset->elemDefCountEmission + asset->elemDefCountLooping + asset->elemDefCountOneShot); - - for (int i = 0; i < (asset->elemDefCountEmission + asset->elemDefCountLooping + asset->elemDefCountOneShot); ++i) - { - Game::FxElemDef* destElemDef = &destElemDefs[i]; - Game::FxElemDef* elemDef = &asset->elemDefs[i]; - - if (elemDef->velSamples) - { - AssertSize(Game::FxElemVelStateSample, 96); - buffer->align(Utils::Stream::ALIGN_4); - - buffer->saveArray(elemDef->velSamples, elemDef->velIntervalCount + 1); - - Utils::Stream::ClearPointer(&destElemDef->velSamples); - } - - if (elemDef->visSamples) - { - AssertSize(Game::FxElemVisStateSample, 48); - buffer->align(Utils::Stream::ALIGN_4); - - buffer->saveArray(elemDef->visSamples, elemDef->visStateIntervalCount + 1); - - Utils::Stream::ClearPointer(&destElemDef->visSamples); - } - - // Save_FxElemDefVisuals - { - if (elemDef->elemType == Game::FX_ELEM_TYPE_DECAL) - { - if (elemDef->visuals.markArray) - { - AssertSize(Game::FxElemMarkVisuals, 8); - buffer->align(Utils::Stream::ALIGN_4); - - Game::FxElemMarkVisuals* destMarkArray = buffer->dest(); - buffer->saveArray(elemDef->visuals.markArray, elemDef->visualCount); - - for (auto j = 0; j < elemDef->visualCount; ++j) - { - if (elemDef->visuals.markArray[j].materials[0]) - { - destMarkArray[j].materials[0] = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, elemDef->visuals.markArray[j].materials[0]).material; - } - - if (elemDef->visuals.markArray[j].materials[1]) - { - destMarkArray[j].materials[1] = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, elemDef->visuals.markArray[j].materials[1]).material; - } - } - - Utils::Stream::ClearPointer(&destElemDef->visuals.markArray); - } - } - else if (elemDef->visualCount > 1) - { - if (elemDef->visuals.array) - { - AssertSize(Game::FxElemVisuals, 4); - buffer->align(Utils::Stream::ALIGN_4); - - Game::FxElemVisuals* destVisuals = buffer->dest(); - buffer->saveArray(elemDef->visuals.array, elemDef->visualCount); - - for (char j = 0; j < elemDef->visualCount; ++j) - { - this->saveFxElemVisuals(&elemDef->visuals.array[j], &destVisuals[j], elemDef->elemType, builder); - } - - Utils::Stream::ClearPointer(&destElemDef->visuals.array); - } - } - else - { - this->saveFxElemVisuals(&elemDef->visuals.instance, &destElemDef->visuals.instance, elemDef->elemType, builder); - } - } - - if (elemDef->effectOnImpact.handle) - { - buffer->saveString(elemDef->effectOnImpact.handle->name); - Utils::Stream::ClearPointer(&destElemDef->effectOnImpact.handle); - } - - if (elemDef->effectOnDeath.handle) - { - buffer->saveString(elemDef->effectOnDeath.handle->name); - Utils::Stream::ClearPointer(&destElemDef->effectOnDeath.handle); - } - - if (elemDef->effectEmitted.handle) - { - buffer->saveString(elemDef->effectEmitted.handle->name); - Utils::Stream::ClearPointer(&destElemDef->effectEmitted.handle); - } - - // Save_FxElemExtendedDefPtr - { - AssertSize(Game::FxElemExtendedDefPtr, 4); - - if (elemDef->elemType == Game::FX_ELEM_TYPE_TRAIL) - { - // Save_FxTrailDef - { - if (elemDef->extended.trailDef) - { - AssertSize(Game::FxTrailDef, 36); - buffer->align(Utils::Stream::ALIGN_4); - - Game::FxTrailDef* trailDef = elemDef->extended.trailDef; - Game::FxTrailDef* destTrailDef = buffer->dest(); - buffer->save(trailDef); - - if (trailDef->verts) - { - AssertSize(Game::FxTrailVertex, 20); - buffer->align(Utils::Stream::ALIGN_4); - - buffer->saveArray(trailDef->verts, trailDef->vertCount); - Utils::Stream::ClearPointer(&destTrailDef->verts); - } - - if (trailDef->inds) - { - buffer->align(Utils::Stream::ALIGN_2); - - buffer->saveArray(trailDef->inds, trailDef->indCount); - Utils::Stream::ClearPointer(&destTrailDef->inds); - } - - Utils::Stream::ClearPointer(&destElemDef->extended.trailDef); - } - } - } - else if (elemDef->elemType == Game::FX_ELEM_TYPE_SPARK_FOUNTAIN) - { - if (elemDef->extended.sparkFountainDef) - { - AssertSize(Game::FxSparkFountainDef, 52); - buffer->align(Utils::Stream::ALIGN_4); - - buffer->save(elemDef->extended.sparkFountainDef); - Utils::Stream::ClearPointer(&destElemDef->extended.sparkFountainDef); - } - } - else - { - if (elemDef->extended.unknownDef) - { - buffer->save(reinterpret_cast(elemDef->extended.unknownDef)); - Utils::Stream::ClearPointer(&destElemDef->extended.unknownDef); - } - } - } - } - - Utils::Stream::ClearPointer(&dest->elemDefs); - } - - buffer->popBlock(); - } -} diff --git a/src/Components/Modules/AssetInterfaces/IFxEffectDef.hpp b/src/Components/Modules/AssetInterfaces/IFxEffectDef.hpp deleted file mode 100644 index 10463eea..00000000 --- a/src/Components/Modules/AssetInterfaces/IFxEffectDef.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -namespace Assets -{ - class IFxEffectDef : public Components::AssetHandler::IAsset - { - public: - Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_FX; } - - void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override; - - private: - void markFxElemVisuals(Game::FxElemVisuals* visuals, char elemType, Components::ZoneBuilder::Zone* builder); - void saveFxElemVisuals(Game::FxElemVisuals* visuals, Game::FxElemVisuals* destVisuals, char elemType, Components::ZoneBuilder::Zone* builder); - - void loadEfx(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder); - void loadNative(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder); - void loadFromIW4OF(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder); - }; -} diff --git a/src/Components/Modules/AssetInterfaces/IFxWorld.cpp b/src/Components/Modules/AssetInterfaces/IFxWorld.cpp deleted file mode 100644 index 4b35cc40..00000000 --- a/src/Components/Modules/AssetInterfaces/IFxWorld.cpp +++ /dev/null @@ -1,218 +0,0 @@ -#include -#include "IFxWorld.hpp" - -namespace Assets -{ - void IFxWorld::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::FxWorld, 116); - - Utils::Stream* buffer = builder->getBuffer(); - SaveLogEnter("FxWorld"); - - Game::FxWorld* asset = header.fxWorld; - Game::FxWorld* dest = buffer->dest(); - buffer->save(asset); - - buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); - - if (asset->name) - { - buffer->saveString(builder->getAssetName(this->getType(), asset->name)); - Utils::Stream::ClearPointer(&dest->name); - } - - // saveFxGlassSystem - { - AssertSize(Game::FxGlassSystem, 112); - if (asset->glassSys.defs) - { - AssertSize(Game::FxGlassDef, 36); - - buffer->align(Utils::Stream::ALIGN_4); - Game::FxGlassDef* glassDefTable = buffer->dest(); - buffer->saveArray(asset->glassSys.defs, asset->glassSys.defCount); - - for (unsigned int i = 0; i < asset->glassSys.defCount; ++i) - { - Game::FxGlassDef* glassDef = &asset->glassSys.defs[i]; - Game::FxGlassDef* destGlassDef = &glassDefTable[i]; - - if (glassDef->physPreset) - { - destGlassDef->physPreset = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_PHYSPRESET, glassDef->physPreset).physPreset; - } - - if (glassDef->material) - { - destGlassDef->material = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, glassDef->material).material; - } - - if (glassDef->materialShattered) - { - destGlassDef->materialShattered = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, glassDef->materialShattered).material; - } - } - - Utils::Stream::ClearPointer(&dest->glassSys.defs); - } - - buffer->pushBlock(Game::XFILE_BLOCK_RUNTIME); - - if (asset->glassSys.piecePlaces) - { - AssertSize(Game::FxGlassPiecePlace, 32); - - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->glassSys.piecePlaces, asset->glassSys.pieceLimit); - Utils::Stream::ClearPointer(&dest->glassSys.piecePlaces); - } - - if (asset->glassSys.pieceStates) - { - AssertSize(Game::FxGlassPieceState, 32); - - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->glassSys.pieceStates, asset->glassSys.pieceLimit); - Utils::Stream::ClearPointer(&dest->glassSys.pieceStates); - } - - if (asset->glassSys.pieceDynamics) - { - AssertSize(Game::FxGlassPieceDynamics, 36); - - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->glassSys.pieceDynamics, asset->glassSys.pieceLimit); - Utils::Stream::ClearPointer(&dest->glassSys.pieceDynamics); - } - - if (asset->glassSys.geoData) - { - AssertSize(Game::FxGlassGeometryData, 4); - - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->glassSys.geoData, asset->glassSys.geoDataLimit); - Utils::Stream::ClearPointer(&dest->glassSys.geoData); - } - - if (asset->glassSys.isInUse) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->glassSys.isInUse, asset->glassSys.pieceWordCount); - Utils::Stream::ClearPointer(&dest->glassSys.isInUse); - } - - if (asset->glassSys.cellBits) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->glassSys.cellBits, asset->glassSys.pieceWordCount * asset->glassSys.cellCount); - Utils::Stream::ClearPointer(&dest->glassSys.cellBits); - } - - if (asset->glassSys.visData) - { - buffer->align(Utils::Stream::ALIGN_16); - buffer->save(asset->glassSys.visData, 1, (asset->glassSys.pieceLimit + 15) & 0xFFFFFFF0); - Utils::Stream::ClearPointer(&dest->glassSys.visData); - } - - if (asset->glassSys.linkOrg) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->glassSys.linkOrg, asset->glassSys.pieceLimit); - Utils::Stream::ClearPointer(&dest->glassSys.linkOrg); - } - - if (asset->glassSys.halfThickness) - { - buffer->align(Utils::Stream::ALIGN_16); - buffer->save(asset->glassSys.halfThickness, 1, ((4 * asset->glassSys.pieceLimit) + 12) & 0xFFFFFFF0); - Utils::Stream::ClearPointer(&dest->glassSys.halfThickness); - } - - buffer->popBlock(); - - if (asset->glassSys.lightingHandles) - { - buffer->align(Utils::Stream::ALIGN_2); - buffer->saveArray(asset->glassSys.lightingHandles, asset->glassSys.initPieceCount); - Utils::Stream::ClearPointer(&dest->glassSys.lightingHandles); - } - - if (asset->glassSys.initPieceStates) - { - AssertSize(Game::FxGlassInitPieceState, 52); - - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->glassSys.initPieceStates, asset->glassSys.initPieceCount); - Utils::Stream::ClearPointer(&dest->glassSys.initPieceStates); - } - - if (asset->glassSys.initGeoData) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->glassSys.initGeoData, asset->glassSys.initGeoDataCount); - Utils::Stream::ClearPointer(&dest->glassSys.initGeoData); - } - } - - SaveLogExit(); - buffer->popBlock(); - } - - void IFxWorld::mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - Game::FxWorld* asset = header.fxWorld; - - if (asset->glassSys.defs) - { - for (unsigned int i = 0; i < asset->glassSys.defCount; ++i) - { - if (asset->glassSys.defs[i].physPreset) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_PHYSPRESET, asset->glassSys.defs[i].physPreset); - } - - if (asset->glassSys.defs[i].material) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, asset->glassSys.defs[i].material); - } - - if (asset->glassSys.defs[i].materialShattered) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, asset->glassSys.defs[i].materialShattered); - } - } - } - } - - void IFxWorld::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) - { - if (!header->fxWorld) loadFromDisk(header, name, builder); - if (!header->fxWorld) generate(header, name, builder); - - assert(header->fxWorld); - } - - void IFxWorld::loadFromDisk(Game::XAssetHeader* header, const std::string& _name, Components::ZoneBuilder::Zone* builder) - { - header->fxWorld = builder->getIW4OfApi()->read(Game::XAssetType::ASSET_TYPE_FXWORLD, _name); - } - - void IFxWorld::generate(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) - { - Game::FxWorld* map = Game::DB_FindXAssetHeader(Game::XAssetType::ASSET_TYPE_FXWORLD, name.data()).fxWorld; - if (map) return; - - // Generate - map = builder->getAllocator()->allocate(); - map->name = builder->getAllocator()->duplicateString(name); - - // No glass for you! - ZeroMemory(&map->glassSys, sizeof(map->glassSys)); - - map->glassSys.firstFreePiece = 0xFFFF; // That's how rust has it (no glass) - - header->fxWorld = map; - } -} diff --git a/src/Components/Modules/AssetInterfaces/IFxWorld.hpp b/src/Components/Modules/AssetInterfaces/IFxWorld.hpp deleted file mode 100644 index 4f1590c1..00000000 --- a/src/Components/Modules/AssetInterfaces/IFxWorld.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -namespace Assets -{ - class IFxWorld : public Components::AssetHandler::IAsset - { - public: - Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_FXWORLD; }; - - void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override; - void loadFromDisk(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder); - void generate(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder); - }; -} diff --git a/src/Components/Modules/AssetInterfaces/IGameWorldMp.cpp b/src/Components/Modules/AssetInterfaces/IGameWorldMp.cpp deleted file mode 100644 index 47444470..00000000 --- a/src/Components/Modules/AssetInterfaces/IGameWorldMp.cpp +++ /dev/null @@ -1,85 +0,0 @@ -#include -#include "IGameWorldMp.hpp" - -#define IW4X_GAMEWORLD_VERSION 1 - -namespace Assets -{ - void IGameWorldMp::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::GameWorldMp, 8); - - Utils::Stream* buffer = builder->getBuffer(); - Game::GameWorldMp* asset = header.gameWorldMp; - Game::GameWorldMp* dest = buffer->dest(); - buffer->save(asset); - - buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); - - if (asset->name) - { - buffer->saveString(builder->getAssetName(this->getType(), asset->name)); - Utils::Stream::ClearPointer(&dest->name); - } - - if (asset->g_glassData) - { - buffer->align(Utils::Stream::ALIGN_4); - - // Save_G_GlassData - { - AssertSize(Game::G_GlassData, 128); - - Game::G_GlassData* destGlass = buffer->dest(); - buffer->save(asset->g_glassData); - - if (asset->g_glassData->glassPieces) - { - AssertSize(Game::G_GlassPiece, 12); - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->g_glassData->glassPieces, asset->g_glassData->pieceCount); - Utils::Stream::ClearPointer(&destGlass->glassPieces); - } - - if (asset->g_glassData->glassNames) - { - AssertSize(Game::G_GlassName, 12); - buffer->align(Utils::Stream::ALIGN_4); - - Game::G_GlassName* destGlassNames = buffer->dest(); - buffer->saveArray(asset->g_glassData->glassNames, asset->g_glassData->glassNameCount); - - for (unsigned int i = 0; i < asset->g_glassData->glassNameCount; ++i) - { - Game::G_GlassName* destGlassName = &destGlassNames[i]; - Game::G_GlassName* glassName = &asset->g_glassData->glassNames[i]; - - if (glassName->nameStr) - { - buffer->saveString(glassName->nameStr); - Utils::Stream::ClearPointer(&destGlassName->nameStr); - } - - if (glassName->pieceIndices) - { - buffer->align(Utils::Stream::ALIGN_2); - buffer->saveArray(glassName->pieceIndices, glassName->pieceCount); - Utils::Stream::ClearPointer(&destGlassName->pieceIndices); - } - } - - Utils::Stream::ClearPointer(&destGlass->glassNames); - } - } - - Utils::Stream::ClearPointer(&dest->g_glassData); - } - - buffer->popBlock(); - } - - void IGameWorldMp::load(Game::XAssetHeader* header, const std::string& _name, Components::ZoneBuilder::Zone* builder) - { - header->gameWorldMp = builder->getIW4OfApi()->read(Game::XAssetType::ASSET_TYPE_GAMEWORLD_MP, _name); - } -} diff --git a/src/Components/Modules/AssetInterfaces/IGameWorldMp.hpp b/src/Components/Modules/AssetInterfaces/IGameWorldMp.hpp deleted file mode 100644 index f19b8d58..00000000 --- a/src/Components/Modules/AssetInterfaces/IGameWorldMp.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -namespace Assets -{ - class IGameWorldMp : public Components::AssetHandler::IAsset - { - public: - Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_GAMEWORLD_MP; } - - void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override; - }; -} diff --git a/src/Components/Modules/AssetInterfaces/IGameWorldSp.cpp b/src/Components/Modules/AssetInterfaces/IGameWorldSp.cpp deleted file mode 100644 index 0b06b0c2..00000000 --- a/src/Components/Modules/AssetInterfaces/IGameWorldSp.cpp +++ /dev/null @@ -1,348 +0,0 @@ -#include -#include "IGameWorldSp.hpp" - -namespace Assets -{ - void IGameWorldSp::mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - Game::GameWorldSp* asset = header.gameWorldSp; - - if (asset->path.nodes) - { - for (unsigned int i = 0; i < asset->path.nodeCount; ++i) - { - Game::pathnode_t* node = &asset->path.nodes[i]; - - for (char j = 0; j < 5; ++j) - { - builder->addScriptString((&node->constant.targetname)[j]); - } - } - } - } - - void IGameWorldSp::savepathnode_tree_info_t(Game::pathnode_tree_t* nodeTree, Game::pathnode_tree_t* destNodeTree, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::pathnode_tree_info_t, 8); - Utils::Stream* buffer = builder->getBuffer(); - - if (nodeTree->axis < 0) - { - AssertSize(Game::pathnode_tree_nodes_t, 8); - - if (nodeTree->u.s.nodes) - { - buffer->align(Utils::Stream::ALIGN_2); - buffer->saveArray(nodeTree->u.s.nodes, nodeTree->u.s.nodeCount); - Utils::Stream::ClearPointer(&destNodeTree->u.s.nodes); - } - } - else - { - for (int i = 0; i < 2; ++i) - { - Game::pathnode_tree_t** destChildNodeTreePtr = &destNodeTree->u.child[i]; - Game::pathnode_tree_t** childNodeTreePtr = &nodeTree->u.child[i]; - - if (*childNodeTreePtr) - { - if (builder->hasPointer(*childNodeTreePtr)) - { - *destChildNodeTreePtr = builder->getPointer(*childNodeTreePtr); - } - else - { - buffer->align(Utils::Stream::ALIGN_4); - builder->storePointer(*childNodeTreePtr); - - Game::pathnode_tree_t* destChildNodeTree = buffer->dest(); - buffer->save(*childNodeTreePtr); - - this->savepathnode_tree_info_t(*childNodeTreePtr, destChildNodeTree, builder); - Utils::Stream::ClearPointer(destChildNodeTreePtr); - } - } - } - } - } - - void IGameWorldSp::saveVehicleTrackSegment_ptrArray(Game::VehicleTrackSegment** trackSegmentPtrs, int count, Components::ZoneBuilder::Zone* builder) - { - Utils::Stream* buffer = builder->getBuffer(); - if (!trackSegmentPtrs) return; - - Game::VehicleTrackSegment** destTrackSegmentPtrs = buffer->dest(); - buffer->saveArray(trackSegmentPtrs, count); - - for (int i = 0; i < count; ++i) - { - Game::VehicleTrackSegment** destTrackSegmentPtr = &destTrackSegmentPtrs[i]; - Game::VehicleTrackSegment** trackSegmentPtr = &trackSegmentPtrs[i]; - - if (*trackSegmentPtr) - { - if (builder->hasPointer(*trackSegmentPtr)) - { - *destTrackSegmentPtr = builder->getPointer(*trackSegmentPtr); - } - else - { - buffer->align(Utils::Stream::ALIGN_4); - builder->storePointer(*trackSegmentPtr); - - Game::VehicleTrackSegment* destTrackSegment = buffer->dest(); - buffer->save(*trackSegmentPtr); - - this->saveVehicleTrackSegment(*trackSegmentPtr, destTrackSegment, builder); - - Utils::Stream::ClearPointer(destTrackSegmentPtr); - } - } - } - } - - void IGameWorldSp::saveVehicleTrackSegment(Game::VehicleTrackSegment* trackSegment, Game::VehicleTrackSegment* destTrackSegment, Components::ZoneBuilder::Zone* builder) - { - Utils::Stream* buffer = builder->getBuffer(); - - if (trackSegment->targetName) - { - buffer->saveString(trackSegment->targetName); - Utils::Stream::ClearPointer(&destTrackSegment->targetName); - } - - if (trackSegment->sectors) - { - AssertSize(Game::VehicleTrackSector, 60); - buffer->align(Utils::Stream::ALIGN_4); - - Game::VehicleTrackSector* destTrackSectors = buffer->dest(); - buffer->saveArray(trackSegment->sectors, trackSegment->sectorCount); - - for (unsigned int i = 0; i < trackSegment->sectorCount; ++i) - { - Game::VehicleTrackSector* destTrackSector = &destTrackSectors[i]; - Game::VehicleTrackSector* trackSector = &trackSegment->sectors[i]; - - if (trackSector->obstacles) - { - AssertSize(Game::VehicleTrackObstacle, 12); - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(trackSector->obstacles, trackSector->obstacleCount); - Utils::Stream::ClearPointer(&destTrackSector->obstacles); - } - } - } - - if (trackSegment->nextBranches) - { - buffer->align(Utils::Stream::ALIGN_4); - this->saveVehicleTrackSegment_ptrArray(trackSegment->nextBranches, trackSegment->nextBranchesCount, builder); - Utils::Stream::ClearPointer(&destTrackSegment->nextBranches); - } - - if (trackSegment->prevBranches) - { - buffer->align(Utils::Stream::ALIGN_4); - this->saveVehicleTrackSegment_ptrArray(trackSegment->prevBranches, trackSegment->prevBranchesCount, builder); - Utils::Stream::ClearPointer(&destTrackSegment->prevBranches); - } - } - - void IGameWorldSp::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::GameWorldSp, 0x38); - - Utils::Stream* buffer = builder->getBuffer(); - auto* asset = header.gameWorldSp; - auto* dest = buffer->dest(); - buffer->save(asset); - - buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); - - if (asset->name) - { - buffer->saveString(builder->getAssetName(this->getType(), asset->name)); - Utils::Stream::ClearPointer(&dest->name); - } - - // Save_PathData - { - AssertSize(Game::PathData, 40); - - if (asset->path.nodes) - { - AssertSize(Game::pathnode_t, 136); - buffer->align(Utils::Stream::ALIGN_4); - - Game::pathnode_t* destNodes = buffer->dest(); - buffer->saveArray(asset->path.nodes, asset->path.nodeCount); - - for (unsigned int i = 0; i < asset->path.nodeCount; ++i) - { - Game::pathnode_t* destNode = &destNodes[i]; - Game::pathnode_t* node = &asset->path.nodes[i]; - - AssertSize(Game::pathnode_constant_t, 64); - - for (char j = 0; j < 5; ++j) - { - builder->mapScriptString((&node->constant.targetname)[j]); - } - - if (node->constant.Links) - { - AssertSize(Game::pathlink_s, 12); - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(node->constant.Links, node->constant.totalLinkCount); - Utils::Stream::ClearPointer(&destNode->constant.Links); - } - } - - Utils::Stream::ClearPointer(&dest->path.nodes); - } - - buffer->pushBlock(Game::XFILE_BLOCK_RUNTIME); - - if (asset->path.basenodes) - { - AssertSize(Game::pathbasenode_t, 16); - - buffer->align(Utils::Stream::ALIGN_16); - buffer->saveArray(asset->path.basenodes, asset->path.nodeCount); - Utils::Stream::ClearPointer(&dest->path.basenodes); - } - - buffer->popBlock(); - - if (asset->path.chainNodeForNode) - { - buffer->align(Utils::Stream::ALIGN_2); - buffer->saveArray(asset->path.chainNodeForNode, asset->path.nodeCount); - Utils::Stream::ClearPointer(&dest->path.chainNodeForNode); - } - - if (asset->path.nodeForChainNode) - { - buffer->align(Utils::Stream::ALIGN_2); - buffer->saveArray(asset->path.nodeForChainNode, asset->path.nodeCount); - Utils::Stream::ClearPointer(&dest->path.nodeForChainNode); - } - - if (asset->path.pathVis) - { - buffer->saveArray(asset->path.pathVis, asset->path.visBytes); - Utils::Stream::ClearPointer(&dest->path.pathVis); - } - - if (asset->path.nodeTree) - { - AssertSize(Game::pathnode_tree_t, 16); - buffer->align(Utils::Stream::ALIGN_4); - - Game::pathnode_tree_t* destNodeTrees = buffer->dest(); - buffer->saveArray(asset->path.nodeTree, asset->path.nodeTreeCount); - - for (int i = 0; i < asset->path.nodeTreeCount; ++i) - { - Game::pathnode_tree_t* destNodeTree = &destNodeTrees[i]; - Game::pathnode_tree_t* nodeTree = &asset->path.nodeTree[i]; - - this->savepathnode_tree_info_t(nodeTree, destNodeTree, builder); - } - - Utils::Stream::ClearPointer(&dest->path.nodeTree); - } - } - - // Save_VehicleTrack - { - AssertSize(Game::VehicleTrack, 8); - - if (asset->vehicleTrack.segments) - { - if (builder->hasPointer(asset->vehicleTrack.segments)) - { - dest->vehicleTrack.segments = builder->getPointer(asset->vehicleTrack.segments); - } - else - { - AssertSize(Game::VehicleTrackSegment, 44); - - buffer->align(Utils::Stream::ALIGN_4); - Game::VehicleTrackSegment* destTrackSegments = buffer->dest(); - - for (unsigned int i = 0; i < asset->vehicleTrack.segmentCount; ++i) - { - builder->storePointer(&asset->vehicleTrack.segments[i]); - buffer->save(&asset->vehicleTrack.segments[i]); - } - - for (unsigned int i = 0; i < asset->vehicleTrack.segmentCount; ++i) - { - Game::VehicleTrackSegment* destTrackSegment = &destTrackSegments[i]; - Game::VehicleTrackSegment* trackSegment = &asset->vehicleTrack.segments[i]; - - this->saveVehicleTrackSegment(trackSegment, destTrackSegment, builder); - } - - Utils::Stream::ClearPointer(&dest->vehicleTrack.segments); - } - } - } - - if (asset->g_glassData) - { - // Save_G_GlassData - { - AssertSize(Game::G_GlassData, 128); - buffer->align(Utils::Stream::ALIGN_4); - - Game::G_GlassData* destGlass = buffer->dest(); - buffer->save(asset->g_glassData); - - if (asset->g_glassData->glassPieces) - { - AssertSize(Game::G_GlassPiece, 12); - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->g_glassData->glassPieces, asset->g_glassData->pieceCount); - Utils::Stream::ClearPointer(&destGlass->glassPieces); - } - - if (asset->g_glassData->glassNames) - { - AssertSize(Game::G_GlassName, 12); - buffer->align(Utils::Stream::ALIGN_4); - - Game::G_GlassName* destGlassNames = buffer->dest(); - buffer->saveArray(asset->g_glassData->glassNames, asset->g_glassData->glassNameCount); - - for (unsigned int i = 0; i < asset->g_glassData->glassNameCount; ++i) - { - Game::G_GlassName* destGlassName = &destGlassNames[i]; - Game::G_GlassName* glassName = &asset->g_glassData->glassNames[i]; - - if (glassName->nameStr) - { - buffer->saveString(glassName->nameStr); - Utils::Stream::ClearPointer(&destGlassName->nameStr); - } - - if (glassName->pieceIndices) - { - buffer->align(Utils::Stream::ALIGN_2); - buffer->saveArray(glassName->pieceIndices, glassName->pieceCount); - Utils::Stream::ClearPointer(&destGlassName->pieceIndices); - } - } - - Utils::Stream::ClearPointer(&destGlass->glassNames); - } - } - - Utils::Stream::ClearPointer(&dest->g_glassData); - } - - buffer->popBlock(); - } -} diff --git a/src/Components/Modules/AssetInterfaces/IGameWorldSp.hpp b/src/Components/Modules/AssetInterfaces/IGameWorldSp.hpp deleted file mode 100644 index 4abc33f2..00000000 --- a/src/Components/Modules/AssetInterfaces/IGameWorldSp.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -namespace Assets -{ - class IGameWorldSp : public Components::AssetHandler::IAsset - { - public: - Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_GAMEWORLD_SP; } - - void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - - private: - void savepathnode_tree_info_t(Game::pathnode_tree_t* nodeTree, Game::pathnode_tree_t* destNodeTree, Components::ZoneBuilder::Zone* builder); - void saveVehicleTrackSegment(Game::VehicleTrackSegment* trackSegment, Game::VehicleTrackSegment* destTrackSegment, Components::ZoneBuilder::Zone* builder); - void saveVehicleTrackSegment_ptrArray(Game::VehicleTrackSegment** trackSegmentPtrs, int count, Components::ZoneBuilder::Zone* builder); - }; -} diff --git a/src/Components/Modules/AssetInterfaces/IGfxImage.cpp b/src/Components/Modules/AssetInterfaces/IGfxImage.cpp deleted file mode 100644 index 4744e3ee..00000000 --- a/src/Components/Modules/AssetInterfaces/IGfxImage.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include -#include "IGfxImage.hpp" - -namespace Assets -{ - void IGfxImage::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) - { - header->image = builder->getIW4OfApi()->read(Game::XAssetType::ASSET_TYPE_IMAGE, name); - } - - void IGfxImage::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::GfxImage, 32); - - Utils::Stream* buffer = builder->getBuffer(); - Game::GfxImage* asset = header.image; - Game::GfxImage* dest = buffer->dest(); - buffer->save(asset); - - buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); - - if (asset->name) - { - buffer->saveString(builder->getAssetName(this->getType(), asset->name)); - Utils::Stream::ClearPointer(&dest->name); - } - - buffer->pushBlock(Game::XFILE_BLOCK_TEMP); - - if (asset->texture.loadDef) - { - buffer->align(Utils::Stream::ALIGN_4); - - Game::GfxImageLoadDef* destTexture = buffer->dest(); - buffer->save(asset->texture.loadDef, 16, 1); - - builder->incrementExternalSize(asset->texture.loadDef->resourceSize); - - if (destTexture->resourceSize > 0) - { - buffer->save(asset->texture.loadDef->data, asset->texture.loadDef->resourceSize); - } - - Utils::Stream::ClearPointer(&dest->texture.loadDef); - } - - buffer->popBlock(); - buffer->popBlock(); - } -} diff --git a/src/Components/Modules/AssetInterfaces/IGfxImage.hpp b/src/Components/Modules/AssetInterfaces/IGfxImage.hpp deleted file mode 100644 index 6b28cd19..00000000 --- a/src/Components/Modules/AssetInterfaces/IGfxImage.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -namespace Assets -{ - class IGfxImage : public Components::AssetHandler::IAsset - { - public: - Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_IMAGE; } - - void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override; - }; -} diff --git a/src/Components/Modules/AssetInterfaces/IGfxLightDef.cpp b/src/Components/Modules/AssetInterfaces/IGfxLightDef.cpp deleted file mode 100644 index 6849e701..00000000 --- a/src/Components/Modules/AssetInterfaces/IGfxLightDef.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include -#include "IGfxLightDef.hpp" - -namespace Assets -{ - void IGfxLightDef::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) - { - header->lightDef = builder->getIW4OfApi()->read(Game::XAssetType::ASSET_TYPE_LIGHT_DEF, name); - } - - void IGfxLightDef::mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - Game::GfxLightDef* asset = header.lightDef; - - if (asset->attenuation.image) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_IMAGE, asset->attenuation.image); - } - } - - void IGfxLightDef::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::GfxLightDef, 16); - AssertSize(Game::GfxLightImage, 8); - - Utils::Stream* buffer = builder->getBuffer(); - Game::GfxLightDef* asset = header.lightDef; - Game::GfxLightDef* dest = buffer->dest(); - buffer->save(asset); - - buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); - - if (asset->name) - { - buffer->saveString(builder->getAssetName(this->getType(), asset->name)); - Utils::Stream::ClearPointer(&dest->name); - } - - if (asset->attenuation.image) - { - dest->attenuation.image = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_IMAGE, asset->attenuation.image).image; - } - - buffer->popBlock(); - } -} diff --git a/src/Components/Modules/AssetInterfaces/IGfxLightDef.hpp b/src/Components/Modules/AssetInterfaces/IGfxLightDef.hpp deleted file mode 100644 index f07708a5..00000000 --- a/src/Components/Modules/AssetInterfaces/IGfxLightDef.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -namespace Assets -{ - class IGfxLightDef : public Components::AssetHandler::IAsset - { - public: - Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_LIGHT_DEF; } - - void mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override; - }; -} diff --git a/src/Components/Modules/AssetInterfaces/IGfxWorld.cpp b/src/Components/Modules/AssetInterfaces/IGfxWorld.cpp deleted file mode 100644 index 6334fad7..00000000 --- a/src/Components/Modules/AssetInterfaces/IGfxWorld.cpp +++ /dev/null @@ -1,945 +0,0 @@ -#include -#include "IGfxWorld.hpp" - -namespace Assets -{ - void IGfxWorld::load(Game::XAssetHeader* header, const std::string& _name, Components::ZoneBuilder::Zone* builder) - { - header->gfxWorld = builder->getIW4OfApi()->read(Game::XAssetType::ASSET_TYPE_GFXWORLD, _name); - } - - void IGfxWorld::mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - auto* asset = header.gfxWorld; - if (asset->draw.reflectionProbes) - { - for (unsigned int i = 0; i < asset->draw.reflectionProbeCount; ++i) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_IMAGE, asset->draw.reflectionProbes[i]); - } - } - - if (asset->draw.lightmaps) - { - for (auto i = 0; i < asset->draw.lightmapCount; ++i) - { - if (asset->draw.lightmaps[i].primary) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_IMAGE, asset->draw.lightmaps[i].primary); - } - - if (asset->draw.lightmaps[i].secondary) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_IMAGE, asset->draw.lightmaps[i].secondary); - } - } - } - - if (asset->draw.lightmapOverridePrimary) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_IMAGE, asset->draw.lightmapOverridePrimary); - } - - if (asset->draw.lightmapOverrideSecondary) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_IMAGE, asset->draw.lightmapOverrideSecondary); - } - - if (asset->sun.spriteMaterial) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, asset->sun.spriteMaterial); - } - - if (asset->sun.flareMaterial) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, asset->sun.flareMaterial); - } - - if (asset->skies) - { - for (int i = 0; i < asset->skyCount; ++i) - { - if (asset->skies[i].skyImage) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_IMAGE, asset->skies[i].skyImage); - } - } - } - - if (asset->materialMemory) - { - for (int i = 0; i < asset->materialMemoryCount; ++i) - { - if (asset->materialMemory[i].material) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, asset->materialMemory[i].material); - } - } - } - - if (asset->outdoorImage) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_IMAGE, asset->outdoorImage); - } - - if (asset->dpvs.surfaces) - { - for (unsigned int i = 0; i < asset->surfaceCount; ++i) - { - if (asset->dpvs.surfaces[i].material) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, asset->dpvs.surfaces[i].material); - } - } - } - - if (asset->dpvs.smodelDrawInsts) - { - for (unsigned int i = 0; i < asset->dpvs.smodelCount; ++i) - { - if (asset->dpvs.smodelDrawInsts[i].model) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_XMODEL, asset->dpvs.smodelDrawInsts[i].model); - } - } - } - } - - void IGfxWorld::saveGfxWorldDpvsPlanes(Game::GfxWorld* world, Game::GfxWorldDpvsPlanes* asset, Game::GfxWorldDpvsPlanes* dest, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::GfxWorldDpvsPlanes, 16); - - Utils::Stream* buffer = builder->getBuffer(); - SaveLogEnter("GfxWorldDpvsPlanes"); - - if (asset->planes) - { - if (builder->hasPointer(asset->planes)) - { - dest->planes = builder->getPointer(asset->planes); - } - else - { - AssertSize(Game::cplane_s, 20); - - buffer->align(Utils::Stream::ALIGN_4); - - for (int i = 0; i < world->planeCount; ++i) - { - builder->storePointer(&asset->planes[i]); - buffer->save(&asset->planes[i]); - } - - Utils::Stream::ClearPointer(&dest->planes); - } - } - - if (asset->nodes) - { - buffer->align(Utils::Stream::ALIGN_2); - buffer->saveArray(asset->nodes, world->nodeCount); - Utils::Stream::ClearPointer(&dest->nodes); - } - - buffer->pushBlock(Game::XFILE_BLOCK_RUNTIME); - - if (asset->sceneEntCellBits) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->save(asset->sceneEntCellBits, 1, asset->cellCount << 11); - Utils::Stream::ClearPointer(&dest->sceneEntCellBits); - } - - buffer->popBlock(); - SaveLogExit(); - } - - void IGfxWorld::saveGfxWorldDraw(Game::GfxWorldDraw* asset, Game::GfxWorldDraw* dest, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::GfxWorldDraw, 72); - SaveLogEnter("GfxWorldDraw"); - - Utils::Stream* buffer = builder->getBuffer(); - - if (asset->reflectionProbes) - { - buffer->align(Utils::Stream::ALIGN_4); - - auto** imageDest = buffer->dest(); - buffer->saveArray(asset->reflectionProbes, asset->reflectionProbeCount); - - for (unsigned int i = 0; i < asset->reflectionProbeCount; ++i) - { - if (asset->reflectionProbes[i]) - { - imageDest[i] = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_IMAGE, asset->reflectionProbes[i]).image; - } - } - - Utils::Stream::ClearPointer(&dest->reflectionProbes); - } - - if (asset->reflectionProbeOrigins) - { - AssertSize(Game::GfxReflectionProbe, 12); - SaveLogEnter("GfxReflectionProbe"); - - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->reflectionProbeOrigins, asset->reflectionProbeCount); - Utils::Stream::ClearPointer(&dest->reflectionProbeOrigins); - - SaveLogExit(); - } - - buffer->pushBlock(Game::XFILE_BLOCK_RUNTIME); - - if (asset->reflectionProbeTextures) - { - AssertSize(Game::GfxTexture, 4); - SaveLogEnter("GfxRawTexture"); - - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->reflectionProbeTextures, asset->reflectionProbeCount); - Utils::Stream::ClearPointer(&dest->reflectionProbeTextures); - - SaveLogExit(); - } - - buffer->popBlock(); - - if (asset->lightmaps) - { - AssertSize(Game::GfxLightmapArray, 8); - SaveLogEnter("GfxLightmapArray"); - - buffer->align(Utils::Stream::ALIGN_4); - - auto* lightmapArrayDestTable = buffer->dest(); - buffer->saveArray(asset->lightmaps, asset->lightmapCount); - - for (int i = 0; i < asset->lightmapCount; ++i) - { - auto* lightmapArrayDest = &lightmapArrayDestTable[i]; - auto* lightmapArray = &asset->lightmaps[i]; - - if (lightmapArray->primary) - { - lightmapArrayDest->primary = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_IMAGE, lightmapArray->primary).image; - } - - if (lightmapArray->secondary) - { - lightmapArrayDest->secondary = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_IMAGE, lightmapArray->secondary).image; - } - } - - Utils::Stream::ClearPointer(&dest->lightmaps); - SaveLogExit(); - } - - buffer->pushBlock(Game::XFILE_BLOCK_RUNTIME); - - if (asset->lightmapPrimaryTextures) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->lightmapPrimaryTextures, asset->lightmapCount); - Utils::Stream::ClearPointer(&dest->lightmapPrimaryTextures); - } - - if (asset->lightmapSecondaryTextures) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->lightmapSecondaryTextures, asset->lightmapCount); - Utils::Stream::ClearPointer(&dest->lightmapSecondaryTextures); - } - - buffer->popBlock(); - - if (asset->lightmapOverridePrimary) - { - dest->lightmapOverridePrimary = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_IMAGE, asset->lightmapOverridePrimary).image; - } - - if (asset->lightmapOverrideSecondary) - { - dest->lightmapOverrideSecondary = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_IMAGE, asset->lightmapOverrideSecondary).image; - } - - // saveGfxWorldVertexData - { - if (asset->vd.vertices) - { - AssertSize(Game::GfxWorldVertex, 44); - SaveLogEnter("GfxWorldVertex"); - - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->vd.vertices, asset->vertexCount); - Utils::Stream::ClearPointer(&dest->vd.vertices); - - SaveLogExit(); - } - } - - // saveGfxWorldVertexLayerData - { - if (asset->vld.data) - { - // no align for char - buffer->saveArray(asset->vld.data, asset->vertexLayerDataSize); - Utils::Stream::ClearPointer(&dest->vld.data); - } - } - - if (asset->indices) - { - buffer->align(Utils::Stream::ALIGN_2); - buffer->saveArray(asset->indices, asset->indexCount); - Utils::Stream::ClearPointer(&dest->indices); - } - - SaveLogExit(); - } - - void IGfxWorld::saveGfxLightGrid(Game::GfxLightGrid* asset, Game::GfxLightGrid* dest, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::GfxLightGrid, 56); - - Utils::Stream* buffer = builder->getBuffer(); - SaveLogEnter("GfxLightGrid"); - - if (asset->rowDataStart) - { - buffer->align(Utils::Stream::ALIGN_2); - buffer->saveArray(asset->rowDataStart, (asset->maxs[asset->rowAxis] - asset->mins[asset->rowAxis]) + 1); - Utils::Stream::ClearPointer(&dest->rowDataStart); - } - - if (asset->rawRowData) - { - // no align for char - buffer->saveArray(asset->rawRowData, asset->rawRowDataSize); - Utils::Stream::ClearPointer(&dest->rawRowData); - } - - if (asset->entries) - { - AssertSize(Game::GfxLightGridEntry, 4); - SaveLogEnter("GfxLightGridEntry"); - - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->entries, asset->entryCount); - Utils::Stream::ClearPointer(&dest->entries); - - SaveLogExit(); - } - - if (asset->colors) - { - AssertSize(Game::GfxLightGridColors, 168); - SaveLogEnter("GfxLightGridColors"); - - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->colors, asset->colorCount); - Utils::Stream::ClearPointer(&dest->colors); - - SaveLogExit(); - } - - SaveLogExit(); - } - - void IGfxWorld::savesunflare_t(Game::sunflare_t* asset, Game::sunflare_t* dest, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::sunflare_t, 96); - SaveLogEnter("sunflare_t"); - - if (asset->spriteMaterial) - { - dest->spriteMaterial = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, asset->spriteMaterial).material; - } - - if (asset->flareMaterial) - { - dest->flareMaterial = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, asset->flareMaterial).material; - } - - SaveLogExit(); - } - - void IGfxWorld::saveGfxWorldDpvsStatic(Game::GfxWorld* world, Game::GfxWorldDpvsStatic* asset, Game::GfxWorldDpvsStatic* dest, int /*planeCount*/, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::GfxWorldDpvsStatic, 108); - - Utils::Stream* buffer = builder->getBuffer(); - SaveLogEnter("GfxWorldDpvsStatic"); - - buffer->pushBlock(Game::XFILE_BLOCK_RUNTIME); - - for (int i = 0; i < 3; ++i) - { - if (asset->smodelVisData[i]) - { - buffer->saveArray(asset->smodelVisData[i], asset->smodelCount); - Utils::Stream::ClearPointer(&dest->smodelVisData[i]); - } - } - - for (int i = 0; i < 3; ++i) - { - if (asset->surfaceVisData[i]) - { - buffer->saveArray(asset->surfaceVisData[i], asset->staticSurfaceCount); - Utils::Stream::ClearPointer(&dest->surfaceVisData[i]); - } - } - - buffer->popBlock(); - - if (asset->sortedSurfIndex) - { - buffer->align(Utils::Stream::ALIGN_2); - buffer->saveArray(asset->sortedSurfIndex, asset->staticSurfaceCount + asset->staticSurfaceCountNoDecal); - Utils::Stream::ClearPointer(&dest->sortedSurfIndex); - } - - if (asset->smodelInsts) - { - AssertSize(Game::GfxStaticModelInst, 36); - SaveLogEnter("GfxStaticModelInst"); - - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->smodelInsts, asset->smodelCount); - Utils::Stream::ClearPointer(&dest->smodelInsts); - - SaveLogExit(); - } - - if (asset->surfaces) - { - AssertSize(Game::GfxSurface, 24); - SaveLogEnter("GfxSurface"); - - buffer->align(Utils::Stream::ALIGN_4); - auto* destSurfaceTable = buffer->dest(); - buffer->saveArray(asset->surfaces, world->surfaceCount); - - for (unsigned int i = 0; i < world->surfaceCount; ++i) - { - auto* surface = &asset->surfaces[i]; - auto* destSurface = &destSurfaceTable[i]; - - if (surface->material) - { - destSurface->material = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, surface->material).material; - } - } - - Utils::Stream::ClearPointer(&dest->surfaces); - SaveLogExit(); - } - - if (asset->surfacesBounds) - { - AssertSize(Game::GfxSurfaceBounds, 24); - SaveLogEnter("GfxSurfaceBounds"); - - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->surfacesBounds, world->surfaceCount); - Utils::Stream::ClearPointer(&dest->surfacesBounds); - - SaveLogExit(); - } - - if (asset->smodelDrawInsts) - { - AssertSize(Game::GfxStaticModelDrawInst, 76); - SaveLogEnter("GfxStaticModelDrawInst"); - - buffer->align(Utils::Stream::ALIGN_4); - auto* destModelTable = buffer->dest(); - buffer->saveArray(asset->smodelDrawInsts, asset->smodelCount); - - for (unsigned int i = 0; i < asset->smodelCount; ++i) - { - auto* model = &asset->smodelDrawInsts[i]; - auto* destModel = &destModelTable[i]; - - if (model->model) - { - destModel->model = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_XMODEL, model->model).model; - } - } - - Utils::Stream::ClearPointer(&dest->smodelDrawInsts); - SaveLogExit(); - } - - buffer->pushBlock(Game::XFILE_BLOCK_RUNTIME); - - if (asset->surfaceMaterials) - { - AssertSize(Game::GfxDrawSurf, 8); - SaveLogEnter("GfxDrawSurf"); - - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->surfaceMaterials, world->surfaceCount); - Utils::Stream::ClearPointer(&dest->surfaceMaterials); - - SaveLogExit(); - } - - if (asset->surfaceCastsSunShadow) - { - AssertSize(Game::GfxDrawSurf, 8); - SaveLogEnter("GfxDrawSurf"); - - buffer->align(Utils::Stream::ALIGN_128); - buffer->save(asset->surfaceCastsSunShadow, 4, asset->surfaceVisDataCount); - Utils::Stream::ClearPointer(&dest->surfaceCastsSunShadow); - - SaveLogExit(); - } - - buffer->popBlock(); - SaveLogExit(); - } - - void IGfxWorld::saveGfxWorldDpvsDynamic(Game::GfxWorldDpvsDynamic* asset, Game::GfxWorldDpvsDynamic* dest, int cellCount, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::GfxWorldDpvsDynamic, 48); - - Utils::Stream* buffer = builder->getBuffer(); - SaveLogEnter("GfxWorldDpvsDynamic"); - - buffer->pushBlock(Game::XFILE_BLOCK_RUNTIME); - - if (asset->dynEntCellBits[0]) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->save(asset->dynEntCellBits[0], 4, asset->dynEntClientWordCount[0] * cellCount); - Utils::Stream::ClearPointer(&dest->dynEntCellBits[0]); - } - - if (asset->dynEntCellBits[1]) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->save(asset->dynEntCellBits[1], 4, asset->dynEntClientWordCount[1] * cellCount); - Utils::Stream::ClearPointer(&dest->dynEntCellBits[1]); - } - - // this covers [0][0], [1][0], [0][1], [1][1], [0][2], [1][2] - for (char i = 0; i < 3; ++i) - { - for (char j = 0; j < 2; ++j) - { - if (asset->dynEntVisData[j][i]) - { - buffer->align(Utils::Stream::ALIGN_16); - buffer->save(asset->dynEntVisData[j][i], 32, asset->dynEntClientWordCount[j]); - Utils::Stream::ClearPointer(&dest->dynEntVisData[j][i]); - } - } - } - - buffer->popBlock(); - SaveLogExit(); - } - - void IGfxWorld::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::GfxWorld, 628); - - Utils::Stream* buffer = builder->getBuffer(); - SaveLogEnter("GfxWorld"); - - auto* asset = header.gfxWorld; - auto* dest = buffer->dest(); - buffer->save(asset); - - buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); - - if (asset->name) - { - buffer->saveString(builder->getAssetName(this->getType(), asset->name)); - Utils::Stream::ClearPointer(&dest->name); - } - - if (asset->baseName) - { - buffer->saveString(asset->baseName); - Utils::Stream::ClearPointer(&dest->baseName); - } - - //buffer->setPointerAssertion(true); - - if (asset->skies) - { - AssertSize(Game::GfxSky, 16); - SaveLogEnter("GfxSky"); - - buffer->align(Utils::Stream::ALIGN_4); - auto* destSkyTable = buffer->dest(); - buffer->saveArray(asset->skies, asset->skyCount); - - for (int i = 0; i < asset->skyCount; ++i) - { - auto* destSky = &destSkyTable[i]; - auto* sky = &asset->skies[i]; - - if (sky->skyStartSurfs) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(sky->skyStartSurfs, sky->skySurfCount); - Utils::Stream::ClearPointer(&destSky->skyStartSurfs); - } - - if (sky->skyImage) - { - destSky->skyImage = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_IMAGE, sky->skyImage).image; - } - } - - Utils::Stream::ClearPointer(&dest->skies); - SaveLogExit(); - } - - this->saveGfxWorldDpvsPlanes(asset, &asset->dpvsPlanes, &dest->dpvsPlanes, builder); - - int cellCount = asset->dpvsPlanes.cellCount; - - if (asset->aabbTreeCounts) - { - AssertSize(Game::GfxCellTreeCount, 4); - SaveLogEnter("GfxCellTreeCount"); - - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->aabbTreeCounts, cellCount); - Utils::Stream::ClearPointer(&dest->aabbTreeCounts); - - SaveLogExit(); - } - - if (asset->aabbTrees) - { - AssertSize(Game::GfxCellTree, 4); - SaveLogEnter("GfxCellTree"); - - buffer->align(Utils::Stream::ALIGN_128); - auto* destCellTreeTable = buffer->dest(); - buffer->saveArray(asset->aabbTrees, cellCount); - - for (int i = 0; i < cellCount; ++i) - { - auto* destCellTree = &destCellTreeTable[i]; - auto* cellTree = &asset->aabbTrees[i]; - - if (cellTree->aabbTree) - { - AssertSize(Game::GfxAabbTree, 44); - SaveLogEnter("GfxAabbTree"); - - buffer->align(Utils::Stream::ALIGN_4); - auto* destAabbTreeTable = buffer->dest(); - buffer->saveArray(cellTree->aabbTree, asset->aabbTreeCounts[i].aabbTreeCount); - - // ok this one is based on some assumptions because the actual count is this - // *(int *)((char *)&varGfxWorld->aabbTreeCounts->aabbTreeCount + (((char *)varGfxCellTree - (char *)varGfxWorld->aabbTrees) & 0xFFFFFFFC)) - // which makes no sense - // what DOES make sense is using the count from the structure - - for (int j = 0; j < asset->aabbTreeCounts[i].aabbTreeCount; ++j) - { - auto* destAabbTree = &destAabbTreeTable[j]; - auto* aabbTree = &cellTree->aabbTree[j]; - - if (aabbTree->smodelIndexes) - { - if (builder->hasPointer(aabbTree->smodelIndexes)) - { - destAabbTree->smodelIndexes = builder->getPointer(aabbTree->smodelIndexes); - } - else - { - buffer->align(Utils::Stream::ALIGN_2); - - for (unsigned short k = 0; k < aabbTree->smodelIndexCount; ++k) - { - builder->storePointer(&aabbTree->smodelIndexes[k]); - buffer->save(&aabbTree->smodelIndexes[k]); - } - - Utils::Stream::ClearPointer(&destAabbTree->smodelIndexes); - } - } - } - - Utils::Stream::ClearPointer(&destCellTree->aabbTree); - SaveLogExit(); - } - } - - Utils::Stream::ClearPointer(&dest->aabbTrees); - SaveLogExit(); - } - - if (asset->cells) - { - AssertSize(Game::GfxCell, 40); - SaveLogEnter("GfxCell"); - - buffer->align(Utils::Stream::ALIGN_4); - auto* destCellTable = buffer->dest(); - buffer->saveArray(asset->cells, cellCount); - - for (int i = 0; i < cellCount; ++i) - { - auto* destCell = &destCellTable[i]; - auto* cell = &asset->cells[i]; - - if (cell->portals) - { - AssertSize(Game::GfxPortal, 60); - SaveLogEnter("GfxPortal"); - - buffer->align(Utils::Stream::ALIGN_4); - auto* destPortalTable = buffer->dest(); - buffer->saveArray(cell->portals, cell->portalCount); - - for (int j = 0; j < cell->portalCount; ++j) - { - auto* destPortal = &destPortalTable[j]; - auto* portal = &cell->portals[j]; - - if (portal->vertices) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(portal->vertices, portal->vertexCount); - Utils::Stream::ClearPointer(&destPortal->vertices); - } - } - - Utils::Stream::ClearPointer(&destCell->portals); - SaveLogExit(); - } - - if (cell->reflectionProbes) - { - // no align for char - buffer->saveArray(cell->reflectionProbes, cell->reflectionProbeCount); - Utils::Stream::ClearPointer(&destCell->reflectionProbes); - } - } - - Utils::Stream::ClearPointer(&dest->cells); - SaveLogExit(); - } - - this->saveGfxWorldDraw(&asset->draw, &dest->draw, builder); - this->saveGfxLightGrid(&asset->lightGrid, &dest->lightGrid, builder); - - if (asset->models) - { - AssertSize(Game::GfxBrushModel, 60); - SaveLogEnter("GfxBrushModel"); - - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->models, asset->modelCount); - Utils::Stream::ClearPointer(&dest->models); - - SaveLogExit(); - } - - if (asset->materialMemory) - { - AssertSize(Game::MaterialMemory, 8); - SaveLogEnter("MaterialMemory"); - - buffer->align(Utils::Stream::ALIGN_4); - auto* destMaterialMemoryTable = buffer->dest(); - buffer->saveArray(asset->materialMemory, asset->materialMemoryCount); - - for (int i = 0; i < asset->materialMemoryCount; ++i) - { - auto* destMaterialMemory = &destMaterialMemoryTable[i]; - auto* materialMemory = &asset->materialMemory[i]; - - if (materialMemory->material) - { - destMaterialMemory->material = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, materialMemory->material).material; - } - } - - Utils::Stream::ClearPointer(&dest->materialMemory); - SaveLogExit(); - } - - this->savesunflare_t(&asset->sun, &dest->sun, builder); - - if (asset->outdoorImage) - { - dest->outdoorImage = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_IMAGE, asset->outdoorImage).image; - } - - buffer->pushBlock(Game::XFILE_BLOCK_RUNTIME); - - if (asset->cellCasterBits) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->save(asset->cellCasterBits, 4, cellCount * ((cellCount + 31) >> 5)); - Utils::Stream::ClearPointer(&dest->cellCasterBits); - } - - if (asset->cellHasSunLitSurfsBits) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->save(asset->cellHasSunLitSurfsBits, 4, ((cellCount + 31) >> 5)); - Utils::Stream::ClearPointer(&dest->cellHasSunLitSurfsBits); - } - - if (asset->sceneDynModel) - { - AssertSize(Game::GfxSceneDynModel, 6); - - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->sceneDynModel, asset->dpvsDyn.dynEntClientCount[0]); - Utils::Stream::ClearPointer(&dest->sceneDynModel); - } - - if (asset->sceneDynBrush) - { - AssertSize(Game::GfxSceneDynBrush, 4); - - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->sceneDynBrush, asset->dpvsDyn.dynEntClientCount[1]); - Utils::Stream::ClearPointer(&dest->sceneDynBrush); - } - - if (asset->primaryLightEntityShadowVis) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->save(asset->primaryLightEntityShadowVis, 1, (asset->primaryLightCount + 0x1FFFF - asset->lastSunPrimaryLightIndex) << 15); - Utils::Stream::ClearPointer(&dest->primaryLightEntityShadowVis); - } - - if (asset->primaryLightDynEntShadowVis[0]) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->primaryLightDynEntShadowVis[0], asset->dpvsDyn.dynEntClientCount[0] * (asset->primaryLightCount - 1 - asset->lastSunPrimaryLightIndex)); - Utils::Stream::ClearPointer(&dest->primaryLightDynEntShadowVis[0]); - } - - if (asset->primaryLightDynEntShadowVis[1]) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->primaryLightDynEntShadowVis[1], asset->dpvsDyn.dynEntClientCount[1] * (asset->primaryLightCount - 1 - asset->lastSunPrimaryLightIndex)); - Utils::Stream::ClearPointer(&dest->primaryLightDynEntShadowVis[1]); - } - - if (asset->nonSunPrimaryLightForModelDynEnt) - { - // no align cause char - buffer->saveArray(asset->nonSunPrimaryLightForModelDynEnt, asset->dpvsDyn.dynEntClientCount[0]); - Utils::Stream::ClearPointer(&dest->nonSunPrimaryLightForModelDynEnt); - } - - buffer->popBlock(); - - if (asset->shadowGeom) - { - AssertSize(Game::GfxShadowGeometry, 12); - SaveLogEnter("GfxShadowGeometry"); - - buffer->align(Utils::Stream::ALIGN_4); - auto* destShadowGeometryTable = buffer->dest(); - buffer->saveArray(asset->shadowGeom, asset->primaryLightCount); - - for (unsigned int i = 0; i < asset->primaryLightCount; ++i) - { - auto* destShadowGeometry = &destShadowGeometryTable[i]; - auto* shadowGeometry = &asset->shadowGeom[i]; - - if (shadowGeometry->sortedSurfIndex) - { - buffer->align(Utils::Stream::ALIGN_2); - buffer->saveArray(shadowGeometry->sortedSurfIndex, shadowGeometry->surfaceCount); - Utils::Stream::ClearPointer(&destShadowGeometry->sortedSurfIndex); - } - - if (shadowGeometry->smodelIndex) - { - buffer->align(Utils::Stream::ALIGN_2); - buffer->saveArray(shadowGeometry->smodelIndex, shadowGeometry->smodelCount); - Utils::Stream::ClearPointer(&destShadowGeometry->smodelIndex); - } - } - - Utils::Stream::ClearPointer(&dest->shadowGeom); - SaveLogExit(); - } - - if (asset->lightRegion) - { - AssertSize(Game::GfxLightRegion, 8); - SaveLogEnter("GfxLightRegion"); - - buffer->align(Utils::Stream::ALIGN_4); - auto* destLightRegionTable = buffer->dest(); - buffer->saveArray(asset->lightRegion, asset->primaryLightCount); - - for (unsigned int i = 0; i < asset->primaryLightCount; ++i) - { - auto* destLightRegion = &destLightRegionTable[i]; - auto* lightRegion = &asset->lightRegion[i]; - - if (lightRegion->hulls) - { - AssertSize(Game::GfxLightRegionHull, 80); - SaveLogEnter("GfxLightRegionHull"); - - buffer->align(Utils::Stream::ALIGN_4); - auto* destLightRegionHullTable = buffer->dest(); - buffer->saveArray(lightRegion->hulls, lightRegion->hullCount); - - for (unsigned int j = 0; j < lightRegion->hullCount; ++j) - { - auto* destLightRegionHull = &destLightRegionHullTable[j]; - auto* lightRegionHull = &lightRegion->hulls[j]; - - if (lightRegionHull->axis) - { - AssertSize(Game::GfxLightRegionAxis, 20); - SaveLogEnter("GfxLightRegionAxis"); - - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(lightRegionHull->axis, lightRegionHull->axisCount); - Utils::Stream::ClearPointer(&destLightRegionHull->axis); - - SaveLogExit(); - } - - } - - Utils::Stream::ClearPointer(&destLightRegion->hulls); - SaveLogExit(); - } - } - - Utils::Stream::ClearPointer(&dest->lightRegion); - SaveLogExit(); - } - - this->saveGfxWorldDpvsStatic(asset, &asset->dpvs, &dest->dpvs, asset->dpvsPlanes.cellCount, builder); - this->saveGfxWorldDpvsDynamic(&asset->dpvsDyn, &dest->dpvsDyn, asset->dpvsPlanes.cellCount, builder); - - if (asset->heroOnlyLights) - { - AssertSize(Game::GfxHeroOnlyLight, 56); - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->heroOnlyLights, asset->heroOnlyLightCount); - Utils::Stream::ClearPointer(&dest->heroOnlyLights); - } - - buffer->popBlock(); - SaveLogExit(); - } -} diff --git a/src/Components/Modules/AssetInterfaces/IGfxWorld.hpp b/src/Components/Modules/AssetInterfaces/IGfxWorld.hpp deleted file mode 100644 index 74f1786e..00000000 --- a/src/Components/Modules/AssetInterfaces/IGfxWorld.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -namespace Assets -{ - class IGfxWorld : public Components::AssetHandler::IAsset - { - public: - Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_GFXWORLD; }; - - void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override; - - private: - void saveGfxWorldDpvsPlanes(Game::GfxWorld* world, Game::GfxWorldDpvsPlanes* asset, Game::GfxWorldDpvsPlanes* dest, Components::ZoneBuilder::Zone* builder); - void saveGfxWorldDraw(Game::GfxWorldDraw* asset, Game::GfxWorldDraw* dest, Components::ZoneBuilder::Zone* builder); - void saveGfxLightGrid(Game::GfxLightGrid* asset, Game::GfxLightGrid* dest, Components::ZoneBuilder::Zone* builder); - void savesunflare_t(Game::sunflare_t* asset, Game::sunflare_t* dest, Components::ZoneBuilder::Zone* builder); - void saveGfxWorldDpvsStatic(Game::GfxWorld* world, Game::GfxWorldDpvsStatic* asset, Game::GfxWorldDpvsStatic* dest, int planeCount, Components::ZoneBuilder::Zone* builder); - void saveGfxWorldDpvsDynamic(Game::GfxWorldDpvsDynamic* asset, Game::GfxWorldDpvsDynamic* dest, int cellCount, Components::ZoneBuilder::Zone* builder); - }; -} diff --git a/src/Components/Modules/AssetInterfaces/ILoadedSound.cpp b/src/Components/Modules/AssetInterfaces/ILoadedSound.cpp deleted file mode 100644 index 803bc4e6..00000000 --- a/src/Components/Modules/AssetInterfaces/ILoadedSound.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include -#include "ILoadedSound.hpp" - -namespace Assets -{ - void ILoadedSound::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) - { - header->loadSnd = builder->getIW4OfApi()->read(Game::XAssetType::ASSET_TYPE_LOADED_SOUND, name); - } - - void ILoadedSound::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::LoadedSound, 44); - - auto* buffer = builder->getBuffer(); - auto* asset = header.loadSnd; - auto* dest = buffer->dest(); - buffer->save(asset); - - buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); - - if (asset->name) - { - buffer->saveString(builder->getAssetName(this->getType(), asset->name)); - Utils::Stream::ClearPointer(&dest->name); - } - - { - buffer->pushBlock(Game::XFILE_BLOCK_TEMP); - - if (asset->sound.data) - { - buffer->saveArray(asset->sound.data, asset->sound.info.data_len); - Utils::Stream::ClearPointer(&dest->sound.data); - } - - buffer->popBlock(); - } - - buffer->popBlock(); - } -} diff --git a/src/Components/Modules/AssetInterfaces/ILoadedSound.hpp b/src/Components/Modules/AssetInterfaces/ILoadedSound.hpp deleted file mode 100644 index 8e2ae56b..00000000 --- a/src/Components/Modules/AssetInterfaces/ILoadedSound.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -namespace Assets -{ - class ILoadedSound : public Components::AssetHandler::IAsset - { - public: - Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_LOADED_SOUND; }; - - void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override; - void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - }; -} diff --git a/src/Components/Modules/AssetInterfaces/ILocalizeEntry.cpp b/src/Components/Modules/AssetInterfaces/ILocalizeEntry.cpp deleted file mode 100644 index 1bd2b6e6..00000000 --- a/src/Components/Modules/AssetInterfaces/ILocalizeEntry.cpp +++ /dev/null @@ -1,131 +0,0 @@ -#include -#include "ILocalizeEntry.hpp" - -namespace Assets -{ - void ILocalizeEntry::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) - { - const auto path = "localizedstrings/" + name; - - Components::FileSystem::File rawFile(path); - if (!rawFile.exists()) - { - return; - } - - Components::Logger::Debug("Parsing localized string \"{}\"...", path); - - auto* asset = builder->getAllocator()->allocate(); - if (!asset) - { - return; - } - - asset->name = builder->getAllocator()->duplicateString(name); - asset->value = builder->getAllocator()->duplicateString(rawFile.getBuffer()); - - header->localize = asset; - } - - void ILocalizeEntry::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::LocalizeEntry, 8); - - auto* buffer = builder->getBuffer(); - auto* asset = header.localize; - auto* dest = buffer->dest(); - buffer->save(asset); - - buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); - - if (asset->value) - { - buffer->saveString(asset->value); - Utils::Stream::ClearPointer(&dest->value); - } - - if (asset->name) - { - buffer->saveString(builder->getAssetName(this->getType(), asset->name)); - Utils::Stream::ClearPointer(&dest->name); - } - - buffer->popBlock(); - } - - void ILocalizeEntry::ParseLocalizedStringsFile(Components::ZoneBuilder::Zone* builder, const std::string& name, const std::string& filename) - { - std::vector assets; - const auto _0 = gsl::finally([] - { - Components::Localization::ParseOutput(nullptr); - Components::Localization::PrefixOverride = {}; - }); - - Components::Localization::PrefixOverride = Utils::String::ToUpper(name) + "_"; - Components::Localization::ParseOutput([&assets](Game::LocalizeEntry* asset) - { - assets.push_back(asset); - }); - - const auto* psLoadedFile = Game::SE_Load(filename.data(), false); - if (psLoadedFile) - { - Game::Com_PrintError(Game::CON_CHANNEL_SYSTEM, "^1Localization ERROR: %s\n", psLoadedFile); - return; - } - - auto type = Game::DB_GetXAssetNameType("localize"); - for (const auto& entry : assets) - { - builder->addRawAsset(type, entry); - } - } - - void ILocalizeEntry::ParseLocalizedStringsJSON(Components::ZoneBuilder::Zone* builder, Components::FileSystem::File& file) - { - nlohmann::json localize; - try - { - Components::Logger::Debug("Parsing localized string \"{}\"...", file.getName()); - localize = nlohmann::json::parse(file.getBuffer()); - } - catch (const std::exception& ex) - { - Components::Logger::PrintError(Game::CON_CHANNEL_ERROR, "{}\n", ex.what()); - return; - } - - if (!localize.is_object()) - { - Components::Logger::PrintError(Game::CON_CHANNEL_ERROR, "Localized strings json file '{}' should be an object!", file.getName()); - return; - } - - std::vector assets; - - try - { - for (const auto& [key, value] : localize.items()) - { - const auto valueStr = value.get(); - - auto* entry = builder->getAllocator()->allocate(); - entry->name = builder->getAllocator()->duplicateString(key); - entry->value = builder->getAllocator()->duplicateString(valueStr); - - assets.emplace_back(entry); - } - } - catch (const std::exception& ex) - { - Components::Logger::PrintError(Game::CON_CHANNEL_ERROR, "{}: Localized strings json file '{}' contains invalid data!", ex.what(), file.getName()); - } - - auto type = Game::DB_GetXAssetNameType("localize"); - for (const auto& entry : assets) - { - builder->addRawAsset(type, entry); - } - } -} diff --git a/src/Components/Modules/AssetInterfaces/ILocalizeEntry.hpp b/src/Components/Modules/AssetInterfaces/ILocalizeEntry.hpp deleted file mode 100644 index 5b64270b..00000000 --- a/src/Components/Modules/AssetInterfaces/ILocalizeEntry.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -namespace Assets -{ - class ILocalizeEntry : public Components::AssetHandler::IAsset - { - public: - Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_LOCALIZE_ENTRY; } - - void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override; - void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - - static void ParseLocalizedStringsFile(Components::ZoneBuilder::Zone* builder, const std::string& name, const std::string& filename); - static void ParseLocalizedStringsJSON(Components::ZoneBuilder::Zone* builder, Components::FileSystem::File& file); - }; -} diff --git a/src/Components/Modules/AssetInterfaces/IMapEnts.cpp b/src/Components/Modules/AssetInterfaces/IMapEnts.cpp deleted file mode 100644 index 48ed5c93..00000000 --- a/src/Components/Modules/AssetInterfaces/IMapEnts.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#include -#include "IMapEnts.hpp" - -namespace Assets -{ - void IMapEnts::load(Game::XAssetHeader* header, const std::string& _name, Components::ZoneBuilder::Zone* builder) - { - header->mapEnts = builder->getIW4OfApi()->read(Game::XAssetType::ASSET_TYPE_MAP_ENTS, _name); - } - - void IMapEnts::mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - Utils::Entities memEnts(header.mapEnts->entityString, header.mapEnts->numEntityChars); - for (auto& model : memEnts.getModels()) - { - builder->loadAssetByName(Game::XAssetType::ASSET_TYPE_XMODEL, model, false); - } - } - - void IMapEnts::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::MapEnts, 44); - - Utils::Stream* buffer = builder->getBuffer(); - Game::MapEnts* asset = header.mapEnts; - Game::MapEnts* dest = buffer->dest(); - buffer->save(asset); - - buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); - - if (asset->name) - { - buffer->saveString(builder->getAssetName(this->getType(), asset->name)); - Utils::Stream::ClearPointer(&dest->name); - } - - if (asset->entityString) - { - buffer->save(asset->entityString, asset->numEntityChars); - Utils::Stream::ClearPointer(&dest->entityString); - } - - AssertSize(Game::MapTriggers, 24); - - if (asset->trigger.models) - { - AssertSize(Game::TriggerModel, 8); - - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->trigger.models, asset->trigger.count); - Utils::Stream::ClearPointer(&dest->trigger.models); - } - - if (asset->trigger.hulls) - { - AssertSize(Game::TriggerHull, 32); - - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->trigger.hulls, asset->trigger.hullCount); - Utils::Stream::ClearPointer(&dest->trigger.hulls); - } - - if (asset->trigger.slabs) - { - AssertSize(Game::TriggerSlab, 20); - - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->trigger.slabs, asset->trigger.slabCount); - Utils::Stream::ClearPointer(&dest->trigger.slabs); - } - - if (asset->stages) - { - AssertSize(Game::Stage, 20); - - buffer->align(Utils::Stream::ALIGN_4); - - Game::Stage* destStages = buffer->dest(); - buffer->saveArray(asset->stages, asset->stageCount); - - for (char i = 0; i < asset->stageCount; ++i) - { - Game::Stage* destStage = &destStages[i]; - Game::Stage* stage = &asset->stages[i]; - - if (stage->name) - { - buffer->saveString(stage->name); - Utils::Stream::ClearPointer(&destStage->name); - } - } - - Utils::Stream::ClearPointer(&dest->stages); - } - - buffer->popBlock(); - } -} diff --git a/src/Components/Modules/AssetInterfaces/IMapEnts.hpp b/src/Components/Modules/AssetInterfaces/IMapEnts.hpp deleted file mode 100644 index 37286311..00000000 --- a/src/Components/Modules/AssetInterfaces/IMapEnts.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -namespace Assets -{ - class IMapEnts : public Components::AssetHandler::IAsset - { - public: - Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_MAP_ENTS; } - - void mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override; - }; -} diff --git a/src/Components/Modules/AssetInterfaces/IMaterial.cpp b/src/Components/Modules/AssetInterfaces/IMaterial.cpp deleted file mode 100644 index a30bfcf7..00000000 --- a/src/Components/Modules/AssetInterfaces/IMaterial.cpp +++ /dev/null @@ -1,178 +0,0 @@ -#include -#include "IMaterial.hpp" - -namespace Assets -{ - void IMaterial::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) - { - if (!header->data) this->loadFromDisk(header, name, builder); // Check if we want to load a material from disk - if (!header->data) this->loadNative(header, name, builder); // Check if there is a native one - assert(header->data); - } - - void IMaterial::loadFromDisk(Game::XAssetHeader* header, const std::string& name, [[maybe_unused]] Components::ZoneBuilder::Zone* builder) - { - header->material = builder->getIW4OfApi()->read(Game::XAssetType::ASSET_TYPE_MATERIAL, name); - } - - void IMaterial::loadNative(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* /*builder*/) - { - header->material = Components::AssetHandler::FindOriginalAsset(this->getType(), name.data()).material; - } - - void IMaterial::mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - Game::Material* asset = header.material; - - if (asset->techniqueSet) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_TECHNIQUE_SET, asset->techniqueSet); - } - - if (asset->textureTable) - { - for (char i = 0; i < asset->textureCount; ++i) - { - if (asset->textureTable[i].u.image) - { - if (asset->textureTable[i].semantic == Game::TextureSemantic::TS_WATER_MAP) - { - if (asset->textureTable[i].u.water->image) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_IMAGE, asset->textureTable[i].u.water->image); - } - } - else - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_IMAGE, asset->textureTable[i].u.image); - } - } - } - } - } - - void IMaterial::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::Material, 96); - - Utils::Stream* buffer = builder->getBuffer(); - Game::Material* asset = header.material; - Game::Material* dest = buffer->dest(); - buffer->save(asset); - - buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); - - if (asset->info.name) - { - buffer->saveString(builder->getAssetName(this->getType(), asset->info.name)); - Utils::Stream::ClearPointer(&dest->info.name); - } - - if (asset->techniqueSet) - { - dest->techniqueSet = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_TECHNIQUE_SET, asset->techniqueSet).techniqueSet; - } - - if (asset->textureTable) - { - AssertSize(Game::MaterialTextureDef, 12); - - // Pointer/Offset insertion is untested, but it worked in T6, so I think it's fine - if (builder->hasPointer(asset->textureTable)) - { - dest->textureTable = builder->getPointer(asset->textureTable); - } - else - { - buffer->align(Utils::Stream::ALIGN_4); - builder->storePointer(asset->textureTable); - - auto* destTextureTable = buffer->dest(); - buffer->saveArray(asset->textureTable, asset->textureCount); - - for (std::uint8_t i = 0; i < asset->textureCount; ++i) - { - auto* destTextureDef = &destTextureTable[i]; - auto* textureDef = &asset->textureTable[i]; - - if (textureDef->semantic == Game::TextureSemantic::TS_WATER_MAP) - { - AssertSize(Game::water_t, 68); - - Game::water_t* destWater = buffer->dest(); - Game::water_t* water = textureDef->u.water; - - if (water) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->save(water); - Utils::Stream::ClearPointer(&destTextureDef->u.water); - - // Save_water_t - if (water->H0) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->save(water->H0, 8, water->M * water->N); - Utils::Stream::ClearPointer(&destWater->H0); - } - - if (water->wTerm) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->save(water->wTerm, 4, water->M * water->N); - Utils::Stream::ClearPointer(&destWater->wTerm); - } - - if (water->image) - { - destWater->image = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_IMAGE, water->image).image; - } - } - } - else if (textureDef->u.image) - { - destTextureDef->u.image = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_IMAGE, textureDef->u.image).image; - } - } - - Utils::Stream::ClearPointer(&dest->textureTable); - } - } - - if (asset->constantTable) - { - AssertSize(Game::MaterialConstantDef, 32); - - if (builder->hasPointer(asset->constantTable)) - { - dest->constantTable = builder->getPointer(asset->constantTable); - } - else - { - buffer->align(Utils::Stream::ALIGN_16); - builder->storePointer(asset->constantTable); - - buffer->saveArray(asset->constantTable, asset->constantCount); - Utils::Stream::ClearPointer(&dest->constantTable); - } - } - - if (asset->stateBitsTable) - { - if (builder->hasPointer(asset->stateBitsTable)) - { - dest->stateBitsTable = builder->getPointer(asset->stateBitsTable); - } - else - { - buffer->align(Utils::Stream::ALIGN_4); - builder->storePointer(asset->stateBitsTable); - - buffer->save(asset->stateBitsTable, 8, asset->stateBitsCount); - Utils::Stream::ClearPointer(&dest->stateBitsTable); - } - } - - buffer->popBlock(); - } -} diff --git a/src/Components/Modules/AssetInterfaces/IMaterial.hpp b/src/Components/Modules/AssetInterfaces/IMaterial.hpp deleted file mode 100644 index adec2e19..00000000 --- a/src/Components/Modules/AssetInterfaces/IMaterial.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -namespace Assets -{ - class IMaterial : public Components::AssetHandler::IAsset - { - public: - Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_MATERIAL; } - - void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override; - void loadFromDisk(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder); - void loadNative(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder); - }; -} diff --git a/src/Components/Modules/AssetInterfaces/IMaterialPixelShader.cpp b/src/Components/Modules/AssetInterfaces/IMaterialPixelShader.cpp deleted file mode 100644 index 99d56b85..00000000 --- a/src/Components/Modules/AssetInterfaces/IMaterialPixelShader.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include -#include "IMaterialPixelShader.hpp" - -namespace Assets -{ - - void IMaterialPixelShader::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) - { - if (!header->data) this->loadBinary(header, name, builder); // Check if we need to import a new one into the game - if (!header->data) this->loadNative(header, name, builder); // Check if there is a native one - } - - void IMaterialPixelShader::loadNative(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* /*builder*/) - { - header->pixelShader = Components::AssetHandler::FindOriginalAsset(this->getType(), name.data()).pixelShader; - } - - void IMaterialPixelShader::loadBinary(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) - { - header->pixelShader = builder->getIW4OfApi()->read(Game::XAssetType::ASSET_TYPE_PIXELSHADER, name); - } - - void IMaterialPixelShader::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::MaterialPixelShader, 16); - - Utils::Stream* buffer = builder->getBuffer(); - Game::MaterialPixelShader* asset = header.pixelShader; - Game::MaterialPixelShader* dest = buffer->dest(); - buffer->save(asset); - - buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); - - if (asset->name) - { - buffer->saveString(builder->getAssetName(this->getType(), asset->name)); - Utils::Stream::ClearPointer(&dest->name); - } - - if (asset->prog.loadDef.program) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->prog.loadDef.program, asset->prog.loadDef.programSize); - Utils::Stream::ClearPointer(&dest->prog.loadDef.program); - } - - buffer->popBlock(); - } -} diff --git a/src/Components/Modules/AssetInterfaces/IMaterialPixelShader.hpp b/src/Components/Modules/AssetInterfaces/IMaterialPixelShader.hpp deleted file mode 100644 index 3705dce1..00000000 --- a/src/Components/Modules/AssetInterfaces/IMaterialPixelShader.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -namespace Assets -{ - class IMaterialPixelShader : public Components::AssetHandler::IAsset - { - public: - Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_PIXELSHADER; } - - void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override; - - void loadNative(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder); - void loadBinary(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder); - }; -} diff --git a/src/Components/Modules/AssetInterfaces/IMaterialTechniqueSet.cpp b/src/Components/Modules/AssetInterfaces/IMaterialTechniqueSet.cpp deleted file mode 100644 index e8c37714..00000000 --- a/src/Components/Modules/AssetInterfaces/IMaterialTechniqueSet.cpp +++ /dev/null @@ -1,198 +0,0 @@ -#include -#include "IMaterialTechniqueSet.hpp" - -#define IW4X_TECHSET_VERSION 1 - -namespace Assets -{ - void IMaterialTechniqueSet::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) - { - if (!header->data) this->loadFromDisk(header, name, builder); // Check if we need to import a new one into the game - if (!header->data) this->loadNative(header, name, builder); // Check if there is a native one - - if (!header->data) - { - AssertUnreachable; - } - } - - void IMaterialTechniqueSet::loadNative(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* /*builder*/) - { - header->techniqueSet = Components::AssetHandler::FindOriginalAsset(this->getType(), name.data()).techniqueSet; - } - - void IMaterialTechniqueSet::loadFromDisk(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) - { - header->techniqueSet = builder->getIW4OfApi()->read(Game::ASSET_TYPE_TECHNIQUE_SET, name); - - auto ptr = header->techniqueSet; - if (ptr) - { - while (ptr->remappedTechniqueSet && ptr->remappedTechniqueSet != ptr) - { - ptr = ptr->remappedTechniqueSet; - builder->loadAsset(Game::ASSET_TYPE_TECHNIQUE_SET, ptr, false); - - for (size_t i = 0; i < Game::TECHNIQUE_COUNT; i++) - { - const auto technique = ptr->techniques[i]; - if (technique) - { - for (size_t j = 0; j < technique->passCount; j++) - { - const auto pass = &technique->passArray[j]; - builder->loadAsset(Game::ASSET_TYPE_VERTEXDECL, pass->vertexDecl, true); - builder->loadAsset(Game::ASSET_TYPE_PIXELSHADER, pass->pixelShader, true); - builder->loadAsset(Game::ASSET_TYPE_VERTEXSHADER, pass->vertexShader, true); - } - } - } - } - } - } - - void IMaterialTechniqueSet::mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - Game::MaterialTechniqueSet* asset = header.techniqueSet; - - for (int i = 0; i < ARRAYSIZE(Game::MaterialTechniqueSet::techniques); ++i) - { - Game::MaterialTechnique* technique = asset->techniques[i]; - - if (!technique) continue; - - for (short j = 0; j < technique->passCount; ++j) - { - Game::MaterialPass* pass = &technique->passArray[j]; - - if (pass->vertexDecl) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_VERTEXDECL, pass->vertexDecl); - } - - if (pass->vertexShader) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_VERTEXSHADER, pass->vertexShader); - } - - if (pass->pixelShader) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_PIXELSHADER, pass->pixelShader); - } - } - } - } - - void IMaterialTechniqueSet::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::MaterialTechniqueSet, 204); - - Utils::Stream* buffer = builder->getBuffer(); - - Game::MaterialTechniqueSet* asset = header.techniqueSet; - Game::MaterialTechniqueSet* dest = buffer->dest(); - - buffer->save(asset); - - buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); - - if (asset->name) - { - buffer->saveString(builder->getAssetName(this->getType(), asset->name)); - Utils::Stream::ClearPointer(&dest->name); - } - - // Save_MaterialTechniquePtrArray - static_assert(ARRAYSIZE(Game::MaterialTechniqueSet::techniques) == 48, "Techniques array invalid!"); - - for (int i = 0; i < ARRAYSIZE(Game::MaterialTechniqueSet::techniques); ++i) - { - Game::MaterialTechnique* technique = asset->techniques[i]; - - if (technique) - { - if (builder->hasPointer(technique)) - { - dest->techniques[i] = builder->getPointer(technique); - } - else - { - // Size-check is obsolete, as the structure is dynamic - buffer->align(Utils::Stream::ALIGN_4); - builder->storePointer(technique); - - Game::MaterialTechnique* destTechnique = buffer->dest(); - buffer->save(technique, 8); - - // Save_MaterialPassArray - Game::MaterialPass* destPasses = buffer->dest(); - buffer->saveArray(technique->passArray, technique->passCount); - - for (short j = 0; j < technique->passCount; ++j) - { - AssertSize(Game::MaterialPass, 20); - - Game::MaterialPass* destPass = &destPasses[j]; - Game::MaterialPass* pass = &technique->passArray[j]; - - if (pass->vertexDecl) - { - destPass->vertexDecl = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_VERTEXDECL, pass->vertexDecl).vertexDecl; - } - - if (pass->vertexShader) - { - destPass->vertexShader = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_VERTEXSHADER, pass->vertexShader).vertexShader; - } - - if (pass->pixelShader) - { - destPass->pixelShader = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_PIXELSHADER, pass->pixelShader).pixelShader; - } - - if (pass->args) - { - buffer->align(Utils::Stream::ALIGN_4); - Game::MaterialShaderArgument* destArgs = buffer->dest(); - buffer->saveArray(pass->args, pass->perPrimArgCount + pass->perObjArgCount + pass->stableArgCount); - - for (int k = 0; k < pass->perPrimArgCount + pass->perObjArgCount + pass->stableArgCount; ++k) - { - Game::MaterialShaderArgument* arg = &pass->args[k]; - Game::MaterialShaderArgument* destArg = &destArgs[k]; - - if (arg->type == 1 || arg->type == 7) - { - if (builder->hasPointer(arg->u.literalConst)) - { - destArg->u.literalConst = builder->getPointer(arg->u.literalConst); - } - else - { - buffer->align(Utils::Stream::ALIGN_4); - builder->storePointer(arg->u.literalConst); - - buffer->saveArray(arg->u.literalConst, 4); - Utils::Stream::ClearPointer(&destArg->u.literalConst); - } - } - } - - Utils::Stream::ClearPointer(&destPass->args); - } - } - - if (technique->name) - { - buffer->saveString(technique->name); - Utils::Stream::ClearPointer(&destTechnique->name); - } - - Utils::Stream::ClearPointer(&dest->techniques[i]); - } - } - } - - buffer->popBlock(); - } -} diff --git a/src/Components/Modules/AssetInterfaces/IMaterialTechniqueSet.hpp b/src/Components/Modules/AssetInterfaces/IMaterialTechniqueSet.hpp deleted file mode 100644 index 60275dc4..00000000 --- a/src/Components/Modules/AssetInterfaces/IMaterialTechniqueSet.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -namespace Assets -{ - class IMaterialTechniqueSet : public Components::AssetHandler::IAsset - { - public: - Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_TECHNIQUE_SET; } - - void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override; - - void loadNative(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder); - void loadFromDisk(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder); - - void loadTechniqueFromDisk(Game::MaterialTechnique** tech, const std::string& name, Components::ZoneBuilder::Zone* builder); - }; -} diff --git a/src/Components/Modules/AssetInterfaces/IMaterialVertexDeclaration.cpp b/src/Components/Modules/AssetInterfaces/IMaterialVertexDeclaration.cpp deleted file mode 100644 index af4894de..00000000 --- a/src/Components/Modules/AssetInterfaces/IMaterialVertexDeclaration.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include -#include "IMaterialVertexDeclaration.hpp" - -#define IW4X_TECHSET_VERSION 1 - -namespace Assets -{ - void IMaterialVertexDeclaration::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) - { - if (!header->data) this->loadBinary(header, name, builder); // Check if we need to import a new one into the game - if (!header->data) this->loadNative(header, name, builder); // Check if there is a native one - } - - void IMaterialVertexDeclaration::loadNative(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* /*builder*/) - { - header->vertexDecl = Components::AssetHandler::FindOriginalAsset(this->getType(), name.data()).vertexDecl; - } - - void IMaterialVertexDeclaration::loadBinary(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) - { - header->vertexDecl = builder->getIW4OfApi()->read(Game::XAssetType::ASSET_TYPE_VERTEXDECL, name); - } - - void IMaterialVertexDeclaration::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::MaterialVertexDeclaration, 100); - - Utils::Stream* buffer = builder->getBuffer(); - Game::MaterialVertexDeclaration* asset = header.vertexDecl; - Game::MaterialVertexDeclaration* dest = buffer->dest(); - buffer->save(asset); - - buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); - - if (asset->name) - { - buffer->saveString(builder->getAssetName(this->getType(), asset->name)); - Utils::Stream::ClearPointer(&dest->name); - } - - AssertSize(Game::MaterialVertexStreamRouting, 92); - - buffer->popBlock(); - } -} diff --git a/src/Components/Modules/AssetInterfaces/IMaterialVertexDeclaration.hpp b/src/Components/Modules/AssetInterfaces/IMaterialVertexDeclaration.hpp deleted file mode 100644 index e4bce229..00000000 --- a/src/Components/Modules/AssetInterfaces/IMaterialVertexDeclaration.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -namespace Assets -{ - class IMaterialVertexDeclaration : public Components::AssetHandler::IAsset - { - public: - Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_VERTEXDECL; } - - void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override; - - void loadNative(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder); - void loadBinary(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder); - }; -} diff --git a/src/Components/Modules/AssetInterfaces/IMaterialVertexShader.cpp b/src/Components/Modules/AssetInterfaces/IMaterialVertexShader.cpp deleted file mode 100644 index bfa0c9b5..00000000 --- a/src/Components/Modules/AssetInterfaces/IMaterialVertexShader.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include -#include "IMaterialVertexShader.hpp" - -#define GFX_RENDERER_SHADER_SM3 0 - -namespace Assets -{ - void IMaterialVertexShader::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) - { - if (!header->data) this->loadBinary(header, name, builder); // Check if we need to import a new one into the game - if (!header->data) this->loadNative(header, name, builder); // Check if there is a native one - } - - void IMaterialVertexShader::loadNative(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* /*builder*/) - { - header->vertexShader = Components::AssetHandler::FindOriginalAsset(this->getType(), name.data()).vertexShader; - } - - void IMaterialVertexShader::loadBinary(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) - { - header->vertexShader = builder->getIW4OfApi()->read(Game::XAssetType::ASSET_TYPE_VERTEXSHADER, name); - } - - void IMaterialVertexShader::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::MaterialVertexShader, 16); - - Utils::Stream* buffer = builder->getBuffer(); - Game::MaterialVertexShader* asset = header.vertexShader; - Game::MaterialVertexShader* dest = buffer->dest(); - buffer->save(asset); - - buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); - - if (asset->name) - { - buffer->saveString(builder->getAssetName(this->getType(), asset->name)); - Utils::Stream::ClearPointer(&dest->name); - } - - if (asset->prog.loadDef.program) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->prog.loadDef.program, asset->prog.loadDef.programSize); - Utils::Stream::ClearPointer(&dest->prog.loadDef.program); - } - - buffer->popBlock(); - } -} diff --git a/src/Components/Modules/AssetInterfaces/IMaterialVertexShader.hpp b/src/Components/Modules/AssetInterfaces/IMaterialVertexShader.hpp deleted file mode 100644 index f84eda27..00000000 --- a/src/Components/Modules/AssetInterfaces/IMaterialVertexShader.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -namespace Assets -{ - class IMaterialVertexShader : public Components::AssetHandler::IAsset - { - public: - Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_VERTEXSHADER; } - - void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override; - - void loadNative(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder); - void loadBinary(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder); - }; -} diff --git a/src/Components/Modules/AssetInterfaces/IMenuList.cpp b/src/Components/Modules/AssetInterfaces/IMenuList.cpp deleted file mode 100644 index 4cfc63d0..00000000 --- a/src/Components/Modules/AssetInterfaces/IMenuList.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include "IMenuList.hpp" - -namespace Assets -{ - void IMenuList::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) - { - Utils::Memory::Allocator* allocator = builder->getAllocator(); - - // actually gets the whole list - auto menus = Components::Menus::LoadMenu(name); - if (menus.empty()) return; - - // Allocate new menu list - auto* newList = allocator->allocate(); - if (!newList) return; - - newList->menus = allocator->allocateArray(menus.size()); - if (!newList->menus) - { - allocator->free(newList); - return; - } - - newList->name = allocator->duplicateString(name); - newList->menuCount = menus.size(); - - // Copy new menus - for (unsigned int i = 0; i < menus.size(); ++i) - { - newList->menus[i] = menus[i].second; - } - - header->menuList = newList; - } - void IMenuList::mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - auto* asset = header.menuList; - - for (int i = 0; i < asset->menuCount; ++i) - { - if (asset->menus[i]) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_MENU, asset->menus[i]); - } - } - } - void IMenuList::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::MenuList, 12); - - Utils::Stream* buffer = builder->getBuffer(); - Game::MenuList* asset = header.menuList; - auto* dest = buffer->dest(); - - buffer->save(asset); - - buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); - - if (asset->name) - { - buffer->saveString(builder->getAssetName(this->getType(), asset->name)); - Utils::Stream::ClearPointer(&dest->name); - } - - if (asset->menus) - { - buffer->align(Utils::Stream::ALIGN_4); - - auto** destMenus = buffer->dest(); - buffer->saveArray(asset->menus, asset->menuCount); - - for (int i = 0; i < asset->menuCount; ++i) - { - destMenus[i] = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_MENU, asset->menus[i]).menu; - } - } - - buffer->popBlock(); - } -} diff --git a/src/Components/Modules/AssetInterfaces/IMenuList.hpp b/src/Components/Modules/AssetInterfaces/IMenuList.hpp deleted file mode 100644 index 23c60695..00000000 --- a/src/Components/Modules/AssetInterfaces/IMenuList.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -namespace Assets -{ - class IMenuList : public Components::AssetHandler::IAsset - { - public: - Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_MENULIST; } - - void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override; - }; -} diff --git a/src/Components/Modules/AssetInterfaces/IPhysCollmap.cpp b/src/Components/Modules/AssetInterfaces/IPhysCollmap.cpp deleted file mode 100644 index 2dd01716..00000000 --- a/src/Components/Modules/AssetInterfaces/IPhysCollmap.cpp +++ /dev/null @@ -1,136 +0,0 @@ -#include -#include "IPhysCollmap.hpp" - -namespace Assets -{ - void IPhysCollmap::saveBrushWrapper(Components::ZoneBuilder::Zone* builder, Game::BrushWrapper* brush) - { - AssertSize(Game::BrushWrapper, 68); - - Utils::Stream* buffer = builder->getBuffer(); - - Game::BrushWrapper* destBrush = buffer->dest(); - buffer->save(brush); - - // Save_cbrushWrapper_t - { - AssertSize(Game::cbrush_t, 36); - - if (brush->brush.sides) - { - AssertSize(Game::cbrushside_t, 8); - - buffer->align(Utils::Stream::ALIGN_4); - - Game::cbrushside_t* destBrushSide = buffer->dest(); - buffer->saveArray(brush->brush.sides, brush->brush.numsides); - - // Save_cbrushside_tArray - for (unsigned short i = 0; i < brush->brush.numsides; ++i) - { - Game::cbrushside_t* destSide = &destBrushSide[i]; - Game::cbrushside_t* side = &brush->brush.sides[i]; - - if (side->plane) - { - if (builder->hasPointer(side->plane)) - { - destSide->plane = builder->getPointer(side->plane); - } - else - { - buffer->align(Utils::Stream::ALIGN_4); - builder->storePointer(side->plane); - - buffer->save(side->plane, sizeof(Game::cplane_s)); - Utils::Stream::ClearPointer(&destSide->plane); - } - } - } - - Utils::Stream::ClearPointer(&destBrush->brush.sides); - } - - if (brush->brush.baseAdjacentSide) - { - buffer->save(brush->brush.baseAdjacentSide, brush->totalEdgeCount); - Utils::Stream::ClearPointer(&destBrush->brush.baseAdjacentSide); - } - } - - if (brush->planes) - { - AssertSize(Game::cplane_s, 20); - - if (builder->hasPointer(brush->planes)) - { - Components::Logger::Print("Loading cplane pointer before the array has been written. Not sure if this is correct!\n"); - destBrush->planes = builder->getPointer(brush->planes); - } - else - { - buffer->align(Utils::Stream::ALIGN_4); - - for (unsigned short j = 0; j < brush->brush.numsides; ++j) - { - builder->storePointer(&brush->planes[j]); - buffer->save(&brush->planes[j]); - } - - Utils::Stream::ClearPointer(&destBrush->planes); - } - } - } - - void IPhysCollmap::savePhysGeomInfoArray(Components::ZoneBuilder::Zone* builder, Game::PhysGeomInfo* geoms, unsigned int count) - { - AssertSize(Game::PhysGeomInfo, 68); - - Utils::Stream* buffer = builder->getBuffer(); - - Game::PhysGeomInfo* destGeoms = buffer->dest(); - buffer->saveArray(geoms, count); - - for (unsigned int i = 0; i < count; ++i) - { - Game::PhysGeomInfo* destGeom = &destGeoms[i]; - Game::PhysGeomInfo* geom = &geoms[i]; - - if (geom->brushWrapper) - { - buffer->align(Utils::Stream::ALIGN_4); - - this->saveBrushWrapper(builder, geom->brushWrapper); - Utils::Stream::ClearPointer(&destGeom->brushWrapper); - } - } - } - - void IPhysCollmap::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::XModel, 304); - - Utils::Stream* buffer = builder->getBuffer(); - Game::PhysCollmap* asset = header.physCollmap; - Game::PhysCollmap* dest = buffer->dest(); - buffer->save(asset, sizeof(Game::PhysCollmap)); - - buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); - - if (asset->name) - { - buffer->saveString(builder->getAssetName(this->getType(), asset->name)); - Utils::Stream::ClearPointer(&dest->name); - } - - if (asset->geoms) - { - buffer->align(Utils::Stream::ALIGN_4); - - this->savePhysGeomInfoArray(builder, asset->geoms, asset->count); - Utils::Stream::ClearPointer(&dest->geoms); - } - - buffer->popBlock(); - } -} diff --git a/src/Components/Modules/AssetInterfaces/IPhysCollmap.hpp b/src/Components/Modules/AssetInterfaces/IPhysCollmap.hpp deleted file mode 100644 index fd42c7e1..00000000 --- a/src/Components/Modules/AssetInterfaces/IPhysCollmap.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -namespace Assets -{ - class IPhysCollmap : public Components::AssetHandler::IAsset - { - public: - Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_PHYSCOLLMAP; } - - void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - - private: - void savePhysGeomInfoArray(Components::ZoneBuilder::Zone* builder, Game::PhysGeomInfo* geoms, unsigned int count); - void saveBrushWrapper(Components::ZoneBuilder::Zone* builder, Game::BrushWrapper* brush); - }; -} diff --git a/src/Components/Modules/AssetInterfaces/IPhysPreset.cpp b/src/Components/Modules/AssetInterfaces/IPhysPreset.cpp deleted file mode 100644 index d485e230..00000000 --- a/src/Components/Modules/AssetInterfaces/IPhysPreset.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include -#include "IPhysPreset.hpp" - -namespace Assets -{ - void IPhysPreset::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::PhysPreset, 44); - - auto* buffer = builder->getBuffer(); - auto* asset = header.physPreset; - auto* dest = buffer->dest(); - buffer->save(asset); - - buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); - - if (asset->name) - { - buffer->saveString(builder->getAssetName(this->getType(), asset->name)); - Utils::Stream::ClearPointer(&dest->name); - } - - if (asset->sndAliasPrefix) - { - buffer->saveString(asset->sndAliasPrefix); - Utils::Stream::ClearPointer(&dest->sndAliasPrefix); - } - - buffer->popBlock(); - } - - void IPhysPreset::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) - { - loadFromDisk(header, name, builder); - } - - void IPhysPreset::loadFromDisk(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) - { - header->physPreset = builder->getIW4OfApi()->read(Game::XAssetType::ASSET_TYPE_PHYSPRESET, name); - } -} diff --git a/src/Components/Modules/AssetInterfaces/IPhysPreset.hpp b/src/Components/Modules/AssetInterfaces/IPhysPreset.hpp deleted file mode 100644 index 47fb85e8..00000000 --- a/src/Components/Modules/AssetInterfaces/IPhysPreset.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -namespace Assets -{ - class IPhysPreset : public Components::AssetHandler::IAsset - { - public: - Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_PHYSPRESET; } - - void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override; - void loadFromDisk(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder); - }; -} diff --git a/src/Components/Modules/AssetInterfaces/IRawFile.cpp b/src/Components/Modules/AssetInterfaces/IRawFile.cpp deleted file mode 100644 index 15782c93..00000000 --- a/src/Components/Modules/AssetInterfaces/IRawFile.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include -#include "IRawFile.hpp" - -#include - -namespace Assets -{ - void IRawFile::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) - { - header->rawfile = builder->getIW4OfApi()->read(Game::XAssetType::ASSET_TYPE_RAWFILE, name); - } - - void IRawFile::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::RawFile, 16); - - auto* buffer = builder->getBuffer(); - auto* asset = header.rawfile; - auto* dest = buffer->dest(); - buffer->save(asset); - - buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); - - if (asset->name) - { - buffer->saveString(builder->getAssetName(this->getType(), asset->name)); - Utils::Stream::ClearPointer(&dest->name); - } - - if (asset->buffer) - { - if (asset->compressedLen) - { - buffer->save(asset->buffer, asset->compressedLen); - } - else - { - buffer->save(asset->buffer, asset->len + 1); - } - - Utils::Stream::ClearPointer(&dest->buffer); - } - - buffer->popBlock(); - } -} diff --git a/src/Components/Modules/AssetInterfaces/IRawFile.hpp b/src/Components/Modules/AssetInterfaces/IRawFile.hpp deleted file mode 100644 index b4c1b818..00000000 --- a/src/Components/Modules/AssetInterfaces/IRawFile.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -namespace Assets -{ - class IRawFile : public Components::AssetHandler::IAsset - { - public: - Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_RAWFILE; } - - void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override; - }; -} diff --git a/src/Components/Modules/AssetInterfaces/ISndCurve.cpp b/src/Components/Modules/AssetInterfaces/ISndCurve.cpp deleted file mode 100644 index a3a7a496..00000000 --- a/src/Components/Modules/AssetInterfaces/ISndCurve.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include "ISndCurve.hpp" - -namespace Assets -{ - void ISndCurve::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::SndCurve, 136); - - auto* buffer = builder->getBuffer(); - auto* asset = header.sndCurve; - auto* dest = buffer->dest(); - buffer->save(asset); - - buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); - - if (asset->filename) - { - buffer->saveString(builder->getAssetName(this->getType(), asset->filename)); - Utils::Stream::ClearPointer(&dest->filename); - } - - buffer->popBlock(); - } - - void ISndCurve::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) - { - header->sndCurve = builder->getIW4OfApi()->read(Game::XAssetType::ASSET_TYPE_SOUND_CURVE, name); - - if (!header->sndCurve) - { - header->sndCurve = Components::AssetHandler::FindOriginalAsset(Game::XAssetType::ASSET_TYPE_SOUND_CURVE, name.data()).sndCurve; - } - } -} diff --git a/src/Components/Modules/AssetInterfaces/ISndCurve.hpp b/src/Components/Modules/AssetInterfaces/ISndCurve.hpp deleted file mode 100644 index 0d2cc831..00000000 --- a/src/Components/Modules/AssetInterfaces/ISndCurve.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -namespace Assets -{ - class ISndCurve : public Components::AssetHandler::IAsset - { - public: - Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_SOUND_CURVE; } - - void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override; - }; -} diff --git a/src/Components/Modules/AssetInterfaces/IStringTable.cpp b/src/Components/Modules/AssetInterfaces/IStringTable.cpp deleted file mode 100644 index e7997114..00000000 --- a/src/Components/Modules/AssetInterfaces/IStringTable.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include "IStringTable.hpp" - -namespace Assets -{ - void IStringTable::saveStringTableCellArray(Components::ZoneBuilder::Zone* builder, Game::StringTableCell* values, int count) - { - AssertSize(Game::StringTableCell, 8); - - Utils::Stream* buffer = builder->getBuffer(); - - Game::StringTableCell* destValues = buffer->dest(); - buffer->saveArray(destValues, count); - - for (int i = 0; i < count; ++i) - { - Game::StringTableCell* destValue = &destValues[i]; - Game::StringTableCell* value = &values[i]; - - buffer->saveString(value->string); - Utils::Stream::ClearPointer(&destValue->string); - } - } - - void IStringTable::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::StringTable, 16); - - Utils::Stream* buffer = builder->getBuffer(); - Game::StringTable* asset = header.stringTable; - Game::StringTable* dest = buffer->dest(); - buffer->save(asset, sizeof(Game::StringTable)); - - buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); - - if (asset->name) - { - buffer->saveString(builder->getAssetName(this->getType(), asset->name)); - Utils::Stream::ClearPointer(&dest->name); - } - - if (asset->values) - { - buffer->align(Utils::Stream::ALIGN_4); - - this->saveStringTableCellArray(builder, asset->values, asset->columnCount * asset->rowCount); - Utils::Stream::ClearPointer(&dest->values); - } - - buffer->popBlock(); - } -} diff --git a/src/Components/Modules/AssetInterfaces/IStringTable.hpp b/src/Components/Modules/AssetInterfaces/IStringTable.hpp deleted file mode 100644 index ac24aba1..00000000 --- a/src/Components/Modules/AssetInterfaces/IStringTable.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -namespace Assets -{ - class IStringTable : public Components::AssetHandler::IAsset - { - public: - Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_STRINGTABLE; } - - void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - - private: - static void saveStringTableCellArray(Components::ZoneBuilder::Zone* builder, Game::StringTableCell* values, int count); - }; -} diff --git a/src/Components/Modules/AssetInterfaces/IStructuredDataDefSet.cpp b/src/Components/Modules/AssetInterfaces/IStructuredDataDefSet.cpp deleted file mode 100644 index 4f6ea2e0..00000000 --- a/src/Components/Modules/AssetInterfaces/IStructuredDataDefSet.cpp +++ /dev/null @@ -1,152 +0,0 @@ -#include -#include "IStructuredDataDefSet.hpp" - -namespace Assets -{ - void IStructuredDataDefSet::saveStructuredDataEnumArray(Game::StructuredDataEnum* enums, int numEnums, Components::ZoneBuilder::Zone* builder) - { - Utils::Stream* buffer = builder->getBuffer(); - - Game::StructuredDataEnum* destEnums = buffer->dest(); - buffer->saveArray(enums, numEnums); - - for (int i = 0; i < numEnums; ++i) - { - Game::StructuredDataEnum* destEnum = &destEnums[i]; - Game::StructuredDataEnum* enum_ = &enums[i]; - - if (enum_->entries) - { - AssertSize(Game::StructuredDataEnumEntry, 8); - buffer->align(Utils::Stream::ALIGN_4); - - Game::StructuredDataEnumEntry* destIndices = buffer->dest(); - buffer->saveArray(enum_->entries, enum_->entryCount); - - for (int j = 0; j < enum_->entryCount; ++j) - { - Game::StructuredDataEnumEntry* destIndex = &destIndices[j]; - Game::StructuredDataEnumEntry* index = &enum_->entries[j]; - - if (index->string) - { - buffer->saveString(index->string); - Utils::Stream::ClearPointer(&destIndex->string); - } - } - - Utils::Stream::ClearPointer(&destEnum->entries); - } - } - } - - void IStructuredDataDefSet::saveStructuredDataStructArray(Game::StructuredDataStruct* structs, int numStructs, Components::ZoneBuilder::Zone* builder) - { - Utils::Stream* buffer = builder->getBuffer(); - - Game::StructuredDataStruct* destStructs = buffer->dest(); - buffer->saveArray(structs, numStructs); - - for (int i = 0; i < numStructs; ++i) - { - Game::StructuredDataStruct* destStruct = &destStructs[i]; - Game::StructuredDataStruct* struct_ = &structs[i]; - - if (struct_->properties) - { - AssertSize(Game::StructuredDataStructProperty, 16); - buffer->align(Utils::Stream::ALIGN_4); - - Game::StructuredDataStructProperty* destProperties = buffer->dest(); - buffer->saveArray(struct_->properties, struct_->propertyCount); - - for (int j = 0; j < struct_->propertyCount; ++j) - { - Game::StructuredDataStructProperty* destProperty = &destProperties[j]; - Game::StructuredDataStructProperty* property = &struct_->properties[j]; - - if (property->name) - { - buffer->saveString(property->name); - Utils::Stream::ClearPointer(&destProperty->name); - } - } - - Utils::Stream::ClearPointer(&destStruct->properties); - } - } - } - - void IStructuredDataDefSet::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::StructuredDataDefSet, 12); - - Utils::Stream* buffer = builder->getBuffer(); - Game::StructuredDataDefSet* asset = header.structuredDataDefSet; - Game::StructuredDataDefSet* dest = buffer->dest(); - buffer->save(asset); - - buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); - - if (asset->name) - { - buffer->saveString(builder->getAssetName(this->getType(), asset->name)); - Utils::Stream::ClearPointer(&dest->name); - } - - if (asset->defs) - { - AssertSize(Game::StructuredDataDef, 52); - buffer->align(Utils::Stream::ALIGN_4); - - Game::StructuredDataDef* destDataArray = buffer->dest(); - buffer->saveArray(asset->defs, asset->defCount); - - for (unsigned int i = 0; i < asset->defCount; ++i) - { - Game::StructuredDataDef* destData = &destDataArray[i]; - Game::StructuredDataDef* data = &asset->defs[i]; - - if (data->enums) - { - AssertSize(Game::StructuredDataEnum, 12); - buffer->align(Utils::Stream::ALIGN_4); - - this->saveStructuredDataEnumArray(data->enums, data->enumCount, builder); - Utils::Stream::ClearPointer(&destData->enums); - } - - if (data->structs) - { - AssertSize(Game::StructuredDataStruct, 16); - buffer->align(Utils::Stream::ALIGN_4); - - this->saveStructuredDataStructArray(data->structs, data->structCount, builder); - Utils::Stream::ClearPointer(&destData->structs); - } - - if (data->indexedArrays) - { - AssertSize(Game::StructuredDataIndexedArray, 16); - buffer->align(Utils::Stream::ALIGN_4); - - buffer->saveArray(data->indexedArrays, data->indexedArrayCount); - Utils::Stream::ClearPointer(&destData->indexedArrays); - } - - if (data->enumedArrays) - { - AssertSize(Game::StructuredDataEnumedArray, 16); - buffer->align(Utils::Stream::ALIGN_4); - - buffer->saveArray(data->enumedArrays, data->enumedArrayCount); - Utils::Stream::ClearPointer(&destData->enumedArrays); - } - } - - Utils::Stream::ClearPointer(&dest->defs); - } - - buffer->popBlock(); - } -} diff --git a/src/Components/Modules/AssetInterfaces/IStructuredDataDefSet.hpp b/src/Components/Modules/AssetInterfaces/IStructuredDataDefSet.hpp deleted file mode 100644 index bf408d5a..00000000 --- a/src/Components/Modules/AssetInterfaces/IStructuredDataDefSet.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -namespace Assets -{ - class IStructuredDataDefSet : public Components::AssetHandler::IAsset - { - public: - Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_STRUCTURED_DATA_DEF; } - - void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - - static void saveStructuredDataEnumArray(Game::StructuredDataEnum* enums, int numEnums, Components::ZoneBuilder::Zone* builder); - static void saveStructuredDataStructArray(Game::StructuredDataStruct* structs, int numStructs, Components::ZoneBuilder::Zone* builder); - }; -} diff --git a/src/Components/Modules/AssetInterfaces/ITracerDef.cpp b/src/Components/Modules/AssetInterfaces/ITracerDef.cpp deleted file mode 100644 index 98962180..00000000 --- a/src/Components/Modules/AssetInterfaces/ITracerDef.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include -#include "ITracerDef.hpp" - -namespace Assets -{ - void ITracerDef::load(Game::XAssetHeader* /*header*/, const std::string& /*name*/, Components::ZoneBuilder::Zone* /*builder*/) - { - // don't load from filesystem right now - } - - void ITracerDef::mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - Game::TracerDef* asset = header.tracerDef; - - if (asset->material) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, asset->material); - } - } - - void ITracerDef::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::TracerDef, 0x70); - - Utils::Stream* buffer = builder->getBuffer(); - Game::TracerDef* asset = header.tracerDef; - Game::TracerDef* dest = buffer->dest(); - buffer->save(asset); - - buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); - - if (asset->name) - { - buffer->saveString(builder->getAssetName(this->getType(), asset->name)); - Utils::Stream::ClearPointer(&dest->name); - } - - if (asset->material) - { - dest->material = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, asset->material).material; - } - - buffer->popBlock(); - } -} diff --git a/src/Components/Modules/AssetInterfaces/ITracerDef.hpp b/src/Components/Modules/AssetInterfaces/ITracerDef.hpp deleted file mode 100644 index 0028d628..00000000 --- a/src/Components/Modules/AssetInterfaces/ITracerDef.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -namespace Assets -{ - class ITracerDef : public Components::AssetHandler::IAsset - { - public: - Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_TRACER; } - - void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override; - }; -} diff --git a/src/Components/Modules/AssetInterfaces/IWeapon.cpp b/src/Components/Modules/AssetInterfaces/IWeapon.cpp deleted file mode 100644 index 40e8fdd5..00000000 --- a/src/Components/Modules/AssetInterfaces/IWeapon.cpp +++ /dev/null @@ -1,785 +0,0 @@ -#include -#include "IWeapon.hpp" - -namespace Assets -{ - void IWeapon::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* /*builder*/) - { - // Try loading raw weapon - if (Components::FileSystem::File(std::format("weapons/mp/{}", name))) - { - // let the function see temporary assets when calling DB_FindXAssetHeader during the loading function - // otherwise it fails to link things properly - Components::AssetHandler::ExposeTemporaryAssets(true); - header->data = Game::BG_LoadWeaponDef_LoadObj(name.data()); - Components::AssetHandler::ExposeTemporaryAssets(false); - } - } - - void IWeapon::mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - Game::WeaponCompleteDef* asset = header.weapon; - - // convert all script strings - if (asset->hideTags) - { - for (char i = 0; i < 32; ++i) - { - if (asset->hideTags[i] == NULL) break; // no more strings - builder->addScriptString(asset->hideTags[i]); - } - } - - if (asset->weapDef->notetrackSoundMapKeys) - { - for (char i = 0; i < 16; ++i) - { - if (asset->weapDef->notetrackSoundMapKeys[i] == NULL) break; // no more strings - builder->addScriptString(asset->weapDef->notetrackSoundMapKeys[i]); - } - } - - if (asset->weapDef->notetrackSoundMapValues) - { - for (char i = 0; i < 16; ++i) - { - if (asset->weapDef->notetrackSoundMapValues[i] == NULL) break; // no more strings - builder->addScriptString(asset->weapDef->notetrackSoundMapValues[i]); - } - } - - if (asset->weapDef->notetrackRumbleMapKeys) - { - for (char i = 0; i < 16; ++i) - { - if (asset->weapDef->notetrackRumbleMapKeys[i] == NULL) break; // no more strings - builder->addScriptString(asset->weapDef->notetrackRumbleMapKeys[i]); - } - } - - if (asset->weapDef->notetrackRumbleMapValues) - { - for (char i = 0; i < 16; ++i) - { - if (asset->weapDef->notetrackRumbleMapValues[i] == NULL) break; // no more strings - builder->addScriptString(asset->weapDef->notetrackRumbleMapValues[i]); - } - } - - - // now load all sub-assets properly - if (asset->killIcon) builder->loadAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, asset->killIcon); - if (asset->dpadIcon) builder->loadAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, asset->dpadIcon); - if (asset->weapDef->reticleCenter) builder->loadAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, asset->weapDef->reticleCenter); - if (asset->weapDef->reticleSide) builder->loadAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, asset->weapDef->reticleSide); - if (asset->weapDef->hudIcon) builder->loadAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, asset->weapDef->hudIcon); - if (asset->weapDef->pickupIcon) builder->loadAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, asset->weapDef->pickupIcon); - if (asset->weapDef->ammoCounterIcon) builder->loadAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, asset->weapDef->ammoCounterIcon); - if (asset->weapDef->overlayMaterial) builder->loadAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, asset->weapDef->overlayMaterial); - if (asset->weapDef->overlayMaterialLowRes) builder->loadAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, asset->weapDef->overlayMaterialLowRes); - if (asset->weapDef->overlayMaterialEMP) builder->loadAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, asset->weapDef->overlayMaterialEMP); - if (asset->weapDef->overlayMaterialEMPLowRes) builder->loadAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, asset->weapDef->overlayMaterialEMPLowRes); - - if (asset->weapDef->gunXModel) - { - for (int i = 0; i < 16; i++) - { - if (asset->weapDef->gunXModel[i]) builder->loadAsset(Game::XAssetType::ASSET_TYPE_XMODEL, asset->weapDef->gunXModel[i]); - } - } - - if (asset->weapDef->handXModel) builder->loadAsset(Game::XAssetType::ASSET_TYPE_XMODEL, asset->weapDef->handXModel); - - if (asset->weapDef->worldModel) - { - for (int i = 0; i < 16; i++) - { - if (asset->weapDef->worldModel[i]) builder->loadAsset(Game::XAssetType::ASSET_TYPE_XMODEL, asset->weapDef->worldModel[i]); - } - } - - if (asset->weapDef->worldClipModel) builder->loadAsset(Game::XAssetType::ASSET_TYPE_XMODEL, asset->weapDef->worldClipModel); - if (asset->weapDef->rocketModel) builder->loadAsset(Game::XAssetType::ASSET_TYPE_XMODEL, asset->weapDef->rocketModel); - if (asset->weapDef->knifeModel) builder->loadAsset(Game::XAssetType::ASSET_TYPE_XMODEL, asset->weapDef->knifeModel); - if (asset->weapDef->worldKnifeModel) builder->loadAsset(Game::XAssetType::ASSET_TYPE_XMODEL, asset->weapDef->worldKnifeModel); - if (asset->weapDef->projectileModel) builder->loadAsset(Game::XAssetType::ASSET_TYPE_XMODEL, asset->weapDef->projectileModel); - - if (asset->weapDef->physCollmap) builder->loadAsset(Game::XAssetType::ASSET_TYPE_PHYSCOLLMAP, asset->weapDef->physCollmap); - - if (asset->weapDef->tracerType) builder->loadAsset(Game::XAssetType::ASSET_TYPE_TRACER, asset->weapDef->tracerType); - - if (asset->weapDef->viewFlashEffect) builder->loadAsset(Game::XAssetType::ASSET_TYPE_FX, asset->weapDef->viewFlashEffect); - if (asset->weapDef->worldFlashEffect) builder->loadAsset(Game::XAssetType::ASSET_TYPE_FX, asset->weapDef->worldFlashEffect); - if (asset->weapDef->viewShellEjectEffect) builder->loadAsset(Game::XAssetType::ASSET_TYPE_FX, asset->weapDef->viewShellEjectEffect); - if (asset->weapDef->worldShellEjectEffect) builder->loadAsset(Game::XAssetType::ASSET_TYPE_FX, asset->weapDef->worldShellEjectEffect); - if (asset->weapDef->viewLastShotEjectEffect) builder->loadAsset(Game::XAssetType::ASSET_TYPE_FX, asset->weapDef->viewLastShotEjectEffect); - if (asset->weapDef->worldLastShotEjectEffect) builder->loadAsset(Game::XAssetType::ASSET_TYPE_FX, asset->weapDef->worldLastShotEjectEffect); - if (asset->weapDef->projExplosionEffect) builder->loadAsset(Game::XAssetType::ASSET_TYPE_FX, asset->weapDef->projExplosionEffect); - if (asset->weapDef->projDudEffect) builder->loadAsset(Game::XAssetType::ASSET_TYPE_FX, asset->weapDef->projDudEffect); - if (asset->weapDef->projTrailEffect) builder->loadAsset(Game::XAssetType::ASSET_TYPE_FX, asset->weapDef->projTrailEffect); - if (asset->weapDef->projBeaconEffect) builder->loadAsset(Game::XAssetType::ASSET_TYPE_FX, asset->weapDef->projBeaconEffect); - if (asset->weapDef->projIgnitionEffect) builder->loadAsset(Game::XAssetType::ASSET_TYPE_FX, asset->weapDef->projIgnitionEffect); - if (asset->weapDef->turretOverheatEffect) builder->loadAsset(Game::XAssetType::ASSET_TYPE_FX, asset->weapDef->turretOverheatEffect); - -#define LoadWeapSound(sound) if (asset->weapDef->##sound##) builder->loadAsset(Game::XAssetType::ASSET_TYPE_SOUND, asset->weapDef->##sound##) - - LoadWeapSound(pickupSound); - LoadWeapSound(pickupSoundPlayer); - LoadWeapSound(ammoPickupSound); - LoadWeapSound(ammoPickupSoundPlayer); - LoadWeapSound(projectileSound); - LoadWeapSound(pullbackSound); - LoadWeapSound(pullbackSoundPlayer); - LoadWeapSound(fireSound); - LoadWeapSound(fireSoundPlayer); - LoadWeapSound(fireSoundPlayerAkimbo); - LoadWeapSound(fireLoopSound); - LoadWeapSound(fireLoopSoundPlayer); - LoadWeapSound(fireStopSound); - LoadWeapSound(fireStopSoundPlayer); - LoadWeapSound(fireLastSound); - LoadWeapSound(fireLastSoundPlayer); - LoadWeapSound(emptyFireSound); - LoadWeapSound(emptyFireSoundPlayer); - LoadWeapSound(meleeSwipeSound); - LoadWeapSound(meleeSwipeSoundPlayer); - LoadWeapSound(meleeHitSound); - LoadWeapSound(meleeMissSound); - LoadWeapSound(rechamberSound); - LoadWeapSound(rechamberSoundPlayer); - LoadWeapSound(reloadSound); - LoadWeapSound(reloadSoundPlayer); - LoadWeapSound(reloadEmptySound); - LoadWeapSound(reloadEmptySoundPlayer); - LoadWeapSound(reloadStartSound); - LoadWeapSound(reloadStartSoundPlayer); - LoadWeapSound(reloadEndSound); - LoadWeapSound(reloadEndSoundPlayer); - LoadWeapSound(detonateSound); - LoadWeapSound(detonateSoundPlayer); - LoadWeapSound(nightVisionWearSound); - LoadWeapSound(nightVisionWearSoundPlayer); - LoadWeapSound(nightVisionRemoveSound); - LoadWeapSound(nightVisionRemoveSoundPlayer); - LoadWeapSound(altSwitchSound); - LoadWeapSound(altSwitchSoundPlayer); - LoadWeapSound(raiseSound); - LoadWeapSound(raiseSoundPlayer); - LoadWeapSound(firstRaiseSound); - LoadWeapSound(firstRaiseSoundPlayer); - LoadWeapSound(putawaySound); - LoadWeapSound(putawaySoundPlayer); - LoadWeapSound(scanSound); - - if (asset->weapDef->bounceSound) - { - for (size_t i = 0; i < 31; i++) - { - LoadWeapSound(bounceSound[i]); - } - } - - LoadWeapSound(projExplosionSound); - LoadWeapSound(projDudSound); - LoadWeapSound(projIgnitionSound); - LoadWeapSound(turretOverheatSound); - LoadWeapSound(turretBarrelSpinMaxSnd); - - for (size_t i = 0; i < 4; i++) - { - LoadWeapSound(turretBarrelSpinUpSnd[i]); - LoadWeapSound(turretBarrelSpinDownSnd[i]); - } - - LoadWeapSound(missileConeSoundAlias); - LoadWeapSound(missileConeSoundAliasAtBase); - } - - void IWeapon::writeWeaponDef(Game::WeaponDef* def, Components::ZoneBuilder::Zone* builder, Utils::Stream* buffer) - { - AssertSize(Game::WeaponDef, 0x684); - - Game::WeaponDef* dest = buffer->dest(); - buffer->save(def); - - if (def->szOverlayName) - { - buffer->saveString(def->szOverlayName); - Utils::Stream::ClearPointer(&dest->szOverlayName); - } - - if (def->gunXModel) - { - buffer->align(Utils::Stream::ALIGN_4); - Game::XModel** pointerTable = buffer->dest(); - buffer->saveMax(16 * sizeof(Game::XModel*)); - for (int i = 0; i < 16; i++) - { - if (!def->gunXModel[i]) - { - pointerTable[i] = NULL; - continue; - } - pointerTable[i] = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_XMODEL, def->gunXModel[i]).model; - } - Utils::Stream::ClearPointer(&dest->gunXModel); - } - - if (def->handXModel) - { - dest->handXModel = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_XMODEL, def->handXModel).model; - } - - if (def->szXAnimsRightHanded) - { - buffer->align(Utils::Stream::ALIGN_4); - int* poinerTable = buffer->dest(); - buffer->saveMax(37 * sizeof(char*)); // array of 37 string pointers - for (int i = 0; i < 37; i++) - { - if (!def->szXAnimsRightHanded[i]) { - poinerTable[i] = 0; // clear poiner if there isn't a string here - continue; - } - - // save string if it is present - buffer->saveString(def->szXAnimsRightHanded[i]); - } - - Utils::Stream::ClearPointer(&dest->szXAnimsRightHanded); - } - - if (def->szXAnimsLeftHanded) - { - buffer->align(Utils::Stream::ALIGN_4); - int* poinerTable = buffer->dest(); - buffer->saveMax(37 * sizeof(char*)); // array of 37 string pointers - for (int i = 0; i < 37; i++) - { - if (!def->szXAnimsLeftHanded[i]) { - poinerTable[i] = 0; // clear poiner if there isn't a string here - continue; - } - - // save string if it is present - buffer->saveString(def->szXAnimsLeftHanded[i]); - } - - Utils::Stream::ClearPointer(&dest->szXAnimsLeftHanded); - } - - if (def->szModeName) - { - buffer->saveString(def->szModeName); - Utils::Stream::ClearPointer(&dest->szModeName); - } - - if (def->notetrackSoundMapKeys) - { - buffer->align(Utils::Stream::ALIGN_2); - unsigned short* scriptStringTable = buffer->dest(); - buffer->saveArray(def->notetrackSoundMapKeys, 16); - for (int i = 0; i < 16; i++) { - builder->mapScriptString(scriptStringTable[i]); - } - - Utils::Stream::ClearPointer(&dest->notetrackSoundMapKeys); - } - - if (def->notetrackSoundMapValues) - { - buffer->align(Utils::Stream::ALIGN_2); - unsigned short* scriptStringTable = buffer->dest(); - buffer->saveArray(def->notetrackSoundMapValues, 16); - for (int i = 0; i < 16; i++) { - builder->mapScriptString(scriptStringTable[i]); - } - - Utils::Stream::ClearPointer(&dest->notetrackSoundMapValues); - } - - if (def->notetrackRumbleMapKeys) - { - buffer->align(Utils::Stream::ALIGN_2); - unsigned short* scriptStringTable = buffer->dest(); - buffer->saveArray(def->notetrackRumbleMapKeys, 16); - for (int i = 0; i < 16; i++) { - builder->mapScriptString(scriptStringTable[i]); - } - - Utils::Stream::ClearPointer(&dest->notetrackRumbleMapKeys); - } - - if (def->notetrackRumbleMapValues) - { - buffer->align(Utils::Stream::ALIGN_2); - unsigned short* scriptStringTable = buffer->dest(); - buffer->saveArray(def->notetrackRumbleMapValues, 16); - for (int i = 0; i < 16; i++) { - builder->mapScriptString(scriptStringTable[i]); - } - - Utils::Stream::ClearPointer(&dest->notetrackRumbleMapValues); - } - - if (def->viewFlashEffect) - { - dest->viewFlashEffect = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_FX, def->viewFlashEffect).fx; - } - - if (def->worldFlashEffect) - { - dest->worldFlashEffect = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_FX, def->worldFlashEffect).fx; - } - - // This is compressed because I don't want to write the same piece of code 47 times - // TODO: verify that this is saving the aliases correctly because the old code looks wrong and this looks right but the old code worked so go figure - Game::snd_alias_list_t ** allSounds = &def->pickupSound; - Game::snd_alias_list_t ** allSoundsDest = &dest->pickupSound; - for (int i = 0; i < 47; i++) { - if (!allSounds[i]) continue; - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveMax(sizeof(Game::snd_alias_list_t*)); - buffer->saveString(allSounds[i]->aliasName); - Utils::Stream::ClearPointer(&allSoundsDest[i]); - } - - if (def->bounceSound) - { - buffer->align(Utils::Stream::ALIGN_4); - int* ptrs = buffer->dest(); - buffer->saveMax(31 * sizeof(Game::snd_alias_list_t*)); - - for (int i = 0; i < 31; i++) - { - if (!def->bounceSound[i]) - { - ptrs[i] = 0; - continue; - } - - buffer->saveMax(sizeof(Game::snd_alias_list_t*)); - buffer->saveString(def->bounceSound[i]->aliasName); - } - - Utils::Stream::ClearPointer(&dest->bounceSound); - } - - if (def->viewShellEjectEffect) - { - dest->viewShellEjectEffect = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_FX, def->viewShellEjectEffect).fx; - } - - if (def->worldShellEjectEffect) - { - dest->worldShellEjectEffect = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_FX, def->worldShellEjectEffect).fx; - } - - if (def->viewLastShotEjectEffect) - { - dest->viewLastShotEjectEffect = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_FX, def->viewLastShotEjectEffect).fx; - } - - if (def->worldLastShotEjectEffect) - { - dest->worldLastShotEjectEffect = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_FX, def->worldLastShotEjectEffect).fx; - } - - if (def->reticleCenter) - { - dest->reticleCenter = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, def->reticleCenter).material; - } - - if (def->reticleSide) - { - dest->reticleSide = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, def->reticleSide).material; - } - - if (def->worldModel) - { - buffer->align(Utils::Stream::ALIGN_4); - Game::XModel** pointerTable = buffer->dest(); - buffer->saveMax(16 * sizeof(Game::XModel*)); - for (int i = 0; i < 16; i++) - { - if (!def->worldModel[i]) - { - pointerTable[i] = NULL; - continue; - } - pointerTable[i] = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_XMODEL, def->worldModel[i]).model; - } - Utils::Stream::ClearPointer(&dest->worldModel); - } - - if (def->worldClipModel) - { - dest->worldClipModel = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_XMODEL, def->worldClipModel).model; - } - - if (def->rocketModel) - { - dest->rocketModel = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_XMODEL, def->rocketModel).model; - } - - if (def->knifeModel) - { - dest->knifeModel = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_XMODEL, def->knifeModel).model; - } - - if (def->worldKnifeModel) - { - dest->worldKnifeModel = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_XMODEL, def->worldKnifeModel).model; - } - - if (def->hudIcon) - { - dest->hudIcon = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, def->hudIcon).material; - } - - if (def->pickupIcon) - { - dest->pickupIcon = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, def->pickupIcon).material; - } - - if (def->ammoCounterIcon) - { - dest->ammoCounterIcon = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, def->ammoCounterIcon).material; - } - - if (def->szAmmoName) - { - buffer->saveString(def->szAmmoName); - Utils::Stream::ClearPointer(&dest->szAmmoName); - } - - if (def->szClipName) - { - buffer->saveString(def->szClipName); - Utils::Stream::ClearPointer(&dest->szClipName); - } - - if (def->szSharedAmmoCapName) - { - buffer->saveString(def->szSharedAmmoCapName); - Utils::Stream::ClearPointer(&dest->szSharedAmmoCapName); - } - - if (def->overlayMaterial) - { - dest->overlayMaterial = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, def->overlayMaterial).material; - } - - if (def->overlayMaterialLowRes) - { - dest->overlayMaterialLowRes = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, def->overlayMaterialLowRes).material; - } - - if (def->overlayMaterialEMP) - { - dest->overlayMaterialEMP = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, def->overlayMaterialEMP).material; - } - - if (def->overlayMaterialEMPLowRes) - { - dest->overlayMaterialEMPLowRes = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, def->overlayMaterialEMPLowRes).material; - } - - if (def->physCollmap) - { - dest->physCollmap = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_PHYSCOLLMAP, def->overlayMaterialEMPLowRes).physCollmap; - } - - if (def->projectileModel) - { - dest->projectileModel = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_XMODEL, def->projectileModel).model; - } - - if (def->projExplosionEffect) - { - dest->projExplosionEffect = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_FX, def->projExplosionEffect).fx; - } - - if (def->projDudEffect) - { - dest->projDudEffect = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_FX, def->projDudEffect).fx; - } - - if (def->projExplosionSound) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveMax(sizeof(Game::snd_alias_list_t*)); - buffer->saveString(def->projExplosionSound->aliasName); - Utils::Stream::ClearPointer(&dest->projExplosionSound); - } - - if (def->projDudSound) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveMax(sizeof(Game::snd_alias_list_t*)); - buffer->saveString(def->projDudSound->aliasName); - Utils::Stream::ClearPointer(&dest->projDudSound); - } - - if (def->parallelBounce) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(def->parallelBounce, 31); - Utils::Stream::ClearPointer(&dest->parallelBounce); - } - - if (def->perpendicularBounce) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(def->perpendicularBounce, 31); - Utils::Stream::ClearPointer(&dest->perpendicularBounce); - } - - if (def->projTrailEffect) - { - dest->projTrailEffect = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_FX, def->projTrailEffect).fx; - } - - if (def->projBeaconEffect) - { - dest->projBeaconEffect = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_FX, def->projBeaconEffect).fx; - } - - if (def->projIgnitionEffect) - { - dest->projIgnitionEffect = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_FX, def->projIgnitionEffect).fx; - } - - if (def->projIgnitionSound) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveMax(sizeof(Game::snd_alias_list_t*)); - buffer->saveString(def->projIgnitionSound->aliasName); - Utils::Stream::ClearPointer(&dest->projIgnitionSound); - } - - if (def->accuracyGraphName[0]) - { - buffer->saveString(def->accuracyGraphName[0]); - Utils::Stream::ClearPointer(&dest->accuracyGraphName[0]); - } - - if (def->originalAccuracyGraphKnots[0]) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(def->originalAccuracyGraphKnots[0], def->originalAccuracyGraphKnotCount[0]); - Utils::Stream::ClearPointer(&dest->originalAccuracyGraphKnots[0]); - } - - if (def->accuracyGraphName[1]) - { - buffer->saveString(def->accuracyGraphName[1]); - Utils::Stream::ClearPointer(&dest->accuracyGraphName[1]); - } - - if (def->originalAccuracyGraphKnots[1]) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(def->originalAccuracyGraphKnots[1], def->originalAccuracyGraphKnotCount[1]); - Utils::Stream::ClearPointer(&dest->originalAccuracyGraphKnots[1]); - } - - if (def->szUseHintString) - { - buffer->saveString(def->szUseHintString); - Utils::Stream::ClearPointer(&dest->szUseHintString); - } - - if (def->dropHintString) - { - buffer->saveString(def->dropHintString); - Utils::Stream::ClearPointer(&dest->dropHintString); - } - - if (def->szScript) - { - buffer->saveString(def->szScript); - Utils::Stream::ClearPointer(&dest->szScript); - } - - if (def->locationDamageMultipliers) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(def->locationDamageMultipliers, 20); - Utils::Stream::ClearPointer(&dest->locationDamageMultipliers); - } - - if (def->fireRumble) - { - buffer->saveString(def->fireRumble); - Utils::Stream::ClearPointer(&dest->fireRumble); - } - - if (def->meleeImpactRumble) - { - buffer->saveString(def->meleeImpactRumble); - Utils::Stream::ClearPointer(&dest->meleeImpactRumble); - } - - if (def->tracerType) - { - dest->tracerType = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_TRACER, def->tracerType).tracerDef; - } - - if (def->turretOverheatSound) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveMax(sizeof(Game::snd_alias_list_t*)); - buffer->saveString(def->turretOverheatSound->aliasName); - Utils::Stream::ClearPointer(&dest->turretOverheatSound); - } - - if (def->turretOverheatEffect) - { - dest->turretOverheatEffect = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_FX, def->turretOverheatEffect).fx; - } - - if (def->turretBarrelSpinRumble) - { - buffer->saveString(def->turretBarrelSpinRumble); - Utils::Stream::ClearPointer(&dest->turretBarrelSpinRumble); - } - - if (def->turretBarrelSpinMaxSnd) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveMax(sizeof(Game::snd_alias_list_t*)); - buffer->saveString(def->turretBarrelSpinMaxSnd->aliasName); - Utils::Stream::ClearPointer(&dest->turretBarrelSpinMaxSnd); - } - - for (int i = 0; i < 4; i++) { - if (!def->turretBarrelSpinUpSnd[i]) continue; - - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveMax(sizeof(Game::snd_alias_list_t*)); - buffer->saveString(def->turretBarrelSpinUpSnd[i]->aliasName); - Utils::Stream::ClearPointer(&dest->turretBarrelSpinUpSnd[i]); - } - - for (int i = 0; i < 4; i++) { - if (!def->turretBarrelSpinDownSnd[i]) continue; - - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveMax(sizeof(Game::snd_alias_list_t*)); - buffer->saveString(def->turretBarrelSpinDownSnd[i]->aliasName); - Utils::Stream::ClearPointer(&dest->turretBarrelSpinDownSnd[i]); - } - - if (def->missileConeSoundAlias) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveMax(sizeof(Game::snd_alias_list_t*)); - buffer->saveString(def->missileConeSoundAlias->aliasName); - Utils::Stream::ClearPointer(&dest->missileConeSoundAlias); - } - - if (def->missileConeSoundAliasAtBase) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveMax(sizeof(Game::snd_alias_list_t*)); - buffer->saveString(def->missileConeSoundAliasAtBase->aliasName); - Utils::Stream::ClearPointer(&dest->missileConeSoundAliasAtBase); - } - } - - void IWeapon::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::WeaponCompleteDef, 0x74); - - Utils::Stream* buffer = builder->getBuffer(); - Game::WeaponCompleteDef* asset = header.weapon; - Game::WeaponCompleteDef* dest = buffer->dest(); - buffer->save(asset); - - buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); - - if (asset->szInternalName) - { - buffer->saveString(builder->getAssetName(this->getType(), asset->szInternalName)); - Utils::Stream::ClearPointer(&dest->szInternalName); - } - - if (asset->weapDef) - { - buffer->align(Utils::Stream::ALIGN_4); - IWeapon::writeWeaponDef(asset->weapDef, builder, buffer); - - Utils::Stream::ClearPointer(&dest->weapDef); - } - - if (asset->szDisplayName) - { - buffer->saveString(asset->szDisplayName); - Utils::Stream::ClearPointer(&dest->szDisplayName); - } - - if (asset->hideTags) - { - buffer->align(Utils::Stream::ALIGN_2); - unsigned short* scriptStringTable = buffer->dest(); - buffer->saveArray(asset->hideTags, 32); - for (int i = 0; i < 32; i++) { - builder->mapScriptString(scriptStringTable[i]); - } - - Utils::Stream::ClearPointer(&dest->hideTags); - } - - if (asset->szXAnims) - { - buffer->align(Utils::Stream::ALIGN_4); - int* poinerTable = buffer->dest(); - buffer->saveMax(37 * sizeof(char*)); // array of 37 string pointers - for (int i = 0; i < 37; i++) - { - if (!asset->szXAnims[i]) { - poinerTable[i] = 0; // clear poiner if there isn't a string here - continue; - } - - // save string if it is present - buffer->saveString(asset->szXAnims[i]); - } - - Utils::Stream::ClearPointer(&dest->szXAnims); - } - - if (asset->szAltWeaponName) - { - buffer->saveString(asset->szAltWeaponName); - Utils::Stream::ClearPointer(&dest->szAltWeaponName); - } - - if (asset->killIcon) - { - dest->killIcon = builder->saveSubAsset(Game::ASSET_TYPE_MATERIAL, asset->killIcon).material; - } - - if (asset->dpadIcon) - { - dest->dpadIcon = builder->saveSubAsset(Game::ASSET_TYPE_MATERIAL, asset->dpadIcon).material; - } - - if (asset->accuracyGraphKnots[0]) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->accuracyGraphKnots[0], asset->accuracyGraphKnotCount[0]); - Utils::Stream::ClearPointer(&dest->accuracyGraphKnots[0]); - } - - if (asset->accuracyGraphKnots[1]) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->accuracyGraphKnots[1], asset->accuracyGraphKnotCount[1]); - Utils::Stream::ClearPointer(&dest->accuracyGraphKnots[1]); - } - - buffer->popBlock(); - } -} diff --git a/src/Components/Modules/AssetInterfaces/IWeapon.hpp b/src/Components/Modules/AssetInterfaces/IWeapon.hpp deleted file mode 100644 index e9f05d5b..00000000 --- a/src/Components/Modules/AssetInterfaces/IWeapon.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -namespace Assets -{ - class IWeapon : public Components::AssetHandler::IAsset - { - public: - Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_WEAPON; } - - void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override; - - private: - void writeWeaponDef(Game::WeaponDef* def, Components::ZoneBuilder::Zone* builder, Utils::Stream* buffer); - }; -} diff --git a/src/Components/Modules/AssetInterfaces/IXAnimParts.cpp b/src/Components/Modules/AssetInterfaces/IXAnimParts.cpp deleted file mode 100644 index e8b9860c..00000000 --- a/src/Components/Modules/AssetInterfaces/IXAnimParts.cpp +++ /dev/null @@ -1,259 +0,0 @@ -#include -#include "IXAnimParts.hpp" - -namespace Assets -{ - void IXAnimParts::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) - { - header->parts = builder->getIW4OfApi()->read(Game::XAssetType::ASSET_TYPE_XANIMPARTS, name); - } - - void IXAnimParts::mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - Game::XAnimParts* asset = header.parts; - - if (asset->names) - { - for (char i = 0; i < asset->boneCount[Game::PART_TYPE_ALL]; ++i) - { - builder->addScriptString(asset->names[i]); - } - } - - if (asset->notify) - { - for (char i = 0; i < asset->notifyCount; ++i) - { - builder->addScriptString(asset->notify[i].name); - } - } - } - - void IXAnimParts::saveXAnimDeltaPart(Game::XAnimDeltaPart* delta, unsigned short framecount, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::XAnimDeltaPart, 12); - - Utils::Stream* buffer = builder->getBuffer(); - Game::XAnimDeltaPart* destDelta = buffer->dest(); - buffer->save(delta); - - if (delta->trans) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->save(delta->trans, 4); - - if (delta->trans->size) - { - buffer->save(&delta->trans->u.frames, 28); - - if (framecount > 0xFF) - { - buffer->saveArray(delta->trans->u.frames.indices._2, delta->trans->size + 1); - } - else - { - buffer->saveArray(delta->trans->u.frames.indices._1, delta->trans->size + 1); - } - - if (delta->trans->u.frames.frames._1) - { - if (delta->trans->smallTrans) - { - buffer->save(delta->trans->u.frames.frames._1, 3, delta->trans->size + 1); - } - else - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->save(delta->trans->u.frames.frames._1, 6, delta->trans->size + 1); - } - } - } - else - { - buffer->save(delta->trans->u.frame0, 12); - } - - Utils::Stream::ClearPointer(&destDelta->trans); - } - - if (delta->quat2) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->save(delta->quat2, 4); - - if (delta->quat2->size) - { - buffer->save(&delta->quat2->u.frames, 4); - - if (framecount > 0xFF) - { - buffer->save(delta->quat2->u.frames.indices._1, 2, delta->quat2->size + 1); - } - else - { - buffer->save(delta->quat2->u.frames.indices._1, 1, delta->quat2->size + 1); - } - - if (delta->quat2->u.frames.frames) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->save(delta->quat2->u.frames.frames, 4, delta->quat2->size + 1); - } - } - else - { - buffer->save(delta->quat2->u.frame0, 4); - } - - Utils::Stream::ClearPointer(&destDelta->quat2); - } - - if (delta->quat) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->save(delta->quat, 4); - - if (delta->quat->size) - { - buffer->save(&delta->quat->u.frames, 4); - - if (framecount > 0xFF) - { - buffer->save(delta->quat->u.frames.indices._1, 2, delta->quat->size + 1); - } - else - { - buffer->save(delta->quat->u.frames.indices._1, 1, delta->quat->size + 1); - } - - if (delta->quat->u.frames.frames) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->save(delta->quat->u.frames.frames, 4, delta->quat->size + 1); - } - } - else - { - buffer->save(delta->quat->u.frame0, 4); - } - - Utils::Stream::ClearPointer(&destDelta->quat); - } - } - - void IXAnimParts::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::XAnimParts, 88); - - Utils::Stream* buffer = builder->getBuffer(); - Game::XAnimParts* asset = header.parts; - Game::XAnimParts* dest = buffer->dest(); - buffer->save(asset, sizeof(Game::XAnimParts)); - - buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); - - if (asset->name) - { - buffer->saveString(builder->getAssetName(this->getType(), asset->name)); - Utils::Stream::ClearPointer(&dest->name); - } - - if (asset->names) - { - buffer->align(Utils::Stream::ALIGN_2); - - unsigned short* destTagnames = buffer->dest(); - buffer->saveArray(asset->names, asset->boneCount[Game::PART_TYPE_ALL]); - - for (char i = 0; i < asset->boneCount[Game::PART_TYPE_ALL]; ++i) - { - builder->mapScriptString(destTagnames[i]); - } - - Utils::Stream::ClearPointer(&dest->names); - } - - if (asset->notify) - { - AssertSize(Game::XAnimNotifyInfo, 8); - buffer->align(Utils::Stream::ALIGN_4); - - Game::XAnimNotifyInfo* destNotetracks = buffer->dest(); - buffer->saveArray(asset->notify, asset->notifyCount); - - for (char i = 0; i < asset->notifyCount; ++i) - { - builder->mapScriptString(destNotetracks[i].name); - } - - Utils::Stream::ClearPointer(&dest->notify); - } - - if (asset->deltaPart) - { - AssertSize(Game::XAnimDeltaPart, 12); - buffer->align(Utils::Stream::ALIGN_4); - - this->saveXAnimDeltaPart(asset->deltaPart, asset->numframes, builder); - - Utils::Stream::ClearPointer(&dest->deltaPart); - } - - if (asset->dataByte) - { - buffer->saveArray(asset->dataByte, asset->dataByteCount); - Utils::Stream::ClearPointer(&dest->dataByte); - } - - if (asset->dataShort) - { - buffer->align(Utils::Stream::ALIGN_2); - buffer->saveArray(asset->dataShort, asset->dataShortCount); - Utils::Stream::ClearPointer(&dest->dataShort); - } - - if (asset->dataInt) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->dataInt, asset->dataIntCount); - Utils::Stream::ClearPointer(&dest->dataInt); - } - - if (asset->randomDataShort) - { - buffer->align(Utils::Stream::ALIGN_2); - buffer->saveArray(asset->randomDataShort, asset->randomDataShortCount); - Utils::Stream::ClearPointer(&dest->randomDataShort); - } - - if (asset->randomDataByte) - { - buffer->saveArray(asset->randomDataByte, asset->randomDataByteCount); - Utils::Stream::ClearPointer(&dest->randomDataByte); - } - - if (asset->randomDataInt) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->randomDataInt, asset->randomDataIntCount); - Utils::Stream::ClearPointer(&dest->randomDataInt); - } - - if (asset->indices.data) - { - if (asset->numframes > 0xFF) - { - buffer->align(Utils::Stream::ALIGN_2); - buffer->saveArray(asset->indices._2, asset->indexCount); - } - else - { - buffer->saveArray(asset->indices._1, asset->indexCount); - } - - Utils::Stream::ClearPointer(&dest->indices.data); - } - - buffer->popBlock(); - } -} diff --git a/src/Components/Modules/AssetInterfaces/IXAnimParts.hpp b/src/Components/Modules/AssetInterfaces/IXAnimParts.hpp deleted file mode 100644 index 8a973216..00000000 --- a/src/Components/Modules/AssetInterfaces/IXAnimParts.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -namespace Assets -{ - class IXAnimParts : public Components::AssetHandler::IAsset - { - public: - Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_XANIMPARTS; } - - void mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override; - - private: - void saveXAnimDeltaPart(Game::XAnimDeltaPart* delta, unsigned short framecount, Components::ZoneBuilder::Zone* builder); - }; -} diff --git a/src/Components/Modules/AssetInterfaces/IXModel.cpp b/src/Components/Modules/AssetInterfaces/IXModel.cpp deleted file mode 100644 index d4444712..00000000 --- a/src/Components/Modules/AssetInterfaces/IXModel.cpp +++ /dev/null @@ -1,260 +0,0 @@ -#include -#include "IXModel.hpp" - -namespace Assets -{ - void IXModel::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) - { - header->model = builder->getIW4OfApi()->read(Game::XAssetType::ASSET_TYPE_XMODEL, name); - - if (header->model) - { - // ??? - if (header->model->physCollmap) - { - Components::AssetHandler::StoreTemporaryAsset(Game::XAssetType::ASSET_TYPE_PHYSCOLLMAP, { header->model->physCollmap }); - } - - if (header->model->physPreset) - { - Components::AssetHandler::StoreTemporaryAsset(Game::XAssetType::ASSET_TYPE_PHYSPRESET, { header->model->physPreset }); - } - - for (size_t i = 0; i < header->model->numLods; i++) - { - const auto& info = header->model->lodInfo[i]; - Components::AssetHandler::StoreTemporaryAsset(Game::XAssetType::ASSET_TYPE_XMODEL_SURFS, { info.modelSurfs }); - } - } - } - - void IXModel::mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - Game::XModel* asset = header.model; - - if (asset->boneNames) - { - for (char i = 0; i < asset->numBones; ++i) - { - builder->addScriptString(asset->boneNames[i]); - } - } - - if (asset->materialHandles) - { - for (unsigned char i = 0; i < asset->numsurfs; ++i) - { - if (asset->materialHandles[i]) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, asset->materialHandles[i]); - } - } - } - - for (int i = 0; i < 4; ++i) - { - if (asset->lodInfo[i].modelSurfs) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_XMODEL_SURFS, asset->lodInfo[i].modelSurfs); - } - } - - if (asset->physPreset) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_PHYSPRESET, asset->physPreset); - } - - if (asset->physCollmap) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_PHYSCOLLMAP, asset->physCollmap); - } - } - - void IXModel::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::XModel, 304); - - Utils::Stream* buffer = builder->getBuffer(); - Game::XModel* asset = header.model; - Game::XModel* dest = buffer->dest(); - buffer->save(asset); - - buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); - - if (asset->name) - { - buffer->saveString(builder->getAssetName(this->getType(), asset->name)); - Utils::Stream::ClearPointer(&dest->name); - } - - if (asset->boneNames) - { - buffer->align(Utils::Stream::ALIGN_2); - - unsigned short* destBoneNames = buffer->dest(); - buffer->saveArray(asset->boneNames, asset->numBones); - - for (char i = 0; i < asset->numBones; ++i) - { - builder->mapScriptString(destBoneNames[i]); - } - - Utils::Stream::ClearPointer(&dest->boneNames); - } - - if (asset->parentList) - { - if (builder->hasPointer(asset->parentList)) - { - dest->parentList = builder->getPointer(asset->parentList); - } - else - { - builder->storePointer(asset->parentList); - buffer->save(asset->parentList, asset->numBones - asset->numRootBones); - Utils::Stream::ClearPointer(&dest->parentList); - } - } - - if (asset->quats) - { - if (builder->hasPointer(asset->quats)) - { - dest->quats = builder->getPointer(asset->quats); - } - else - { - buffer->align(Utils::Stream::ALIGN_2); - builder->storePointer(asset->quats); - buffer->saveArray(asset->quats, (asset->numBones - asset->numRootBones) * 4); - Utils::Stream::ClearPointer(&dest->quats); - } - } - - if (asset->trans) - { - if (builder->hasPointer(asset->trans)) - { - dest->trans = builder->getPointer(asset->trans); - } - else - { - buffer->align(Utils::Stream::ALIGN_4); - builder->storePointer(asset->trans); - buffer->saveArray(asset->trans, (asset->numBones - asset->numRootBones) * 3); - Utils::Stream::ClearPointer(&dest->trans); - } - } - - if (asset->partClassification) - { - if (builder->hasPointer(asset->partClassification)) - { - dest->partClassification = builder->getPointer(asset->partClassification); - } - else - { - builder->storePointer(asset->partClassification); - buffer->save(asset->partClassification, asset->numBones); - Utils::Stream::ClearPointer(&dest->partClassification); - } - } - - if (asset->baseMat) - { - AssertSize(Game::DObjAnimMat, 32); - if (builder->hasPointer(asset->baseMat)) - { - dest->baseMat = builder->getPointer(asset->baseMat); - } - else - { - buffer->align(Utils::Stream::ALIGN_4); - builder->storePointer(asset->baseMat); - buffer->saveArray(asset->baseMat, asset->numBones); - Utils::Stream::ClearPointer(&dest->baseMat); - } - - } - - if (asset->materialHandles) - { - buffer->align(Utils::Stream::ALIGN_4); - - Game::Material** destMaterials = buffer->dest(); - buffer->saveArray(asset->materialHandles, asset->numsurfs); - - for (unsigned char i = 0; i < asset->numsurfs; ++i) - { - if (asset->materialHandles[i]) - { - destMaterials[i] = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, asset->materialHandles[i]).material; - } - } - - Utils::Stream::ClearPointer(&dest->materialHandles); - } - - // Save_XModelLodInfoArray - { - AssertSize(Game::XModelLodInfo, 44); - - for (int i = 0; i < 4; ++i) - { - if (asset->lodInfo[i].modelSurfs) - { - dest->lodInfo[i].modelSurfs = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_XMODEL_SURFS, asset->lodInfo[i].modelSurfs).modelSurfs; - } - } - } - - // Save_XModelCollSurfArray - if (asset->collSurfs) - { - AssertSize(Game::XModelCollSurf_s, 44); - - buffer->align(Utils::Stream::ALIGN_4); - - Game::XModelCollSurf_s* destColSurfs = buffer->dest(); - buffer->saveArray(asset->collSurfs, asset->numCollSurfs); - - for (int i = 0; i < asset->numCollSurfs; ++i) - { - Game::XModelCollSurf_s* destCollSurf = &destColSurfs[i]; - Game::XModelCollSurf_s* collSurf = &asset->collSurfs[i]; - - if (collSurf->collTris) - { - buffer->align(Utils::Stream::ALIGN_4); - - buffer->save(collSurf->collTris, 48, collSurf->numCollTris); - Utils::Stream::ClearPointer(&destCollSurf->collTris); - } - } - - Utils::Stream::ClearPointer(&dest->collSurfs); - } - - if (asset->boneInfo) - { - AssertSize(Game::XBoneInfo, 28); - - buffer->align(Utils::Stream::ALIGN_4); - - buffer->saveArray(asset->boneInfo, asset->numBones); - Utils::Stream::ClearPointer(&dest->boneInfo); - } - - if (asset->physPreset) - { - dest->physPreset = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_PHYSPRESET, asset->physPreset).physPreset; - } - - if (asset->physCollmap) - { - dest->physCollmap = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_PHYSCOLLMAP, asset->physCollmap).physCollmap; - } - - buffer->popBlock(); - } -} diff --git a/src/Components/Modules/AssetInterfaces/IXModel.hpp b/src/Components/Modules/AssetInterfaces/IXModel.hpp deleted file mode 100644 index 2c68489a..00000000 --- a/src/Components/Modules/AssetInterfaces/IXModel.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -namespace Assets -{ - class IXModel : public Components::AssetHandler::IAsset - { - public: - Game::XAssetType getType() override { return Game::ASSET_TYPE_XMODEL; } - - void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override; - }; -} diff --git a/src/Components/Modules/AssetInterfaces/IXModelSurfs.cpp b/src/Components/Modules/AssetInterfaces/IXModelSurfs.cpp deleted file mode 100644 index 15c4333a..00000000 --- a/src/Components/Modules/AssetInterfaces/IXModelSurfs.cpp +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include "IXModelSurfs.hpp" - -namespace Assets -{ - void IXModelSurfs::saveXSurfaceCollisionTree(Game::XSurfaceCollisionTree* entry, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::XSurfaceCollisionTree, 40); - - Utils::Stream* buffer = builder->getBuffer(); - - Game::XSurfaceCollisionTree* destEntry = buffer->dest(); - buffer->save(entry); - - if (entry->nodes) - { - AssertSize(Game::XSurfaceCollisionNode, 16); - - buffer->align(Utils::Stream::ALIGN_16); - buffer->saveArray(entry->nodes, entry->nodeCount); - Utils::Stream::ClearPointer(&destEntry->nodes); - } - - if (entry->leafs) - { - AssertSize(Game::XSurfaceCollisionLeaf, 2); - - buffer->align(Utils::Stream::ALIGN_2); - buffer->saveArray(entry->leafs, entry->leafCount); - Utils::Stream::ClearPointer(&destEntry->leafs); - } - } - - void IXModelSurfs::saveXSurface(Game::XSurface* surf, Game::XSurface* destSurf, Components::ZoneBuilder::Zone* builder) - { - Utils::Stream* buffer = builder->getBuffer(); - - if (surf->vertInfo.vertsBlend) - { - if (builder->hasPointer(surf->vertInfo.vertsBlend)) - { - destSurf->vertInfo.vertsBlend = builder->getPointer(surf->vertInfo.vertsBlend); - } - else - { - - buffer->align(Utils::Stream::ALIGN_2); - builder->storePointer(surf->vertInfo.vertsBlend); - buffer->saveArray(surf->vertInfo.vertsBlend, surf->vertInfo.vertCount[0] + (surf->vertInfo.vertCount[1] * 3) + (surf->vertInfo.vertCount[2] * 5) + (surf->vertInfo.vertCount[3] * 7)); - Utils::Stream::ClearPointer(&destSurf->vertInfo.vertsBlend); - } - } - - // Access vertex block - buffer->pushBlock(Game::XFILE_BLOCK_VERTEX); - if (surf->verts0) - { - AssertSize(Game::GfxPackedVertex, 32); - - if (builder->hasPointer(surf->verts0)) - { - destSurf->verts0 = builder->getPointer(surf->verts0); - } - else - { - buffer->align(Utils::Stream::ALIGN_16); - builder->storePointer(surf->verts0); - buffer->saveArray(surf->verts0, surf->vertCount); - Utils::Stream::ClearPointer(&destSurf->verts0); - } - } - buffer->popBlock(); - - // Save_XRigidVertListArray - if (surf->vertList) - { - AssertSize(Game::XRigidVertList, 12); - - if (builder->hasPointer(surf->vertList)) - { - destSurf->vertList = builder->getPointer(surf->vertList); - } - else - { - buffer->align(Utils::Stream::ALIGN_4); - builder->storePointer(surf->vertList); - - Game::XRigidVertList* destCt = buffer->dest(); - buffer->saveArray(surf->vertList, surf->vertListCount); - - for (unsigned int i = 0; i < surf->vertListCount; ++i) - { - Game::XRigidVertList* destRigidVertList = &destCt[i]; - Game::XRigidVertList* rigidVertList = &surf->vertList[i]; - - if (rigidVertList->collisionTree) - { - if (builder->hasPointer(rigidVertList->collisionTree)) - { - destRigidVertList->collisionTree = builder->getPointer(rigidVertList->collisionTree); - } - else { - buffer->align(Utils::Stream::ALIGN_4); - builder->storePointer(rigidVertList->collisionTree); - this->saveXSurfaceCollisionTree(rigidVertList->collisionTree, builder); - Utils::Stream::ClearPointer(&destRigidVertList->collisionTree); - } - } - } - - Utils::Stream::ClearPointer(&destSurf->vertList); - } - } - - // Access index block - buffer->pushBlock(Game::XFILE_BLOCK_INDEX); - if (builder->hasPointer(surf->triIndices)) - { - destSurf->triIndices = builder->getPointer(surf->triIndices); - } - else - { - buffer->align(Utils::Stream::ALIGN_16); - builder->storePointer(surf->triIndices); - buffer->saveArray(surf->triIndices, surf->triCount * 3); - Utils::Stream::ClearPointer(&destSurf->triIndices); - } - buffer->popBlock(); - } - - void IXModelSurfs::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::XModelSurfs, 36); - - Utils::Stream* buffer = builder->getBuffer(); - Game::XModelSurfs* asset = header.modelSurfs; - Game::XModelSurfs* dest = buffer->dest(); - buffer->save(asset); - - buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); - - if (asset->name) - { - buffer->saveString(builder->getAssetName(this->getType(), asset->name)); - Utils::Stream::ClearPointer(&dest->name); - } - - if (asset->surfs) - { - AssertSize(Game::XSurface, 64); - - buffer->align(Utils::Stream::ALIGN_4); - - Game::XSurface* destSurfaces = buffer->dest(); - buffer->saveArray(asset->surfs, asset->numsurfs); - - for (int i = 0; i < asset->numsurfs; ++i) - { - this->saveXSurface(&asset->surfs[i], &destSurfaces[i], builder); - } - - Utils::Stream::ClearPointer(&dest->surfs); - } - - buffer->popBlock(); - } -} diff --git a/src/Components/Modules/AssetInterfaces/IXModelSurfs.hpp b/src/Components/Modules/AssetInterfaces/IXModelSurfs.hpp deleted file mode 100644 index b4b3bbcd..00000000 --- a/src/Components/Modules/AssetInterfaces/IXModelSurfs.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -namespace Assets -{ - class IXModelSurfs : public Components::AssetHandler::IAsset - { - public: - Game::XAssetType getType() override { return Game::ASSET_TYPE_XMODEL_SURFS; } - - void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - - private: - void saveXSurface(Game::XSurface* surf, Game::XSurface* destSurf, Components::ZoneBuilder::Zone* builder); - void saveXSurfaceCollisionTree(Game::XSurfaceCollisionTree* entry, Components::ZoneBuilder::Zone* builder); - }; -} diff --git a/src/Components/Modules/AssetInterfaces/IclipMap_t.cpp b/src/Components/Modules/AssetInterfaces/IclipMap_t.cpp deleted file mode 100644 index 82a1c3fd..00000000 --- a/src/Components/Modules/AssetInterfaces/IclipMap_t.cpp +++ /dev/null @@ -1,585 +0,0 @@ -#include -#include "IclipMap_t.hpp" - -namespace Assets -{ - void IclipMap_t::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::clipMap_t, 256); - SaveLogEnter("clipMap_t"); - - Utils::Stream* buffer = builder->getBuffer(); - Game::clipMap_t* asset = header.clipMap; - Game::clipMap_t* dest = buffer->dest(); - buffer->save(asset); - - buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); - - if (asset->name) - { - buffer->saveString(builder->getAssetName(this->getType(), asset->name)); - Utils::Stream::ClearPointer(&dest->name); - } - - if (asset->planes) - { - AssertSize(Game::cplane_s, 20); - SaveLogEnter("cplane_t"); - - if (builder->hasPointer(asset->planes)) - { - dest->planes = builder->getPointer(asset->planes); - } - else - { - buffer->align(Utils::Stream::ALIGN_4); - - // not sure if this is needed but both brushside and brushedge need it and it can't hurt - for (size_t i = 0; i < asset->planeCount; ++i) - { - builder->storePointer(&asset->planes[i]); - buffer->save(&asset->planes[i]); - } - Utils::Stream::ClearPointer(&dest->planes); - } - - SaveLogExit(); - } - - if (asset->staticModelList) - { - - AssertSize(Game::cStaticModel_s, 76); - SaveLogEnter("cStaticModel_t"); - - // xmodel is already stored - buffer->align(Utils::Stream::ALIGN_4); - Game::cStaticModel_s* destStaticModelList = buffer->dest(); - buffer->saveArray(asset->staticModelList, asset->numStaticModels); - - for (unsigned int i = 0; i < asset->numStaticModels; ++i) - { - if (asset->staticModelList[i].xmodel) - { - destStaticModelList[i].xmodel = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_XMODEL, asset->staticModelList[i].xmodel).model; - } - } - - Utils::Stream::ClearPointer(&dest->staticModelList); - SaveLogExit(); - } - - if (asset->materials) - { - AssertSize(Game::ClipMaterial, 12); - SaveLogEnter("ClipMaterial"); - - buffer->align(Utils::Stream::ALIGN_4); - Game::ClipMaterial* mats = buffer->dest(); - buffer->saveArray(asset->materials, asset->numMaterials); - - for (unsigned int i = 0; i < asset->numMaterials; ++i) - { - buffer->saveString(asset->materials[i].name); - Utils::Stream::ClearPointer(&mats[i].name); - } - - Utils::Stream::ClearPointer(&dest->materials); - SaveLogExit(); - } - - if (asset->brushsides) - { - AssertSize(Game::cbrushside_t, 8); - SaveLogEnter("cbrushside_t"); - - buffer->align(Utils::Stream::ALIGN_4); - Game::cbrushside_t* sides = buffer->dest(); - // we need the pointer to each of these to be stored so we can't write them all at once - for (unsigned int i = 0; i < asset->numBrushSides; ++i) - { - builder->storePointer(&asset->brushsides[i]); // for reference in cBrush - buffer->save(&asset->brushsides[i]); - } - - for (unsigned int i = 0; i < asset->numBrushSides; ++i) - { - if (sides[i].plane) - { - AssertSize(Game::cplane_s, 20); - - if (builder->hasPointer(sides[i].plane)) - { - sides[i].plane = builder->getPointer(sides[i].plane); - } - else - { - buffer->align(Utils::Stream::ALIGN_4); - builder->storePointer(sides[i].plane); - - buffer->save(sides[i].plane); - Utils::Stream::ClearPointer(&sides[i].plane); - } - } - } - - Utils::Stream::ClearPointer(&dest->brushsides); - SaveLogExit(); - } - - if (asset->brushEdges) - { - SaveLogEnter("cBrushEdge"); - - // no align for char - for (unsigned int i = 0; i < asset->numBrushEdges; ++i) - { - builder->storePointer(&asset->brushEdges[i]); // for reference in cBrush - buffer->save(&asset->brushEdges[i]); - } - Utils::Stream::ClearPointer(&dest->brushEdges); - - SaveLogExit(); - } - - if (asset->nodes) - { - AssertSize(Game::cNode_t, 8); - SaveLogEnter("cNode_t"); - - buffer->align(Utils::Stream::ALIGN_4); - Game::cNode_t* nodes = buffer->dest(); - buffer->saveArray(asset->nodes, asset->numNodes); - - for (unsigned int i = 0; i < asset->numNodes; ++i) - { - if (nodes[i].plane) - { - if (builder->hasPointer(nodes[i].plane)) - { - nodes[i].plane = builder->getPointer(nodes[i].plane); - } - else - { - buffer->align(Utils::Stream::ALIGN_4); - builder->storePointer(nodes[i].plane); - - buffer->save(nodes[i].plane); - Utils::Stream::ClearPointer(&nodes[i].plane); - } - } - else - { - AssertUnreachable; - Components::Logger::Error(Game::ERR_FATAL, "node {} of clipmap {} has no plane!", i, asset->name); - } - } - - Utils::Stream::ClearPointer(&dest->nodes); - SaveLogExit(); - } - - if (asset->leafs) - { - AssertSize(Game::cLeaf_t, 40); - SaveLogEnter("cLeaf_t"); - - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->leafs, asset->numLeafs); - Utils::Stream::ClearPointer(&dest->leafs); - SaveLogExit(); - } - - if (asset->leafbrushes) - { - SaveLogEnter("cLeafBrush_t"); - - buffer->align(Utils::Stream::ALIGN_2); - - for (size_t i = 0; i < asset->numLeafBrushes; i++) - { - builder->storePointer(&asset->leafbrushes[i]); - buffer->saveObject(asset->leafbrushes[i]); - } - - Utils::Stream::ClearPointer(&dest->leafbrushes); - - SaveLogExit(); - } - - if (asset->leafbrushNodes) - { - AssertSize(Game::cLeafBrushNode_s, 20); - SaveLogEnter("cLeafBrushNode_t"); - - buffer->align(Utils::Stream::ALIGN_4); - Game::cLeafBrushNode_s* node = buffer->dest(); - buffer->saveArray(asset->leafbrushNodes, asset->leafbrushNodesCount); - - for (unsigned int i = 0; i < asset->leafbrushNodesCount; ++i) - { - if (node[i].leafBrushCount > 0) - { - if (node[i].data.leaf.brushes) - { - if (builder->hasPointer(node[i].data.leaf.brushes)) - { - node[i].data.leaf.brushes = builder->getPointer(node[i].data.leaf.brushes); - } - else - { - buffer->align(Utils::Stream::ALIGN_2); - - for (short j = 0; j < node[i].leafBrushCount; ++j) - { - builder->storePointer(&node[i].data.leaf.brushes[j]); - buffer->save(&node[i].data.leaf.brushes[j]); - } - - Utils::Stream::ClearPointer(&node[i].data.leaf.brushes); - } - } - } - } - - Utils::Stream::ClearPointer(&dest->leafbrushNodes); - SaveLogExit(); - } - - if (asset->leafsurfaces) - { - SaveLogEnter("cLeafSurface_t"); - - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->leafsurfaces, asset->numLeafSurfaces); - Utils::Stream::ClearPointer(&dest->leafsurfaces); - - SaveLogExit(); - } - - if (asset->verts) - { - AssertSize(Game::vec3_t, 12); - - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->verts, asset->vertCount); - Utils::Stream::ClearPointer(&dest->verts); - } - - if (asset->triIndices) - { - buffer->align(Utils::Stream::ALIGN_2); - buffer->save(asset->triIndices, 6, asset->triCount); - Utils::Stream::ClearPointer(&dest->triIndices); - } - - if (asset->triEdgeIsWalkable) - { - // no align for char - buffer->save(asset->triEdgeIsWalkable, 1, 4 * ((3 * asset->triCount + 31) >> 5)); - Utils::Stream::ClearPointer(&dest->triEdgeIsWalkable); - } - - if (asset->borders) - { - AssertSize(Game::CollisionBorder, 28); - SaveLogEnter("CollisionBorder"); - - buffer->align(Utils::Stream::ALIGN_4); - - for (size_t i = 0; i < asset->borderCount; ++i) - { - builder->storePointer(&asset->borders[i]); - buffer->save(&asset->borders[i]); - } - - Utils::Stream::ClearPointer(&dest->borders); - SaveLogExit(); - } - - if (asset->partitions) - { - AssertSize(Game::CollisionPartition, 12); - SaveLogEnter("CollisionPartition"); - - buffer->align(Utils::Stream::ALIGN_4); - Game::CollisionPartition* destPartitions = buffer->dest(); - buffer->saveArray(asset->partitions, asset->partitionCount); - - for (int i = 0; i < asset->partitionCount; ++i) - { - Game::CollisionPartition* destPartition = &destPartitions[i]; - Game::CollisionPartition* partition = &asset->partitions[i]; - - if (partition->borders) - { - if (builder->hasPointer(partition->borders)) - { - destPartition->borders = builder->getPointer(partition->borders); - } - else - { - buffer->align(Utils::Stream::ALIGN_4); - builder->storePointer(partition->borders); - buffer->save(partition->borders); - Utils::Stream::ClearPointer(&destPartition->borders); - } - } - } - - Utils::Stream::ClearPointer(&dest->partitions); - SaveLogExit(); - } - - if (asset->aabbTrees) - { - AssertSize(Game::CollisionAabbTree, 32); - SaveLogEnter("CollisionAabbTree"); - - buffer->align(Utils::Stream::ALIGN_16); - buffer->saveArray(asset->aabbTrees, asset->aabbTreeCount); - Utils::Stream::ClearPointer(&dest->aabbTrees); - - SaveLogExit(); - } - - if (asset->cmodels) - { - AssertSize(Game::cmodel_t, 68); - SaveLogEnter("cmodel_t"); - - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->cmodels, asset->numSubModels); - Utils::Stream::ClearPointer(&dest->cmodels); - - SaveLogExit(); - } - - if (asset->brushes) - { - AssertSize(Game::cbrush_t, 36); - SaveLogEnter("cbrush_t"); - - buffer->align(Utils::Stream::ALIGN_128); - Game::cbrush_t* destBrushes = buffer->dest(); - buffer->saveArray(asset->brushes, asset->numBrushes); - - for (short i = 0; i < asset->numBrushes; ++i) - { - Game::cbrush_t* destBrush = &destBrushes[i]; - Game::cbrush_t* brush = &asset->brushes[i]; - - if (brush->sides) - { - if (builder->hasPointer(brush->sides)) - { - destBrush->sides = builder->getPointer(brush->sides); - } - else - { - AssertSize(Game::cbrushside_t, 8); - - MessageBoxA(nullptr, "BrushSide shouldn't be written in cBrush!", "WARNING", MB_ICONEXCLAMATION); - - buffer->align(Utils::Stream::ALIGN_4); - builder->storePointer(brush->sides); - - Game::cbrushside_t* side = buffer->dest(); - buffer->save(brush->sides); - - if (brush->sides->plane) - { - if (builder->hasPointer(brush->sides->plane)) - { - side->plane = builder->getPointer(brush->sides->plane); - } - else - { - buffer->align(Utils::Stream::ALIGN_4); - builder->storePointer(brush->sides->plane); - buffer->save(brush->sides->plane); - Utils::Stream::ClearPointer(&side->plane); - } - } - - Utils::Stream::ClearPointer(&destBrush->sides); - } - } - - if (brush->baseAdjacentSide) - { - if (builder->hasPointer(brush->baseAdjacentSide)) - { - destBrush->baseAdjacentSide = builder->getPointer(brush->baseAdjacentSide); - } - else - { - builder->storePointer(brush->baseAdjacentSide); - buffer->save(brush->baseAdjacentSide); - Utils::Stream::ClearPointer(&destBrush->baseAdjacentSide); - } - } - } - - Utils::Stream::ClearPointer(&dest->brushes); - SaveLogExit(); - } - - if (asset->brushBounds) - { - AssertSize(Game::Bounds, 24); - SaveLogEnter("Bounds"); - - buffer->align(Utils::Stream::ALIGN_128); - buffer->saveArray(asset->brushBounds, asset->numBrushes); - Utils::Stream::ClearPointer(&dest->brushBounds); - - SaveLogExit(); - } - - if (asset->brushContents) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->brushContents, asset->numBrushes); - Utils::Stream::ClearPointer(&dest->brushContents); - } - - if (asset->smodelNodes) - { - AssertSize(Game::SModelAabbNode, 28); - SaveLogEnter("SModelAabbNode"); - - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->smodelNodes, asset->smodelNodeCount); - Utils::Stream::ClearPointer(&dest->smodelNodes); - - SaveLogExit(); - } - - if (asset->mapEnts) - { - dest->mapEnts = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_MAP_ENTS, asset->mapEnts).mapEnts; - } - - for (int i = 0; i < 2; ++i) - { - if (asset->dynEntDefList[i]) - { - AssertSize(Game::DynEntityDef, 92); - - buffer->align(Utils::Stream::ALIGN_4); - Game::DynEntityDef* dynEntDest = buffer->dest(); - buffer->saveArray(asset->dynEntDefList[i], asset->dynEntCount[i]); - - Game::DynEntityDef* dynEnt = asset->dynEntDefList[i]; - for (int j = 0; j < asset->dynEntCount[i]; ++j) - { - if (dynEnt[j].xModel) - { - dynEntDest[j].xModel = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_XMODEL, dynEnt[j].xModel).model; - } - - if (dynEnt[j].destroyFx) - { - dynEntDest[j].destroyFx = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_FX, dynEnt[j].destroyFx).fx; - } - - if (dynEnt[j].physPreset) - { - dynEntDest[j].physPreset = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_PHYSPRESET, dynEnt[j].physPreset).physPreset; - } - } - - Utils::Stream::ClearPointer(&dest->dynEntDefList[i]); - } - } - - buffer->pushBlock(Game::XFILE_BLOCK_RUNTIME); - - for (int i = 0; i < 2; ++i) - { - if (asset->dynEntPoseList[i]) - { - AssertSize(Game::DynEntityPose, 32); - - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->dynEntPoseList[i], asset->dynEntCount[i]); - Utils::Stream::ClearPointer(&dest->dynEntPoseList[i]); - - } - } - - for (int i = 0; i < 2; ++i) - { - if (asset->dynEntClientList[i]) - { - AssertSize(Game::DynEntityClient, 12); - - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->dynEntClientList[i], asset->dynEntCount[i]); - Utils::Stream::ClearPointer(&dest->dynEntClientList[i]); - } - } - - for (int i = 0; i < 2; ++i) - { - if (asset->dynEntCollList[i]) - { - AssertSize(Game::DynEntityColl, 20); - - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->dynEntCollList[i], asset->dynEntCount[i]); - Utils::Stream::ClearPointer(&dest->dynEntCollList[i]); - } - } - - buffer->popBlock(); - buffer->popBlock(); - - SaveLogExit(); - } - - void IclipMap_t::mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - Game::clipMap_t* asset = header.clipMap; - for (unsigned int i = 0; i < asset->numStaticModels; ++i) - { - Game::XModel* m = asset->staticModelList[i].xmodel; - if (m) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_XMODEL, m); - } - } - - for (int j = 0; j < 2; ++j) - { - Game::DynEntityDef* def = asset->dynEntDefList[j]; - - for (int i = 0; i < asset->dynEntCount[j]; ++i) - { - if (def[i].xModel) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_XMODEL, def[i].xModel); - } - - if (def[i].destroyFx) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_FX, def[i].destroyFx); - } - - if (def[i].physPreset) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_PHYSPRESET, def[i].physPreset); - } - } - } - - builder->loadAsset(Game::XAssetType::ASSET_TYPE_MAP_ENTS, asset->mapEnts); - } - - void IclipMap_t::load(Game::XAssetHeader* header, const std::string& _name, Components::ZoneBuilder::Zone* builder) - { - header->clipMap = builder->getIW4OfApi()->read(Game::XAssetType::ASSET_TYPE_CLIPMAP_MP, _name); - assert(header->data); - } -} diff --git a/src/Components/Modules/AssetInterfaces/IclipMap_t.hpp b/src/Components/Modules/AssetInterfaces/IclipMap_t.hpp deleted file mode 100644 index 2edb3089..00000000 --- a/src/Components/Modules/AssetInterfaces/IclipMap_t.hpp +++ /dev/null @@ -1,94 +0,0 @@ -#pragma once - -namespace Assets -{ - class IclipMap_t : public Components::AssetHandler::IAsset - { - public: - Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_CLIPMAP_MP; } - - void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override; - static void dump(Game::XAssetHeader /*header*/); - - private: - class SModelQuadtree - { - public: - SModelQuadtree() - { - } - - SModelQuadtree(Game::cStaticModel_s* modelList, int numModels) - { - numValues = 0; - - for (int i = 0; i < numModels; ++i) - { - insert(&modelList[i]); - } - } - - void insert(Game::cStaticModel_s* item) - { - if (numValues < 4) // add here - { - values[numValues++] = item; - } - else // add to child - { - if (numValues == 4) // split - { - // create children objects - for (int i = 0; i < 4; ++i) - { - children[i] = new SModelQuadtree(); - } - - for (int i = 0; i < numValues; ++i) - { - if (item->origin[0] > x && values[i]->origin[1] > y) - children[0]->insert(values[i]); - if (item->origin[0] < x && values[i]->origin[1] > y) - children[1]->insert(values[i]); - if (item->origin[0] < x && values[i]->origin[1] < y) - children[2]->insert(values[i]); - if (item->origin[0] > x && values[i]->origin[1] < y) - children[3]->insert(values[i]); - - values[i] = nullptr; - } - - for (int i = 0; i < 4; ++i) - { - children[i]->halfX = halfX / 2; - children[i]->halfY = halfY / 2; - children[i]->halfZ = halfZ; - } - - // update origins here - - numValues++; - } - - if (item->origin[0] > x && item->origin[1] > y) - children[0]->insert(item); - if (item->origin[0] < x && item->origin[1] > y) - children[1]->insert(item); - if (item->origin[0] < x && item->origin[1] < y) - children[2]->insert(item); - if (item->origin[0] > x && item->origin[1] < y) - children[3]->insert(item); - } - } - - private: - SModelQuadtree* children[4]; - Game::cStaticModel_s* values[4]; - int numValues; - float x, y, z; - float halfX, halfY, halfZ; - }; - }; -} diff --git a/src/Components/Modules/AssetInterfaces/ImenuDef_t.cpp b/src/Components/Modules/AssetInterfaces/ImenuDef_t.cpp deleted file mode 100644 index 65a10757..00000000 --- a/src/Components/Modules/AssetInterfaces/ImenuDef_t.cpp +++ /dev/null @@ -1,700 +0,0 @@ -#include -#include "ImenuDef_t.hpp" - -namespace Assets -{ - - std::unordered_map ImenuDef_t::LoadedMenus; - - void ImenuDef_t::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* /*builder*/) - { - // load from disk - auto menus = Components::Menus::LoadMenu(std::format("ui_mp/{}.menu", name)); - - if (menus.empty()) return; - if (menus.size() > 1) Components::Logger::Print("Menu '{}' on disk has more than one menudef in it. Only saving the first one\n", name); - - header->menu = menus[0].second; - } - - - void ImenuDef_t::mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - auto* asset = header.menu; - - if (asset->window.background) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, asset->window.background); - } - - // mark items - for (int i = 0; i < asset->itemCount; ++i) - { - if (asset->items[i]->window.background) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, asset->items[i]->window.background); - } - - if (asset->items[i]->focusSound) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_SOUND, asset->items[i]->focusSound); - } - - if (asset->items[i]->type == 6 && asset->items[i]->typeData.listBox && - asset->items[i]->typeData.listBox->selectIcon) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, asset->items[i]->typeData.listBox->selectIcon); - } - } - } - - void ImenuDef_t::save_ExpressionSupportingData(Game::ExpressionSupportingData* asset, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::ExpressionSupportingData, 24); - Utils::Stream* buffer = builder->getBuffer(); - -#ifdef WRITE_LOGS - buffer->enterStruct("ExpressionSupportingData"); -#endif - - buffer->align(Utils::Stream::ALIGN_4); - - auto* dest = buffer->dest(); - buffer->save(asset); - - if (asset->uifunctions.functions) - { - buffer->align(Utils::Stream::ALIGN_4); - - auto** destStatement = buffer->dest(); - buffer->saveArray(asset->uifunctions.functions, asset->uifunctions.totalFunctions); - - for (int i = 0; i < asset->uifunctions.totalFunctions; ++i) - { - if (asset->uifunctions.functions[i]) - { - Utils::Stream::ClearPointer(&destStatement[i]); - - buffer->align(Utils::Stream::ALIGN_4); - this->save_Statement_s(asset->uifunctions.functions[i], builder); - } - } - - Utils::Stream::ClearPointer(&dest->uifunctions.functions); - } - - if (asset->staticDvarList.staticDvars) - { - buffer->align(Utils::Stream::ALIGN_4); - - auto** destStaticDvars = buffer->dest(); - buffer->saveArray(asset->staticDvarList.staticDvars, asset->staticDvarList.numStaticDvars); - - for (auto i = 0; i < asset->staticDvarList.numStaticDvars; ++i) - { - if (asset->staticDvarList.staticDvars[i]) - { - Utils::Stream::ClearPointer(&destStaticDvars[i]); - - buffer->align(Utils::Stream::ALIGN_4); - auto* destStaticDvar = buffer->dest(); - buffer->save(asset->staticDvarList.staticDvars[i]); - - if (asset->staticDvarList.staticDvars[i]->dvarName) - { - buffer->saveString(asset->staticDvarList.staticDvars[i]->dvarName); - Utils::Stream::ClearPointer(&destStaticDvar->dvarName); - } - } - } - - Utils::Stream::ClearPointer(&dest->staticDvarList.staticDvars); - } - - if (asset->uiStrings.strings) - { - buffer->align(Utils::Stream::ALIGN_4); - - const auto** destUIStrings = buffer->dest(); - buffer->saveArray(asset->uiStrings.strings, asset->uiStrings.totalStrings); - - for (int i = 0; i < asset->uiStrings.totalStrings; ++i) - { - if (asset->uiStrings.strings[i]) - { - buffer->saveString(asset->uiStrings.strings[i]); - Utils::Stream::ClearPointer(&destUIStrings[i]); - } - } - } -#ifdef WRITE_LOGS - buffer->leaveStruct(); -#endif - } - - void ImenuDef_t::save_Statement_s(Game::Statement_s* asset, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::Statement_s, 24); - AssertSize(Game::expressionEntry, 12); - Utils::Stream* buffer = builder->getBuffer(); - -#ifdef WRITE_LOGS - buffer->enterStruct("Statement_s"); -#endif - - // Write header data - auto* dest = buffer->dest(); - buffer->save(asset); - - // Write statement entries - if (asset->entries) - { -#ifdef WRITE_LOGS - buffer->enterStruct("statement entries"); -#endif - buffer->align(Utils::Stream::ALIGN_4); - - // Write entries - auto* destEntries = buffer->dest(); - buffer->save(asset->entries, sizeof(Game::expressionEntry), asset->numEntries); - - // Loop through entries - for (int i = 0; i < asset->numEntries; ++i) - { -#ifdef WRITE_LOGS - buffer->enterStruct("entry"); -#endif - if (asset->entries[i].type) - { - switch (asset->entries[i].data.operand.dataType) - { - // Those types do not require additional data - case 0: - case 1: - break; - - // Expression string - case 2: - if (asset->entries[i].data.operand.internals.stringVal.string) - { - buffer->saveString(asset->entries[i].data.operand.internals.stringVal.string); - Utils::Stream::ClearPointer(&destEntries[i].data.operand.internals.stringVal.string); - } - break; - - // Function - case 3: - if (asset->entries[i].data.operand.internals.function) - { - buffer->align(Utils::Stream::ALIGN_4); - this->save_Statement_s(asset->entries[i].data.operand.internals.function, builder); - Utils::Stream::ClearPointer(&destEntries[i].data.operand.internals.function); - } - break; - } - } -#ifdef WRITE_LOGS - buffer->leaveStruct(); -#endif - } -#ifdef WRITE_LOGS - buffer->leaveStruct(); -#endif - } - - if (asset->supportingData) - { - this->save_ExpressionSupportingData(asset->supportingData, builder); - Utils::Stream::ClearPointer(&dest->supportingData); - } -#ifdef WRITE_LOGS - buffer->leaveStruct(); -#endif - } - - void ImenuDef_t::save_MenuEventHandlerSet(Game::MenuEventHandlerSet* asset, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::MenuEventHandlerSet, 8); - Utils::Stream* buffer = builder->getBuffer(); - -#ifdef WRITE_LOGS - buffer->enterStruct("MenuEventHandlerSet"); -#endif - - // Write header data - auto* destset = buffer->dest(); - buffer->save(asset); - - // Event handlers - if (asset->eventHandlers) - { - buffer->align(Utils::Stream::ALIGN_4); - - // Write pointers to zone - buffer->save(asset->eventHandlers, sizeof(Game::MenuEventHandler*), asset->eventHandlerCount); - - // Loop through eventHandlers - for (auto i = 0; i < asset->eventHandlerCount; ++i) - { - if (asset->eventHandlers[i]) - { - buffer->align(Utils::Stream::ALIGN_4); -#ifdef WRITE_LOGS - buffer->enterStruct("MenuEventHandler"); -#endif - - // Write menu event handler - auto* dest = buffer->dest(); - buffer->save(asset->eventHandlers[i]); - - // Write additional data based on type - switch (asset->eventHandlers[i]->eventType) - { - // unconditional scripts - case 0: - if (asset->eventHandlers[i]->eventData.unconditionalScript) - { - buffer->saveString(asset->eventHandlers[i]->eventData.unconditionalScript); - Utils::Stream::ClearPointer(&dest->eventData.unconditionalScript); - } - break; - - // ConditionalScript - case 1: - if (asset->eventHandlers[i]->eventData.conditionalScript) - { - buffer->align(Utils::Stream::ALIGN_4); - auto* destConditionalScript = buffer->dest(); - buffer->save(asset->eventHandlers[i]->eventData.conditionalScript); - - // eventExpression - if (asset->eventHandlers[i]->eventData.conditionalScript->eventExpression) - { - buffer->align(Utils::Stream::ALIGN_4); - this->save_Statement_s(asset->eventHandlers[i]->eventData.conditionalScript->eventExpression, builder); - Utils::Stream::ClearPointer(&destConditionalScript->eventExpression); - } - - // eventHandlerSet - if (asset->eventHandlers[i]->eventData.conditionalScript->eventHandlerSet) - { - buffer->align(Utils::Stream::ALIGN_4); - this->save_MenuEventHandlerSet(asset->eventHandlers[i]->eventData.conditionalScript->eventHandlerSet, builder); - Utils::Stream::ClearPointer(&destConditionalScript->eventHandlerSet); - } - - Utils::Stream::ClearPointer(&dest->eventData.conditionalScript); - } - break; - - // elseScript - case 2: - if (asset->eventHandlers[i]->eventData.elseScript) - { - buffer->align(Utils::Stream::ALIGN_4); - this->save_MenuEventHandlerSet(asset->eventHandlers[i]->eventData.elseScript, builder); - Utils::Stream::ClearPointer(&dest->eventData.elseScript); - } - break; - - // localVarData expressions - case 3: - case 4: - case 5: - case 6: - if (asset->eventHandlers[i]->eventData.setLocalVarData) - { - buffer->align(Utils::Stream::ALIGN_4); - - // header data - auto* destLocalVarData = buffer->dest(); - buffer->save(asset->eventHandlers[i]->eventData.setLocalVarData); - - // localVarName - if (asset->eventHandlers[i]->eventData.setLocalVarData->localVarName) - { - buffer->saveString(asset->eventHandlers[i]->eventData.setLocalVarData->localVarName); - Utils::Stream::ClearPointer(&destLocalVarData->localVarName); - } - - // statement - if (asset->eventHandlers[i]->eventData.setLocalVarData->expression) - { - buffer->align(Utils::Stream::ALIGN_4); - this->save_Statement_s(asset->eventHandlers[i]->eventData.setLocalVarData->expression, builder); - Utils::Stream::ClearPointer(&destLocalVarData->expression); - } - - Utils::Stream::ClearPointer(&dest->eventData.setLocalVarData); - } - break; - } -#ifdef WRITE_LOGS - buffer->leaveStruct(); -#endif - } - } - - Utils::Stream::ClearPointer(&destset->eventHandlers); - } -#ifdef WRITE_LOGS - buffer->leaveStruct(); -#endif - } - - void ImenuDef_t::save_ItemKeyHandler(Game::ItemKeyHandler* asset, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::ItemKeyHandler, 12); - Utils::Stream* buffer = builder->getBuffer(); - -#ifdef WRITE_LOGS - buffer->enterStruct("ItemKeyHandler"); -#endif - - while (asset) - { - // Write header - auto* dest = buffer->dest(); - buffer->save(asset); - - // MenuEventHandlerSet - if (asset->action) - { - buffer->align(Utils::Stream::ALIGN_4); - this->save_MenuEventHandlerSet(asset->action, builder); - Utils::Stream::ClearPointer(&dest->action); - } - - if (asset->next) - { - // align every index, besides the first one? - buffer->align(Utils::Stream::ALIGN_4); - } - - // Next key handler - asset = asset->next; - } -#ifdef WRITE_LOGS - buffer->leaveStruct(); -#endif - } - -#define EVENTHANDLERSET(__index) \ - if (asset->__index) \ - { \ - buffer->align(Utils::Stream::ALIGN_4); \ - this->save_MenuEventHandlerSet(asset->__index, builder); \ - Utils::Stream::ClearPointer(&dest->__index); \ - } - -#define STATEMENT(__index) \ - if (asset->__index) \ - { \ - buffer->align(Utils::Stream::ALIGN_4); \ - this->save_Statement_s(asset->__index, builder); \ - Utils::Stream::ClearPointer(&dest->__index); \ - } - - void ImenuDef_t::save_itemDefData_t(Game::itemDefData_t* asset, int type, Game::itemDef_s* dest, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::newsTickerDef_s, 28); - AssertSize(Game::listBoxDef_s, 324); - AssertSize(Game::editFieldDef_s, 32); - AssertSize(Game::multiDef_s, 392); - - Utils::Stream* buffer = builder->getBuffer(); - -#ifdef WRITE_LOGS - buffer->enterStruct("itemDefData_t"); -#endif - - // feeder - if (type == 6) - { - buffer->align(Utils::Stream::ALIGN_4); - auto* destlb = buffer->dest(); - buffer->save(asset->listBox); - - if (asset->listBox->onDoubleClick) - { - buffer->align(Utils::Stream::ALIGN_4); - this->save_MenuEventHandlerSet(asset->listBox->onDoubleClick, builder); - } - - if (asset->listBox->selectIcon) - { - destlb->selectIcon = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, asset->listBox->selectIcon).material; - } - } - // HexRays spaghetti - else if (type != 4 && type != 9 && type != 16 && type != 18 && type != 11 && type != 14 && type != 10 && type != 17 && type != 22 && type != 23 && type != 0) - { - switch (type) - { - // enum dvar - case 13: - buffer->saveString(asset->enumDvarName); - break; - // newsticker - case 20: - buffer->align(Utils::Stream::ALIGN_4); - buffer->save(asset->ticker); - break; - // textScrollDef - case 21: - buffer->align(Utils::Stream::ALIGN_4); - buffer->save(asset->scroll); - break; - case 12: - buffer->align(Utils::Stream::ALIGN_4); - auto* destdef = buffer->dest(); - buffer->save(asset->multi); - - for (int i = 0; i < 32; ++i) - { - if (asset->multi->dvarList[i]) - { - buffer->saveString(asset->multi->dvarList[i]); - Utils::Stream::ClearPointer(&destdef->dvarList[i]); - } - } - - for (int i = 0; i < 32; ++i) - { - if (asset->multi->dvarStr[i]) - { - buffer->saveString(asset->multi->dvarStr[i]); - Utils::Stream::ClearPointer(&destdef->dvarStr[i]); - } - } - - break; - } - } - // editFieldDef - else - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->save(asset->editField); - } - - Utils::Stream::ClearPointer(&dest->typeData.data); - -#ifdef WRITE_LOGS - buffer->leaveStruct(); -#endif - } - - void ImenuDef_t::save_itemDef_s(Game::itemDef_s *asset, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::itemDef_s, 0x17C); - - Utils::Stream* buffer = builder->getBuffer(); - auto* dest = buffer->dest(); - -#ifdef WRITE_LOGS - if (asset->window.name) - buffer->enterStruct(Utils::String::VA("itemDef_s: name = '%s'", asset->window.name)); - else if (asset->window.background) - buffer->enterStruct(Utils::String::VA("itemDef_s: bg = '%s'", asset->window.background->info.name)); - else - buffer->enterStruct("itemDef_s"); -#endif - - buffer->save(asset); - - // window data - save_windowDef_t(&asset->window, dest, builder); - - // text - if (asset->text) - { - buffer->saveString(asset->text); - Utils::Stream::ClearPointer(&dest->text); - } - - // MenuEventHandlerSets - EVENTHANDLERSET(mouseEnterText); - EVENTHANDLERSET(mouseExitText); - EVENTHANDLERSET(mouseEnter); - EVENTHANDLERSET(mouseExit); - EVENTHANDLERSET(action); - EVENTHANDLERSET(accept); - EVENTHANDLERSET(onFocus); - EVENTHANDLERSET(leaveFocus); - - // Dvar strings - if (asset->dvar) - { - buffer->saveString(asset->dvar); - Utils::Stream::ClearPointer(&dest->dvar); - } - - if (asset->dvarTest) - { - buffer->saveString(asset->dvarTest); - Utils::Stream::ClearPointer(&dest->dvarTest); - } - - // ItemKeyHandler - if (asset->onKey) - { - buffer->align(Utils::Stream::ALIGN_4); - this->save_ItemKeyHandler(asset->onKey, builder); - Utils::Stream::ClearPointer(&dest->onKey); - } - - // Dvar strings - if (asset->enableDvar) - { - buffer->saveString(asset->enableDvar); - Utils::Stream::ClearPointer(&dest->enableDvar); - } - - if (asset->localVar) - { - buffer->saveString(asset->localVar); - Utils::Stream::ClearPointer(&dest->localVar); - } - - // Focus sound - if (asset->focusSound) - { - dest->focusSound = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_SOUND, asset->focusSound).sound; - } - - // itemDefData - if (asset->typeData.data) - { - this->save_itemDefData_t(&asset->typeData, asset->type, dest, builder); - } - - // floatExpressions - if (asset->floatExpressions) - { - buffer->align(Utils::Stream::ALIGN_4); -#ifdef WRITE_LOGS - buffer->enterStruct("floatExpressions"); -#endif - - auto* destExp = buffer->dest(); - buffer->saveArray(asset->floatExpressions, asset->floatExpressionCount); - - for (int i = 0; i < asset->floatExpressionCount; ++i) - { - buffer->align(Utils::Stream::ALIGN_4); - this->save_Statement_s(asset->floatExpressions[i].expression, builder); - Utils::Stream::ClearPointer(&destExp[i].expression); - } - - Utils::Stream::ClearPointer(&dest->floatExpressions); - -#ifdef WRITE_LOGS - buffer->leaveStruct(); -#endif - } - - // Statements - STATEMENT(visibleExp); - STATEMENT(disabledExp); - STATEMENT(textExp); - STATEMENT(materialExp); - -#ifdef WRITE_LOGS - buffer->leaveStruct(); -#endif - } - - void ImenuDef_t::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::menuDef_t, 400); - AssertSize(Game::windowDef_t, 0xA4); - -#ifdef WRITE_LOGS - buffer->enterStruct("ImenuDef_t"); -#endif - - Utils::Stream* buffer = builder->getBuffer(); - auto* asset = header.menu; - auto* dest = buffer->dest(); - buffer->save(asset); - - buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); - - // ExpressionSupportingData - if (asset->expressionData) - { - // dest->expressionData = nullptr; - this->save_ExpressionSupportingData(asset->expressionData, builder); - Utils::Stream::ClearPointer(&dest->expressionData); - } - - // Window data - save_windowDef_t(&asset->window, dest, builder); - - // Font - if (asset->font) - { - buffer->saveString(asset->font); - Utils::Stream::ClearPointer(&dest->font); - } - - // MenuEventHandlerSets - EVENTHANDLERSET(onOpen); - EVENTHANDLERSET(onCloseRequest); - EVENTHANDLERSET(onClose); - EVENTHANDLERSET(onESC); - - // ItemKeyHandler - if (asset->onKey) - { - buffer->align(Utils::Stream::ALIGN_4); - this->save_ItemKeyHandler(asset->onKey, builder); - Utils::Stream::ClearPointer(&dest->onKey); - } - - // Statement - STATEMENT(visibleExp); - - // Strings - if (asset->allowedBinding) - { - buffer->saveString(asset->allowedBinding); - Utils::Stream::ClearPointer(&dest->allowedBinding); - } - if (asset->soundName) - { - buffer->saveString(asset->soundName); - Utils::Stream::ClearPointer(&dest->soundName); - } - - // Statements - STATEMENT(rectXExp); - STATEMENT(rectYExp); - STATEMENT(rectHExp); - STATEMENT(rectWExp); - STATEMENT(openSoundExp); - STATEMENT(closeSoundExp); - - // Items - if (asset->items) - { - buffer->align(Utils::Stream::ALIGN_4); - buffer->saveArray(asset->items, asset->itemCount); - - for (int i = 0; i < asset->itemCount; ++i) - { - if (asset->items[i]) - { - buffer->align(Utils::Stream::ALIGN_4); - this->save_itemDef_s(asset->items[i], builder); - } - } - } -#ifdef WRITE_LOGS - buffer->leaveStruct(); -#endif - - buffer->popBlock(); - } -} diff --git a/src/Components/Modules/AssetInterfaces/ImenuDef_t.hpp b/src/Components/Modules/AssetInterfaces/ImenuDef_t.hpp deleted file mode 100644 index 33daafba..00000000 --- a/src/Components/Modules/AssetInterfaces/ImenuDef_t.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once - -namespace Assets -{ - class ImenuDef_t : public Components::AssetHandler::IAsset - { - public: - Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_MENU; } - - void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override; - - static std::unordered_map LoadedMenus; - - private: - template void save_windowDef_t(Game::windowDef_t* asset, T* dest, Components::ZoneBuilder::Zone* builder) - { - Utils::Stream* buffer = builder->getBuffer(); - - if (asset->name) - { - buffer->saveString(asset->name); - Utils::Stream::ClearPointer(&dest->window.name); - } - - if (asset->group) - { - buffer->saveString(asset->group); - Utils::Stream::ClearPointer(&dest->window.group); - } - - if (asset->background) - { - dest->window.background = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, asset->background).material; - } - } - void save_ExpressionSupportingData(Game::ExpressionSupportingData* asset, Components::ZoneBuilder::Zone* builder); - void save_Statement_s(Game::Statement_s* asset, Components::ZoneBuilder::Zone* builder); - void save_MenuEventHandlerSet(Game::MenuEventHandlerSet* asset, Components::ZoneBuilder::Zone* builder); - void save_ItemKeyHandler(Game::ItemKeyHandler* asset, Components::ZoneBuilder::Zone* builder); - void save_itemDefData_t(Game::itemDefData_t* asset, int type, Game::itemDef_s* dest, Components::ZoneBuilder::Zone* builder); - void save_itemDef_s(Game::itemDef_s *asset, Components::ZoneBuilder::Zone* builder); - }; -} diff --git a/src/Components/Modules/AssetInterfaces/Isnd_alias_list_t.cpp b/src/Components/Modules/AssetInterfaces/Isnd_alias_list_t.cpp deleted file mode 100644 index 42d917d4..00000000 --- a/src/Components/Modules/AssetInterfaces/Isnd_alias_list_t.cpp +++ /dev/null @@ -1,226 +0,0 @@ -#include -#include "Isnd_alias_list_t.hpp" - -namespace Assets -{ - void Isnd_alias_list_t::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) - { - header->sound = builder->getIW4OfApi()->read(Game::XAssetType::ASSET_TYPE_SOUND, name); - - if (!header->sound) - { - header->sound = Components::AssetHandler::FindOriginalAsset(Game::XAssetType::ASSET_TYPE_SOUND_CURVE, name.data()).sound; - } - } - - void Isnd_alias_list_t::mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - Game::snd_alias_list_t* asset = header.sound; - - for (unsigned int i = 0; i < asset->count; ++i) - { - Game::snd_alias_t* alias = &asset->head[i]; - - if (alias->soundFile && alias->soundFile->type == Game::snd_alias_type_t::SAT_LOADED) - { - builder->loadAsset(Game::XAssetType::ASSET_TYPE_LOADED_SOUND, alias->soundFile->u.loadSnd); - } - - if (alias->volumeFalloffCurve) - { - if (!builder->loadAsset(Game::XAssetType::ASSET_TYPE_SOUND_CURVE, alias->volumeFalloffCurve)) - { - // (Should never happen, but just in case) - alias->volumeFalloffCurve->filename = "$default"; - builder->loadAsset(Game::XAssetType::ASSET_TYPE_SOUND_CURVE, alias->volumeFalloffCurve); - } - } - } - } - - void Isnd_alias_list_t::dump(Game::XAssetHeader header) - { - Components::ZoneBuilder::GetExporter()->write(Game::XAssetType::ASSET_TYPE_SOUND, header.data); - } - - Isnd_alias_list_t::Isnd_alias_list_t() - { - Components::Command::Add("dumpSound", [this](const Components::Command::Params* param) - { - const auto header = Game::DB_FindXAssetHeader(Game::ASSET_TYPE_SOUND, param->get(1)); - if (header.data) - { - Components::ZoneBuilder::RefreshExporterWorkDirectory(); - this->dump(header); - } - }); - } - - void Isnd_alias_list_t::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) - { - AssertSize(Game::snd_alias_list_t, 12); - - auto* buffer = builder->getBuffer(); - auto* asset = header.sound; - auto* dest = buffer->dest(); - buffer->save(asset); - - buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); - - if (asset->aliasName) - { - if (builder->hasPointer(asset->aliasName)) - { - dest->aliasName = builder->getPointer(asset->aliasName); - } - else - { - builder->storePointer(asset->aliasName); - buffer->saveString(asset->aliasName); - Utils::Stream::ClearPointer(&dest->aliasName); - } - } - - if (asset->head) - { - if (builder->hasPointer(asset->head)) - { - dest->head = builder->getPointer(asset->head); - } - else - { - AssertSize(Game::snd_alias_t, 100); - - buffer->align(Utils::Stream::ALIGN_4); - builder->storePointer(asset->head); - - auto* destHead = buffer->dest(); - buffer->saveArray(asset->head, asset->count); - - for (unsigned int i = 0; i < asset->count; ++i) - { - Game::snd_alias_t* destAlias = &destHead[i]; - Game::snd_alias_t* alias = &asset->head[i]; - - if (alias->aliasName) - { - if (builder->hasPointer(alias->aliasName)) - { - destAlias->aliasName = builder->getPointer(alias->aliasName); - } - else - { - builder->storePointer(alias->aliasName); - buffer->saveString(alias->aliasName); - Utils::Stream::ClearPointer(&destAlias->aliasName); - } - } - - if (alias->subtitle) - { - buffer->saveString(alias->subtitle); - Utils::Stream::ClearPointer(&destAlias->subtitle); - } - - if (alias->secondaryAliasName) - { - buffer->saveString(alias->secondaryAliasName); - Utils::Stream::ClearPointer(&destAlias->secondaryAliasName); - } - - if (alias->chainAliasName) - { - buffer->saveString(alias->chainAliasName); - Utils::Stream::ClearPointer(&destAlias->chainAliasName); - } - - if (alias->mixerGroup) - { - buffer->saveString(alias->mixerGroup); - Utils::Stream::ClearPointer(&destAlias->mixerGroup); - } - - if (alias->soundFile) - { - if (builder->hasPointer(alias->soundFile)) - { - destAlias->soundFile = builder->getPointer(alias->soundFile); - } - else - { - AssertSize(Game::snd_alias_t, 100); - - buffer->align(Utils::Stream::ALIGN_4); - builder->storePointer(alias->soundFile); - - auto* destSoundFile = buffer->dest(); - buffer->save(alias->soundFile); - - // Save_SoundFileRef - { - if (alias->soundFile->type == Game::snd_alias_type_t::SAT_LOADED) - { - destSoundFile->u.loadSnd = builder->saveSubAsset(Game::ASSET_TYPE_LOADED_SOUND, alias->soundFile->u.loadSnd).loadSnd; - } - else - { - // Save_StreamedSound - { - if (alias->soundFile->u.streamSnd.filename.info.raw.dir) - { - buffer->saveString(alias->soundFile->u.streamSnd.filename.info.raw.dir); - Utils::Stream::ClearPointer(&destSoundFile->u.streamSnd.filename.info.raw.dir); - } - - if (alias->soundFile->u.streamSnd.filename.info.raw.name) - { - buffer->saveString(alias->soundFile->u.streamSnd.filename.info.raw.name); - Utils::Stream::ClearPointer(&destSoundFile->u.streamSnd.filename.info.raw.name); - } - } - } - } - - Utils::Stream::ClearPointer(&destAlias->soundFile); - } - } - - if (alias->volumeFalloffCurve) - { - destAlias->volumeFalloffCurve = builder->saveSubAsset(Game::ASSET_TYPE_SOUND_CURVE, alias->volumeFalloffCurve).sndCurve; - } - - if (alias->speakerMap) - { - if (builder->hasPointer(alias->speakerMap)) - { - destAlias->speakerMap = builder->getPointer(alias->speakerMap); - } - else - { - AssertSize(Game::SpeakerMap, 408); - - buffer->align(Utils::Stream::ALIGN_4); - builder->storePointer(alias->speakerMap); - - auto* destSoundFile = buffer->dest(); - buffer->save(alias->speakerMap); - - if (alias->speakerMap->name) - { - buffer->saveString(alias->speakerMap->name); - Utils::Stream::ClearPointer(&destSoundFile->name); - } - - Utils::Stream::ClearPointer(&destAlias->speakerMap); - } - } - } - - Utils::Stream::ClearPointer(&dest->head); - } - } - - buffer->popBlock(); - } -} diff --git a/src/Components/Modules/AssetInterfaces/Isnd_alias_list_t.hpp b/src/Components/Modules/AssetInterfaces/Isnd_alias_list_t.hpp deleted file mode 100644 index 8a38cfa1..00000000 --- a/src/Components/Modules/AssetInterfaces/Isnd_alias_list_t.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -namespace Assets -{ - class Isnd_alias_list_t : public Components::AssetHandler::IAsset - { - public: - Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_SOUND; } - - void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override; - void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; - void dump(Game::XAssetHeader header) override; - - Isnd_alias_list_t(); - }; -} diff --git a/src/Components/Modules/Auth.cpp b/src/Components/Modules/Auth.cpp index ef93603f..8b4ee641 100644 --- a/src/Components/Modules/Auth.cpp +++ b/src/Components/Modules/Auth.cpp @@ -329,7 +329,7 @@ namespace Components void Auth::StoreKey() { - if (!Dedicated::IsEnabled() && !ZoneBuilder::IsEnabled() && GuidKey.isValid()) + if (!Dedicated::IsEnabled() && GuidKey.isValid()) { Proto::Auth::Certificate cert; cert.set_token(GuidToken.toString()); @@ -350,7 +350,7 @@ namespace Components void Auth::LoadKey(bool force) { - if (Dedicated::IsEnabled() || ZoneBuilder::IsEnabled()) return; + if (Dedicated::IsEnabled()) return; if (!force && GuidKey.isValid()) return; Proto::Auth::Certificate cert; @@ -509,7 +509,7 @@ namespace Components Logger::Print("Your guid: {:#X}\n", Steam::SteamUser()->GetSteamID().bits); }); - if (!Dedicated::IsEnabled() && !ZoneBuilder::IsEnabled()) + if (!Dedicated::IsEnabled()) { Command::Add("securityLevel", [](const Command::Params* params) { diff --git a/src/Components/Modules/Branding.cpp b/src/Components/Modules/Branding.cpp index c0f1eaab..c14b7e03 100644 --- a/src/Components/Modules/Branding.cpp +++ b/src/Components/Modules/Branding.cpp @@ -135,11 +135,7 @@ namespace Components Utils::Hook(0x5AC975, CG_DrawVersion_Hk, HOOK_CALL).install()->quick(); // Console title - if (ZoneBuilder::IsEnabled()) - { - Utils::Hook::Set(0x4289E8, "IW4x (" REVISION_STR "): ZoneBuilder"); - } - else if (Dedicated::IsEnabled()) + if (Dedicated::IsEnabled()) { #ifdef EXPERIMENTAL_BUILD Utils::Hook::Set(0x4289E8, "IW4x " REVISION_STR "-develop: Dedicated"); diff --git a/src/Components/Modules/Console.cpp b/src/Components/Modules/Console.cpp index 3699c58b..c0f6b5dd 100644 --- a/src/Components/Modules/Console.cpp +++ b/src/Components/Modules/Console.cpp @@ -909,7 +909,7 @@ namespace Components AddConsoleCommand(); #endif - if (Dedicated::IsEnabled() && !ZoneBuilder::IsEnabled()) + if (Dedicated::IsEnabled()) { Scheduler::Loop(RefreshStatus, Scheduler::Pipeline::MAIN); } @@ -923,7 +923,7 @@ namespace Components Utils::Hook(0x4B2080, StdOutPrint, HOOK_JUMP).install()->quick(); Utils::Hook(0x43D570, StdOutError, HOOK_JUMP).install()->quick(); } - else if (Flags::HasFlag("console") || ZoneBuilder::IsEnabled()) // ZoneBuilder uses the game's console, until the native one is adapted. + else if (Flags::HasFlag("console")) // ZoneBuilder uses the game's console, until the native one is adapted. { Utils::Hook::Nop(0x60BB58, 11); diff --git a/src/Components/Modules/Dedicated.cpp b/src/Components/Modules/Dedicated.cpp index a758e58c..fb9f08cc 100644 --- a/src/Components/Modules/Dedicated.cpp +++ b/src/Components/Modules/Dedicated.cpp @@ -182,7 +182,7 @@ namespace Components COMLogFilter = Dvar::Register("com_logFilter", true, Game::DVAR_LATCH, "Removes ~95% of unneeded lines from the log"); - if (IsEnabled() || ZoneBuilder::IsEnabled()) + if (IsEnabled()) { // Make sure all callbacks are handled Scheduler::Loop(Steam::SteamAPI_RunCallbacks, Scheduler::Pipeline::SERVER); @@ -243,9 +243,7 @@ namespace Components // Intercept time wrapping Utils::Hook(0x62737D, TimeWrapStub, HOOK_CALL).install()->quick(); - //Utils::Hook::Set(0x62735C, 50'000); // Time wrap after 50 seconds (for testing - i don't want to wait 3 weeks) - if (!ZoneBuilder::IsEnabled()) { Events::OnDvarInit([] { diff --git a/src/Components/Modules/Discord.cpp b/src/Components/Modules/Discord.cpp index b487e106..9223d116 100644 --- a/src/Components/Modules/Discord.cpp +++ b/src/Components/Modules/Discord.cpp @@ -116,7 +116,7 @@ namespace Components Discord::Discord() { - if (Dedicated::IsEnabled() || ZoneBuilder::IsEnabled()) + if (Dedicated::IsEnabled()) { return; } diff --git a/src/Components/Modules/Dvar.cpp b/src/Components/Modules/Dvar.cpp index 74d883d0..cb7c44e1 100644 --- a/src/Components/Modules/Dvar.cpp +++ b/src/Components/Modules/Dvar.cpp @@ -207,7 +207,7 @@ namespace Components const Game::dvar_t* Dvar::Dvar_RegisterName(const char* dvarName, const char* /*value*/, std::uint16_t flags, const char* description) { // Name watcher - if (!Dedicated::IsEnabled() && !ZoneBuilder::IsEnabled()) + if (!Dedicated::IsEnabled()) { Scheduler::Loop([] { diff --git a/src/Components/Modules/FastFiles.cpp b/src/Components/Modules/FastFiles.cpp index d2a35cbd..ff5eb1e2 100644 --- a/src/Components/Modules/FastFiles.cpp +++ b/src/Components/Modules/FastFiles.cpp @@ -527,12 +527,9 @@ namespace Components Utils::Hook(Game::DB_ReadXFile, FastFiles::ReadXFileStub, HOOK_JUMP).install()->quick(); // Allow custom zone loading - if (!ZoneBuilder::IsEnabled()) - { - Utils::Hook(0x506BC7, FastFiles::LoadInitialZones, HOOK_CALL).install()->quick(); - Utils::Hook(0x60B4AC, FastFiles::LoadDLCUIZones, HOOK_CALL).install()->quick(); - Utils::Hook(0x506B25, FastFiles::LoadGfxZones, HOOK_CALL).install()->quick(); - } + Utils::Hook(0x506BC7, FastFiles::LoadInitialZones, HOOK_CALL).install()->quick(); + Utils::Hook(0x60B4AC, FastFiles::LoadDLCUIZones, HOOK_CALL).install()->quick(); + Utils::Hook(0x506B25, FastFiles::LoadGfxZones, HOOK_CALL).install()->quick(); // basic checks (hash jumps, both normal and playlist) Utils::Hook::Nop(0x5B97A3, 2); @@ -583,7 +580,7 @@ namespace Components FastFiles::AddZonePath("zone\\patch\\"); FastFiles::AddZonePath("zone\\dlc\\"); - if (!Dedicated::IsEnabled() && !ZoneBuilder::IsEnabled()) + if (!Dedicated::IsEnabled()) { Scheduler::Loop([] { diff --git a/src/Components/Modules/FileSystem.cpp b/src/Components/Modules/FileSystem.cpp index 02b27006..a29d0fbb 100644 --- a/src/Components/Modules/FileSystem.cpp +++ b/src/Components/Modules/FileSystem.cpp @@ -253,11 +253,6 @@ namespace Components void FileSystem::RegisterFolders() { - if (ZoneBuilder::IsEnabled()) - { - RegisterFolder("zonedata"); - } - RegisterFolder("userraw"); } diff --git a/src/Components/Modules/Friends.cpp b/src/Components/Modules/Friends.cpp index 90cf83c7..58170472 100644 --- a/src/Components/Modules/Friends.cpp +++ b/src/Components/Modules/Friends.cpp @@ -554,7 +554,7 @@ namespace Components { Friends::LoggedOn = false; - if (Dedicated::IsEnabled() || ZoneBuilder::IsEnabled()) return; + if (Dedicated::IsEnabled()) return; Friends::UIStreamFriendly = Dvar::Register("ui_streamFriendly", false, Game::DVAR_ARCHIVE, "Stream friendly UI"); Friends::CLAnonymous = Dvar::Register("cl_anonymous", false, Game::DVAR_ARCHIVE, "Enable invisible mode for Steam"); @@ -704,7 +704,7 @@ namespace Components Friends::~Friends() { - if (Dedicated::IsEnabled() || ZoneBuilder::IsEnabled()) return; + if (Dedicated::IsEnabled()) return; Friends::StoreFriendsList(); diff --git a/src/Components/Modules/Gamepad.cpp b/src/Components/Modules/Gamepad.cpp index 0fe01d91..f70db251 100644 --- a/src/Components/Modules/Gamepad.cpp +++ b/src/Components/Modules/Gamepad.cpp @@ -2082,11 +2082,6 @@ namespace Components Gamepad::Gamepad() { - if (ZoneBuilder::IsEnabled()) - { - return; - } - // Initialize gamepad environment Utils::Hook(0x4059FE, CG_RegisterDvars_Hk, HOOK_CALL).install()->quick(); diff --git a/src/Components/Modules/IPCPipe.cpp b/src/Components/Modules/IPCPipe.cpp index f14132d7..0273adde 100644 --- a/src/Components/Modules/IPCPipe.cpp +++ b/src/Components/Modules/IPCPipe.cpp @@ -201,7 +201,7 @@ namespace Components IPCPipe::IPCPipe() { - if (Dedicated::IsEnabled() || Loader::IsPerformingUnitTests() || ZoneBuilder::IsEnabled()) return; + if (Dedicated::IsEnabled() || Loader::IsPerformingUnitTests()) return; // Server pipe ServerPipe.onConnect(ConnectClient); diff --git a/src/Components/Modules/MapDump.cpp b/src/Components/Modules/MapDump.cpp deleted file mode 100644 index c4dc4bcc..00000000 --- a/src/Components/Modules/MapDump.cpp +++ /dev/null @@ -1,464 +0,0 @@ -#include -#include "MapDump.hpp" - -namespace Components -{ - class MapDumper - { - public: - MapDumper(Game::GfxWorld* world) : world_(world) - { - } - - void dump() - { - if (!this->world_) return; - - Logger::Print("Exporting '{}'...\n", this->world_->baseName); - - this->parseVertices(); - this->parseFaces(); - this->parseStaticModels(); - - this->write(); - } - - private: - struct Vertex - { - Game::vec3_t coordinate; - Game::vec2_t texture; - Game::vec3_t normal; - }; - - struct Face - { - int a{}; - int b{}; - int c{}; - }; - - struct FaceList - { - std::vector indices{}; - }; - - class File - { - public: - File() {} - - File(const std::string& file) - { - Utils::IO::WriteFile(file, {}); - this->stream_ = std::ofstream(file, std::ofstream::out); - } - - void append(const std::string& str) - { - this->stream_.write(str.data(), str.size()); - } - - private: - std::ofstream stream_{}; - }; - - Game::GfxWorld* world_{}; - std::vector vertices_{}; - std::unordered_map faces_{}; - std::vector facesOrder_{}; - - File object_{}; - File material_{}; - - void transformAxes(Game::vec3_t& vec) const - { - std::swap(vec[0], vec[1]); - std::swap(vec[1], vec[2]); - } - - void parseVertices() - { - Logger::Print("Parsing vertices...\n"); - - for (unsigned int i = 0; i < this->world_->draw.vertexCount; ++i) - { - const auto* vertex = &this->world_->draw.vd.vertices[i]; - - Vertex v{}; - - v.coordinate[0] = vertex->xyz[0]; - v.coordinate[1] = vertex->xyz[1]; - v.coordinate[2] = vertex->xyz[2]; - this->transformAxes(v.coordinate); - - v.texture[0] = vertex->texCoord[0]; - v.texture[1] = -vertex->texCoord[1]; - - Game::Vec3UnpackUnitVec(vertex->normal, &v.normal); - this->transformAxes(v.normal); - - this->vertices_.push_back(v); - } - } - - void parseFaces() - { - Logger::Print("Parsing faces...\n"); - - for (unsigned int i = 0; i < this->world_->dpvs.staticSurfaceCount; ++i) - { - const auto* surface = &this->world_->dpvs.surfaces[i]; - - const unsigned int vertOffset = surface->tris.firstVertex + 1; - const unsigned int indexOffset = surface->tris.baseIndex; - - // Fuck cube maps for now - if(this->findImage(surface->material, "colorMap")->mapType == 5) continue; - - auto& f = this->getFaceList(surface->material); - - for (unsigned short j = 0; j < surface->tris.triCount; ++j) - { - Face face{}; - face.a = this->world_->draw.indices[indexOffset + j * 3 + 0] + vertOffset; - face.b = this->world_->draw.indices[indexOffset + j * 3 + 1] + vertOffset; - face.c = this->world_->draw.indices[indexOffset + j * 3 + 2] + vertOffset; - - f.indices.push_back(face); - } - } - } - - FaceList& getFaceList(Game::Material* material) - { - auto& faceList = this->faces_[material]; - - if (this->facesOrder_.size() < this->faces_.size()) - { - this->facesOrder_.push_back(material); - } - - return faceList; - } - - void performWorldTransformation(const Game::GfxPackedPlacement& placement, Vertex& v) const - { - Game::MatrixVecMultiply(placement.axis, v.normal, v.normal); - Game::Vec3Normalize(v.normal); - - Game::MatrixVecMultiply(placement.axis, v.coordinate, v.coordinate); - v.coordinate[0] = v.coordinate[0] * placement.scale + placement.origin[0]; - v.coordinate[1] = v.coordinate[1] * placement.scale + placement.origin[1]; - v.coordinate[2] = v.coordinate[2] * placement.scale + placement.origin[2]; - } - - std::vector parseSurfaceVertices(const Game::XSurface* surface, const Game::GfxPackedPlacement& placement) - { - std::vector vertices; - - for (unsigned short j = 0; j < surface->vertCount; j++) - { - const auto *vertex = &surface->verts0[j]; - - Vertex v{}; - - v.coordinate[0] = vertex->xyz[0]; - v.coordinate[1] = vertex->xyz[1]; - v.coordinate[2] = vertex->xyz[2]; - - // Why... - Game::Vec2UnpackTexCoords(vertex->texCoord, &v.texture); - std::swap(v.texture[0], v.texture[1]); - v.texture[1] *= -1; - - Game::Vec3UnpackUnitVec(vertex->normal, &v.normal); - - this->performWorldTransformation(placement, v); - this->transformAxes(v.coordinate); - this->transformAxes(v.normal); - - vertices.push_back(v); - } - - return vertices; - } - - std::vector parseSurfaceFaces(const Game::XSurface* surface) const - { - std::vector faces; - - for (unsigned short j = 0; j < surface->triCount; ++j) - { - Face face{}; - face.a = surface->triIndices[j * 3 + 0]; - face.b = surface->triIndices[j * 3 + 1]; - face.c = surface->triIndices[j * 3 + 2]; - - faces.push_back(face); - } - - return faces; - } - - void removeVertex(const int index, std::vector& faces, std::vector& vertices) const - { - vertices.erase(vertices.begin() + index); - - for (auto &face : faces) - { - if (face.a > index) --face.a; - if (face.b > index) --face.b; - if (face.c > index) --face.c; - } - } - - void filterSurfaceVertices(std::vector& faces, std::vector& vertices) const - { - for (auto i = 0; i < int(vertices.size()); ++i) - { - auto referenced = false; - - for (const auto &face : faces) - { - if (face.a == i || face.b == i || face.c == i) - { - referenced = true; - break; - } - } - - if (!referenced) - { - this->removeVertex(i--, faces, vertices); - } - } - } - - void parseStaticModel(Game::GfxStaticModelDrawInst* model) - { - for (unsigned char i = 0; i < model->model->numsurfs; ++i) - { - this->getFaceList(model->model->materialHandles[i]); - } - - const auto* lod = &model->model->lodInfo[model->model->numLods - 1]; - - const auto baseIndex = this->vertices_.size() + 1; - const auto surfIndex = lod->surfIndex; - - assert(lod->modelSurfs->numsurfs <= model->model->numsurfs); - - for (unsigned short i = 0; i < lod->modelSurfs->numsurfs; ++i) - { - // TODO: Something is still wrong about the models. Probably baseTriIndex and baseVertIndex might help - - const auto* surface = &lod->modelSurfs->surfs[i]; - auto faces = this->parseSurfaceFaces(surface); - auto vertices = this->parseSurfaceVertices(surface, model->placement); - this->filterSurfaceVertices(faces, vertices); - - auto& f = this->getFaceList(model->model->materialHandles[i + surfIndex]); - - for (const auto& vertex : vertices) - { - this->vertices_.push_back(vertex); - } - - for (auto face : faces) - { - face.a += baseIndex; - face.b += baseIndex; - face.c += baseIndex; - f.indices.push_back(std::move(face)); - } - } - } - - void parseStaticModels() - { - Logger::Print("Parsing static models...\n"); - - for (unsigned i = 0u; i < this->world_->dpvs.smodelCount; ++i) - { - this->parseStaticModel(this->world_->dpvs.smodelDrawInsts + i); - } - } - - void write() - { - this->object_ = File(Utils::String::VA("raw/mapdump/%s/%s.obj", this->world_->baseName, this->world_->baseName)); - this->material_ = File(Utils::String::VA("raw/mapdump/%s/%s.mtl", this->world_->baseName, this->world_->baseName)); - - this->object_.append("# Generated by IW4x\n"); - this->object_.append("# Credit to SE2Dev for his D3DBSP Tool\n"); - this->object_.append(Utils::String::VA("o %s\n", this->world_->baseName)); - this->object_.append(Utils::String::VA("mtllib %s.mtl\n\n", this->world_->baseName)); - - this->material_.append("# IW4x MTL File\n"); - this->material_.append("# Credit to SE2Dev for his D3DBSP Tool\n"); - - this->writeVertices(); - this->writeFaces(); - - Logger::Print("Writing files...\n"); - - this->object_ = {}; - this->material_ = {}; - } - - void writeVertices() - { - Logger::Print("Writing vertices...\n"); - this->object_.append("# Vertices\n"); - - for (const auto& vertex : this->vertices_) - { - this->object_.append(Utils::String::VA("v %.6f %.6f %.6f\n", vertex.coordinate[0], vertex.coordinate[1], vertex.coordinate[2])); - } - - Logger::Print("Writing texture coordinates...\n"); - this->object_.append("\n# Texture coordinates\n"); - - for (const auto& vertex : this->vertices_) - { - this->object_.append(Utils::String::VA("vt %.6f %.6f\n", vertex.texture[0], vertex.texture[1])); - } - - Logger::Print("Writing normals...\n"); - this->object_.append("\n# Normals\n"); - - for (const auto& vertex : this->vertices_) - { - this->object_.append(Utils::String::VA("vn %.6f %.6f %.6f\n", vertex.normal[0], vertex.normal[1], vertex.normal[2])); - } - - this->object_.append("\n"); - } - - Game::GfxImage* findImage(Game::Material* material, const std::string& type) const - { - Game::GfxImage* image = nullptr; - - const auto hash = Game::R_HashString(type.data()); - - for (char l = 0; l < material->textureCount; ++l) - { - if (material->textureTable[l].nameHash == hash) - { - image = material->textureTable[l].u.image; // Hopefully our map - break; - } - } - - return image; - } - - Game::GfxImage* extractImage(Game::Material* material, const std::string& type) const - { - auto* image = this->findImage(material, type); - - if (!image) - { - return image; - } - - std::string _name = Utils::String::VA("raw/mapdump/%s/textures/%s.png", this->world_->baseName, image->name); - D3DXSaveTextureToFileA(_name.data(), D3DXIFF_PNG, image->texture.map, nullptr); - - return image; - } - - void writeMaterial(Game::Material* material) - { - std::string name = material->info.name; - - const auto pos = name.find_last_of('/'); - if (pos != std::string::npos) - { - name = name.substr(pos + 1); - } - - this->object_.append(Utils::String::VA("usemtl %s\n", name.data())); - this->object_.append("s off\n"); - - auto* colorMap = this->extractImage(material, "colorMap"); - auto* normalMap = this->extractImage(material, "normalMap"); - auto* specularMap = this->extractImage(material, "specularMap"); - - this->material_.append(Utils::String::VA("\nnewmtl %s\n", name.data())); - this->material_.append("Ka 1.0000 1.0000 1.0000\n"); - this->material_.append("Kd 1.0000 1.0000 1.0000\n"); - this->material_.append("illum 1\n"); - this->material_.append(Utils::String::VA("map_Ka textures/%s.png\n", colorMap->name)); - this->material_.append(Utils::String::VA("map_Kd textures/%s.png\n", colorMap->name)); - - if (specularMap) - { - this->material_.append(Utils::String::VA("map_Ks textures/%s.png\n", specularMap->name)); - } - - if (normalMap) - { - this->material_.append(Utils::String::VA("bump textures/%s.png\n", normalMap->name)); - } - } - - void writeFaces() - { - Logger::Print("Writing faces...\n"); - Utils::IO::CreateDir(Utils::String::VA("raw/mapdump/%s/textures", this->world_->baseName)); - - this->material_.append(Utils::String::VA("# Material count: %d\n", this->faces_.size())); - - this->object_.append("# Faces\n"); - - for (const auto& material : this->facesOrder_) - { - this->writeMaterial(material); - - const auto& faces = this->getFaceList(material); - for (const auto& index : faces.indices) - { - const int a = index.a; - const int b = index.b; - const int c = index.c; - - this->object_.append(Utils::String::VA("f %d/%d/%d %d/%d/%d %d/%d/%d\n", a, a, a, b, b, b, c, c, c)); - } - - this->object_.append("\n"); - } - } - }; - - MapDump::MapDump() - { - Command::Add("dumpmap", []() - { - if (Dedicated::IsEnabled() || ZoneBuilder::IsEnabled()) - { - Logger::Print("DirectX needs to be enabled, please start a client to use this command!\n"); - return; - } - - Game::GfxWorld* world = nullptr; - Game::DB_EnumXAssets(Game::XAssetType::ASSET_TYPE_GFXWORLD, [](Game::XAssetHeader header, void* world) - { - *reinterpret_cast(world) = header.gfxWorld; - }, &world, false); - - if (world) - { - MapDumper dumper(world); - dumper.dump(); - - Logger::Print("Map '{}' exported!\n", world->baseName); - } - else - { - Logger::Print("No map loaded, unable to dump anything!\n"); - } - }); - } -} diff --git a/src/Components/Modules/MapDump.hpp b/src/Components/Modules/MapDump.hpp deleted file mode 100644 index 2662ce2f..00000000 --- a/src/Components/Modules/MapDump.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -namespace Components -{ - class MapDump : public Component - { - public: - MapDump(); - }; -} diff --git a/src/Components/Modules/Maps.cpp b/src/Components/Modules/Maps.cpp index 46ff7ff4..faa66156 100644 --- a/src/Components/Modules/Maps.cpp +++ b/src/Components/Modules/Maps.cpp @@ -862,7 +862,7 @@ namespace Components // Allow hiding specific smodels Utils::Hook(0x50E67C, Maps::HideModelStub, HOOK_CALL).install()->quick(); - if (Dedicated::IsEnabled() || ZoneBuilder::IsEnabled()) + if (Dedicated::IsEnabled()) { return; } diff --git a/src/Components/Modules/Menus.cpp b/src/Components/Modules/Menus.cpp index 54857572..5ae6163f 100644 --- a/src/Components/Modules/Menus.cpp +++ b/src/Components/Modules/Menus.cpp @@ -793,11 +793,6 @@ namespace Components { menuParseKeywordHash = reinterpret_cast**>(0x63AE928); - if (ZoneBuilder::IsEnabled()) - { - Game::Menu_Setup(Game::uiContext); - } - if (Dedicated::IsEnabled()) return; // Intercept asset finding diff --git a/src/Components/Modules/ModelSurfs.cpp b/src/Components/Modules/ModelSurfs.cpp index 55e30ba1..cfc5c10c 100644 --- a/src/Components/Modules/ModelSurfs.cpp +++ b/src/Components/Modules/ModelSurfs.cpp @@ -58,14 +58,7 @@ namespace Components } #endif - if (ZoneBuilder::IsEnabled()) - { - Logger::Print("Loading model surface {} at path \"{}\" failed!", name, path); - } - else - { - Logger::Error(Game::ERR_FATAL, "Loading model {} failed!", name); - } + Logger::Error(Game::ERR_FATAL, "Loading model {} failed!", name); return nullptr; } diff --git a/src/Components/Modules/News.cpp b/src/Components/Modules/News.cpp index 39a4b4e6..389def85 100644 --- a/src/Components/Modules/News.cpp +++ b/src/Components/Modules/News.cpp @@ -39,7 +39,7 @@ namespace Components News::News() { - if (ZoneBuilder::IsEnabled() || Dedicated::IsEnabled()) return; // Maybe also dedi? + if (Dedicated::IsEnabled()) return; Dvar::Register("g_firstLaunch", true, Game::DVAR_ARCHIVE, ""); diff --git a/src/Components/Modules/Node.cpp b/src/Components/Modules/Node.cpp index 50b0c8fe..cd56f7b7 100644 --- a/src/Components/Modules/Node.cpp +++ b/src/Components/Modules/Node.cpp @@ -395,7 +395,6 @@ namespace Components Node::Node() { - if (ZoneBuilder::IsEnabled()) return; Dvar::Register("net_natFix", false, 0, "Fix node registration for certain firewalls/routers"); Scheduler::Loop([] diff --git a/src/Components/Modules/Party.cpp b/src/Components/Modules/Party.cpp index fadefcb1..650de47f 100644 --- a/src/Components/Modules/Party.cpp +++ b/src/Components/Modules/Party.cpp @@ -317,7 +317,7 @@ namespace Components Connect(Container.target); }); - if (!Dedicated::IsEnabled() && !ZoneBuilder::IsEnabled()) + if (!Dedicated::IsEnabled()) { Scheduler::Loop([] { diff --git a/src/Components/Modules/Singleton.cpp b/src/Components/Modules/Singleton.cpp index 9ae0b43b..4eb27bfa 100644 --- a/src/Components/Modules/Singleton.cpp +++ b/src/Components/Modules/Singleton.cpp @@ -29,7 +29,7 @@ namespace Components Console::FreeNativeConsole(); - if (Loader::IsPerformingUnitTests() || Dedicated::IsEnabled() || ZoneBuilder::IsEnabled()) return; + if (Loader::IsPerformingUnitTests() || Dedicated::IsEnabled()) return; FirstInstance = (CreateMutexA(nullptr, FALSE, "iw4x_mutex") && GetLastError() != ERROR_ALREADY_EXISTS); diff --git a/src/Components/Modules/StructuredData.cpp b/src/Components/Modules/StructuredData.cpp index c3a2e6ff..7036559e 100644 --- a/src/Components/Modules/StructuredData.cpp +++ b/src/Components/Modules/StructuredData.cpp @@ -149,159 +149,10 @@ namespace Components { if (Dedicated::IsEnabled()) return; - // Do not execute this when building zones - if (!ZoneBuilder::IsEnabled()) - { - // Correctly upgrade stats - Utils::Hook(0x42F088, StructuredData::UpdateVersionOffsets, HOOK_CALL).install()->quick(); + // Correctly upgrade stats + Utils::Hook(0x42F088, StructuredData::UpdateVersionOffsets, HOOK_CALL).install()->quick(); - // 15 or more custom classes - Utils::Hook::Set(0x60A2FE, NUM_CUSTOM_CLASSES); - - return; - } - - AssetHandler::OnLoad([](Game::XAssetType type, Game::XAssetHeader asset, const std::string& filename, bool* /*restrict*/) - { - // Only intercept playerdatadef loading - if (type != Game::ASSET_TYPE_STRUCTURED_DATA_DEF || filename != "mp/playerdata.def") return; - - // Store asset - Game::StructuredDataDefSet* data = asset.structuredDataDefSet; - if (!data) return; - - if (data->defCount != 1) - { - Logger::Error(Game::ERR_FATAL, "PlayerDataDefSet contains more than 1 definition!"); - return; - } - - if (data->defs[0].version != 155) - { - Logger::Error(Game::ERR_FATAL, "Initial PlayerDataDef is not version 155, patching not possible!"); - return; - } - - std::unordered_map>> patchDefinitions; - std::unordered_map> otherPatchDefinitions; - - // First check if all versions are present - for (int i = 156;; ++i) - { - // We're on DB thread (OnLoad) so use DB thread for FS - FileSystem::File definition(std::format("{}/{}.json", filename, i), Game::FsThread::FS_THREAD_DATABASE); - if (!definition.exists()) break; - - std::vector> enumContainer; - std::unordered_map otherPatches; - - nlohmann::json defData; - try - { - defData = nlohmann::json::parse(definition.getBuffer()); - } - catch (const nlohmann::json::parse_error& ex) - { - Logger::PrintError(Game::CON_CHANNEL_ERROR, "JSON Parse Error: {}\n", ex.what()); - return; - } - - if (!defData.is_object()) - { - Logger::Error(Game::ERR_FATAL, "PlayerDataDef patch for version {} is invalid!", i); - return; - } - - for (auto pType = 0; pType < StructuredData::PlayerDataType::COUNT; ++pType) - { - auto enumData = defData[StructuredData::EnumTranslation[pType]]; - - std::vector entryData; - - if (enumData.is_array()) - { - for (const auto& rawEntry : enumData) - { - if (rawEntry.is_string()) - { - entryData.push_back(rawEntry.get()); - } - } - } - - enumContainer.push_back(entryData); - } - - auto other = defData["other"]; - - if (other.is_object()) - { - for (auto& item : other.items()) - { - if (item.value().is_string()) - { - otherPatches[item.key()] = item.value().get(); - } - } - } - - patchDefinitions[i] = enumContainer; - otherPatchDefinitions[i] = otherPatches; - } - - // Nothing to patch - if (patchDefinitions.empty()) return; - - // Reallocate the definition - auto* newData = StructuredData::MemAllocator.allocateArray(data->defCount + patchDefinitions.size()); - std::memcpy(&newData[patchDefinitions.size()], data->defs, sizeof Game::StructuredDataDef * data->defCount); - - // Prepare the buffers - for (unsigned int i = 0; i < patchDefinitions.size(); ++i) - { - std::memcpy(&newData[i], data->defs, sizeof Game::StructuredDataDef); - newData[i].version = (patchDefinitions.size() - i) + 155; - - // Reallocate the enum array - auto* newEnums = StructuredData::MemAllocator.allocateArray(data->defs->enumCount); - std::memcpy(newEnums, data->defs->enums, sizeof Game::StructuredDataEnum * data->defs->enumCount); - newData[i].enums = newEnums; - } - - // Apply new data - data->defs = newData; - data->defCount += patchDefinitions.size(); - - // Patch the definition - for (unsigned int i = 0; i < data->defCount; ++i) - { - // No need to patch version 155 - if (newData[i].version == 155) continue; - - if (patchDefinitions.contains(newData[i].version)) - { - auto patchData = patchDefinitions[newData[i].version]; - auto otherData = otherPatchDefinitions[newData[i].version]; - - // Invalid patch data - if (patchData.size() != StructuredData::PlayerDataType::COUNT) - { - Logger::Error(Game::ERR_FATAL, "PlayerDataDef patch for version {} wasn't parsed correctly!", newData[i].version); - continue; - } - - // Apply the patch data - for (auto pType = 0; pType < StructuredData::PlayerDataType::COUNT; ++pType) - { - if (!patchData[pType].empty()) - { - StructuredData::PatchPlayerDataEnum(&newData[i], static_cast(pType), patchData[pType]); - } - } - - StructuredData::PatchAdditionalData(&newData[i], otherData); - } - } - }); + // 15 or more custom classes + Utils::Hook::Set(0x60A2FE, NUM_CUSTOM_CLASSES); } } diff --git a/src/Components/Modules/Toast.cpp b/src/Components/Modules/Toast.cpp index 78c78ca0..5c43366d 100644 --- a/src/Components/Modules/Toast.cpp +++ b/src/Components/Modules/Toast.cpp @@ -147,7 +147,7 @@ namespace Components Toast::Toast() { - if (Dedicated::IsEnabled() || ZoneBuilder::IsEnabled()) + if (Dedicated::IsEnabled()) { return; } diff --git a/src/Components/Modules/ZoneBuilder.cpp b/src/Components/Modules/ZoneBuilder.cpp deleted file mode 100644 index 15bc2932..00000000 --- a/src/Components/Modules/ZoneBuilder.cpp +++ /dev/null @@ -1,1762 +0,0 @@ -#include -#include - -#include "Console.hpp" -#include "FastFiles.hpp" - -#include - -#include "AssetInterfaces/ILocalizeEntry.hpp" - -namespace Components -{ - std::string ZoneBuilder::TraceZone; - std::vector> ZoneBuilder::TraceAssets; - - bool ZoneBuilder::MainThreadInterrupted; - DWORD ZoneBuilder::InterruptingThreadId; - - volatile bool ZoneBuilder::CommandThreadTerminate = false; - std::thread ZoneBuilder::CommandThread; - iw4of::api ZoneBuilder::ExporterAPI(GetExporterAPIParams()); - std::string ZoneBuilder::DumpingZone{}; - - ZoneBuilder::Zone::Zone(const std::string& name) : indexStart(0), externalSize(0), - // Reserve 100MB by default. - // That's totally fine, as the dedi doesn't load images and therefore doesn't need much memory. - // That way we can be sure it won't need to reallocate memory. - // Side note: if you need a fastfile larger than 100MB, you're doing it wrong- - // Well, decompressed maps can get way larger than 100MB, so let's increase that. - buffer(0xC800000), - zoneName(name), - dataMap("zone_source/" + name + ".csv"), - branding{nullptr}, - assetDepth(0), - iw4ofApi(getIW4OfApiParams()) - { - } - - ZoneBuilder::Zone::~Zone() - { -#ifdef DEBUG - for (auto& subAsset : this->loadedSubAssets) - { - bool found = false; - std::string name = Game::DB_GetXAssetName(&subAsset); - - for (auto& alias : this->aliasList) - { - if (subAsset.type == alias.first.type && name == Game::DB_GetXAssetName(&alias.first)) - { - found = true; - break; - } - } - - if (!found) - { - Logger::Print("Asset {} of type {} was loaded, but not written!\n", name, Game::DB_GetXAssetTypeName(subAsset.type)); - } - } - - for (auto& alias : this->aliasList) - { - bool found = false; - std::string name = Game::DB_GetXAssetName(&alias.first); - - for (auto& subAsset : this->loadedSubAssets) - { - if (subAsset.type == alias.first.type && name == Game::DB_GetXAssetName(&subAsset)) - { - found = true; - break; - } - } - - if (!found) - { - Logger::Error(Game::ERR_FATAL, "Asset {} of type {} was written, but not loaded!\n", name, Game::DB_GetXAssetTypeName(alias.first.type)); - } - } -#endif - - // Unload our fastfiles - Game::XZoneInfo info{}; - info.name = nullptr; - info.allocFlags = 0; - info.freeFlags = 0x20; - - - Game::DB_LoadXAssets(&info, 1, true); - - AssetHandler::ClearTemporaryAssets(); - } - - Utils::Stream* ZoneBuilder::Zone::getBuffer() - { - return &this->buffer; - } - - Utils::Memory::Allocator* ZoneBuilder::Zone::getAllocator() - { - return &this->memAllocator; - } - - iw4of::api* ZoneBuilder::Zone::getIW4OfApi() - { - return &iw4ofApi; - } - - void ZoneBuilder::Zone::Zone::build() - { - if (!this->dataMap.isValid()) - { - Logger::Print("Unable to load CSV for '{}'!\n", this->zoneName); - return; - } - - this->loadFastFiles(); - - Logger::Print("Linking assets...\n"); - if (!this->loadAssets()) return; - - this->addBranding(); - - Logger::Print("Saving...\n"); - this->saveData(); - - if (this->buffer.hasBlock()) - { - Logger::Error(Game::ERR_FATAL, "Non-popped blocks left!\n"); - } - - Logger::Print("Compressing...\n"); - this->writeZone(); - } - - void ZoneBuilder::Zone::loadFastFiles() const - { - Logger::Print("Loading required FastFiles...\n"); - - for (std::size_t i = 0; i < this->dataMap.getRows(); ++i) - { - if (this->dataMap.getElementAt(i, 0) == "require") - { - std::string fastfile = this->dataMap.getElementAt(i, 1); - - if (!Game::DB_IsZoneLoaded(fastfile.data())) - { - Game::XZoneInfo info; - info.name = fastfile.data(); - info.allocFlags = 0x20; - info.freeFlags = 0; - - Game::DB_LoadXAssets(&info, 1, true); - } - else - { - Logger::Print("Zone '{}' already loaded\n", fastfile); - } - } - } - } - - bool ZoneBuilder::Zone::loadAssets() - { - for (std::size_t i = 0; i < this->dataMap.getRows(); ++i) - { - if (this->dataMap.getElementAt(i, 0) == "require"s) - { - continue; - } - - if (this->dataMap.getElementAt(i, 0) == "localize"s) - { - const auto filename = this->dataMap.getElementAt(i, 1); - if (FileSystem::File file = std::format("localizedstrings/{}.str", filename)) - { - Assets::ILocalizeEntry::ParseLocalizedStringsFile(this, filename, file.getName()); - continue; - } - - if (FileSystem::File file = std::format("localizedstrings/{}.json", filename)) - { - Assets::ILocalizeEntry::ParseLocalizedStringsJSON(this, file); - continue; - } - } - - if (this->dataMap.getColumns(i) > 2) - { - auto oldName = this->dataMap.getElementAt(i, 1); - auto newName = this->dataMap.getElementAt(i, 2); - auto typeName = this->dataMap.getElementAt(i, 0); - auto type = Game::DB_GetXAssetNameType(typeName.data()); - - if (type < Game::XAssetType::ASSET_TYPE_COUNT && type >= 0) - { - this->renameAsset(type, oldName, newName); - } - else - { - Logger::Error(Game::ERR_FATAL, "Unable to rename '{}' to '{}' as the asset type '{}' is invalid!", oldName, newName, typeName); - } - } - - if (!this->loadAssetByName(this->dataMap.getElementAt(i, 0), this->dataMap.getElementAt(i, 1), false)) - { - return false; - } - - } - - return true; - } - - bool ZoneBuilder::Zone::loadAsset(Game::XAssetType type, void* data, bool isSubAsset) - { - Game::XAsset asset{ type, { data } }; - - const char* name = Game::DB_GetXAssetName(&asset); - - if (name) return this->loadAssetByName(type, std::string(name), isSubAsset); - else return false; - } - - bool ZoneBuilder::Zone::loadAssetByName(Game::XAssetType type, const std::string& name, bool isSubAsset) - { - return this->loadAssetByName(Game::DB_GetXAssetTypeName(type), name, isSubAsset); - } - - bool ZoneBuilder::Zone::loadAssetByName(const std::string& typeName, std::string name, bool isSubAsset) - { - Game::XAssetType type = Game::DB_GetXAssetNameType(typeName.data()); - - if (name.find(' ', 0) != std::string::npos) - { - Logger::Warning(Game::CON_CHANNEL_DONT_FILTER, "Asset with name '{}' contains spaces. Check your zone source file to ensure this is correct!\n", name); - } - - // Sanitize name for empty assets - if (name[0] == ',') name.erase(name.begin()); - - // Fix forward slashes for FXEffectDef (and probably other assets) - std::replace(name.begin(), name.end(), '\\', '/'); - - if (this->findAsset(type, name) != -1 || this->findSubAsset(type, name).data) return true; - - if (type == Game::XAssetType::ASSET_TYPE_INVALID || type >= Game::XAssetType::ASSET_TYPE_COUNT) - { - Logger::Error(Game::ERR_FATAL, "Invalid asset type '{}'\n", typeName); - return false; - } - - Game::XAssetHeader assetHeader = AssetHandler::FindAssetForZone(type, name, this, isSubAsset); - - if (!assetHeader.data) - { - Logger::Error(Game::ERR_FATAL, "Missing asset '{}' of type '{}'\n", name, Game::DB_GetXAssetTypeName(type)); - return false; - } - - Game::XAsset asset; - asset.type = type; - asset.header = assetHeader; - - // Handle script strings - AssetHandler::ZoneMark(asset, this); - - if (isSubAsset) - { - this->loadedSubAssets.push_back(asset); - } - else - { - this->loadedAssets.push_back(asset); - } - - - return true; - } - - int ZoneBuilder::Zone::findAsset(Game::XAssetType type, std::string name) - { - if (name[0] == ',') name.erase(name.begin()); - - for (unsigned int i = 0; i < this->loadedAssets.size(); ++i) - { - Game::XAsset* asset = &this->loadedAssets[i]; - - if (asset->type != type) continue; - - const auto* assetName = Game::DB_GetXAssetName(asset); - if (!assetName) return -1; - if (assetName[0] == ',' && assetName[1] != '\0') ++assetName; - - if (this->getAssetName(type, assetName) == name) - { - return i; - } - - if (name == assetName) - { - return i; - } - } - - return -1; - } - - Game::XAssetHeader ZoneBuilder::Zone::findSubAsset(Game::XAssetType type, std::string name) - { - if (name[0] == ',') name.erase(name.begin()); - - for (unsigned int i = 0; i < this->loadedSubAssets.size(); ++i) - { - Game::XAsset* asset = &this->loadedSubAssets[i]; - - if (asset->type != type) continue; - - const char* assetName = Game::DB_GetXAssetName(asset); - if (assetName[0] == ',') ++assetName; - - if (name == assetName) - { - return asset->header; - } - } - - return { nullptr }; - } - - Game::XAsset* ZoneBuilder::Zone::getAsset(int index) - { - if (static_cast(index) < this->loadedAssets.size()) - { - return &this->loadedAssets[index]; - } - - return nullptr; - } - - uint32_t ZoneBuilder::Zone::getAssetTableOffset(int index) - { - Utils::Stream::Offset offset; - offset.block = Game::XFILE_BLOCK_VIRTUAL; - offset.offset = (this->indexStart + (index * sizeof(Game::XAsset)) + 4); - return offset.getPackedOffset(); - } - - bool ZoneBuilder::Zone::hasAlias(Game::XAsset asset) - { - return this->getAlias(asset) != 0; - } - - Game::XAssetHeader ZoneBuilder::Zone::saveSubAsset(Game::XAssetType type, void* ptr) - { - Game::XAssetHeader header { ptr }; - Game::XAsset asset { type, header }; - std::string name = Game::DB_GetXAssetName(&asset); - - int assetIndex = this->findAsset(type, name); - if (assetIndex == -1) // nested asset - { - // already written. find alias and store in ptr - if (this->hasAlias(asset)) - { - header.data = reinterpret_cast(this->getAlias(asset)); - } - else - { - asset.header = this->findSubAsset(type, name); - if (!asset.header.data) - { - Logger::Error(Game::ERR_FATAL, "Missing required asset '{}' ({}). Export failed!", name, Game::DB_GetXAssetTypeName(type)); - } - - - // we alias the next 4 (aligned) bytes of the stream b/c DB_InsertPointer gives us a nice pointer to use as the alias - // otherwise it would be a fuckfest trying to figure out where the alias is in the stream - this->buffer.pushBlock(Game::XFILE_BLOCK_VIRTUAL); - this->buffer.align(Utils::Stream::ALIGN_4); - this->storeAlias(asset); - this->buffer.increaseBlockSize(4); - this->buffer.popBlock(); - - this->buffer.pushBlock(Game::XFILE_BLOCK_TEMP); - this->buffer.align(Utils::Stream::ALIGN_4); - AssetHandler::ZoneSave(asset, this); - this->buffer.popBlock(); - - header.data = reinterpret_cast(-2); // DB_InsertPointer marker - } - } - else - { - // asset was written normally. not sure this is even possible but its here - header.data = reinterpret_cast(this->getAssetTableOffset(assetIndex)); - } - - return header; - } - - void ZoneBuilder::Zone::writeZone() - { - FILETIME fileTime; - GetSystemTimeAsFileTime(&fileTime); - - Game::XFileHeader header = - { -#ifndef GENERATE_IW4X_SPECIFIC_ZONES - XFILE_MAGIC_UNSIGNED, -#else - XFILE_HEADER_IW4X | (static_cast(XFILE_VERSION_IW4X) << 32), -#endif - XFILE_VERSION, - Game::XFileLanguage::XLANG_NONE, - fileTime.dwHighDateTime, - fileTime.dwLowDateTime - }; - - std::string outBuffer; - outBuffer.append(reinterpret_cast(&header), sizeof(header)); - - std::string zoneBuffer = this->buffer.toBuffer(); - -#ifdef GENERATE_IW4X_SPECIFIC_ZONES - // Insert a random byte, this will destroy the whole alignment and result in a crash, if not handled - zoneBuffer.insert(zoneBuffer.begin(), static_cast(Utils::Cryptography::Rand::GenerateInt())); - - char lastByte = 0; - for(unsigned int i = 0; i < zoneBuffer.size(); ++i ) - { - char oldLastByte = lastByte; - lastByte = zoneBuffer[i]; - - Utils::RotLeft(zoneBuffer[i], 6); - zoneBuffer[i] ^= -1; - Utils::RotRight(zoneBuffer[i], 4); - zoneBuffer[i] ^= oldLastByte; - } -#endif - - Utils::IO::WriteFile("uncompressed", zoneBuffer); - const auto _0 = gsl::finally([] - { - Utils::IO::RemoveFile("uncompressed"); - }); - - zoneBuffer = Utils::Compression::ZLib::Compress(zoneBuffer); - outBuffer.append(zoneBuffer); - - std::string outFile = "zone/" + this->zoneName + ".ff"; - Utils::IO::WriteFile(outFile, outBuffer); - - Logger::Print("done.\n"); - Logger::Print("Zone '{}' written with {} assets and {} script strings\n", outFile, (this->aliasList.size() + this->loadedAssets.size()), this->scriptStrings.size()); - } - - void ZoneBuilder::Zone::saveData() - { - // Add header - Game::ZoneHeader zoneHeader = { 0 }; - zoneHeader.assetList.assetCount = this->loadedAssets.size(); - Utils::Stream::ClearPointer(&zoneHeader.assetList.assets); - - // Increment ScriptStrings count (for empty script string) if available - zoneHeader.assetList.stringList.count = this->scriptStrings.size() + 1; - Utils::Stream::ClearPointer(&zoneHeader.assetList.stringList.strings); - - // Write header - this->buffer.save(&zoneHeader, sizeof(Game::ZoneHeader)); - this->buffer.pushBlock(Game::XFILE_BLOCK_VIRTUAL); // Push main stream onto the stream stack - - // Write ScriptStrings, if available - this->buffer.saveNull(4); - // Empty script string? - // This actually represents a NULL string, but as scriptString. - // So scriptString loading for NULL scriptStrings from fastfile results in a NULL scriptString. - // That's the reason why the count is incremented by 1, if scriptStrings are available. - - // Write ScriptString pointer table - for (std::size_t i = 0; i < this->scriptStrings.size(); ++i) - { - this->buffer.saveMax(4); - } - - // Write ScriptStrings - for (auto ScriptString : this->scriptStrings) - { - this->buffer.saveString(ScriptString.data()); - } - - // Align buffer (4 bytes) to get correct offsets for pointers - this->buffer.align(Utils::Stream::ALIGN_4); - this->indexStart = this->buffer.getBlockSize(Game::XFILE_BLOCK_VIRTUAL); // Mark AssetTable offset - - // AssetTable - for (auto asset : this->loadedAssets) - { - Game::XAsset entry = { asset.type, nullptr }; - Utils::Stream::ClearPointer(&entry.header.data); - - this->buffer.save(&entry); - } - - // Assets - for (auto asset : this->loadedAssets) - { - this->buffer.pushBlock(Game::XFILE_BLOCK_TEMP); - this->buffer.align(Utils::Stream::ALIGN_4); - - - this->store(asset.header); - AssetHandler::ZoneSave(asset, this); - - this->buffer.popBlock(); - } - - // Adapt header - this->buffer.enterCriticalSection(); - Game::XFile* header = reinterpret_cast(this->buffer.data()); - header->size = this->buffer.length() - sizeof(Game::XFile); // Write correct data size - header->externalSize = this->externalSize; // This actually stores how much external data has to be loaded. It's used to calculate the loadscreen progress - - // Write stream sizes - for (int i = 0; i < Game::MAX_XFILE_COUNT; ++i) - { - header->blockSize[i] = this->buffer.getBlockSize(static_cast(i)); - } - - this->buffer.leaveCriticalSection(); - this->buffer.popBlock(); - } - - // Add branding asset - void ZoneBuilder::Zone::addBranding() - { - const auto now = std::chrono::system_clock::now(); - - auto zoneBranding = std::format("Built using the IW4x ZoneBuilder! {:%d-%m-%Y %H:%M:%OS}", now); - auto brandingLen = zoneBranding.size(); // + 1 is added by the save code - - this->branding = {this->zoneName.data(), 0, static_cast(brandingLen), getAllocator()->duplicateString(zoneBranding)}; - - if (this->findAsset(Game::ASSET_TYPE_RAWFILE, this->branding.name) != -1) - { - Logger::Error(Game::ERR_FATAL, "Unable to add branding. Asset '{}' already exists!", this->branding.name); - } - - Game::XAssetHeader header = { &this->branding }; - Game::XAsset brandingAsset = { Game::ASSET_TYPE_RAWFILE, header }; - this->loadedAssets.push_back(brandingAsset); - } - - // Check if the given pointer has already been mapped - bool ZoneBuilder::Zone::hasPointer(const void* pointer) - { - return this->pointerMap.contains(pointer); - } - - // Get stored offset for given file pointer - unsigned int ZoneBuilder::Zone::safeGetPointer(const void* pointer) - { - if (this->hasPointer(pointer)) - { - return this->pointerMap[pointer]; - } - - return NULL; - } - - void ZoneBuilder::Zone::storePointer(const void* pointer) - { - this->pointerMap[pointer] = this->buffer.getPackedOffset(); - } - - void ZoneBuilder::Zone::storeAlias(Game::XAsset asset) - { - if (!this->hasAlias(asset)) - { - this->aliasList.push_back({ asset, this->buffer.getPackedOffset() }); - } - } - - unsigned int ZoneBuilder::Zone::getAlias(Game::XAsset asset) - { - std::string name = Game::DB_GetXAssetName(&asset); - - for (auto& entry : this->aliasList) - { - if (asset.type == entry.first.type && name == Game::DB_GetXAssetName(&entry.first)) - { - return entry.second; - } - } - - return 0; - } - - int ZoneBuilder::Zone::addScriptString(const std::string& str) - { - return this->addScriptString(static_cast(Game::SL_GetString(str.data(), 0))); - } - - // Mark a scriptString for writing and map it. - int ZoneBuilder::Zone::addScriptString(unsigned short gameIndex) - { - // Handle NULL scriptStrings - // Might optimize that later - if (!gameIndex) - { - if (this->scriptStrings.empty()) - { - this->scriptStrings.push_back(""); - } - - return 0; - } - - std::string str = Game::SL_ConvertToString(gameIndex); - int prev = this->findScriptString(str); - - if (prev > 0) - { - this->scriptStringMap[gameIndex] = prev; - return prev; - } - - this->scriptStrings.push_back(str); - this->scriptStringMap[gameIndex] = this->scriptStrings.size(); - return this->scriptStrings.size(); - } - - // Find a local scriptString - int ZoneBuilder::Zone::findScriptString(const std::string& str) - { - for (unsigned int i = 0; i < this->scriptStrings.size(); ++i) - { - if (this->scriptStrings[i] == str) - { - return (i + 1); - } - } - - return -1; - } - - void ZoneBuilder::Zone::addRawAsset(Game::XAssetType type, void* ptr) - { - this->loadedAssets.push_back({type, {ptr}}); - } - - // Remap a scriptString to it's corresponding value in the local scriptString table. - void ZoneBuilder::Zone::mapScriptString(unsigned short& gameIndex) - { - gameIndex = 0xFFFF & this->scriptStringMap[gameIndex]; - } - - // Store a new name for a given asset - void ZoneBuilder::Zone::renameAsset(Game::XAssetType type, const std::string& asset, const std::string& newName) - { - if (type < Game::XAssetType::ASSET_TYPE_COUNT && type >= 0) - { - this->renameMap[type][asset] = newName; - } - else - { - Logger::Error(Game::ERR_FATAL, "Unable to rename '{}' to '{}' as the asset type is invalid!", asset, newName); - } - } - - // Return the new name for a given asset - std::string ZoneBuilder::Zone::getAssetName(Game::XAssetType type, const std::string& asset) - { - if (type < Game::XAssetType::ASSET_TYPE_COUNT && type >= 0) - { - if (this->renameMap[type].contains(asset)) - { - return this->renameMap[type][asset]; - } - } - else - { - Logger::Error(Game::ERR_FATAL, "Unable to get name for '{}' as the asset type is invalid!", asset); - } - - return asset; - } - - void ZoneBuilder::Zone::store(Game::XAssetHeader header) - { - if (!this->hasPointer(header.data)) // We should never have to restore a pointer, so this expression should always resolve into false - { - this->storePointer(header.data); - } - } - - void ZoneBuilder::Zone::incrementExternalSize(unsigned int size) - { - this->externalSize += size; - } - - bool ZoneBuilder::IsEnabled() - { - static std::optional flag; - - if (!flag.has_value()) - { - flag.emplace(Flags::HasFlag("zonebuilder")); - } - - return (flag.value() && !Dedicated::IsEnabled()); - } - - void ZoneBuilder::BeginAssetTrace(const std::string& zone) - { - ZoneBuilder::TraceZone = zone; - } - - std::vector> ZoneBuilder::EndAssetTrace() - { - ZoneBuilder::TraceZone.clear(); - - std::vector> AssetTrace; - Utils::Merge(&AssetTrace, ZoneBuilder::TraceAssets); - - ZoneBuilder::TraceAssets.clear(); - - return AssetTrace; - } - - Game::XAssetHeader ZoneBuilder::GetEmptyAssetIfCommon(Game::XAssetType type, const std::string& name, ZoneBuilder::Zone* builder) - { - Game::XAssetHeader header = { nullptr }; - - if (type >= 0 && type < Game::XAssetType::ASSET_TYPE_COUNT) - { - int zoneIndex = Game::DB_GetZoneIndex("common_mp"); - - if (zoneIndex > 0) - { - Game::XAssetEntry* entry = Game::DB_FindXAssetEntry(type, name.data()); - - if (entry && entry->zoneIndex == zoneIndex) - { - // Allocate an empty asset (filled with zeros) - header.data = builder->getAllocator()->allocate(Game::DB_GetXAssetSizeHandlers[type]()); - - // Set the name to the original name, so it can be stored - Game::DB_SetXAssetNameHandlers[type](&header, name.data()); - AssetHandler::StoreTemporaryAsset(type, header); - - // Set the name to the empty name - Game::DB_SetXAssetNameHandlers[type](&header, builder->getAllocator()->duplicateString("," + name)); - } - } - } - - return header; - } - - void ZoneBuilder::RefreshExporterWorkDirectory() - { - if (ZoneBuilder::DumpingZone.empty()) - { - ExporterAPI.set_work_path(std::format("userraw/dump/stray")); - } - else - { - ExporterAPI.set_work_path(std::format("userraw/dump/{}", ZoneBuilder::DumpingZone)); - } - } - - iw4of::api* ZoneBuilder::GetExporter() - { - return &ExporterAPI; - } - - iw4of::params_t ZoneBuilder::Zone::getIW4OfApiParams() - { - iw4of::params_t params{}; - - params.write_only_once = true; - - params.find_other_asset = [this](int type, const std::string& name) -> void* - { - return AssetHandler::FindAssetForZone(static_cast(type), name, this).data; - }; - - params.fs_read_file = [](const std::string& filename) -> std::string - { - auto file = FileSystem::File(filename); - if (file.exists()) - { - return file.getBuffer(); - } - - return {}; - }; - - params.store_in_string_table = [](const std::string& text) -> unsigned int - { - return Game::SL_GetString(text.data(), 0); - }; - - params.print = [](iw4of::params_t::print_type t, const std::string& message) -> void - { - switch (t) - { - case iw4of::params_t::P_ERR: - Logger::Error(Game::ERR_FATAL, "{}", message); - break; - case iw4of::params_t::P_WARN: - Logger::Print("{}", message); - break; - } - }; - - if (*Game::fs_basepath && *Game::fs_gameDirVar) - { - params.work_directory = std::format("{}/{}", (*Game::fs_basepath)->current.string, (*Game::fs_gameDirVar)->current.string); - } - else - { - Logger::Error(Game::ERR_FATAL, "Missing FS Game directory or basepath directory!"); - } - - return params; - } - - int ZoneBuilder::StoreTexture(Game::GfxImageLoadDef **loadDef, Game::GfxImage *image) - { - size_t size = 16 + (*loadDef)->resourceSize; - void* data = Utils::Memory::GetAllocator()->allocate(size); - std::memcpy(data, *loadDef, size); - - image->texture.loadDef = static_cast(data); - - return 0; - } - - void ZoneBuilder::ReleaseTexture(Game::XAssetHeader header) - { - if (header.image && header.image->texture.loadDef) - { - Utils::Memory::GetAllocator()->free(header.image->texture.loadDef); - } - } - - void ZoneBuilder::AssumeMainThreadRole() - { - ZoneBuilder::MainThreadInterrupted = true; - ZoneBuilder::InterruptingThreadId = GetCurrentThreadId(); - } - - void ZoneBuilder::ResetThreadRole() - { - ZoneBuilder::MainThreadInterrupted = false; - ZoneBuilder::InterruptingThreadId = 0x0; - } - - bool ZoneBuilder::IsThreadMainThreadHook() - { - // this is the thread that is interrupting so let it act as the main thread - if (ZoneBuilder::MainThreadInterrupted && GetCurrentThreadId() == ZoneBuilder::InterruptingThreadId) - { - return true; - } - - // block the main thread from doing anything "main thread" specific while - // the other thread is interrupting - - //while (ZoneBuilder::mainThreadInterrupted) std::this_thread::sleep_for(100ms); - - // normal functionality - return GetCurrentThreadId() == Utils::Hook::Get(0x1CDE7FC); - } - - static Game::XZoneInfo baseZones[] = - { - { "code_pre_gfx_mp", Game::DB_ZONE_CODE, 0 }, - { "localized_code_pre_gfx_mp", Game::DB_ZONE_CODE_LOC, 0 }, - { "code_post_gfx_mp", Game::DB_ZONE_CODE, 0 }, - { "localized_code_post_gfx_mp", Game::DB_ZONE_CODE_LOC, 0 }, - { "common_mp", Game::DB_ZONE_COMMON, 0 }, - { "localized_common_mp", Game::DB_ZONE_COMMON_LOC, 0 }, - { "ui_mp", Game::DB_ZONE_GAME, 0 }, - { "localized_ui_mp", Game::DB_ZONE_GAME, 0 } - }; - - void ZoneBuilder::Com_Quitf_t() - { - ExitProcess(0); - } - - void ZoneBuilder::CommandThreadCallback() - { - Com_InitThreadData(); - - while (!ZoneBuilder::CommandThreadTerminate) - { - ZoneBuilder::AssumeMainThreadRole(); - Utils::Hook::Call(0x4E2C80)(0, 0); // Cbuf_Execute - ZoneBuilder::ResetThreadRole(); - std::this_thread::sleep_for(1ms); - } - } - - BOOL APIENTRY ZoneBuilder::EntryPoint(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int /*nShowCmd*/) - { - Utils::Hook::Call(0x42F0A0)(); // Com_InitCriticalSections - Utils::Hook::Call(0x4301B0)(); // Com_InitMainThread - Utils::Hook::Call(0x406D10)(0); // Win_InitLocalization - Utils::Hook::Call(0x4FF220)(); // Com_InitParse - Utils::Hook::Call(0x4D8220)(); // Dvar_Init - Utils::Hook::Call(0x4D2280)(); // SL_Init - Utils::Hook::Call(0x48F660)(); // Cmd_Init - Utils::Hook::Call(0x4D9210)(); // Cbuf_Init - Utils::Hook::Call(0x47F390)(); // Swap_Init - Utils::Hook::Call(0x60AD10)(); // Com_InitDvars - Utils::Hook::Call(0x420830)(); // Com_InitHunkMemory - Utils::Hook::Call(0x4A62A0)(); // LargeLocalInit - Utils::Hook::Call(0x4DCC10)(); // Sys_InitCmdEvents - Utils::Hook::Call(0x64A020)(); // PMem_Init - - if (!Flags::HasFlag("stdout")) - { - Console::ShowAsyncConsole(); - Utils::Hook::Call(0x43D140)(); // Com_EventLoop - } - - - Utils::Hook::Call(0x502580)(static_cast(__rdtsc())); // Netchan_Init - Utils::Hook::Call(0x429080)(); // FS_InitFileSystem - Utils::Hook::Call(0x4BFBE0)(); // Con_InitChannels - Utils::Hook::Call(0x4E0FB0)(); // DB_InitThread - Utils::Hook::Call(0x5196C0)(); // R_RegisterDvars - Game::NET_Init(); - Utils::Hook::Call(0x4F5090)(); // SND_InitDriver - Utils::Hook::Call(0x46A630)(); // SND_Init - Utils::Hook::Call(0x43D140)(); // Com_EventLoop - - ZoneBuilder::CommandThread = Utils::Thread::CreateNamedThread("Command Thread", ZoneBuilder::CommandThreadCallback); - ZoneBuilder::CommandThread.detach(); - - Command::Add("quit", ZoneBuilder::Com_Quitf_t); - - // now load default assets and shaders - Game::DB_LoadXAssets(baseZones, ARRAYSIZE(baseZones), 0); - - Logger::Print("Waiting for fastiles to load...\n"); - while (!Game::Sys_IsDatabaseReady()) - { - Utils::Hook::Call(0x43D140)(); // Com_EventLoop - std::this_thread::sleep_for(100ms); - } - Logger::Print("Done!\n"); - - // defaults need to load before we do this - Utils::Hook::Call(0x4E1F30)(); // G_SetupWeaponDef - Utils::Hook::Call(0x4454C0)(); // Item_SetupKeywordHash (for loading menus) - Utils::Hook::Call(0x501BC0)(); // Menu_SetupKeywordHash (for loading menus) - Utils::Hook::Call(0x4A1280)(); // something related to uiInfoArray - - - Utils::Hook::Call(0x464A90)(GetCommandLineA()); // Com_ParseCommandLine - Utils::Hook::Call(0x60C3D0)(); // Com_AddStartupCommands - - // so for this i'm going to say that we just run the commands (after + signs) - // and don't spawn into a shell because why not? - if (Flags::HasFlag("stdout")) - { - Utils::Hook::Call(0x440EC0)(); // DB_Update - Utils::Hook::Call(0x43D140)(); // Com_EventLoop - Utils::Hook::Call(0x4E2C80)(0, 0); // Cbuf_Execute - - return 0; - } - - Logger::Print(" --------------------------------------------------------------------------------\n"); - Logger::Print(" IW4x ZoneBuilder - {}\n", REVISION_STR); - Logger::Print(" Commands:\n"); - Logger::Print("\t-buildzone [zone]: builds a zone from a csv located in zone_source\n"); - Logger::Print("\t-buildall: builds all zones in zone_source\n"); - Logger::Print("\t-verifyzone [zone]: loads and verifies the specified zone\n"); - Logger::Print("\t-dumpzone [zone]: loads and dump the specified zone\n"); - Logger::Print("\t-listassets [assettype]: lists all loaded assets of the specified type\n"); - Logger::Print("\t-quit: quits the program\n"); - Logger::Print(" --------------------------------------------------------------------------------\n"); - - // now run main loop until quit - unsigned int frames = 0; - while (true) - { - if (frames % 100 == 0) - { - Utils::Hook::Call(0x440EC0)(); // DB_Update - Utils::Hook::Call(0x43EBB0)(); // check for quit - } - - Utils::Hook::Call(0x43D140)(); // Com_EventLoop - std::this_thread::sleep_for(1ms); - frames++; - } - - return 0; - } - - void ZoneBuilder::HandleError(Game::errorParm_t code, const char* fmt, ...) - { - char buffer[0x1000]{}; - va_list ap; - - va_start(ap, fmt); - vsnprintf_s(buffer, _TRUNCATE, fmt, ap); - va_end(ap); - - if (!Flags::HasFlag("stdout")) - { - MessageBoxA(nullptr, buffer, "Error!", MB_OK | MB_ICONERROR); - } - else - { - perror(buffer); - fflush(stderr); - } - - if (code == Game::ERR_FATAL) - { - ExitProcess(1); - } - } - - __declspec(naked) void ZoneBuilder::SoftErrorAssetOverflow() - { - // fuck with the stack to return to before DB_AddXAsset - __asm - { - add esp, 12 // exit from DB_AllocXAssetEntry - pop edi - pop esi - pop ebp - pop ebx - add esp, 14h - mov eax, [esp + 8] - retn - } - } - - std::string ZoneBuilder::FindMaterialByTechnique(const std::string& techniqueName) - { - static bool replacementFound = false; - replacementFound = false; // the above one only runs the first time - - const char* ret = "default"; - - Game::DB_EnumXAssetEntries(Game::XAssetType::ASSET_TYPE_MATERIAL, [techniqueName, &ret](Game::XAssetEntry* entry) - { - if (!replacementFound) - { - Game::XAssetHeader header = entry->asset.header; - std::string name = techniqueName; - if (name[0] == ',') name = name.substr(1); - if (name == header.material->techniqueSet->name) - { - ret = header.material->info.name; - replacementFound = true; - } - } - }, false); - - if (replacementFound) return ret; - return ""; - } - - void ZoneBuilder::ReallocateLoadedSounds(void*& data, [[maybe_unused]] void* a2) - { - assert(data); - auto* sound = Utils::Hook::Get(0x112AE04); - const auto length = sound->info.data_len; - const auto allocatedSpace = Game::Z_Malloc(static_cast(length)); - memcpy_s(allocatedSpace, length, data, length); - - data = allocatedSpace; - sound->data = static_cast(allocatedSpace); - sound->info.data_ptr = allocatedSpace; - } - - Game::Sys_File ZoneBuilder::Sys_CreateFile_Stub(const char* dir, const char* filename) - { - auto file = Game::Sys_CreateFile(dir, filename); - - if (file.handle == INVALID_HANDLE_VALUE) - { - file = Game::Sys_CreateFile("zone\\zonebuilder\\", filename); - } - - return file; - } - - iw4of::params_t ZoneBuilder::GetExporterAPIParams() - { - iw4of::params_t params{}; - - params.write_only_once = true; - - params.find_other_asset = [](int type, const std::string& name) -> void* - { - if (ZoneBuilder::DumpingZone.empty()) - { - return Game::DB_FindXAssetHeader(static_cast(type), name.data()).data; - } - - // Do not deadlock the DB - return nullptr; - }; - - params.fs_read_file = [](const std::string& filename) -> std::string - { - auto file = FileSystem::File(filename); - if (file.exists()) - { - return file.getBuffer(); - } - - return {}; - }; - - params.get_from_string_table = [](const unsigned int& id) -> std::string - { - return Game::SL_ConvertToString(static_cast(id)); - }; - - params.print = [](iw4of::params_t::print_type t, const std::string& message) -> void - { - switch (t) - { - case iw4of::params_t::P_ERR: - Logger::Error(Game::ERR_FATAL, "{}", message); - break; - case iw4of::params_t::P_WARN: - Logger::Print("{}", message); - break; - } - }; - - return params; - } - - ZoneBuilder::ZoneBuilder() - { - // ReSharper disable CppStaticAssertFailure - AssertSize(Game::XFileHeader, 21); - AssertSize(Game::XFile, 40); - static_assert(Game::MAX_XFILE_COUNT == 8, "XFile block enum is invalid!"); - - if (ZoneBuilder::IsEnabled()) - { - // Prevent loading textures (preserves loaddef) - //Utils::Hook::Set(Game::Load_Texture, 0xC3); - - Utils::Hook(0x5BC832, Sys_CreateFile_Stub, HOOK_CALL).install()->quick(); - - // Store the loaddef - Utils::Hook(Game::Load_Texture, StoreTexture, HOOK_JUMP).install()->quick(); - - // Release the loaddef - Game::DB_ReleaseXAssetHandlers[Game::XAssetType::ASSET_TYPE_IMAGE] = ZoneBuilder::ReleaseTexture; - - // r_loadForrenderer = 0 - Utils::Hook::Set(0x519DDF, 0); - - // r_delayloadimage ret - Utils::Hook::Set(0x51F450, 0xC3); - - // r_registerDvars hack - Utils::Hook::Set(0x51B1CD, 0xC3); - - // Prevent destroying textures - Utils::Hook::Set(0x51F03D, 0xEB); - - // Don't create default assets - Utils::Hook::Set(0x407BAA, 0xEB); - - // Don't mark clip maps as 'in use' - Utils::Hook::Nop(0x405E07, 7); - - // Don't mark assets - //Utils::Hook::Nop(0x5BB632, 5); - - // Load sounds - Utils::Hook(0x492EFC, ReallocateLoadedSounds, HOOK_CALL).install()->quick(); - - // Don't display errors when assets are missing (we might manually build those) - Utils::Hook::Nop(0x5BB3F2, 5); - Utils::Hook::Nop(0x5BB422, 5); - Utils::Hook::Nop(0x5BB43A, 5); - - // Don't read stats - Utils::Hook(0x4875E1, 0x487717, HOOK_JUMP).install()->quick(); - - // patch g_copyInfo because we're using so many more assets than originally intended - int newLimit = 0x2000; - int* g_copyInfo_new = Utils::Memory::GetAllocator()->allocateArray(newLimit); - Utils::Hook::Set(0x494083, g_copyInfo_new); // DB_DelayLoadImages - Utils::Hook::Set(0x5BB9CC, g_copyInfo_new); // DB_AddXAsset - Utils::Hook::Set(0x5BC723, g_copyInfo_new); // DB_PostLoadXZone - Utils::Hook::Set(0x5BC759, g_copyInfo_new); - Utils::Hook::Set(0x5BB9AD, newLimit); // limit check - - // hunk size (was 300 MiB) - Utils::Hook::Set(0x64A029, 0x38400000); // 900 MiB - Utils::Hook::Set(0x64A057, 0x38400000); - - // change FS_GameDirDomainFunc - Utils::Hook::Set(0x643203, [](Game::dvar_t* dvar, Game::DvarValue value) - { - int result = Utils::Hook::Call(0x642FC0)(dvar, value); - - if (result) - { - if (std::strcmp(value.string, dvar->current.string) != 0) - { - dvar->current.string = value.string; - Game::FS_Restart(0, 0); - } - } - - return result; - }); - - // set new entry point - Utils::Hook(0x4513DA, ZoneBuilder::EntryPoint, HOOK_JUMP).install()->quick(); - - // set quit handler - Utils::Hook(0x4D4000, ZoneBuilder::Com_Quitf_t, HOOK_JUMP).install()->quick(); - - // handle Com_error Calls - Utils::Hook(Game::Com_Error, ZoneBuilder::HandleError, HOOK_JUMP).install()->quick(); - - // Sys_IsMainThread hook - Utils::Hook(0x4C37D0, ZoneBuilder::IsThreadMainThreadHook, HOOK_JUMP).install()->quick(); - - // Don't exec startup config in fs_restart - Utils::Hook::Set(0x461B48, 0xEB); - - // remove overriding asset messages - Utils::Hook::Nop(0x5BC74E, 5); - - // don't remap techsets - Utils::Hook::Nop(0x5BC791, 5); - - AssetHandler::OnLoad([](Game::XAssetType type, Game::XAssetHeader asset, const std::string& name, bool* /*restrict*/) - { - if (!ZoneBuilder::TraceZone.empty() && ZoneBuilder::TraceZone == FastFiles::Current()) - { - ZoneBuilder::TraceAssets.emplace_back(std::make_pair(type, name)); -#ifdef _DEBUG - OutputDebugStringA(Utils::String::Format("%s\n", name)); -#endif - } - - if (!ZoneBuilder::DumpingZone.empty()) - { - if (ExporterAPI.is_type_supported(type) && name[0] != ',') - { - ExporterAPI.write(type, asset.data); - Components::Logger::Print("."); - } - } - }); - - Command::Add("dumpzone", [](const Command::Params* params) - { - if (params->size() < 2) return; - - std::string zone = params->get(1); - ZoneBuilder::DumpingZone = zone; - ZoneBuilder::RefreshExporterWorkDirectory(); - - Game::XZoneInfo info; - info.name = zone.data(); - info.allocFlags = Game::DB_ZONE_MOD; - info.freeFlags = 0; - - Logger::Print("Dumping zone '{}'...\n", zone); - - Game::DB_LoadXAssets(&info, 1, true); - AssetHandler::FindOriginalAsset(Game::ASSET_TYPE_RAWFILE, zone.data()); // Lock until zone is loaded - - Logger::Print("Unloading zone '{}'...\n", zone); - info.freeFlags = Game::DB_ZONE_MOD; - info.allocFlags = 0; - info.name = nullptr; - - Game::DB_LoadXAssets(&info, 1, true); - AssetHandler::FindOriginalAsset(Game::ASSET_TYPE_RAWFILE, "default"); // Lock until zone is unloaded - Logger::Print("Zone '{}' dumped", ZoneBuilder::DumpingZone); - ZoneBuilder::DumpingZone = std::string(); - }); - - Command::Add("verifyzone", [](const Command::Params* params) - { - if (params->size() < 2) return; - - std::string zone = params->get(1); - - ZoneBuilder::BeginAssetTrace(zone); - - Game::XZoneInfo info; - info.name = zone.data(); - info.allocFlags = Game::DB_ZONE_MOD; - info.freeFlags = 0; - - Logger::Print("Loading zone '{}'...\n", zone); - - Game::DB_LoadXAssets(&info, 1, true); - AssetHandler::FindOriginalAsset(Game::XAssetType::ASSET_TYPE_RAWFILE, zone.data()); // Lock until zone is loaded - - auto assets = ZoneBuilder::EndAssetTrace(); - - Logger::Print("Unloading zone '{}'...\n", zone); - info.freeFlags = Game::DB_ZONE_MOD; - info.allocFlags = 0; - info.name = nullptr; - - Game::DB_LoadXAssets(&info, 1, true); - AssetHandler::FindOriginalAsset(Game::XAssetType::ASSET_TYPE_RAWFILE, "default"); // Lock until zone is unloaded - - Logger::Print("Zone '{}' loaded with {} assets:\n", zone, assets.size()); - - int count = 0; - for (auto i = assets.begin(); i != assets.end(); ++i, ++count) - { - Logger::Print(" {}: {}: {}\n", count, Game::DB_GetXAssetTypeName(i->first), i->second); - } - - Logger::Print("\n"); - }); - - Command::Add("buildzone", [](const Command::Params* params) - { - if (params->size() < 2) return; - - std::string zoneName = params->get(1); - Logger::Print("Building zone '{}'...\n", zoneName); - - Zone(zoneName).build(); - }); - - Command::Add("buildall", []() - { - auto path = std::format("{}\\zone_source", (*Game::fs_basepath)->current.string); - auto zoneSources = FileSystem::GetSysFileList(path, "csv", false); - - for (auto source : zoneSources) - { - if (Utils::String::EndsWith(source, ".csv")) - { - source = source.substr(0, source.find(".csv")); - } - - Command::Execute(std::format("buildzone {}", source), true); - } - }); - - static std::set curTechsets_list; - static std::set techsets_list; - - AssetHandler::OnLoad([](Game::XAssetType type, Game::XAssetHeader, const std::string& name, bool*) - { - if (type == Game::ASSET_TYPE_TECHNIQUE_SET) - { - if (name[0] == ',') return; // skip techsets from common_mp - if (techsets_list.find(name) == techsets_list.end()) - { - curTechsets_list.emplace(name); - techsets_list.emplace(name); - } - } - }); - - - AssetHandler::OnLoad([](Game::XAssetType type, Game::XAssetHeader asset, [[maybe_unused]] const std::string& name, [[maybe_unused]] bool* restrict) - { - if (type != Game::ASSET_TYPE_SOUND) - { - return; - } - - auto sound = asset.sound; - - for (size_t i = 0; i < sound->count; i++) - { - auto thisSound = sound->head[i]; - - if (thisSound.soundFile->type == Game::SAT_LOADED) - { - if (thisSound.soundFile->u.loadSnd->sound.data == nullptr) - { - // ouch - // This should never happen and will cause a memory leak - // Let's change it to a streamed sound instead - thisSound.soundFile->type = Game::SAT_STREAMED; - - auto virtualPath = std::filesystem::path(thisSound.soundFile->u.loadSnd->name); - - thisSound.soundFile->u.streamSnd.filename.info.raw.name = Utils::Memory::DuplicateString(virtualPath.filename().string()); - - auto dir = virtualPath.remove_filename().string(); - dir = dir.substr(0, dir.size() - 1); // remove / - thisSound.soundFile->u.streamSnd.filename.info.raw.dir = Utils::Memory::DuplicateString(dir); - } - } - } - }); - - Command::Add("buildtechsets", [](const Command::Params*) - { - Utils::IO::CreateDir("zone_source/techsets"); - Utils::IO::CreateDir("zone/techsets"); - - std::string csvStr; - - const auto dir = std::format("zone/{}", Game::Win_GetLanguage()); - auto fileList = Utils::IO::ListFiles(dir, false); - for (const auto& entry : fileList) - { - auto zone = entry.path().string(); - Utils::String::Replace(zone, Utils::String::VA("zone/%s/", Game::Win_GetLanguage()), ""); - Utils::String::Replace(zone, ".ff", ""); - - if (Utils::IO::FileExists("zone/techsets/" + zone + "_techsets.ff")) - { - Logger::Print("Skipping previously generated zone {}\n", zone); - continue; - } - - if (zone.find("_load") != std::string::npos) - { - Logger::Print("Skipping loadscreen zone {}\n", zone); - continue; - } - - if (Game::DB_IsZoneLoaded(zone.c_str()) || !FastFiles::Exists(zone)) - { - continue; - } - - if (zone[0] == '.') continue; // fucking mac dotfiles - - curTechsets_list.clear(); // clear from last run - - // load the zone - Game::XZoneInfo info; - info.name = zone.c_str(); - info.allocFlags = Game::DB_ZONE_MOD; - info.freeFlags = 0x0; - Game::DB_LoadXAssets(&info, 1, 0); - - while (!Game::Sys_IsDatabaseReady()) std::this_thread::sleep_for(100ms); // wait till its fully loaded - - if (curTechsets_list.empty()) - { - Logger::Print("Skipping empty zone {}\n", zone); - // unload zone - info.name = nullptr; - info.allocFlags = 0x0; - info.freeFlags = Game::DB_ZONE_MOD; - Game::DB_LoadXAssets(&info, 1, true); - continue; - } - - // ok so we're just gonna use the materials because they will use the techsets - csvStr.clear(); - for (auto tech : curTechsets_list) - { - std::string mat = ZoneBuilder::FindMaterialByTechnique(tech); - if (mat.length() == 0) - { - csvStr.append("techset," + tech + "\n"); - } - else - { - csvStr.append("material," + mat + "\n"); - } - } - - // save csv - Utils::IO::WriteFile("zone_source/techsets/" + zone + "_techsets.csv", csvStr); - - // build the techset zone - std::string zoneName = "techsets/" + zone + "_techsets"; - Logger::Print("Building zone '{}'...\n", zoneName); - Zone(zoneName).build(); - - // unload original zone - info.name = nullptr; - info.allocFlags = 0x0; - info.freeFlags = Game::DB_ZONE_MOD; - Game::DB_LoadXAssets(&info, 1, true); - - while (!Game::Sys_IsDatabaseReady()) std::this_thread::sleep_for(10ms); // wait till its fully loaded - } - - curTechsets_list.clear(); - techsets_list.clear(); - - Game::DB_EnumXAssets(Game::ASSET_TYPE_TECHNIQUE_SET, [](Game::XAssetHeader header, void*) - { - curTechsets_list.emplace(header.techniqueSet->name); - techsets_list.emplace(header.techniqueSet->name); - }, nullptr, false); - - // HACK: set language to 'techsets' to load from that dir - const char* language = Utils::Hook::Get(0x649E740); - Utils::Hook::Set(0x649E740, "techsets"); - - // load generated techset fastfiles - auto list = Utils::IO::ListFiles("zone/techsets", false); - int i = 0; - int subCount = 0; - for (const auto& entry : list) - { - auto it = entry.path().string(); - - Utils::String::Replace(it, "zone/techsets/", ""); - Utils::String::Replace(it, ".ff", ""); - - if (it.find("_techsets") == std::string::npos) continue; // skip files we didn't generate for this - - if (!Game::DB_IsZoneLoaded(it.data())) - { - Game::XZoneInfo info; - info.name = it.data(); - info.allocFlags = Game::DB_ZONE_MOD; - info.freeFlags = 0; - - Game::DB_LoadXAssets(&info, 1, 0); - while (!Game::Sys_IsDatabaseReady()) std::this_thread::sleep_for(10ms); // wait till its fully loaded - } - else - { - Logger::Print("Zone '{}' already loaded\n", it); - } - - if (i == 20) // cap at 20 just to be safe - { - // create csv with the techsets in it - csvStr.clear(); - for (auto tech : curTechsets_list) - { - std::string mat = ZoneBuilder::FindMaterialByTechnique(tech); - if (mat.length() == 0) - { - csvStr.append("techset," + tech + "\n"); - } - else - { - csvStr.append("material," + mat + "\n"); - } - } - - std::string tempZoneFile = Utils::String::VA("zone_source/techsets/techsets%d.csv", subCount); - std::string tempZone = Utils::String::VA("techsets/techsets%d", subCount); - - Utils::IO::WriteFile(tempZoneFile, csvStr); - - Logger::Print("Building zone '{}'...\n", tempZone); - Zone(tempZone).build(); - - // unload all zones - Game::XZoneInfo info; - info.name = nullptr; - info.allocFlags = 0x0; - info.freeFlags = Game::DB_ZONE_MOD; - Game::DB_LoadXAssets(&info, 1, true); - - Utils::Hook::Set(0x649E740, "techsets"); - - i = 0; - subCount++; - curTechsets_list.clear(); - techsets_list.clear(); - } - - i++; - } - - // last iteration - if (i != 0) - { - // create csv with the techsets in it - csvStr.clear(); - for (auto tech : curTechsets_list) - { - std::string mat = ZoneBuilder::FindMaterialByTechnique(tech); - if (mat.length() == 0) - { - Logger::Print("Couldn't find a material for techset {}. Sort Keys will be incorrect.\n", tech); - csvStr.append("techset," + tech + "\n"); - } - else - { - csvStr.append("material," + mat + "\n"); - } - } - - std::string tempZoneFile = Utils::String::VA("zone_source/techsets/techsets%d.csv", subCount); - std::string tempZone = Utils::String::VA("techsets/techsets%d", subCount); - - Utils::IO::WriteFile(tempZoneFile, csvStr); - - Logger::Print("Building zone '{}'...\n", tempZone); - Zone(tempZone).build(); - - // unload all zones - Game::XZoneInfo info; - info.name = nullptr; - info.allocFlags = 0x0; - info.freeFlags = Game::DB_ZONE_MOD; - Game::DB_LoadXAssets(&info, 1, true); - - subCount++; - } - - // build final techsets fastfile - if (subCount > 24) - { - Logger::Error(Game::ERR_DROP, "How did you have 576 fastfiles?\n"); - } - - curTechsets_list.clear(); - techsets_list.clear(); - - for (int j = 0; j < subCount; ++j) - { - Game::XZoneInfo info; - info.name = Utils::String::VA("techsets%d", j); - info.allocFlags = Game::DB_ZONE_MOD; - info.freeFlags = 0; - - Game::DB_LoadXAssets(&info, 1, 0); - while (!Game::Sys_IsDatabaseReady()) std::this_thread::sleep_for(10ms); // wait till its fully loaded - } - - // create csv with the techsets in it - csvStr.clear(); - for (const auto& tech : curTechsets_list) - { - auto mat = ZoneBuilder::FindMaterialByTechnique(tech); - if (mat.length() == 0) - { - csvStr.append("techset," + tech + "\n"); - } - else - { - csvStr.append("material," + mat + "\n"); - } - } - - Utils::IO::WriteFile("zone_source/techsets/techsets.csv", csvStr); - - // set language back - Utils::Hook::Set(0x649E740, language); - - Logger::Print("Building zone 'techsets/techsets'...\n"); - Zone("techsets/techsets").build(); - }); - - Command::Add("listassets", [](const Command::Params* params) - { - if (params->size() < 2) return; - Game::XAssetType type = Game::DB_GetXAssetNameType(params->get(1)); - - if (type != Game::XAssetType::ASSET_TYPE_INVALID) - { - Game::DB_EnumXAssets(type, [](Game::XAssetHeader header, void* data) - { - Game::XAsset asset = { *reinterpret_cast(data), header }; - Logger::Print("{}\n", Game::DB_GetXAssetName(&asset)); - }, &type, false); - } - }); - - Command::Add("loadtempzone", [](const Command::Params* params) - { - if (params->size() < 2) return; - - if (FastFiles::Exists(params->get(1))) - { - Game::XZoneInfo info; - info.name = params->get(1); - info.allocFlags = 0x80; - info.freeFlags = 0x0; - Game::DB_LoadXAssets(&info, 1, 0); - } - }); - - Command::Add("unloadtempzones", [](const Command::Params*) - { - Game::XZoneInfo info; - info.name = nullptr; - info.allocFlags = 0x0; - info.freeFlags = 0x80; - Game::DB_LoadXAssets(&info, 1, true); - AssetHandler::FindOriginalAsset(Game::XAssetType::ASSET_TYPE_RAWFILE, "default"); // Lock until zone is unloaded - }); - - Command::Add("materialInfoDump", [](const Command::Params*) - { - Game::DB_EnumXAssets(Game::ASSET_TYPE_MATERIAL, [](Game::XAssetHeader header, void*) - { - Logger::Print("{}: {:#X} {:#X} {:#X}\n", - header.material->info.name, header.material->info.sortKey & 0xFF, header.material->info.gameFlags & 0xFF, header.material->stateFlags & 0xFF); - }, nullptr, false); - }); - } - } - - ZoneBuilder::~ZoneBuilder() - { - ZoneBuilder::CommandThreadTerminate = true; - if (ZoneBuilder::CommandThread.joinable()) - { - ZoneBuilder::CommandThread.join(); - } - } - -#if defined(DEBUG) || defined(FORCE_UNIT_TESTS) - bool ZoneBuilder::unitTest() - { - printf("Testing circular bit shifting (left)..."); - - unsigned int integer = 0x80000000; - Utils::RotLeft(integer, 1); - - if (integer != 1) - { - printf("Error\n"); - printf("Bit shifting failed: %X\n", integer); - return false; - } - - printf("Success\n"); - printf("Testing circular bit shifting (right)..."); - - unsigned char byte = 0b00000011; - Utils::RotRight(byte, 2); - - if (byte != 0b11000000) - { - printf("Error\n"); - printf("Bit shifting failed %X\n", byte & 0xFF); - return false; - } - - printf("Success\n"); - return true; - } -#endif -} diff --git a/src/Components/Modules/ZoneBuilder.hpp b/src/Components/Modules/ZoneBuilder.hpp deleted file mode 100644 index c6fb46b6..00000000 --- a/src/Components/Modules/ZoneBuilder.hpp +++ /dev/null @@ -1,175 +0,0 @@ -#pragma once - -#include - -#define XFILE_MAGIC_UNSIGNED 0x3030317566665749 -#define XFILE_VERSION 276 - -#define XFILE_HEADER_IW4X 0x78345749 // 'IW4x' -#define XFILE_VERSION_IW4X 3 - -namespace Components -{ - class ZoneBuilder : public Component - { - public: - class Zone - { - public: - class AssetRecursionMarker - { - public: - AssetRecursionMarker(Zone* _builder) : builder(_builder) - { - this->builder->increaseAssetDepth(); - } - - ~AssetRecursionMarker() - { - this->builder->decreaseAssetDepth(); - } - - private: - Zone* builder; - }; - - Zone(const std::string& zoneName); - ~Zone(); - - void build(); - - Utils::Stream* getBuffer(); - Utils::Memory::Allocator* getAllocator(); - iw4of::api* getIW4OfApi(); - - bool hasPointer(const void* pointer); - void storePointer(const void* pointer); - - template - T* getPointer(const T* pointer) { return reinterpret_cast(this->safeGetPointer(pointer)); } - - int findAsset(Game::XAssetType type, std::string name); - Game::XAssetHeader findSubAsset(Game::XAssetType type, std::string name); - Game::XAsset* getAsset(int index); - uint32_t getAssetTableOffset(int index); - - bool hasAlias(Game::XAsset asset); - Game::XAssetHeader saveSubAsset(Game::XAssetType type, void* ptr); - bool loadAssetByName(Game::XAssetType type, const std::string& name, bool isSubAsset = true); - bool loadAsset(Game::XAssetType type, void* data, bool isSubAsset = true); - - int addScriptString(unsigned short gameIndex); - int addScriptString(const std::string& str); - int findScriptString(const std::string& str); - void addRawAsset(Game::XAssetType type, void* ptr); - - void mapScriptString(unsigned short& gameIndex); - - void renameAsset(Game::XAssetType type, const std::string& asset, const std::string& newName); - std::string getAssetName(Game::XAssetType type, const std::string& asset); - - void store(Game::XAssetHeader header); - - void incrementExternalSize(unsigned int size); - - void increaseAssetDepth() { ++this->assetDepth; } - void decreaseAssetDepth() { --this->assetDepth; } - bool isPrimaryAsset() { return this->assetDepth <= 1; } - - private: - void loadFastFiles() const; - - bool loadAssets(); - bool loadAssetByName(const std::string& type, std::string name, bool isSubAsset = true); - - void saveData(); - void writeZone(); - - unsigned int getAlias(Game::XAsset asset); - void storeAlias(Game::XAsset asset); - - void addBranding(); - - iw4of::params_t getIW4OfApiParams(); - - uint32_t safeGetPointer(const void* pointer); - - int indexStart; - unsigned int externalSize; - Utils::Stream buffer; - iw4of::api iw4ofApi; - - std::string zoneName; - Utils::CSV dataMap; - - Utils::Memory::Allocator memAllocator; - - std::vector loadedAssets; - std::vector markedAssets; - std::vector loadedSubAssets; - std::vector scriptStrings; - - std::map scriptStringMap; - - std::map renameMap[Game::XAssetType::ASSET_TYPE_COUNT]; - - std::map pointerMap; - std::vector> aliasList; - - Game::RawFile branding; - - size_t assetDepth; - }; - - ZoneBuilder(); - ~ZoneBuilder(); - -#if defined(DEBUG) || defined(FORCE_UNIT_TESTS) - bool unitTest() override; -#endif - - static bool IsEnabled(); - - static std::string TraceZone; - static std::vector> TraceAssets; - - static void BeginAssetTrace(const std::string& zone); - static std::vector> EndAssetTrace(); - - static Game::XAssetHeader GetEmptyAssetIfCommon(Game::XAssetType type, const std::string& name, Zone* builder); - static void RefreshExporterWorkDirectory(); - - static iw4of::api* GetExporter(); - - private: - static int StoreTexture(Game::GfxImageLoadDef **loadDef, Game::GfxImage *image); - static void ReleaseTexture(Game::XAssetHeader header); - - static std::string FindMaterialByTechnique(const std::string& name); - static void ReallocateLoadedSounds(void*& data, void* a2); - - static BOOL APIENTRY EntryPoint(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int /*nShowCmd*/); - static void HandleError(Game::errorParm_t code, const char* fmt, ...); - static void SoftErrorAssetOverflow(); - - static void AssumeMainThreadRole(); - static void ResetThreadRole(); - - static bool IsThreadMainThreadHook(); - static Game::Sys_File Sys_CreateFile_Stub(const char* dir, const char* filename); - - static iw4of::params_t GetExporterAPIParams(); - - static void Com_Quitf_t(); - - static void CommandThreadCallback(); - - static bool MainThreadInterrupted; - static DWORD InterruptingThreadId; - - static volatile bool CommandThreadTerminate; - static std::thread CommandThread; - static iw4of::api ExporterAPI; - static std::string DumpingZone; - }; -} diff --git a/src/Components/Modules/Zones.cpp b/src/Components/Modules/Zones.cpp index 89bb812a..9c24af91 100644 --- a/src/Components/Modules/Zones.cpp +++ b/src/Components/Modules/Zones.cpp @@ -2969,279 +2969,6 @@ namespace Components } } - static const unsigned int crcTable[] = - { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, - 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, - 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, - 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, - 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, - 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, - 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, - 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, - 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, - 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, - 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, - 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, - 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, - 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, - 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, - 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, - 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, - 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, - 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, - 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, - 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, - 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, - 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, - 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, - 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, - 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, - 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d - }; - uint32_t Zones::HashCRC32StringInt(const std::string& string, uint32_t initialCrc) - { - auto curPtr = reinterpret_cast(const_cast(string.data())); - auto remaining = string.size(); - auto crc = ~initialCrc; - - for (; remaining--; ++curPtr) - { - crc = (crc >> 8) ^ crcTable[(crc ^ *curPtr) & 0xFF]; - } - - return (~crc); - } - - std::unordered_map Zones::fileDataMap; - std::mutex Zones::fileDataMutex; - - __declspec(naked) int Zones::FS_FOpenFileReadForThreadOriginal(const char*, int*, int) - { - __asm - { - sub esp, 0x33C - - push 0x643276 - ret - } - } - - int Zones::FS_FOpenFileReadForThreadHook(const char* file, int* filePointer, int thread) - { - const auto retval = FS_FOpenFileReadForThreadOriginal(file, filePointer, thread); - - if (file != nullptr && filePointer != nullptr && strlen(file) >= 4 && retval > 0) - { - std::string fileBuffer; - fileBuffer.resize(retval); - auto readSize = Game::FS_Read(&fileBuffer[0], retval, *filePointer); - - // check if file should be skipped - auto skipFile = false; - - if (std::strlen(file) > 5 && ((std::strncmp(&file[strlen(file) - 4], ".iwi", 4) != 0))) - { - skipFile = true; - } - else if (readSize >= 3 && (std::memcmp(&fileBuffer[0], "IWi", 3) == 0)) - { - skipFile = true; - } - - // if the header seems encrypted... - if (fileBuffer.size() > 4 && readSize == retval && !skipFile) - { - auto packedSize = fileBuffer.size() - 4; - auto unpackedSize = *reinterpret_cast(&fileBuffer[fileBuffer.size() - 4]); - - // calc encrypted buffer size - auto encryptedBufferSize = fileBuffer.size(); - encryptedBufferSize -= 4; - encryptedBufferSize += 16 - (encryptedBufferSize % 16); - - // prepare encryptedData buffer - std::string encryptedData; - encryptedData.resize(encryptedBufferSize); - memcpy(&encryptedData[0], &fileBuffer[0], packedSize); - - // prepare decryptedData buffer - std::string decryptedData; - decryptedData.resize(encryptedBufferSize); - - register_cipher(&aes_desc); - - auto aes = find_cipher("aes"); - - // attempt to decrypt the IWI - symmetric_CTR ctr_state; - ZeroMemory(&ctr_state, sizeof(symmetric_CTR)); - - // decryption keys - std::uint8_t aesKey[24] = { 0x15, 0x9a, 0x03, 0x25, 0xe0, 0x75, 0x2e, 0x80, 0xc6, 0xc0, 0x94, 0x2a, 0x50, 0x5c, 0x1c, 0x68, 0x8c, 0x17, 0xef, 0x53, 0x99, 0xf8, 0x68, 0x3c }; - std::uint32_t aesIV[4] = { 0x1010101, 0x1010101, 0x1010101, 0x1010101 }; - - auto strippedFileName = std::filesystem::path(file).filename().string(); - auto nonce = HashCRC32StringInt(strippedFileName, strippedFileName.size()); - - std::uint8_t iv[16]; - std::memset(iv, 0, sizeof iv); - std::memcpy(iv, &nonce, 4); - std::memcpy(iv + 4, &unpackedSize, 4); - - ctr_start(aes, reinterpret_cast(&aesIV[0]), &aesKey[0], sizeof aesKey, 0, CTR_COUNTER_BIG_ENDIAN, &ctr_state); - - // decrypt image - auto readDataSize = 0u; - while (readDataSize < packedSize) - { - auto left = (packedSize - readDataSize); - auto blockSize = (left > 0x8000) ? 0x8000 : left; - - std::memcpy(iv + 8, &readDataSize, 4); - std::memcpy(iv + 12, &blockSize, 4); - - ctr_setiv(iv, sizeof iv, &ctr_state); - ctr_decrypt(reinterpret_cast(&encryptedData[readDataSize]), reinterpret_cast(&decryptedData[readDataSize]), blockSize, &ctr_state); - - readDataSize += blockSize; - } - - ctr_done(&ctr_state); - - if (static_cast(decryptedData[0]) == 0x78) - { - FileData data = {}; - data.readPos = 0; - data.len = unpackedSize; - data.fileContents.resize(unpackedSize); - - // decompress the buffer - auto result = uncompress(reinterpret_cast(&data.fileContents[0]), - reinterpret_cast(&data.len), reinterpret_cast(&decryptedData[0]), packedSize); - - // insert file data - if (result == Z_OK) - { - std::lock_guard _(fileDataMutex); - fileDataMap[*filePointer] = data; - return unpackedSize; - } - } - } - - // un-read data, file is apparently not encrypted - Game::FS_Seek(*filePointer, 0, Game::FS_SEEK_SET); - } - - return retval; - } - - __declspec(naked) int Zones::FS_ReadOriginal(void*, size_t, int) - { - __asm - { - push ecx - mov eax, [esp + 0x10] - - push 0x4A04C5 - ret - } - } - - int Zones::FS_ReadHook(void* buffer, size_t size, int filePointer) - { - std::lock_guard _(fileDataMutex); - - if (auto itr = fileDataMap.find(filePointer); itr != fileDataMap.end()) - { - if (!itr->second.fileContents.empty()) - { - const auto readSize = std::min(size, itr->second.fileContents.size() - itr->second.readPos); - std::memcpy(buffer, &itr->second.fileContents[itr->second.readPos], readSize); - itr->second.readPos += readSize; - return static_cast(readSize); - } - } - - return FS_ReadOriginal(buffer, size, filePointer); - } - - __declspec(naked) void Zones::FS_FCloseFileOriginal(int) - { - __asm - { - mov eax, [esp + 4] - push esi - - push 0x462005 - ret - } - } - - void Zones::FS_FCloseFileHook(int filePointer) - { - std::lock_guard _(fileDataMutex); - - FS_FCloseFileOriginal(filePointer); - - if (const auto itr = fileDataMap.find(filePointer); itr != fileDataMap.end()) - { - fileDataMap.erase(itr); - } - } - __declspec(naked) std::uint32_t Zones::FS_SeekOriginal(int, int, int) - { - __asm - { - push esi - mov esi, [esp + 8] - - push 0x4A63D5 - ret - } - } - std::uint32_t Zones::FS_SeekHook(int fileHandle, int seekPosition, int seekOrigin) - { - std::lock_guard _(fileDataMutex); - - if (const auto itr = fileDataMap.find(fileHandle); itr != fileDataMap.end()) - { - if (seekOrigin == Game::FS_SEEK_SET) - { - itr->second.readPos = seekPosition; - } - else if (seekOrigin == Game::FS_SEEK_CUR) - { - itr->second.readPos += seekPosition; - } - else if (seekOrigin == Game::FS_SEEK_END) - { - itr->second.readPos = itr->second.fileContents.size() - seekPosition; - } - - return itr->second.readPos; - } - - return FS_SeekOriginal(fileHandle, seekPosition, seekOrigin); - } - __declspec(naked) void Zones::LoadMapTriggersModelPointer() { static auto DB_ConvertOffsetToPointer_Address = 0x4A82B0; @@ -3483,75 +3210,6 @@ namespace Components { Zones::ZoneVersion = 0; - if (ZoneBuilder::IsEnabled()) - { - Command::Add("decryptImages", []() - { - auto images = FileSystem::GetSysFileList("iw4x/images", "iwi"); - Logger::Print("decrypting {} images...\n", images.size()); - - for (auto& image : images) - { - char* buffer = nullptr; - auto fileLength = Game::FS_ReadFile(Utils::String::Format("images/{}", image), &buffer); - - if (fileLength && buffer) - { - if (!std::filesystem::exists("raw/images")) - { - std::filesystem::create_directories("raw/images"); - } - - if (!std::filesystem::exists(Utils::String::Format("raw/images/{}", image))) - { - const auto fp = fopen(Utils::String::Format("raw/images/{}", image), "wb"); - if (fp) - { - fwrite(buffer, fileLength, 1, fp); - fclose(fp); - } - } - - Game::FS_FreeFile(buffer); - } - } - - Logger::Print("decrypted {} images!\n", images.size()); - }); - - Command::Add("decryptSounds", []() - { - auto sounds = FileSystem::GetSysFileList("iw4x/sound", "iwi"); - Logger::Print("decrypting {} sounds...\n", sounds.size()); - - for (auto& sound : sounds) - { - char* buffer = nullptr; - auto len = Game::FS_ReadFile(Utils::String::Format("sound/{}", sound), &buffer); - - if (len && buffer) - { - auto path = std::filesystem::path(sound.data()); - std::filesystem::create_directories("raw/sound" / path.parent_path()); - - if (!std::filesystem::exists(std::format("raw/sound/{}", sound))) - { - FILE* fp; - if (!fopen_s(&fp, Utils::String::Format("raw/sound/{}", sound), "wb") && fp) - { - fwrite(buffer, len, 1, fp); - fclose(fp); - } - } - - Game::FS_FreeFile(buffer); - } - } - - Logger::Print("decrypted {} sounds!\n", sounds.size()); - }); - } - // patch max filecount Sys_ListFiles can return Utils::Hook::Set(0x45A66B, (maxFileCount + fileCountMultiplier) * 4); Utils::Hook::Set(0x64AF78, maxFileCount); @@ -3572,15 +3230,6 @@ namespace Components // addon_map_ents asset type (we reuse it for weaponattach) Utils::Hook::Set(0x418B31, 0x72); - // encrypted images hooks - if (ZoneBuilder::IsEnabled()) - { - Utils::Hook(0x462000, Zones::FS_FCloseFileHook, HOOK_JUMP).install()->quick(); - Utils::Hook(0x4A04C0, Zones::FS_ReadHook, HOOK_JUMP).install()->quick(); - Utils::Hook(0x643270, Zones::FS_FOpenFileReadForThreadHook, HOOK_JUMP).install()->quick(); - Utils::Hook(0x4A63D0, Zones::FS_SeekHook, HOOK_JUMP).install()->quick(); - } - // asset hooks Utils::Hook(0x47146D, Zones::LoadTracerDef, HOOK_CALL).install()->quick(); Utils::Hook(0x4714A3, Zones::LoadTracerDefFxEffect, HOOK_JUMP).install()->quick(); diff --git a/src/Components/Modules/Zones.hpp b/src/Components/Modules/Zones.hpp index 97154438..f22b52eb 100644 --- a/src/Components/Modules/Zones.hpp +++ b/src/Components/Modules/Zones.hpp @@ -29,9 +29,6 @@ namespace Components static int FxEffectIndex; static char* FxEffectStrings[64]; - static std::unordered_map fileDataMap; - static std::mutex fileDataMutex; - static bool CheckGameMapSp(int type); static void GameMapSpPatchStub(); @@ -83,15 +80,6 @@ namespace Components static int LoadMapEnts(bool atStreamStart, Game::MapEnts* buffer, int size); static void Load_ClipInfo(bool atStreamStart); static int LoadClipMap(bool atStreamStart); - static uint32_t HashCRC32StringInt(const std::string& Value, uint32_t Initial); - static int FS_FOpenFileReadForThreadOriginal(const char*, int*, int); - static int FS_FOpenFileReadForThreadHook(const char* file, int* filePointer, int thread); - static int FS_ReadOriginal(void*, size_t, int); - static int FS_ReadHook(void* buffer, size_t size, int filePointer); - static void FS_FCloseFileOriginal(int); - static void FS_FCloseFileHook(int filePointer); - static std::uint32_t FS_SeekOriginal(int, int, int); - static std::uint32_t FS_SeekHook(int fileHandle, int seekPosition, int seekOrigin); static void LoadMapTriggersModelPointer(); static void LoadMapTriggersHullPointer(); static void LoadMapTriggersSlabPointer(); diff --git a/src/STDInclude.hpp b/src/STDInclude.hpp index 59bbb4ea..03aad46b 100644 --- a/src/STDInclude.hpp +++ b/src/STDInclude.hpp @@ -143,6 +143,12 @@ using namespace std::literals; #define BASEGAME_NAME "iw4mp_ceg.exe" #define CLIENT_CONFIG "iw4x_config.cfg" +#define XFILE_MAGIC_UNSIGNED 0x3030317566665749 +#define XFILE_VERSION 276 + +#define XFILE_HEADER_IW4X 0x78345749 // 'IW4x' +#define XFILE_VERSION_IW4X 3 + // Resource stuff #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS diff --git a/src/Steam/Interfaces/SteamUser.cpp b/src/Steam/Interfaces/SteamUser.cpp index 46b42887..d040b3d4 100644 --- a/src/Steam/Interfaces/SteamUser.cpp +++ b/src/Steam/Interfaces/SteamUser.cpp @@ -23,11 +23,7 @@ namespace Steam if (!idBits) { - if (Components::ZoneBuilder::IsEnabled()) - { - idBits = *reinterpret_cast(const_cast("DEDICATE")); - } - else if (Components::Singleton::IsFirstInstance() && !Components::Dedicated::IsEnabled()) // ECDSA guid + if (Components::Singleton::IsFirstInstance() && !Components::Dedicated::IsEnabled()) // ECDSA guid { idBits = Components::Auth::GetKeyHash(); } diff --git a/src/Steam/Proxy.cpp b/src/Steam/Proxy.cpp index 9d546d20..c4710b4a 100644 --- a/src/Steam/Proxy.cpp +++ b/src/Steam/Proxy.cpp @@ -132,7 +132,7 @@ namespace Steam void Proxy::RunGame() { - if (Steam::Enabled() && !Components::Dedicated::IsEnabled() && !Components::ZoneBuilder::IsEnabled()) + if (Steam::Enabled() && !Components::Dedicated::IsEnabled()) { SetEnvironmentVariableA("SteamAppId", ::Utils::String::VA("%lu", Proxy::AppId)); SetEnvironmentVariableA("SteamGameId", ::Utils::String::VA("%llu", Proxy::AppId & 0xFFFFFF)); @@ -146,7 +146,7 @@ namespace Steam void Proxy::SetMod(const std::string& mod) { - if (!Proxy::ClientUser || !Proxy::SteamApps || !Steam::Enabled() || Components::Dedicated::IsEnabled() || Components::ZoneBuilder::IsEnabled()) return; + if (!Proxy::ClientUser || !Proxy::SteamApps || !Steam::Enabled() || Components::Dedicated::IsEnabled()) return; if (!Proxy::SteamApps->BIsSubscribedApp(Proxy::AppId)) { @@ -382,7 +382,7 @@ namespace Steam SetDllDirectoryA(directoy.data()); - if (!Components::Dedicated::IsEnabled() && !Components::ZoneBuilder::IsEnabled()) + if (!Components::Dedicated::IsEnabled()) { Proxy::LaunchWatchGuard(); From 77bfbd8e85badb27ca60060bf5f52446bddb5645 Mon Sep 17 00:00:00 2001 From: Diavolo Date: Sun, 18 Jun 2023 15:10:29 +0200 Subject: [PATCH 09/22] fix(serverlist): remove toast notification --- src/Components/Modules/ServerList.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Components/Modules/ServerList.cpp b/src/Components/Modules/ServerList.cpp index 1f5f58db..3a070f6b 100644 --- a/src/Components/Modules/ServerList.cpp +++ b/src/Components/Modules/ServerList.cpp @@ -302,8 +302,7 @@ namespace Components Game::netadr_t masterServerAddr; if (!GetMasterServer(masterServerName, masterPort, masterServerAddr)) { - Logger::Print("Could not resolve address for {}:{}", masterServerName, masterPort); - Toast::Show("cardicon_headshot", "^1Error", std::format("Could not resolve address for {}:{}", masterServerName, masterPort), 5000); + Logger::Print("Could not resolve address for {}:{}\n", masterServerName, masterPort); UseMasterServer = false; return; } From c1c5a06c24de8c369986d32b0ab30f6092ba9b4a Mon Sep 17 00:00:00 2001 From: Diavolo Date: Sun, 18 Jun 2023 15:18:19 +0200 Subject: [PATCH 10/22] feature(github): deploy binary --- .github/workflows/build.yml | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e871fcdf..f3692290 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -50,3 +50,31 @@ jobs: path: | build/bin/Win32/${{matrix.configuration}}/iw4x.dll build/bin/Win32/${{matrix.configuration}}/iw4x.pdb + + deploy: + name: Deploy artifacts + needs: build + runs-on: ubuntu-latest + if: github.event_name == 'push' && (github.ref == 'refs/heads/develop') + steps: + - name: Setup develop environment + if: github.ref == 'refs/heads/develop' + run: echo "DIAMANTE_MASTER_PATH=${{ secrets.DIAMANTE_MASTER_SSH_PATH }}" >> $GITHUB_ENV + + - name: Download Release binaries + uses: actions/download-artifact@v3.0.2 + with: + name: Release binaries + + # Set up committer info and GPG key + - name: Install SSH key + uses: shimataro/ssh-key-action@v2.5.1 + with: + key: ${{ secrets.DIAMANTE_MASTER_SSH_PRIVATE_KEY }} + known_hosts: 'just-a-placeholder-so-we-dont-get-errors' + + - name: Add known hosts + run: ssh-keyscan -H ${{ secrets.DIAMANTE_MASTER_SSH_ADDRESS }} >> ~/.ssh/known_hosts + + - name: Upload iw4x-client binary + run: rsync -avz iw4x.dll ${{ secrets.DIAMANTE_MASTER_SSH_USER }}@${{ secrets.DIAMANTE_MASTER_SSH_ADDRESS }}:${{ env.DIAMANTE_MASTER_PATH }}/legacy/ From 94e9429926f029f60a67a8f2b95223139d5ad675 Mon Sep 17 00:00:00 2001 From: Diavolo Date: Sun, 18 Jun 2023 15:30:12 +0200 Subject: [PATCH 11/22] maint: remove spooky references --- .github/CODEOWNERS | 2 +- .github/ISSUE_TEMPLATE/config.yml | 4 ++-- .github/ISSUE_TEMPLATE/get-help.md | 4 ++-- .github/ISSUE_TEMPLATE/request-a-feature.md | 2 +- .github/pull_request_template.md | 4 ++-- SECURITY.md | 9 ++------- src/Components/Modules/FileSystem.cpp | 4 ++-- src/Components/Modules/Maps.cpp | 11 +---------- src/Components/Modules/QuickPatch.cpp | 8 ++++---- src/DllMain.cpp | 2 +- src/Resource.rc | 4 ++-- src/Utils/Cache.cpp | 4 ++-- src/Utils/Utils.cpp | 10 +++++----- 13 files changed, 27 insertions(+), 41 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 639efdba..b03212bc 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,3 +1,3 @@ # SPDX-License-Identifier: GPL-3.0 -* @XLabsProject/Developers +* @diamante0018 diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index bfa69ba1..d26c96e1 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -3,6 +3,6 @@ contact_links: - name: Discord Server url: https://discord.gg/sKeVmR3/ about: Please ask and answer support questions here. - - name: XLabsProject Website - url: https://xlabs.dev/ + - name: AlterWare Website + url: https://alterware.dev/ about: The official website. \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/get-help.md b/.github/ISSUE_TEMPLATE/get-help.md index 7426ade0..fae523bd 100644 --- a/.github/ISSUE_TEMPLATE/get-help.md +++ b/.github/ISSUE_TEMPLATE/get-help.md @@ -8,8 +8,8 @@ assignees: '' --- _Do not open an issue here if you need help with modding or have a problem getting the client to run. -It is very likely your problem will be resolved by reading the [FAQ](https://xlabs.dev/iw4x_faq) carefully. -Ask in `iw4x-support` or `iw4x-modding` channels on the [Discord](https://discord.gg/sKeVmR3) server if you still have problems. +It is very likely your problem will be resolved by reading the [FAQ](https://youtu.be/dQw4w9WgXcQ) carefully. +Ask in `iw4x-support` or `iw4x-modding` channels on the [Discord](https://alterware.dev/) server if you still have problems. If this does not apply, please continue by filling in the template below._ **What are you trying to do?** diff --git a/.github/ISSUE_TEMPLATE/request-a-feature.md b/.github/ISSUE_TEMPLATE/request-a-feature.md index 37d72635..f950302a 100644 --- a/.github/ISSUE_TEMPLATE/request-a-feature.md +++ b/.github/ISSUE_TEMPLATE/request-a-feature.md @@ -7,7 +7,7 @@ assignees: '' --- -_Before opening a new feature request, please see [Issues](https://github.com/XLabsProject/iw4x-client/issues) and check that a similar issue does not already exist. +_Before opening a new feature request, please see [Issues](https://github.com/diamante0018/iw4x-client/issues) and check that a similar issue does not already exist. If this a new request, help us help you by filling in the template below._ **What problem will this solve?** diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 82a087e1..a2d02d10 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -14,6 +14,6 @@ Add any other context about your changes here. **Did you check all the boxes?** - [ ] Focus on a single fix or feature; remove any unrelated formatting or code changes -- [ ] Mention any [related issues](https://github.com/XLabsProject/iw4x-client/issues) (put `closes #XXXX` in comment to auto-close issue when PR is merged) -- [ ] Follow our [coding conventions](https://github.com/XLabsProject/iw4x-client/blob/master/CODESTYLE.md) +- [ ] Mention any [related issues](https://github.com/diamante0018/iw4x-client/issues) (put `closes #XXXX` in comment to auto-close issue when PR is merged) +- [ ] Follow our [coding conventions](https://github.com/diamante0018/iw4x-client/blob/master/CODESTYLE.md) - [ ] Minimize the number of commits diff --git a/SECURITY.md b/SECURITY.md index ab88d3a6..b8759f91 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,15 +1,10 @@ ## iw4x-client Security -We take security very seriously at XLabsProject. We welcome any peer review of our 100% free software source code to ensure nobody's IW4x clients or servers are ever compromised or hacked. +We take security very seriously at AlterWare. We welcome any peer review of our 100% free software source code to ensure nobody's IW4x clients or servers are ever compromised or hacked. ### Where should I report security issues? In order to give the community time to respond and upgrade we strongly urge you report all security issues privately. -Please e-mail MauriceHeumann@gmail.com directly to provide details and repro steps. - -### Other key people - -In the exceptional case that you do not receive a response within a reasonable time frame from our lead developer, please contact any of the following people: -- Future/diamante0018: iw4x-sp@proton.me +Please e-mail iw4x-sp@proton.me directly to provide details and repro steps. We will try respond as soon as possible, but please note: diff --git a/src/Components/Modules/FileSystem.cpp b/src/Components/Modules/FileSystem.cpp index a29d0fbb..40a33d9f 100644 --- a/src/Components/Modules/FileSystem.cpp +++ b/src/Components/Modules/FileSystem.cpp @@ -153,7 +153,7 @@ namespace Components CoTaskMemFree(path); }); - return std::filesystem::path(path) / "xlabs"; + return std::filesystem::path(path); } std::vector FileSystem::GetFileList(const std::string& path, const std::string& extension) @@ -376,7 +376,7 @@ namespace Components // Handle IWD freeing Utils::Hook(0x642F60, IwdFreeStub, HOOK_CALL).install()->quick(); - // Set the working dir based on info from the Xlabs launcher + // Set the working dir based on info from the AlterWare launcher Utils::Hook(0x4326E0, Sys_DefaultInstallPath_Hk, HOOK_JUMP).install()->quick(); } diff --git a/src/Components/Modules/Maps.cpp b/src/Components/Modules/Maps.cpp index faa66156..d1fc3b2c 100644 --- a/src/Components/Modules/Maps.cpp +++ b/src/Components/Modules/Maps.cpp @@ -767,16 +767,7 @@ namespace Components UIScript::Add("downloadDLC", []([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info) { - int dlc = token.get(); - - for (const auto& pack : Maps::DlcPacks) - { - if (pack.index == dlc) - { - ShellExecuteW(0, 0, L"https://xlabs.dev/support_iw4x_client.html", 0, 0, SW_SHOW); - return; - } - } + const auto dlc = token.get(); Game::ShowMessageBox(Utils::String::VA("DLC %d does not exist!", dlc), "ERROR"); }); diff --git a/src/Components/Modules/QuickPatch.cpp b/src/Components/Modules/QuickPatch.cpp index 8ea1cafb..fb3a1561 100644 --- a/src/Components/Modules/QuickPatch.cpp +++ b/src/Components/Modules/QuickPatch.cpp @@ -245,10 +245,10 @@ namespace Components } auto workingDir = std::filesystem::current_path().string(); - auto binary = FileSystem::GetAppdataPath() / "data" / "iw4x" / *Game::sys_exitCmdLine; + const std::string binary = *Game::sys_exitCmdLine; - SetEnvironmentVariableA("XLABS_MW2_INSTALL", workingDir.data()); - Utils::Library::LaunchProcess(binary.string(), "-singleplayer", workingDir); + SetEnvironmentVariableA("MW2_INSTALL", workingDir.data()); + Utils::Library::LaunchProcess(binary, "-singleplayer", workingDir); } __declspec(naked) void QuickPatch::SND_GetAliasOffset_Stub() @@ -320,7 +320,7 @@ namespace Components Utils::Hook::Set(0x51FCDD, QuickPatch::R_AddImageToList_Hk); - Utils::Hook::Set(0x41DB8C, "iw4x-sp.exe"); + Utils::Hook::Set(0x41DB8C, "iw4-sp.exe"); Utils::Hook(0x4D6989, QuickPatch::Sys_SpawnQuitProcess_Hk, HOOK_CALL).install()->quick(); // Fix crash as nullptr goes unchecked diff --git a/src/DllMain.cpp b/src/DllMain.cpp index 3f92b015..1bb781b0 100644 --- a/src/DllMain.cpp +++ b/src/DllMain.cpp @@ -61,7 +61,7 @@ BOOL APIENTRY DllMain(HINSTANCE /*hinstDLL*/, DWORD fdwReason, LPVOID /*lpvReser MessageBoxA(nullptr, "Failed to load game binary.\n" "You did not install the iw4x-rawfiles!\n" - "Please use the XLabs launcher to run the game. For support, please visit https://xlabs.dev/support_iw4x_client", + "Please use the AlterWare launcher to run the game. For support, please visit https://alterware.dev/", "ERROR", MB_ICONERROR ); diff --git a/src/Resource.rc b/src/Resource.rc index 8cbfe655..9cd3ff35 100644 --- a/src/Resource.rc +++ b/src/Resource.rc @@ -63,7 +63,7 @@ BEGIN BEGIN BLOCK "040904b0" BEGIN - VALUE "CompanyName", "XLabsProject" + VALUE "CompanyName", "AlterWare" #ifdef _DEBUG VALUE "FileDescription", "IW4 client modification (DEBUG)" #else @@ -71,7 +71,7 @@ BEGIN #endif VALUE "FileVersion", REVISION_STR VALUE "InternalName", "iw4x" - VALUE "LegalCopyright", "Copyright 2023 The XLabsProject Team. All rights reserved." + VALUE "LegalCopyright", "Copyright 2023 The AlterWare Team. All rights reserved." VALUE "OriginalFilename", "iw4x.dll" VALUE "ProductName", "IW4x" VALUE "ProductVersion", REVISION_STR diff --git a/src/Utils/Cache.cpp b/src/Utils/Cache.cpp index b3240757..d7e6d7dc 100644 --- a/src/Utils/Cache.cpp +++ b/src/Utils/Cache.cpp @@ -5,8 +5,8 @@ namespace Utils { const char* Cache::Urls[] = { - "https://raw.githubusercontent.com/XLabsProject/iw4x-client", - "https://xlabs.dev", + "https://raw.githubusercontent.com/diamante0018/iw4x-client", + "https://alterware.dev", }; std::string Cache::ValidUrl; diff --git a/src/Utils/Utils.cpp b/src/Utils/Utils.cpp index 6b789189..a1066804 100644 --- a/src/Utils/Utils.cpp +++ b/src/Utils/Utils.cpp @@ -112,15 +112,15 @@ namespace Utils auto* exeBaseName = std::wcsrchr(binaryPath, L'\\'); exeBaseName[0] = L'\0'; - // Make the game work without the xlabs launcher + // Make the game work without the AlterWare launcher SetCurrentDirectoryW(binaryPath); } void SetEnvironment() { - wchar_t* buffer{}; + char* buffer{}; std::size_t size{}; - if (_wdupenv_s(&buffer, &size, L"XLABS_MW2_INSTALL") != 0 || buffer == nullptr) + if (_dupenv_s(&buffer, &size, "MW2_INSTALL") != 0 || buffer == nullptr) { SetLegacyEnvironment(); return; @@ -128,8 +128,8 @@ namespace Utils const auto _0 = gsl::finally([&] { std::free(buffer); }); - SetCurrentDirectoryW(buffer); - SetDllDirectoryW(buffer); + SetCurrentDirectoryA(buffer); + SetDllDirectoryA(buffer); } HMODULE GetNTDLL() From 3f3cfc0be80a1cd2a2386c96834bd7efe9681789 Mon Sep 17 00:00:00 2001 From: Diavolo Date: Sun, 18 Jun 2023 16:07:39 +0200 Subject: [PATCH 12/22] maint(branding): rename --- README.md | 1 - src/Components/Modules/Branding.cpp | 15 +++++++++------ src/Components/Modules/Console.cpp | 8 ++++---- src/Components/Modules/Localization.cpp | 3 ++- src/Components/Modules/News.cpp | 2 +- src/Components/Modules/QuickPatch.cpp | 3 --- src/Components/Modules/Singleton.cpp | 2 +- src/Steam/Steam.cpp | 2 +- src/Utils/Cryptography.hpp | 1 - 9 files changed, 18 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 9b9e005c..fa718f07 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,6 @@ | `-dump` | Write info of loaded assets to the raw folder as they are being loaded. | | `-nointro` | Skip game's cinematic intro. | | `-version` | Print IW4x build info on startup. | -| `-zonebuilder` | Start the interactive zonebuilder tool console instead of starting the game. | | `-nosteam` | Disable friends feature and do not update Steam about the game's current status just like an invisible mode. | | `-unprotect-dvars` | Allow the server to modify saved/archive dvars. | diff --git a/src/Components/Modules/Branding.cpp b/src/Components/Modules/Branding.cpp index c14b7e03..f5e900f6 100644 --- a/src/Components/Modules/Branding.cpp +++ b/src/Components/Modules/Branding.cpp @@ -10,9 +10,9 @@ namespace Components Dvar::Var Branding::CGDrawVersionY; #ifdef _DEBUG - constexpr auto* BUILD_TYPE = "IW4x_DEV MP"; + constexpr auto* BUILD_TYPE = "IW4y_DEV MP"; #else - constexpr auto* BUILD_TYPE = "IW4x MP"; + constexpr auto* BUILD_TYPE = "IW4y MP"; #endif void Branding::CG_DrawVersion() @@ -101,7 +101,10 @@ namespace Components RegisterBrandingDvars(); // UI version string - Utils::Hook::Set(0x43F73B, "IW4x " REVISION_STR); + Utils::Hook::Set(0x43F73B, "IW4y " REVISION_STR); + + // Window title + Utils::Hook::Set(0x5076A0, "IW4y: Multiplayer"); // Short version dvar Utils::Hook::Set(0x60BD91, REVISION_STR); @@ -138,14 +141,14 @@ namespace Components if (Dedicated::IsEnabled()) { #ifdef EXPERIMENTAL_BUILD - Utils::Hook::Set(0x4289E8, "IW4x " REVISION_STR "-develop: Dedicated"); + Utils::Hook::Set(0x4289E8, "IW4y " REVISION_STR "-develop: Dedicated"); #else - Utils::Hook::Set(0x4289E8, "IW4x " REVISION_STR ": Dedicated"); + Utils::Hook::Set(0x4289E8, "IW4y " REVISION_STR ": Dedicated"); #endif } else { - Utils::Hook::Set(0x4289E8, "IW4x (" REVISION_STR "): Console"); + Utils::Hook::Set(0x4289E8, "IW4y (" REVISION_STR "): Console"); } } } diff --git a/src/Components/Modules/Console.cpp b/src/Components/Modules/Console.cpp index c0f6b5dd..9f061ad4 100644 --- a/src/Components/Modules/Console.cpp +++ b/src/Components/Modules/Console.cpp @@ -99,9 +99,9 @@ namespace Components else if (IsWindow(GetWindow()) != FALSE) { #ifdef EXPERIMENTAL_BUILD - SetWindowTextA(GetWindow(), Utils::String::Format("IW4x " REVISION_STR "-develop : {}", hostname)); + SetWindowTextA(GetWindow(), Utils::String::Format("IW4y " REVISION_STR "-develop : {}", hostname)); #else - SetWindowTextA(GetWindow(), Utils::String::Format("IW4x " REVISION_STR " : {}", hostname)); + SetWindowTextA(GetWindow(), Utils::String::Format("IW4y " REVISION_STR " : {}", hostname)); #endif } } @@ -862,9 +862,9 @@ namespace Components // Console '%s: %s> ' string #ifdef EXPERIMENTAL_BUILD - Utils::Hook::Set(0x5A44B4, "IW4x MP: " REVISION_STR "-develop> "); + Utils::Hook::Set(0x5A44B4, "IW4y MP: " REVISION_STR "-develop> "); #else - Utils::Hook::Set(0x5A44B4, "IW4x MP: " REVISION_STR "> "); + Utils::Hook::Set(0x5A44B4, "IW4y MP: " REVISION_STR "> "); #endif // Patch console color diff --git a/src/Components/Modules/Localization.cpp b/src/Components/Modules/Localization.cpp index a76cad20..a5261eeb 100644 --- a/src/Components/Modules/Localization.cpp +++ b/src/Components/Modules/Localization.cpp @@ -158,10 +158,11 @@ namespace Components { "NTAuthority", "aerosoul94", + "FutureRave", "ReactIW4", "IW4Play", "V2", - "luckyy" + "luckyy", }; std::string credits = "^2The IW4x Team:^7\n"; diff --git a/src/Components/Modules/News.cpp b/src/Components/Modules/News.cpp index 389def85..eff7af5c 100644 --- a/src/Components/Modules/News.cpp +++ b/src/Components/Modules/News.cpp @@ -2,7 +2,7 @@ #include "Changelog.hpp" #include "News.hpp" -#define NEWS_MOTD_DEFAULT "Welcome to IW4x Multiplayer!" +#define NEWS_MOTD_DEFAULT "Welcome to IW4y Multiplayer!" namespace Components { diff --git a/src/Components/Modules/QuickPatch.cpp b/src/Components/Modules/QuickPatch.cpp index fb3a1561..69cf95f6 100644 --- a/src/Components/Modules/QuickPatch.cpp +++ b/src/Components/Modules/QuickPatch.cpp @@ -339,9 +339,6 @@ namespace Components // fs_basegame Utils::Hook::Set(0x6431D1, BASEGAME); - // window title - Utils::Hook::Set(0x5076A0, "IW4x: Multiplayer"); - // sv_hostname Utils::Hook::Set(0x4D378B, "IW4Host"); diff --git a/src/Components/Modules/Singleton.cpp b/src/Components/Modules/Singleton.cpp index 4eb27bfa..59b09b5a 100644 --- a/src/Components/Modules/Singleton.cpp +++ b/src/Components/Modules/Singleton.cpp @@ -17,7 +17,7 @@ namespace Components { if (Flags::HasFlag("version")) { - printf("%s", "IW4x " VERSION " (built " __DATE__ " " __TIME__ ")\n"); + printf("%s", "IW4y " VERSION " (built " __DATE__ " " __TIME__ ")\n"); #ifdef EXPERIMENTAL_BUILD printf("Revision: %i - develop\n", REVISION); #else diff --git a/src/Steam/Steam.cpp b/src/Steam/Steam.cpp index 37ec9361..e55b8c1f 100644 --- a/src/Steam/Steam.cpp +++ b/src/Steam/Steam.cpp @@ -130,7 +130,7 @@ namespace Steam } else { - Proxy::SetMod("IW4x: Modern Warfare 2"); + Proxy::SetMod("IW4y: Modern Warfare 2"); Proxy::RunGame(); } diff --git a/src/Utils/Cryptography.hpp b/src/Utils/Cryptography.hpp index f3b48560..44b35859 100644 --- a/src/Utils/Cryptography.hpp +++ b/src/Utils/Cryptography.hpp @@ -30,7 +30,6 @@ namespace Utils if (!i) { - // Prepend here, as /dev/urandom says so ;) https://github.com/IW4x/iw4x-client-node/wikis/technical-information#incrementing-the-token this->tokenString = std::basic_string(reinterpret_cast(const_cast("\0")), 1) + this->tokenString; break; } From 1bdb56f6a09c0464cf372d3d82558b671f24c03e Mon Sep 17 00:00:00 2001 From: Diavolo Date: Mon, 19 Jun 2023 19:08:53 +0200 Subject: [PATCH 13/22] maint: use {} initializer for strings more often --- src/Components/Modules/RCon.cpp | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/Components/Modules/RCon.cpp b/src/Components/Modules/RCon.cpp index 52a5cc25..b0349093 100644 --- a/src/Components/Modules/RCon.cpp +++ b/src/Components/Modules/RCon.cpp @@ -224,21 +224,23 @@ namespace Components // Load public key static std::uint8_t publicKey[] = { - 0x04, 0x01, 0x9D, 0x18, 0x7F, 0x57, 0xD8, 0x95, 0x4C, 0xEE, 0xD0, 0x21, - 0xB5, 0x00, 0x53, 0xEC, 0xEB, 0x54, 0x7C, 0x4C, 0x37, 0x18, 0x53, 0x89, - 0x40, 0x12, 0xF7, 0x08, 0x8D, 0x9A, 0x8D, 0x99, 0x9C, 0x79, 0x79, 0x59, - 0x6E, 0x32, 0x06, 0xEB, 0x49, 0x1E, 0x00, 0x99, 0x71, 0xCB, 0x4A, 0xE1, - 0x90, 0xF1, 0x7C, 0xB7, 0x4D, 0x60, 0x88, 0x0A, 0xB7, 0xF3, 0xD7, 0x0D, - 0x4F, 0x08, 0x13, 0x7C, 0xEB, 0x01, 0xFF, 0x00, 0x32, 0xEE, 0xE6, 0x23, - 0x07, 0xB1, 0xC2, 0x9E, 0x45, 0xD6, 0xD7, 0xBD, 0xED, 0x05, 0x23, 0xB5, - 0xE7, 0x83, 0xEF, 0xD7, 0x8E, 0x36, 0xDC, 0x16, 0x79, 0x74, 0xD1, 0xD5, - 0xBA, 0x2C, 0x4C, 0x28, 0x61, 0x29, 0x5C, 0x49, 0x7D, 0xD4, 0xB6, 0x56, - 0x17, 0x75, 0xF5, 0x2B, 0x58, 0xCD, 0x0D, 0x76, 0x65, 0x10, 0xF7, 0x51, - 0x69, 0x1D, 0xB9, 0x0F, 0x38, 0xF6, 0x53, 0x3B, 0xF7, 0xCE, 0x76, 0x4F, - 0x08 + 0x04, 0x01, 0xC1, 0x86, 0x33, 0x59, 0x69, 0xE0, 0x8A, 0x85, + 0x59, 0x5A, 0x30, 0xC9, 0x9D, 0x34, 0x4B, 0x12, 0x81, 0x32, + 0xE7, 0x55, 0x13, 0xC1, 0x5A, 0x08, 0x78, 0x6A, 0xB2, 0x69, + 0x5D, 0x7F, 0x68, 0x2C, 0xE6, 0xA5, 0x55, 0xF0, 0xE1, 0x87, + 0xCB, 0xA7, 0x32, 0xBA, 0x5F, 0x68, 0xFC, 0xD2, 0x31, 0xFC, + 0x51, 0x7D, 0xEF, 0x9D, 0x46, 0x6E, 0xBF, 0xB6, 0x84, 0xA4, + 0xBD, 0x19, 0xBD, 0x03, 0x28, 0x3B, 0xCD, 0x00, 0x67, 0xCD, + 0x8B, 0x90, 0x08, 0xB0, 0x05, 0xBF, 0x45, 0x93, 0xCB, 0x31, + 0xD0, 0xFB, 0xA6, 0x50, 0xE0, 0x0B, 0x04, 0x95, 0x60, 0x83, + 0x88, 0xC5, 0xDC, 0x6F, 0xD7, 0xC3, 0xFA, 0x4F, 0x4B, 0xF2, + 0x17, 0xCC, 0x75, 0x7E, 0xE9, 0xD9, 0xE8, 0xC4, 0xEB, 0xA4, + 0x73, 0x93, 0xCF, 0xD1, 0x51, 0x9A, 0xE0, 0x69, 0x37, 0xAA, + 0x20, 0x2F, 0xFD, 0xC4, 0xBA, 0xFB, 0x86, 0x1E, 0x08, 0xEB, + 0xA0, 0x72, 0x84, }; - RconKey.set(std::string(reinterpret_cast(publicKey), sizeof(publicKey))); + RconKey.set(std::string{ reinterpret_cast(publicKey), sizeof(publicKey) }); RconContainer.timestamp = 0; From 73413a7d64b08f7f280e967b194e272cbd70234c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Jun 2023 17:10:42 +0000 Subject: [PATCH 14/22] Bump deps/libtommath from `0df542c` to `f6507b7` Bumps [deps/libtommath](https://github.com/libtom/libtommath) from `0df542c` to `f6507b7`. - [Release notes](https://github.com/libtom/libtommath/releases) - [Commits](https://github.com/libtom/libtommath/compare/0df542cb70f621bbeec207be1949832fb1442479...f6507b7a1bef22965dd7a0e17bd010cd16704463) --- updated-dependencies: - dependency-name: deps/libtommath dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/libtommath | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/libtommath b/deps/libtommath index 0df542cb..f6507b7a 160000 --- a/deps/libtommath +++ b/deps/libtommath @@ -1 +1 @@ -Subproject commit 0df542cb70f621bbeec207be1949832fb1442479 +Subproject commit f6507b7a1bef22965dd7a0e17bd010cd16704463 From dd5e900cab24678d826f3160e9eb916b76f0340c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Jun 2023 09:28:28 +0000 Subject: [PATCH 15/22] Bump deps/libtommath from `f6507b7` to `c6a00c2` Bumps [deps/libtommath](https://github.com/libtom/libtommath) from `f6507b7` to `c6a00c2`. - [Release notes](https://github.com/libtom/libtommath/releases) - [Commits](https://github.com/libtom/libtommath/compare/f6507b7a1bef22965dd7a0e17bd010cd16704463...c6a00c26ca2192c713a36227fdd84d126cdc95b9) --- updated-dependencies: - dependency-name: deps/libtommath dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/libtommath | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/libtommath b/deps/libtommath index f6507b7a..c6a00c26 160000 --- a/deps/libtommath +++ b/deps/libtommath @@ -1 +1 @@ -Subproject commit f6507b7a1bef22965dd7a0e17bd010cd16704463 +Subproject commit c6a00c26ca2192c713a36227fdd84d126cdc95b9 From 2c809e57e10cec34d5b8842de4f32cc7f7fbd695 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Jun 2023 09:46:40 +0000 Subject: [PATCH 16/22] Bump deps/libtomcrypt from `fae62af` to `93f5348` Bumps [deps/libtomcrypt](https://github.com/libtom/libtomcrypt) from `fae62af` to `93f5348`. - [Release notes](https://github.com/libtom/libtomcrypt/releases) - [Commits](https://github.com/libtom/libtomcrypt/compare/fae62af0ab16f469c2512ec04575dd60ca018657...93f5348c47d3578091a4ee5b90f4add216b46d1b) --- updated-dependencies: - dependency-name: deps/libtomcrypt dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/libtomcrypt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/libtomcrypt b/deps/libtomcrypt index fae62af0..93f5348c 160000 --- a/deps/libtomcrypt +++ b/deps/libtomcrypt @@ -1 +1 @@ -Subproject commit fae62af0ab16f469c2512ec04575dd60ca018657 +Subproject commit 93f5348c47d3578091a4ee5b90f4add216b46d1b From 0da8167a0ad596a961a90302a40e15135f92aaf2 Mon Sep 17 00:00:00 2001 From: Diavolo Date: Tue, 20 Jun 2023 19:10:41 +0200 Subject: [PATCH 17/22] maint: re-order local variable definitions --- src/Components/Modules/RCon.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Components/Modules/RCon.cpp b/src/Components/Modules/RCon.cpp index b0349093..6c5486bd 100644 --- a/src/Components/Modules/RCon.cpp +++ b/src/Components/Modules/RCon.cpp @@ -39,13 +39,13 @@ namespace Components Password.clear(); return; } - - auto* addr = reinterpret_cast(0xA5EA44); + if (Password.empty()) { Logger::Print("You need to be logged in and connected to a server!\n"); } + auto* addr = reinterpret_cast(0xA5EA44); Network::Address target(addr); if (!target.isValid() || target.getIP().full == 0) { From e26eed4c11e410c80f360940b754b9913438e0cb Mon Sep 17 00:00:00 2001 From: Diavolo Date: Wed, 21 Jun 2023 20:47:09 +0200 Subject: [PATCH 18/22] maint(utils): clean up crypto utils --- src/Utils/Cryptography.cpp | 21 ++++---- src/Utils/Cryptography.hpp | 103 ++++++++++++++++++------------------- 2 files changed, 61 insertions(+), 63 deletions(-) diff --git a/src/Utils/Cryptography.cpp b/src/Utils/Cryptography.cpp index 66b791a2..89111a27 100644 --- a/src/Utils/Cryptography.cpp +++ b/src/Utils/Cryptography.cpp @@ -61,14 +61,14 @@ namespace Utils { if (!key.isValid()) return {}; - std::uint8_t buffer[512]; + std::uint8_t buffer[512]{}; unsigned long length = sizeof(buffer); ltc_mp = ltm_desc; register_prng(&sprng_desc); ecc_sign_hash(reinterpret_cast(message.data()), message.size(), buffer, &length, nullptr, find_prng("sprng"), key.getKeyPtr()); - return std::string{ reinterpret_cast(buffer), length }; + return std::string{ reinterpret_cast(buffer), length }; } bool ECC::VerifyMessage(Key key, const std::string& message, const std::string& signature) @@ -115,7 +115,7 @@ namespace Utils rsa_sign_hash(reinterpret_cast(message.data()), message.size(), buffer, &length, NULL, find_prng("sprng"), find_hash("sha1"), 0, key.getKeyPtr()); - return std::string{ reinterpret_cast(buffer), length }; + return std::string{ reinterpret_cast(buffer), length }; } bool RSA::VerifyMessage(Key key, const std::string& message, const std::string& signature) @@ -145,9 +145,9 @@ namespace Utils encData.resize(text.size()); symmetric_CBC cbc; - int des3 = find_cipher("3des"); + const auto des3 = find_cipher("3des"); - cbc_start(des3, reinterpret_cast(iv.data()), reinterpret_cast(key.data()), key.size(), 0, &cbc); + cbc_start(des3, reinterpret_cast(iv.data()), reinterpret_cast(key.data()), static_cast(key.size()), 0, &cbc); cbc_encrypt(reinterpret_cast(text.data()), reinterpret_cast(encData.data()), text.size(), &cbc); cbc_done(&cbc); @@ -160,9 +160,9 @@ namespace Utils decData.resize(data.size()); symmetric_CBC cbc; - int des3 = find_cipher("3des"); + const auto des3 = find_cipher("3des"); - cbc_start(des3, reinterpret_cast(iv.data()), reinterpret_cast(key.data()), key.size(), 0, &cbc); + cbc_start(des3, reinterpret_cast(iv.data()), reinterpret_cast(key.data()), static_cast(key.size()), 0, &cbc); cbc_decrypt(reinterpret_cast(data.data()), reinterpret_cast(decData.data()), data.size(), &cbc); cbc_done(&cbc); @@ -269,20 +269,21 @@ namespace Utils #pragma region JenkinsOneAtATime - unsigned int JenkinsOneAtATime::Compute(const std::string& data) + std::size_t JenkinsOneAtATime::Compute(const std::string& data) { return Compute(data.data(), data.size()); } - unsigned int JenkinsOneAtATime::Compute(const char* key, std::size_t len) + std::size_t JenkinsOneAtATime::Compute(const char* key, const std::size_t len) { - unsigned int hash, i; + std::size_t hash, i; for (hash = i = 0; i < len; ++i) { hash += key[i]; hash += (hash << 10); hash ^= (hash >> 6); } + hash += (hash << 3); hash ^= (hash >> 11); hash += (hash << 15); diff --git a/src/Utils/Cryptography.hpp b/src/Utils/Cryptography.hpp index 44b35859..4473a70a 100644 --- a/src/Utils/Cryptography.hpp +++ b/src/Utils/Cryptography.hpp @@ -9,16 +9,16 @@ namespace Utils class Token { public: - Token() { this->tokenString.clear(); }; - Token(const Token& obj) : tokenString(obj.tokenString) { }; - Token(const std::string& token) : tokenString(token.begin(), token.end()) { }; - Token(const std::basic_string& token) : tokenString(token.begin(), token.end()) { }; + Token() { this->tokenString.clear(); } + Token(const Token& obj) : tokenString(obj.tokenString) { } + Token(const std::string& token) : tokenString(token.begin(), token.end()) { } + Token(const std::basic_string& token) : tokenString(token.begin(), token.end()) { } Token& operator++ () { if (this->tokenString.empty()) { - this->tokenString.append(reinterpret_cast(const_cast("\0")), 1); + this->tokenString.append(reinterpret_cast(const_cast("\0")), 1); } else { @@ -30,7 +30,7 @@ namespace Utils if (!i) { - this->tokenString = std::basic_string(reinterpret_cast(const_cast("\0")), 1) + this->tokenString; + this->tokenString = std::basic_string{ reinterpret_cast(const_cast("\0")), 1 } + this->tokenString; break; } } @@ -68,25 +68,25 @@ namespace Utils { return false; } - else if (this->toString().size() < token.toString().size()) + + if (this->toString().size() < token.toString().size()) { return true; } - else if (this->toString().size() > token.toString().size()) + + if (this->toString().size() > token.toString().size()) { return false; } - else - { - auto lStr = this->toString(); - auto rStr = token.toString(); - for (unsigned int i = 0; i < lStr.size(); ++i) + auto lStr = this->toString(); + auto rStr = token.toString(); + + for (std::size_t i = 0; i < lStr.size(); ++i) + { + if (lStr[i] < rStr[i]) { - if (lStr[i] < rStr[i]) - { - return true; - } + return true; } } @@ -108,17 +108,12 @@ namespace Utils return !(*this < token); } - std::string toString() + [[nodiscard]] std::string toString() const { - return std::string(this->tokenString.begin(), this->tokenString.end()); + return std::string{ this->tokenString.begin(), this->tokenString.end() }; } - std::string toString() const - { - return std::string(this->tokenString.begin(), this->tokenString.end()); - } - - std::basic_string toUnsignedString() + [[nodiscard]] std::basic_string toUnsignedString() const { return this->tokenString; } @@ -136,7 +131,7 @@ namespace Utils { public: static std::string GenerateChallenge(); - static uint32_t GenerateInt(); + static std::uint32_t GenerateInt(); static void Initialize(); private: @@ -152,45 +147,47 @@ namespace Utils Key() : keyStorage(new ecc_key) { ZeroMemory(this->getKeyPtr(), sizeof(*this->getKeyPtr())); - }; - Key(ecc_key* key) : Key() { if (key) std::memmove(this->getKeyPtr(), key, sizeof(*key)); }; - Key(ecc_key key) : Key(&key) {}; + } + + Key(ecc_key* key) : Key() { if (key) std::memmove(this->getKeyPtr(), key, sizeof(*key)); } + Key(ecc_key key) : Key(&key) {} + ~Key() { if (this->keyStorage.use_count() <= 1) { this->free(); } - }; - - bool isValid() - { - return (!Utils::Memory::IsSet(this->getKeyPtr(), 0, sizeof(*this->getKeyPtr()))); } - ecc_key* getKeyPtr() + [[nodiscard]] bool isValid() + { + return (!Memory::IsSet(this->getKeyPtr(), 0, sizeof(*this->getKeyPtr()))); + } + + [[nodiscard]] ecc_key* getKeyPtr() { return this->keyStorage.get(); } - std::string getPublicKey() + [[nodiscard]] std::string getPublicKey() { - uint8_t buffer[512] = { 0 }; + std::uint8_t buffer[512]{}; DWORD length = sizeof(buffer); if (ecc_ansi_x963_export(this->getKeyPtr(), buffer, &length) == CRYPT_OK) { - return std::string(reinterpret_cast(buffer), length); + return std::string{ reinterpret_cast(buffer), length }; } - return ""; + return std::string{}; } void set(const std::string& pubKeyBuffer) { this->free(); - if (ecc_ansi_x963_import(reinterpret_cast(pubKeyBuffer.data()), pubKeyBuffer.size(), this->getKeyPtr()) != CRYPT_OK) + if (ecc_ansi_x963_import(reinterpret_cast(pubKeyBuffer.data()), pubKeyBuffer.size(), this->getKeyPtr()) != CRYPT_OK) { ZeroMemory(this->getKeyPtr(), sizeof(*this->getKeyPtr())); } @@ -200,23 +197,23 @@ namespace Utils { this->free(); - if (ecc_import(reinterpret_cast(key.data()), key.size(), this->getKeyPtr()) != CRYPT_OK) + if (ecc_import(reinterpret_cast(key.data()), key.size(), this->getKeyPtr()) != CRYPT_OK) { ZeroMemory(this->getKeyPtr(), sizeof(*this->getKeyPtr())); } } - std::string serialize(int type = PK_PRIVATE) + [[nodiscard]] std::string serialize(int type = PK_PRIVATE) { - uint8_t buffer[4096] = { 0 }; + std::uint8_t buffer[4096]{}; DWORD length = sizeof(buffer); if (ecc_export(buffer, &length, type, this->getKeyPtr()) == CRYPT_OK) { - return std::string(reinterpret_cast(buffer), length); + return std::string{ reinterpret_cast(buffer), length }; } - return ""; + return std::string{}; } void free() @@ -265,16 +262,16 @@ namespace Utils } } - rsa_key* getKeyPtr() - { - return this->keyStorage.get(); - } - - bool isValid() + [[nodiscard]] bool isValid() { return (!Memory::IsSet(this->getKeyPtr(), 0, sizeof(*this->getKeyPtr()))); } + [[nodiscard]] rsa_key* getKeyPtr() + { + return this->keyStorage.get(); + } + void free() { if (this->isValid()) @@ -333,8 +330,8 @@ namespace Utils class JenkinsOneAtATime { public: - static unsigned int Compute(const std::string& data); - static unsigned int Compute(const char* key, std::size_t len); + static std::size_t Compute(const std::string& data); + static std::size_t Compute(const char* key, std::size_t len); }; } } From da34ecbba72069a64a86d4082fd5d6af49d58cd1 Mon Sep 17 00:00:00 2001 From: Diavolo Date: Wed, 21 Jun 2023 21:50:41 +0200 Subject: [PATCH 19/22] maint(utils): clean up RSA code --- src/Components/Modules/Node.cpp | 8 ++++-- src/Components/Modules/Node.hpp | 6 ++-- src/Components/Modules/ServerInfo.cpp | 8 +++--- src/Utils/Cryptography.cpp | 23 ++++++++++----- src/Utils/Cryptography.hpp | 40 +++++++++++++++++++++++++-- 5 files changed, 67 insertions(+), 18 deletions(-) diff --git a/src/Components/Modules/Node.cpp b/src/Components/Modules/Node.cpp index cd56f7b7..4f170bb4 100644 --- a/src/Components/Modules/Node.cpp +++ b/src/Components/Modules/Node.cpp @@ -15,6 +15,8 @@ namespace Components bool Node::WasIngame = false; + const Game::dvar_t* Node::net_natFix; + bool Node::Entry::isValid() const { return (this->lastResponse.has_value() && !this->lastResponse->elapsed(NODE_HALFLIFE * 2)); @@ -349,9 +351,9 @@ namespace Components } } - unsigned short Node::GetPort() + std::uint16_t Node::GetPort() { - if (Dvar::Var("net_natFix").get()) return 0; + if (net_natFix->current.enabled) return 0; return Network::GetPort(); } @@ -395,7 +397,7 @@ namespace Components Node::Node() { - Dvar::Register("net_natFix", false, 0, "Fix node registration for certain firewalls/routers"); + net_natFix = Game::Dvar_RegisterBool("net_natFix", false, 0, "Fix node registration for certain firewalls/routers"); Scheduler::Loop([] { diff --git a/src/Components/Modules/Node.hpp b/src/Components/Modules/Node.hpp index d0943b43..03e21e15 100644 --- a/src/Components/Modules/Node.hpp +++ b/src/Components/Modules/Node.hpp @@ -12,7 +12,7 @@ namespace Components class Data { public: - uint64_t protocol; + std::uint64_t protocol; }; class Entry @@ -46,6 +46,8 @@ namespace Components static std::vector Nodes; static bool WasIngame; + static const Game::dvar_t* net_natFix; + static void HandleResponse(const Network::Address& address, const std::string& data); static void SendList(const Network::Address& address); @@ -54,7 +56,7 @@ namespace Components static void LoadNodes(); static void StoreNodes(bool force); - static unsigned short GetPort(); + static std::uint16_t GetPort(); static void Migrate(); }; diff --git a/src/Components/Modules/ServerInfo.cpp b/src/Components/Modules/ServerInfo.cpp index 824ead48..5a7b5c3c 100644 --- a/src/Components/Modules/ServerInfo.cpp +++ b/src/Components/Modules/ServerInfo.cpp @@ -127,10 +127,10 @@ namespace Components { Utils::InfoString info; - info.set("admin", Dvar::Var("_Admin").get()); - info.set("website", Dvar::Var("_Website").get()); - info.set("email", Dvar::Var("_Email").get()); - info.set("location", Dvar::Var("_Location").get()); + info.set("admin", Dvar::Var("_Admin").get()); + info.set("website", Dvar::Var("_Website").get()); + info.set("email", Dvar::Var("_Email").get()); + info.set("location", Dvar::Var("_Location").get()); return info; } diff --git a/src/Utils/Cryptography.cpp b/src/Utils/Cryptography.cpp index 89111a27..180aceb7 100644 --- a/src/Utils/Cryptography.cpp +++ b/src/Utils/Cryptography.cpp @@ -92,7 +92,6 @@ namespace Utils Key key; register_prng(&sprng_desc); - register_hash(&sha1_desc); ltc_mp = ltm_desc; @@ -105,15 +104,20 @@ namespace Utils { if (!key.isValid()) return {}; - std::uint8_t buffer[512]; + std::uint8_t buffer[512]{}; unsigned long length = sizeof(buffer); + const auto hash = SHA512::Compute(message); + register_prng(&sprng_desc); - register_hash(&sha1_desc); + + const ltc_hash_descriptor& hash_desc = sha512_desc; + const int hash_index = register_hash(&hash_desc); ltc_mp = ltm_desc; - rsa_sign_hash(reinterpret_cast(message.data()), message.size(), buffer, &length, NULL, find_prng("sprng"), find_hash("sha1"), 0, key.getKeyPtr()); + rsa_sign_hash_ex(reinterpret_cast(hash.data()), hash.size(), + buffer, &length, LTC_PKCS_1_V1_5, nullptr, find_prng("sprng"), hash_index, 0, key.getKeyPtr()); return std::string{ reinterpret_cast(buffer), length }; } @@ -122,12 +126,17 @@ namespace Utils { if (!key.isValid()) return false; - register_hash(&sha1_desc); + const auto hash = SHA512::Compute(message); + + const ltc_hash_descriptor& hash_desc = sha512_desc; + const int hash_index = register_hash(&hash_desc); ltc_mp = ltm_desc; - int result = 0; - return (rsa_verify_hash(reinterpret_cast(signature.data()), signature.size(), reinterpret_cast(message.data()), message.size(), find_hash("sha1"), 0, &result, key.getKeyPtr()) == CRYPT_OK && result != 0); + auto result = 0; + return (rsa_verify_hash_ex(reinterpret_cast(signature.data()), signature.size(), + reinterpret_cast(hash.data()), hash.size(), LTC_PKCS_1_V1_5, + hash_index, 0, &result, key.getKeyPtr()) == CRYPT_OK && result != 0); } #pragma endregion diff --git a/src/Utils/Cryptography.hpp b/src/Utils/Cryptography.hpp index 4473a70a..ab0ac3df 100644 --- a/src/Utils/Cryptography.hpp +++ b/src/Utils/Cryptography.hpp @@ -173,7 +173,7 @@ namespace Utils [[nodiscard]] std::string getPublicKey() { std::uint8_t buffer[512]{}; - DWORD length = sizeof(buffer); + unsigned long length = sizeof(buffer); if (ecc_ansi_x963_export(this->getKeyPtr(), buffer, &length) == CRYPT_OK) { @@ -206,7 +206,7 @@ namespace Utils [[nodiscard]] std::string serialize(int type = PK_PRIVATE) { std::uint8_t buffer[4096]{}; - DWORD length = sizeof(buffer); + unsigned long length = sizeof(buffer); if (ecc_export(buffer, &length, type, this->getKeyPtr()) == CRYPT_OK) { @@ -272,6 +272,42 @@ namespace Utils return this->keyStorage.get(); } + [[nodiscard]] std::string getPublicKey() + { + std::uint8_t buffer[4096]{}; + unsigned long length = sizeof(buffer); + + if (rsa_export(buffer, &length, PK_PUBLIC, this->getKeyPtr()) == CRYPT_OK) + { + return std::string{ reinterpret_cast(buffer), length }; + } + + return std::string{}; + } + + void deserialize(const std::string& pubKeyBuffer) + { + this->free(); + + if (rsa_import(reinterpret_cast(pubKeyBuffer.data()), pubKeyBuffer.size(), this->getKeyPtr()) != CRYPT_OK) + { + ZeroMemory(this->getKeyPtr(), sizeof(*this->getKeyPtr())); + } + } + + [[nodiscard]] std::string serialize(int type = PK_PRIVATE) + { + std::uint8_t buffer[4096]{}; + unsigned long length = sizeof(buffer); + + if (rsa_export(buffer, &length, type, this->getKeyPtr()) == CRYPT_OK) + { + return std::string{ reinterpret_cast(buffer), length }; + } + + return std::string{}; + } + void free() { if (this->isValid()) From 6fd4ec54cc16e95ff9b48adf656c926a1ad7fecb Mon Sep 17 00:00:00 2001 From: Diavolo Date: Wed, 21 Jun 2023 22:12:38 +0200 Subject: [PATCH 20/22] fix(utils): fix RSA function --- src/Utils/Cryptography.cpp | 4 +--- src/Utils/Cryptography.hpp | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Utils/Cryptography.cpp b/src/Utils/Cryptography.cpp index 180aceb7..d07525ff 100644 --- a/src/Utils/Cryptography.cpp +++ b/src/Utils/Cryptography.cpp @@ -109,15 +109,13 @@ namespace Utils const auto hash = SHA512::Compute(message); - register_prng(&sprng_desc); - const ltc_hash_descriptor& hash_desc = sha512_desc; const int hash_index = register_hash(&hash_desc); ltc_mp = ltm_desc; rsa_sign_hash_ex(reinterpret_cast(hash.data()), hash.size(), - buffer, &length, LTC_PKCS_1_V1_5, nullptr, find_prng("sprng"), hash_index, 0, key.getKeyPtr()); + buffer, &length, LTC_PKCS_1_V1_5, nullptr, 0, hash_index, 0, key.getKeyPtr()); return std::string{ reinterpret_cast(buffer), length }; } diff --git a/src/Utils/Cryptography.hpp b/src/Utils/Cryptography.hpp index ab0ac3df..ec837130 100644 --- a/src/Utils/Cryptography.hpp +++ b/src/Utils/Cryptography.hpp @@ -285,7 +285,7 @@ namespace Utils return std::string{}; } - void deserialize(const std::string& pubKeyBuffer) + void set(const std::string& pubKeyBuffer) { this->free(); From 4d7d51fb291a94fd135764a5734cc1cd94b8076e Mon Sep 17 00:00:00 2001 From: Diavolo Date: Thu, 22 Jun 2023 00:30:34 +0200 Subject: [PATCH 21/22] maint(node): literally a one line fix I can't do without --- src/Components/Modules/Node.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Components/Modules/Node.hpp b/src/Components/Modules/Node.hpp index 03e21e15..d1e72a2e 100644 --- a/src/Components/Modules/Node.hpp +++ b/src/Components/Modules/Node.hpp @@ -1,6 +1,6 @@ #pragma once -#define NODE_HALFLIFE (3 * 60 * 1000) //3min +#define NODE_HALFLIFE (3 * 60 * 1000) // 3min #define NODE_MAX_NODES_TO_SEND 64 #define NODE_SEND_RATE 500ms From 008775d1b4a7a544aac287b1704c25b9ede49163 Mon Sep 17 00:00:00 2001 From: Diavolo Date: Thu, 22 Jun 2023 11:19:25 +0200 Subject: [PATCH 22/22] fix(utils): typo --- premake5.lua | 3 +-- src/Utils/Cryptography.hpp | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/premake5.lua b/premake5.lua index 41cda692..35554fdf 100644 --- a/premake5.lua +++ b/premake5.lua @@ -273,8 +273,7 @@ workspace "iw4x" dependencies.imports() -- Pre-build - prebuildcommands - { + prebuildcommands { "pushd %{_MAIN_SCRIPT_DIR}", "tools\\premake5 generate-buildinfo", "popd", diff --git a/src/Utils/Cryptography.hpp b/src/Utils/Cryptography.hpp index ec837130..46ac5e14 100644 --- a/src/Utils/Cryptography.hpp +++ b/src/Utils/Cryptography.hpp @@ -285,11 +285,11 @@ namespace Utils return std::string{}; } - void set(const std::string& pubKeyBuffer) + void set(const std::string& keyBuffer) { this->free(); - if (rsa_import(reinterpret_cast(pubKeyBuffer.data()), pubKeyBuffer.size(), this->getKeyPtr()) != CRYPT_OK) + if (rsa_import(reinterpret_cast(keyBuffer.data()), keyBuffer.size(), this->getKeyPtr()) != CRYPT_OK) { ZeroMemory(this->getKeyPtr(), sizeof(*this->getKeyPtr())); }