diff --git a/binaries/data/mods/public/simulation/components/AIInterface.js b/binaries/data/mods/public/simulation/components/AIInterface.js index 873f48d164..c7b7f6bc87 100644 --- a/binaries/data/mods/public/simulation/components/AIInterface.js +++ b/binaries/data/mods/public/simulation/components/AIInterface.js @@ -42,7 +42,7 @@ AIInterface.prototype.GetFullRepresentation = function() var cmpGuiInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); // Return the same game state as the GUI uses - var state = cmpGuiInterface.GetSimulationState(-1); + var state = cmpGuiInterface.GetExtendedSimulationState(-1); // Add some extra AI-specific data state.events = this.events; diff --git a/binaries/data/mods/public/simulation/components/AIProxy.js b/binaries/data/mods/public/simulation/components/AIProxy.js index 0b54bb9a5b..ffac2bd79c 100644 --- a/binaries/data/mods/public/simulation/components/AIProxy.js +++ b/binaries/data/mods/public/simulation/components/AIProxy.js @@ -288,4 +288,10 @@ AIProxy.prototype.OnTrainingFinished = function(msg) cmpAIInterface.PushEvent("TrainingFinished", msg); }; +AIProxy.prototype.OnAIMetadata = function(msg) +{ + var cmpAIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_AIInterface); + cmpAIInterface.PushEvent("AIMetadata", msg); +}; + Engine.RegisterComponentType(IID_AIProxy, "AIProxy", AIProxy); diff --git a/binaries/data/mods/public/simulation/helpers/Commands.js b/binaries/data/mods/public/simulation/helpers/Commands.js index a78d387d04..9b4431929b 100644 --- a/binaries/data/mods/public/simulation/helpers/Commands.js +++ b/binaries/data/mods/public/simulation/helpers/Commands.js @@ -650,6 +650,7 @@ function TryConstructBuilding(player, cmpPlayer, controlAllUnits, cmd) // "x": ..., // "z": ..., // "angle": ..., + // "metadata": "...", // AI metadata of the building // "actorSeed": ..., // "autorepair": true, // whether to automatically start constructing/repairing the new foundation // "autocontinue": true, // whether to automatically gather/build/etc after finishing this @@ -800,6 +801,10 @@ function TryConstructBuilding(player, cmpPlayer, controlAllUnits, cmd) var cmpFoundation = Engine.QueryInterface(ent, IID_Foundation); cmpFoundation.InitialiseConstruction(player, cmd.template); + // send Metadata info if any + if (cmd.metadata) + Engine.PostMessage(ent, MT_AIMetadata, { "id": ent, "metadata" : cmd.metadata, "owner" : player } ); + // Tell the units to start building this new entity if (cmd.autorepair) { diff --git a/source/simulation2/components/CCmpAIManager.cpp b/source/simulation2/components/CCmpAIManager.cpp index 564d5b8f7a..84979389ea 100644 --- a/source/simulation2/components/CCmpAIManager.cpp +++ b/source/simulation2/components/CCmpAIManager.cpp @@ -131,6 +131,7 @@ private: /** * Debug function for AI scripts to dump 2D array data (e.g. terrain tile weights). + * TODO: check if this needs to be here too. */ static void DumpImage(void* UNUSED(cbdata), std::wstring name, std::vector data, u32 w, u32 h, u32 max) { @@ -328,7 +329,8 @@ public: m_ScriptInterface.RegisterFunction("PostCommand"); m_ScriptInterface.RegisterFunction("DumpHeap"); m_ScriptInterface.RegisterFunction("ForceGC"); - + + m_ScriptInterface.RegisterFunction, u32, u32, u32, CAIWorker::DumpImage>("DumpImage"); } ~CAIWorker() @@ -374,6 +376,45 @@ public: PROFILE3("AI compute GC"); JS_GC(self->m_ScriptInterface.GetContext()); } + + /** + * Debug function for AI scripts to dump 2D array data (e.g. terrain tile weights). + */ + static void DumpImage(void* UNUSED(cbdata), std::wstring name, std::vector data, u32 w, u32 h, u32 max) + { + // TODO: this is totally not threadsafe. + VfsPath filename = L"screenshots/aidump/" + name; + + if (data.size() != w*h) + { + debug_warn(L"DumpImage: data size doesn't match w*h"); + return; + } + + if (max == 0) + { + debug_warn(L"DumpImage: max must not be 0"); + return; + } + + const size_t bpp = 8; + int flags = TEX_BOTTOM_UP|TEX_GREY; + + const size_t img_size = w * h * bpp/8; + const size_t hdr_size = tex_hdr_size(filename); + shared_ptr buf; + AllocateAligned(buf, hdr_size+img_size, maxSectorSize); + Tex t; + if (tex_wrap(w, h, bpp, flags, buf, hdr_size, &t) < 0) + return; + + u8* img = buf.get() + hdr_size; + for (size_t i = 0; i < data.size(); ++i) + img[i] = (u8)((data[i] * 255) / max); + + tex_write(&t, filename); + tex_free(&t); + } bool TryLoadSharedComponent(bool hasTechs) { @@ -489,6 +530,7 @@ public: { // this will be run last by InitGame.Js, passing the full game representation. // For now it will run for the shared Component. + // This is NOT run during deserialization. CScriptVal state = m_ScriptInterface.ReadStructuredClone(gameState); JSContext* cx = m_ScriptInterface.GetContext();