1
0
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:
Ted John
2018-03-17 19:31:06 +00:00
parent 27a8597214
commit 43508e0402
6 changed files with 146 additions and 30 deletions

View File

@@ -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();
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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()

View 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);
}
}

View 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);
};
}