--- a/rts/Game/WebbarBrowser.h +++ b/rts/Game/WebbarBrowser.h @@ -46,6 +46,7 @@ #include "WebbarCloak.h" #include "WebbarWorkAudio.h" #include "WebbarEconomy.h" +#include "WebbarCatalog.h" static bool WebbarSupports(const UnitDef* def) { @@ -90,9 +91,7 @@ }, gu->myPlayerNum, gu->myTeam, gu->myAllyTeam, int(gu->spectating)); for (const UnitDef& def: unitDefHandler->GetUnitDefsVec()) { if (!WebbarSupports(&def)) continue; - MAIN_THREAD_EM_ASM({ - if (Module['webbarCatalog']) Module['webbarCatalog']($0, UTF8ToString($1), $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12); - }, def.id, def.name.c_str(), def.cost.metal, def.cost.energy, def.buildTime, def.xsize * SQUARE_SIZE, def.zsize * SQUARE_SIZE, def.IsBuilderUnit(), def.IsFactoryUnit(), def.IsExtractorUnit(), !def.IsImmobileUnit(), def.CanDamage(), def.needGeo); + PublishWebbarCatalog(def); for (const auto& option: def.buildOptions) { const UnitDef* target = unitDefHandler->GetUnitDefByName(option.second); if (!WebbarSupports(target)) continue; --- /dev/null +++ b/rts/Game/WebbarCatalog.h @@ -0,0 +1,45 @@ +/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */ +#pragma once + +// Read-only initial match definitions, after the game's definition processing. +// They are public specifications, never unit state, occupancy or net income. +static void PublishWebbarCatalog(const UnitDef& def) +{ + const float values[] = { + def.upkeep.metal, def.upkeep.energy, def.resourceMake.metal, def.resourceMake.energy, + def.makesResources.metal, def.makesResources.energy, def.windGenerator.metal, def.windGenerator.energy, + def.tidalGenerator.metal, def.tidalGenerator.energy, def.storage.metal, def.storage.energy, + def.extractsMetal, def.extractRange, def.minWaterDepth, def.maxWaterDepth, def.maxHeightDif, def.waterline, + }; + std::vector yardmap; + yardmap.reserve(def.yardmap.size()); + for (const auto cell: def.yardmap) yardmap.push_back(uint8_t(cell)); + const auto param = [&def](const char* key) -> const char* { + const auto found = def.customParams.find(key); + return found == def.customParams.end() ? nullptr : found->second.c_str(); + }; + const auto pointer = [](const void* value) { return uint32_t(reinterpret_cast(value)); }; + const uint32_t words[] = { + pointer(yardmap.data()), uint32_t(yardmap.size()), uint32_t(def.xsize), uint32_t(def.zsize), + uint32_t(def.onoffable), uint32_t(def.activateWhenBuilt), uint32_t(def.floatOnWater), + pointer(param("energyconv_capacity")), pointer(param("energyconv_efficiency")), + pointer(param("metal_extractor")), pointer(param("energymultiplier")), uint32_t(def.levelGround), def.buildingMask, + }; + MAIN_THREAD_EM_ASM({ + if (!Module['webbarCatalog']) return; + const values = Array.from(HEAPF32.subarray($13 >> 2, ($13 >> 2) + 18)); + // Keep the host-call argument count below Emscripten's 16-argument limit. + const words = HEAPU32.subarray($14 >> 2, ($14 >> 2) + 13); + const yardmap = Array.from(HEAPU8.subarray(words[0], words[0] + words[1])); + const nativeEconomy = ({version: 1, values, yardmap, xsize: words[2], zsize: words[3], + onoffable: Boolean(words[4]), activateWhenBuilt: Boolean(words[5]), floatOnWater: Boolean(words[6]), + conversionCapacity: words[7] ? UTF8ToString(words[7]) : null, + conversionEfficiency: words[8] ? UTF8ToString(words[8]) : null, + extractionMultiplier: words[9] ? UTF8ToString(words[9]) : null, + energyMultiplier: words[10] ? UTF8ToString(words[10]) : null, levelGround: Boolean(words[11]), buildingMask: words[12]}); + Module['webbarCatalog']($0, UTF8ToString($1), $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, nativeEconomy); + }, def.id, def.name.c_str(), def.cost.metal, def.cost.energy, def.buildTime, + def.xsize * SQUARE_SIZE, def.zsize * SQUARE_SIZE, def.IsBuilderUnit(), def.IsFactoryUnit(), + def.IsExtractorUnit(), !def.IsImmobileUnit(), def.CanDamage(), def.needGeo, + values, words); +}