mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-22 14:24:33 +01:00
Add script engine and connect to std console
This commit is contained in:
@@ -57,6 +57,7 @@
|
||||
#include "ride/TrackDesignRepository.h"
|
||||
#include "scenario/Scenario.h"
|
||||
#include "scenario/ScenarioRepository.h"
|
||||
#include "scripting/ScriptEngine.h"
|
||||
#include "title/TitleScreen.h"
|
||||
#include "title/TitleSequenceManager.h"
|
||||
#include "ui/UiContext.h"
|
||||
@@ -76,6 +77,7 @@ using namespace OpenRCT2::Audio;
|
||||
using namespace OpenRCT2::Drawing;
|
||||
using namespace OpenRCT2::Localisation;
|
||||
using namespace OpenRCT2::Paint;
|
||||
using namespace OpenRCT2::Scripting;
|
||||
using namespace OpenRCT2::Ui;
|
||||
|
||||
namespace OpenRCT2
|
||||
@@ -100,6 +102,7 @@ namespace OpenRCT2
|
||||
std::unique_ptr<DiscordService> _discordService;
|
||||
#endif
|
||||
StdInOutConsole _stdInOutConsole;
|
||||
ScriptEngine _scriptEngine;
|
||||
|
||||
// Game states
|
||||
std::unique_ptr<TitleScreen> _titleScreen;
|
||||
@@ -135,6 +138,7 @@ namespace OpenRCT2
|
||||
, _uiContext(uiContext)
|
||||
, _localisationService(std::make_unique<LocalisationService>(env))
|
||||
, _painter(std::make_unique<Painter>(uiContext))
|
||||
, _scriptEngine(_stdInOutConsole, *env)
|
||||
{
|
||||
// Can't have more than one context currently.
|
||||
Guard::Assert(Instance == nullptr);
|
||||
@@ -176,6 +180,11 @@ namespace OpenRCT2
|
||||
return _uiContext;
|
||||
}
|
||||
|
||||
Scripting::ScriptEngine& GetScriptEngine() override
|
||||
{
|
||||
return _scriptEngine;
|
||||
}
|
||||
|
||||
GameState* GetGameState() override
|
||||
{
|
||||
return _gameState.get();
|
||||
@@ -1015,7 +1024,7 @@ namespace OpenRCT2
|
||||
|
||||
Twitch::Update();
|
||||
chat_update();
|
||||
_stdInOutConsole.ProcessEvalQueue();
|
||||
_scriptEngine.Update();
|
||||
_uiContext->Update();
|
||||
}
|
||||
|
||||
|
||||
@@ -85,6 +85,11 @@ namespace OpenRCT2
|
||||
class LocalisationService;
|
||||
}
|
||||
|
||||
namespace Scripting
|
||||
{
|
||||
class ScriptEngine;
|
||||
}
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
interface IUiContext;
|
||||
@@ -109,6 +114,7 @@ namespace OpenRCT2
|
||||
virtual Localisation::LocalisationService& GetLocalisationService() abstract;
|
||||
virtual IObjectManager& GetObjectManager() abstract;
|
||||
virtual IObjectRepository& GetObjectRepository() abstract;
|
||||
virtual Scripting::ScriptEngine& GetScriptEngine() abstract;
|
||||
virtual ITrackDesignRepository* GetTrackDesignRepository() abstract;
|
||||
virtual IScenarioRepository* GetScenarioRepository() abstract;
|
||||
virtual IReplayManager* GetReplayManager() abstract;
|
||||
|
||||
@@ -12,11 +12,8 @@
|
||||
#include "../common.h"
|
||||
#include "../localisation/FormatCodes.h"
|
||||
|
||||
#include <deque>
|
||||
#include <future>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
struct rct_drawpixelinfo;
|
||||
struct TextInputSession;
|
||||
@@ -53,13 +50,9 @@ public:
|
||||
|
||||
class StdInOutConsole final : public InteractiveConsole
|
||||
{
|
||||
private:
|
||||
std::queue<std::tuple<std::promise<void>, std::string>> _evalQueue;
|
||||
|
||||
public:
|
||||
void Start();
|
||||
std::future<void> Eval(const std::string& s);
|
||||
void ProcessEvalQueue();
|
||||
|
||||
void Clear() override;
|
||||
void Close() override;
|
||||
|
||||
@@ -7,11 +7,15 @@
|
||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "../Context.h"
|
||||
#include "../OpenRCT2.h"
|
||||
#include "../platform/Platform2.h"
|
||||
#include "../scripting/ScriptEngine.h"
|
||||
#include "../thirdparty/linenoise.hpp"
|
||||
#include "InteractiveConsole.h"
|
||||
|
||||
using namespace OpenRCT2;
|
||||
|
||||
void StdInOutConsole::Start()
|
||||
{
|
||||
std::thread replThread([this]() -> void {
|
||||
@@ -51,28 +55,8 @@ void StdInOutConsole::Start()
|
||||
|
||||
std::future<void> StdInOutConsole::Eval(const std::string& s)
|
||||
{
|
||||
// Push on-demand evaluations onto a queue so that it can be processed deterministically
|
||||
// on the main thead at the right time.
|
||||
std::promise<void> barrier;
|
||||
auto future = barrier.get_future();
|
||||
_evalQueue.emplace(std::move(barrier), s);
|
||||
return future;
|
||||
}
|
||||
|
||||
void StdInOutConsole::ProcessEvalQueue()
|
||||
{
|
||||
while (_evalQueue.size() > 0)
|
||||
{
|
||||
auto item = std::move(_evalQueue.front());
|
||||
_evalQueue.pop();
|
||||
auto promise = std::move(std::get<0>(item));
|
||||
auto command = std::move(std::get<1>(item));
|
||||
|
||||
Execute(command);
|
||||
|
||||
// Signal the promise so caller can continue
|
||||
promise.set_value();
|
||||
}
|
||||
auto& scriptEngine = GetContext()->GetScriptEngine();
|
||||
return scriptEngine.Eval(s);
|
||||
}
|
||||
|
||||
void StdInOutConsole::Clear()
|
||||
|
||||
79
src/openrct2/scripting/ScriptEngine.cpp
Normal file
79
src/openrct2/scripting/ScriptEngine.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
/*****************************************************************************
|
||||
* Copyright (c) 2014-2018 OpenRCT2 developers
|
||||
*
|
||||
* For a complete list of all authors, please refer to contributors.md
|
||||
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
|
||||
*
|
||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "ScriptEngine.h"
|
||||
#include "../interface/InteractiveConsole.h"
|
||||
#include <duktape.h>
|
||||
#include <stdexcept>
|
||||
|
||||
using namespace OpenRCT2;
|
||||
using namespace OpenRCT2::Scripting;
|
||||
|
||||
static std::string Stringify(duk_context * ctx, duk_idx_t idx);
|
||||
|
||||
ScriptEngine::ScriptEngine(InteractiveConsole& console, IPlatformEnvironment& env) :
|
||||
_console(console),
|
||||
_env(env)
|
||||
{
|
||||
_context = duk_create_heap_default();
|
||||
if (_context == nullptr)
|
||||
{
|
||||
throw std::runtime_error("Unable to initialise duktape context.");
|
||||
}
|
||||
}
|
||||
|
||||
ScriptEngine::~ScriptEngine()
|
||||
{
|
||||
duk_destroy_heap(_context);
|
||||
}
|
||||
|
||||
void ScriptEngine::Update()
|
||||
{
|
||||
while (_evalQueue.size() > 0)
|
||||
{
|
||||
auto item = std::move(_evalQueue.front());
|
||||
_evalQueue.pop();
|
||||
auto promise = std::move(std::get<0>(item));
|
||||
auto command = std::move(std::get<1>(item));
|
||||
if (duk_peval_string(_context, command.c_str()) != 0)
|
||||
{
|
||||
std::string result = std::string(duk_safe_to_string(_context, -1));
|
||||
_console.WriteLineError(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string result = Stringify(_context, -1);
|
||||
_console.WriteLine(result);
|
||||
}
|
||||
duk_pop(_context);
|
||||
// Signal the promise so caller can continue
|
||||
promise.set_value();
|
||||
}
|
||||
}
|
||||
|
||||
std::future<void> ScriptEngine::Eval(const std::string &s)
|
||||
{
|
||||
std::promise<void> barrier;
|
||||
auto future = barrier.get_future();
|
||||
_evalQueue.emplace(std::move(barrier), s);
|
||||
return future;
|
||||
}
|
||||
|
||||
static std::string Stringify(duk_context * ctx, duk_idx_t idx)
|
||||
{
|
||||
auto type = duk_get_type(ctx, idx);
|
||||
if (type == DUK_TYPE_OBJECT && !duk_is_function(ctx, idx))
|
||||
{
|
||||
return duk_json_encode(ctx, idx);
|
||||
}
|
||||
else
|
||||
{
|
||||
return duk_safe_to_string(ctx, idx);
|
||||
}
|
||||
}
|
||||
45
src/openrct2/scripting/ScriptEngine.h
Normal file
45
src/openrct2/scripting/ScriptEngine.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*****************************************************************************
|
||||
* Copyright (c) 2014-2018 OpenRCT2 developers
|
||||
*
|
||||
* For a complete list of all authors, please refer to contributors.md
|
||||
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
|
||||
*
|
||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||
*****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../common.h"
|
||||
#include <future>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
|
||||
struct duk_hthread;
|
||||
typedef struct duk_hthread duk_context;
|
||||
|
||||
class InteractiveConsole;
|
||||
|
||||
namespace OpenRCT2
|
||||
{
|
||||
interface IPlatformEnvironment;
|
||||
}
|
||||
|
||||
namespace OpenRCT2::Scripting
|
||||
{
|
||||
class ScriptEngine
|
||||
{
|
||||
private:
|
||||
InteractiveConsole& _console;
|
||||
IPlatformEnvironment& _env;
|
||||
duk_context * _context;
|
||||
std::queue<std::tuple<std::promise<void>, std::string>> _evalQueue;
|
||||
|
||||
public:
|
||||
ScriptEngine(InteractiveConsole& console, IPlatformEnvironment& env);
|
||||
ScriptEngine(ScriptEngine&&) = delete;
|
||||
~ScriptEngine();
|
||||
|
||||
void Update();
|
||||
std::future<void> Eval(const std::string &s);
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user