Added invoke_plan, removed viewer
This commit is contained in:
@@ -2,10 +2,10 @@
|
||||
|
||||
LuaDefineType(Gui);
|
||||
|
||||
void Gui::add_menu_item(const std::string &id, const std::string &label) {
|
||||
void Gui::menu_item(const std::string &action, const std::string &label) {
|
||||
GuiElt elt;
|
||||
elt.type_ = GuiElt::TYPE_MENU_ITEM;
|
||||
elt.id_ = id;
|
||||
elt.action_ = action;
|
||||
elt.label_ = label;
|
||||
elts_.push_back(elt);
|
||||
}
|
||||
@@ -18,10 +18,11 @@ LuaDefine(gui_create, "c") {
|
||||
}
|
||||
|
||||
LuaDefine(gui_menu_item, "c") {
|
||||
LuaArg lgui, lid;
|
||||
LuaStack LS(L, lgui, lid);
|
||||
LuaArg lgui, laction, llabel;
|
||||
LuaStack LS(L, lgui, laction, llabel);
|
||||
Gui *gui = LS.ckuserdata<Gui>(lgui);
|
||||
std::string id = LS.ckstring(lid);
|
||||
gui->add_menu_item(id, id);
|
||||
std::string action = LS.ckstring(laction);
|
||||
std::string label = LS.ckstring(llabel);
|
||||
gui->menu_item(action, label);
|
||||
return LS.result();
|
||||
}
|
||||
|
||||
@@ -13,14 +13,14 @@ public:
|
||||
};
|
||||
private:
|
||||
Type type_;
|
||||
std::string id_;
|
||||
std::string action_;
|
||||
std::string label_;
|
||||
|
||||
GuiElt() {}
|
||||
public:
|
||||
~GuiElt() {}
|
||||
Type type() const { return type_; }
|
||||
const std::string &id() const { return id_; }
|
||||
const std::string &action() const { return action_; }
|
||||
const std::string &label() const { return label_; }
|
||||
};
|
||||
|
||||
@@ -32,7 +32,7 @@ private:
|
||||
public:
|
||||
const EltVec &elts() const { return elts_; }
|
||||
void clear() { elts_.clear(); }
|
||||
void add_menu_item(const std::string &id, const std::string &label);
|
||||
void menu_item(const std::string &action, const std::string &label);
|
||||
};
|
||||
|
||||
#endif // GUI_HPP
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// LUASNAP
|
||||
//
|
||||
// A lua interpreter that can be checkpointed (snapshotted).
|
||||
// This makes it possible to roll the entire interpreter back
|
||||
// to a previously-snapshotted state.
|
||||
// A lua interpreter that can be checkpointed (snapshotted). This makes it
|
||||
// possible to roll the entire interpreter back to a previously-snapshotted
|
||||
// state.
|
||||
//
|
||||
// To accomplish this, we take advantage of the 'allocf' parameter
|
||||
// to lua_newstate. This lets us hook the lua allocator, which
|
||||
// in turn lets us find every block of memory currently in use by
|
||||
// lua. To snapshot, we 'memcpy' every block of memory
|
||||
// that lua is using into a buffer. To rollback, we just 'memcpy'
|
||||
// the data back.
|
||||
// To accomplish this, we take advantage of the 'allocf' parameter to
|
||||
// lua_newstate. This lets us hook the lua allocator, which in turn lets us
|
||||
// find every block of memory currently in use by lua. To snapshot, we 'memcpy'
|
||||
// every block of memory that lua is using into a buffer. To rollback, we just
|
||||
// 'memcpy' the data back.
|
||||
//
|
||||
// The current implementation is a proof-of-concept. It's quite
|
||||
// wasteful of memory, roughly doubling the amount of RAM that
|
||||
// LUA uses. But it does demonstrate that this method of snapshot
|
||||
// and rollback is feasible.
|
||||
// The current implementation is a proof-of-concept. It's quite wasteful of
|
||||
// memory, roughly doubling the amount of RAM that LUA uses. It's also not
|
||||
// super-fast, since it allocates tons of tiny blocks. But it totally
|
||||
// works, so it demonstrate that this method of snapshot and rollback is
|
||||
// feasible.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef LUASNAP_HPP
|
||||
#define LUASNAP_HPP
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include "luastack.hpp"
|
||||
#include "util.hpp"
|
||||
#include "gui.hpp"
|
||||
#include "viewer.hpp"
|
||||
#include "world.hpp"
|
||||
#include "traceback.hpp"
|
||||
#include "textgame.hpp"
|
||||
#include "luaconsole.hpp"
|
||||
@@ -44,7 +44,7 @@ static void l_message(const char *msg)
|
||||
}
|
||||
|
||||
void TextGame::do_lua(const std::string &exp) {
|
||||
lua_State *L = viewer_.state();
|
||||
lua_State *L = world_->state();
|
||||
int status = luaL_loadbuffer(L, exp.c_str(), exp.size(), "=stdin");
|
||||
assert(status == LUA_OK);
|
||||
globalL = L;
|
||||
@@ -81,8 +81,8 @@ void TextGame::do_view_command(const StringVec &cmd) {
|
||||
std::cerr << "v command (view) takes no arguments" << std::endl;
|
||||
return;
|
||||
}
|
||||
for (int64_t id : viewer_.get_near()) {
|
||||
const Tangible *tan = viewer_.tangible_get(id);
|
||||
for (int64_t id : world_->get_near(1, 100)) {
|
||||
const Tangible *tan = world_->tangible_get(id);
|
||||
const AnimQueue &aq = tan->anim_queue_;
|
||||
std::cerr << id << ": " << aq.get_graphic() << " " << aq.get_plane() << " " << aq.get_xyz() << std::endl;
|
||||
}
|
||||
@@ -98,8 +98,8 @@ void TextGame::do_menu_command(const StringVec &cmd) {
|
||||
std::cerr << "m command (menu) expects a tangible ID or defaults to 1" << std::endl;
|
||||
return;
|
||||
}
|
||||
gui_id_ = id;
|
||||
viewer_.update_gui(id, &gui_);
|
||||
gui_place_ = id;
|
||||
world_->update_gui(1, id, &gui_);
|
||||
int index = 0;
|
||||
for (const GuiElt &elt : gui_.elts()) {
|
||||
std::cerr << index << " " << elt.label() << std::endl;
|
||||
@@ -120,7 +120,9 @@ void TextGame::do_choose_command(const StringVec &cmd) {
|
||||
std::cerr << "No menu item #" << index << std::endl;
|
||||
return;
|
||||
}
|
||||
std::cerr << "Choosing menu item: " << elts[index].id() << std::endl;
|
||||
std::string action = elts[index].action();
|
||||
std::cerr << "Invoking plan: " << action << std::endl;
|
||||
world_->invoke_plan(1, gui_place_, action, &gui_);
|
||||
}
|
||||
|
||||
void TextGame::do_snapshot_command(const StringVec &cmd) {
|
||||
@@ -128,7 +130,7 @@ void TextGame::do_snapshot_command(const StringVec &cmd) {
|
||||
std::cerr << "s command (snapshot) takes no arguments" << std::endl;
|
||||
return;
|
||||
}
|
||||
viewer_.snapshot();
|
||||
world_->snapshot();
|
||||
}
|
||||
|
||||
void TextGame::do_rollback_command(const StringVec &cmd) {
|
||||
@@ -136,7 +138,7 @@ void TextGame::do_rollback_command(const StringVec &cmd) {
|
||||
std::cerr << "r command (rollback) takes no arguments" << std::endl;
|
||||
return;
|
||||
}
|
||||
viewer_.rollback();
|
||||
world_->rollback();
|
||||
}
|
||||
|
||||
void TextGame::do_quit_command(const StringVec &cmd) {
|
||||
@@ -161,6 +163,8 @@ void TextGame::do_command(const StringVec &words) {
|
||||
|
||||
void TextGame::run()
|
||||
{
|
||||
world_.reset(new World);
|
||||
world_->init_standalone();
|
||||
console_.clear();
|
||||
while (true) {
|
||||
console_.add_stdin();
|
||||
|
||||
@@ -2,16 +2,17 @@
|
||||
#ifndef TEXTGAME_HPP
|
||||
#define TEXTGAME_HPP
|
||||
|
||||
#include "viewer.hpp"
|
||||
#include "luaconsole.hpp"
|
||||
#include "world.hpp"
|
||||
#include <memory>
|
||||
|
||||
class TextGame {
|
||||
private:
|
||||
using StringVec = LuaConsole::StringVec;
|
||||
Viewer viewer_;
|
||||
std::unique_ptr<World> world_;
|
||||
LuaConsole console_;
|
||||
Gui gui_;
|
||||
int64_t gui_id_;
|
||||
int64_t gui_place_;
|
||||
|
||||
void do_view_command(const StringVec &cmd);
|
||||
void do_menu_command(const StringVec &cmd);
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
|
||||
#include "viewer.hpp"
|
||||
|
||||
Viewer::Viewer() {
|
||||
world_.reset(new World);
|
||||
world_->init_standalone();
|
||||
}
|
||||
|
||||
Viewer::~Viewer() {
|
||||
}
|
||||
|
||||
int64_t Viewer::get_player_id() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Viewer::update_gui(int64_t place, Gui *gui) {
|
||||
world_->update_gui(get_player_id(), place, gui);
|
||||
}
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
#ifndef VIEWER_HPP
|
||||
#define VIEWER_HPP
|
||||
|
||||
#include "world.hpp"
|
||||
#include "animqueue.hpp"
|
||||
#include "gui.hpp"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
class Viewer {
|
||||
private:
|
||||
std::unique_ptr<World> world_;
|
||||
|
||||
public:
|
||||
Viewer();
|
||||
~Viewer();
|
||||
|
||||
// Snapshot/rollback the lua state (temporary hack)
|
||||
void snapshot() { world_->lua_snap_.snapshot(); }
|
||||
void rollback() { world_->lua_snap_.rollback(); }
|
||||
|
||||
// Get the lua state for interaction.
|
||||
//
|
||||
lua_State *state() { return world_->state(); }
|
||||
|
||||
// Get the player ID of the current player.
|
||||
//
|
||||
int64_t get_player_id();
|
||||
|
||||
// Get the list of tangibles near the player.
|
||||
//
|
||||
std::vector<int64_t> get_near() { return world_->get_near(1, 100); }
|
||||
|
||||
// Get the specified tangible.
|
||||
//
|
||||
const Tangible *tangible_get(int64_t id) { return world_->tangible_get(id); }
|
||||
|
||||
// Update the GUI for the specified sprite.
|
||||
//
|
||||
// The gui passed in will be overwritten.
|
||||
//
|
||||
void update_gui(int64_t id, Gui *g);
|
||||
};
|
||||
|
||||
#endif // VIEWER_HPP
|
||||
@@ -140,8 +140,8 @@ void World::update_gui(int64_t actor_id, int64_t place_id, Gui *gui) {
|
||||
gui->clear();
|
||||
lua_State *L = state();
|
||||
|
||||
LuaVar actor, place, ugui, func, tangibles;
|
||||
LuaStack LS(L, actor, place, ugui, func, tangibles);
|
||||
LuaVar actor, place, ugui, func, tangibles, mt, index;
|
||||
LuaStack LS(L, actor, place, ugui, func, tangibles, mt, index);
|
||||
|
||||
// Get the actor and place.
|
||||
LS.rawget(tangibles, LuaRegistry, "tangibles");
|
||||
@@ -153,8 +153,17 @@ void World::update_gui(int64_t actor_id, int64_t place_id, Gui *gui) {
|
||||
}
|
||||
|
||||
// Get the interface closure.
|
||||
// Use of 'gettable' instead of 'rawget' is deliberate.
|
||||
LS.gettable(func, place, "interface");
|
||||
LS.getmetatable(mt, place);
|
||||
if (!LS.istable(mt)) {
|
||||
LS.result();
|
||||
return;
|
||||
}
|
||||
LS.rawget(index, mt, "__index");
|
||||
if (!LS.istable(index)) {
|
||||
LS.result();
|
||||
return;
|
||||
}
|
||||
LS.rawget(func, index, "interface");
|
||||
if (!LS.isfunction(func)) {
|
||||
LS.result();
|
||||
return;
|
||||
@@ -182,7 +191,67 @@ void World::update_gui(int64_t actor_id, int64_t place_id, Gui *gui) {
|
||||
// And we're done.
|
||||
LS.result();
|
||||
}
|
||||
|
||||
void World::invoke_plan(int64_t actor_id, int64_t place_id, const std::string &action, Gui *gui) {
|
||||
lua_State *L = state();
|
||||
|
||||
LuaVar actor, place, ugui, func, tangibles, mt, index, actions;
|
||||
LuaStack LS(L, actor, place, ugui, func, tangibles, mt, index, actions);
|
||||
|
||||
// Get the actor and place.
|
||||
LS.rawget(tangibles, LuaRegistry, "tangibles");
|
||||
LS.rawget(actor, tangibles, actor_id);
|
||||
LS.rawget(place, tangibles, place_id);
|
||||
if (!LS.istable(actor) || !LS.istable(place)) {
|
||||
LS.result();
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the action closure.
|
||||
LS.getmetatable(mt, place);
|
||||
if (!LS.istable(mt)) {
|
||||
LS.result();
|
||||
return;
|
||||
}
|
||||
LS.rawget(index, mt, "__index");
|
||||
if (!LS.istable(index)) {
|
||||
LS.result();
|
||||
return;
|
||||
}
|
||||
LS.rawget(actions, index, "action");
|
||||
if (!LS.istable(actions)) {
|
||||
LS.result();
|
||||
return;
|
||||
}
|
||||
LS.rawget(func, actions, action);
|
||||
if (!LS.isfunction(func)) {
|
||||
LS.result();
|
||||
return;
|
||||
}
|
||||
|
||||
// Construct the userdata with the GUI pointer.
|
||||
LS.newpointer<Gui>(ugui, gui, false);
|
||||
|
||||
// Call the action function.
|
||||
lua_pushvalue(L, func.index());
|
||||
lua_pushvalue(L, actor.index());
|
||||
lua_pushvalue(L, place.index());
|
||||
lua_pushvalue(L, ugui.index());
|
||||
int status = traceback_pcall(L, 3, 0);
|
||||
if (status != 0) {
|
||||
gui->clear();
|
||||
std::cerr << lua_tostring(L, -1);
|
||||
LS.result();
|
||||
return;
|
||||
}
|
||||
|
||||
// Nuke the userdata, in case somebody saved a pointer to it.
|
||||
LS.clearuserdata(ugui);
|
||||
|
||||
// And we're done.
|
||||
LS.result();
|
||||
}
|
||||
|
||||
LuaDefine(tangible_get, "c") {
|
||||
LuaArg id;
|
||||
LuaRet database;
|
||||
|
||||
@@ -112,12 +112,21 @@ public:
|
||||
//
|
||||
void update_gui(int64_t actor_id, int64_t place_id, Gui *gui);
|
||||
|
||||
// Invoke an action plan.
|
||||
//
|
||||
void invoke_plan(int64_t actor_id, int64_t place_id, const std::string &action, Gui *gui);
|
||||
|
||||
// fetch
|
||||
//
|
||||
// Given a lua state, fetch the world model associated with
|
||||
// that lua state.
|
||||
//
|
||||
static World *fetch(lua_State *L);
|
||||
|
||||
// Snapshot and rollback - temporary.
|
||||
//
|
||||
void snapshot() { lua_snap_.snapshot(); }
|
||||
void rollback() { lua_snap_.rollback(); }
|
||||
};
|
||||
|
||||
#endif // WORLD_HPP
|
||||
|
||||
Reference in New Issue
Block a user