17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-18 06:49:18 +02:00
Files
maszyna/vehicle/graph/graph_lua.h

85 lines
3.1 KiB
C++

/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "vehicle/graph/graph_types.h"
#include <cstdint>
#include <functional>
#include <string>
#include <vector>
struct lua_State;
// lua function blocks of the vehicle graph. each vehicle gets a lua state of its own, separate from the scenery's
// one, and each block an environment of its own within it. scripts run in lua 5.1 (luajit) with a restricted set of
// libraries: no files, operating system, modules, ffi or bytecode loading. the jit compiler is turned off for these
// states, so the instruction budget which stops endless loops works reliably
namespace vgraph
{
// messages of the lua blocks (print, errors). the simulator directs them to its log, the command line tools to the console
using log_sink = std::function<void(std::string const &)>;
void set_log_sink(log_sink Sink);
void log_message(std::string const &Message);
// whether this build of the simulator can run lua blocks (WITH_LUA)
bool lua_available();
// interface of a lua block, read from its script:
// block "name" { inputs = { a = "bool" }, outputs = { q = "float" }, params = { k = 1.0 }, state = { ... }, rate = 20,
// update = function(self, i, o, dt) ... end }
struct lua_block_definition
{
std::string name;
std::vector<port_def> ports; // inputs then outputs, each sorted by key so the order doesn't depend on the lua hash
std::vector<param_def> params; // numeric parameters of the script as "lua.<key>", with the script's values as defaults
double rate{0.0}; // updates per second; 0 updates the block in every step
};
// runs the script in a temporary state and reads the block interface. returns false with the reason on failure
bool parse_lua_block(std::string const &Script, std::string const &Chunkname, lua_block_definition &Definition, std::string &Error);
// lua state shared by the lua blocks of one vehicle
class lua_host
{
public:
lua_host();
~lua_host();
lua_host(lua_host const &) = delete;
lua_host &operator=(lua_host const &) = delete;
lua_State *state() const
{
return m_state;
}
// runs the script of a block in a new environment and returns the registry reference of the block definition table,
// or a negative value with the reason on failure. the environment's random generator is seeded from the node id
int load_block(std::string const &Script, std::string const &Nodeid, std::string &Error);
// calls the function placed on the stack below its arguments, within the instruction budget. returns false with the reason on failure
bool call(int Arguments, std::string &Error);
void release(int Reference);
private:
lua_State *m_state{nullptr};
};
// random generator used by math.random of the lua blocks; the external editor uses the same one, so previews match
struct block_random
{
std::uint64_t state;
explicit block_random(std::uint64_t Seed);
double next(); // [0, 1)
static std::uint64_t seed_from(std::string const &Text);
};
} // namespace vgraph