Changeset View
Changeset View
Standalone View
Standalone View
source/simulation2/components/CCmpCommandQueue.cpp
Show All 11 Lines | |||||
* GNU General Public License for more details. | * GNU General Public License for more details. | ||||
* | * | ||||
* You should have received a copy of the GNU General Public License | * You should have received a copy of the GNU General Public License | ||||
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. | * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. | ||||
*/ | */ | ||||
#include "precompiled.h" | #include "precompiled.h" | ||||
#include "CCmpCommandQueue.h" | |||||
#include "simulation2/system/Component.h" | #include "simulation2/system/Component.h" | ||||
#include "ICmpCommandQueue.h" | |||||
#include "ps/CLogger.h" | #include "ps/CLogger.h" | ||||
#include "ps/Game.h" | #include "ps/Game.h" | ||||
#include "ps/Profile.h" | #include "ps/Profile.h" | ||||
#include "scriptinterface/FunctionWrapper.h" | #include "scriptinterface/FunctionWrapper.h" | ||||
#include "scriptinterface/JSON.h" | #include "scriptinterface/JSON.h" | ||||
#include "simulation2/system/TurnManager.h" | #include "simulation2/system/TurnManager.h" | ||||
class CCmpCommandQueue final : public ICmpCommandQueue | void CCmpCommandQueue::ClassInit(CComponentManager& UNUSED(componentManager)) | ||||
{ | {} | ||||
public: | |||||
static void ClassInit(CComponentManager& UNUSED(componentManager)) | IComponent* CCmpCommandQueue::Allocate(const ScriptInterface&, JS::HandleValue) | ||||
{ | { | ||||
return nullptr; | |||||
} | } | ||||
DEFAULT_COMPONENT_ALLOCATOR(CommandQueue) | void CCmpCommandQueue::Deallocate(IComponent*) | ||||
{} | |||||
std::vector<SimulationCommand> m_LocalQueue; | int CCmpCommandQueue::GetComponentTypeId() const | ||||
static std::string GetSchema() | |||||
{ | { | ||||
return "<a:component type='system'/><empty/>"; | return CID_CommandQueue; | ||||
} | } | ||||
void Init(const CParamNode& UNUSED(paramNode)) override | std::string CCmpCommandQueue::CCmpCommandQueue::GetSchema() | ||||
{ | { | ||||
return "<a:component type='system'/><empty/>"; | |||||
} | } | ||||
void Deinit() override | void CCmpCommandQueue::Init(const CParamNode& UNUSED(paramNode)) | ||||
{ | {} | ||||
} | |||||
void CCmpCommandQueue::Deinit() | |||||
{} | |||||
void Serialize(ISerializer& serialize) override | void CCmpCommandQueue::Serialize(ISerializer& serialize) | ||||
{ | { | ||||
ScriptRequest rq(GetSimContext().GetScriptInterface()); | ScriptRequest rq(GetSimContext().GetScriptInterface()); | ||||
serialize.NumberU32_Unbounded("num commands", (u32)m_LocalQueue.size()); | serialize.NumberU32_Unbounded("num commands", (u32)m_LocalQueue.size()); | ||||
for (size_t i = 0; i < m_LocalQueue.size(); ++i) | for (size_t i = 0; i < m_LocalQueue.size(); ++i) | ||||
{ | { | ||||
serialize.NumberI32_Unbounded("player", m_LocalQueue[i].player); | serialize.NumberI32_Unbounded("player", m_LocalQueue[i].player); | ||||
serialize.ScriptVal("data", &m_LocalQueue[i].data); | serialize.ScriptVal("data", &m_LocalQueue[i].data); | ||||
} | } | ||||
} | } | ||||
void Deserialize(const CParamNode& UNUSED(paramNode), IDeserializer& deserialize) override | void CCmpCommandQueue::Deserialize(const CParamNode& UNUSED(paramNode), IDeserializer& deserialize) | ||||
{ | { | ||||
ScriptRequest rq(GetSimContext().GetScriptInterface()); | ScriptRequest rq(GetSimContext().GetScriptInterface()); | ||||
u32 numCmds; | u32 numCmds; | ||||
deserialize.NumberU32_Unbounded("num commands", numCmds); | deserialize.NumberU32_Unbounded("num commands", numCmds); | ||||
for (size_t i = 0; i < numCmds; ++i) | for (size_t i = 0; i < numCmds; ++i) | ||||
{ | { | ||||
i32 player; | i32 player; | ||||
JS::RootedValue data(rq.cx); | JS::RootedValue data(rq.cx); | ||||
deserialize.NumberI32_Unbounded("player", player); | deserialize.NumberI32_Unbounded("player", player); | ||||
deserialize.ScriptVal("data", &data); | deserialize.ScriptVal("data", &data); | ||||
m_LocalQueue.emplace_back(SimulationCommand(player, rq.cx, data)); | m_LocalQueue.emplace_back(SimulationCommand(player, rq.cx, data)); | ||||
} | } | ||||
} | } | ||||
void PushLocalCommand(player_id_t player, JS::HandleValue cmd) override | void CCmpCommandQueue::PushLocalCommand(player_id_t player, JS::HandleValue cmd) | ||||
{ | { | ||||
ScriptRequest rq(GetSimContext().GetScriptInterface()); | ScriptRequest rq(GetSimContext().GetScriptInterface()); | ||||
m_LocalQueue.emplace_back(SimulationCommand(player, rq.cx, cmd)); | m_LocalQueue.emplace_back(SimulationCommand(player, rq.cx, cmd)); | ||||
} | } | ||||
void PostNetworkCommand(JS::HandleValue cmd1) override | void CCmpCommandQueue::PostNetworkCommand(JS::HandleValue cmd1) | ||||
{ | { | ||||
ScriptRequest rq(GetSimContext().GetScriptInterface()); | ScriptRequest rq(GetSimContext().GetScriptInterface()); | ||||
// TODO: This is a workaround because we need to pass a MutableHandle to StringifyJSON. | // TODO: This is a workaround because we need to pass a MutableHandle to StringifyJSON. | ||||
JS::RootedValue cmd(rq.cx, cmd1.get()); | JS::RootedValue cmd(rq.cx, cmd1.get()); | ||||
PROFILE2_EVENT("post net command"); | PROFILE2_EVENT("post net command"); | ||||
PROFILE2_ATTR("command: %s", Script::StringifyJSON(rq, &cmd, false).c_str()); | PROFILE2_ATTR("command: %s", Script::StringifyJSON(rq, &cmd, false).c_str()); | ||||
// TODO: would be nicer to not use globals | // TODO: would be nicer to not use globals | ||||
if (g_Game && g_Game->GetTurnManager()) | if (g_Game && g_Game->GetTurnManager()) | ||||
g_Game->GetTurnManager()->PostCommand(cmd); | g_Game->GetTurnManager()->PostCommand(cmd); | ||||
} | } | ||||
void FlushTurn(const std::vector<SimulationCommand>& commands) override | void CCmpCommandQueue::FlushTurn(const std::vector<SimulationCommand>& commands) | ||||
{ | { | ||||
const ScriptInterface& scriptInterface = GetSimContext().GetScriptInterface(); | const ScriptInterface& scriptInterface = GetSimContext().GetScriptInterface(); | ||||
ScriptRequest rq(scriptInterface); | ScriptRequest rq(scriptInterface); | ||||
JS::RootedValue global(rq.cx, rq.globalValue()); | JS::RootedValue global(rq.cx, rq.globalValue()); | ||||
std::vector<SimulationCommand> localCommands; | std::vector<SimulationCommand> localCommands; | ||||
m_LocalQueue.swap(localCommands); | m_LocalQueue.swap(localCommands); | ||||
for (size_t i = 0; i < localCommands.size(); ++i) | for (size_t i = 0; i < localCommands.size(); ++i) | ||||
{ | { | ||||
bool ok = ScriptFunction::CallVoid(rq, global, "ProcessCommand", localCommands[i].player, localCommands[i].data); | bool ok = ScriptFunction::CallVoid(rq, global, "ProcessCommand", localCommands[i].player, localCommands[i].data); | ||||
if (!ok) | if (!ok) | ||||
LOGERROR("Failed to call ProcessCommand() global script function"); | LOGERROR("Failed to call ProcessCommand() global script function"); | ||||
} | } | ||||
for (size_t i = 0; i < commands.size(); ++i) | for (size_t i = 0; i < commands.size(); ++i) | ||||
{ | { | ||||
bool ok = ScriptFunction::CallVoid(rq, global, "ProcessCommand", commands[i].player, commands[i].data); | bool ok = ScriptFunction::CallVoid(rq, global, "ProcessCommand", commands[i].player, commands[i].data); | ||||
if (!ok) | if (!ok) | ||||
LOGERROR("Failed to call ProcessCommand() global script function"); | LOGERROR("Failed to call ProcessCommand() global script function"); | ||||
} | } | ||||
} | } | ||||
}; | |||||
REGISTER_COMPONENT_TYPE(CommandQueue) | REGISTER_COMPONENT_TYPE(CommandQueue) |
Wildfire Games · Phabricator