From 2da4c9157a0653b2c10a6d28f7a0c1cd452684c5 Mon Sep 17 00:00:00 2001 From: Chris Beck Date: Tue, 4 Nov 2014 15:52:29 -0500 Subject: [PATCH] add lua map generator type --- src/CMakeLists.txt | 1 + src/SConscript | 1 + src/generators/lua_map_generator.cpp | 98 ++++++++++++++++++++++++++++ src/generators/lua_map_generator.hpp | 53 +++++++++++++++ src/generators/map_create.cpp | 14 ++-- src/wesnoth.cpp | 2 + 6 files changed, 165 insertions(+), 4 deletions(-) create mode 100644 src/generators/lua_map_generator.cpp create mode 100644 src/generators/lua_map_generator.hpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 005a589d2ec..a57a30d6a64 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1006,6 +1006,7 @@ set(libwesnoth-game_STAT_SRC generators/map_create.cpp generators/map_generator.cpp generators/default_map_generator.cpp + generators/lua_map_generator.cpp generators/yamg/ya_mapgen.cpp generators/yamg/yamg_hex.cpp generators/yamg/yamg_hexheap.cpp diff --git a/src/SConscript b/src/SConscript index 9cd0ce97bab..224489e38dd 100644 --- a/src/SConscript +++ b/src/SConscript @@ -93,6 +93,7 @@ libwesnoth_sources = Split(""" generators/map_create.cpp generators/map_generator.cpp generators/default_map_generator.cpp + generators/lua_map_generator.cpp generators/yamg/ya_mapgen.cpp generators/yamg/yamg_hex.cpp generators/yamg/yamg_hexheap.cpp diff --git a/src/generators/lua_map_generator.cpp b/src/generators/lua_map_generator.cpp new file mode 100644 index 00000000000..e97ad94cf05 --- /dev/null +++ b/src/generators/lua_map_generator.cpp @@ -0,0 +1,98 @@ +/* + Copyright (C) 2014 by Chris Beck + Part of the Battle for Wesnoth Project http://www.wesnoth.org/ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. + + See the COPYING file for more details. +*/ + +#include "lua_map_generator.hpp" + +#include "config.hpp" + +#include "lua/lauxlib.h" +#include "lua/lua.h" +#include "lua/lualib.h" + +#ifdef DEBUG_LUA +#include "scripting/debug_lua.hpp" +#endif + +#include "scripting/lua_api.hpp" + +#include + +#include + +lua_map_generator::lua_map_generator(const config & cfg) + : id_(cfg["id"]) + , config_name_(cfg["config_name"]) + , create_map_(cfg["create_map"]) + , mState_(luaL_newstate()) +{ + const char* required[] = {"id", "config_name", "create_map"}; + BOOST_FOREACH(std::string req, required) { + if (!cfg.has_attribute(req)) { + std::string msg = "Error when constructing a lua map generator -- missing a required attribute '"; + msg += req + "'\n"; + msg += "Config was '" + cfg.debug() + "'"; + throw mapgen_exception(msg); + } + } +} + +lua_map_generator::~lua_map_generator() +{ + lua_close(mState_); +} + +std::string lua_map_generator::create_map() +{ + { + int errcode = luaL_loadstring(mState_, create_map_.c_str()); + if (errcode != LUA_OK) { + std::string msg = "Error when running lua_map_generator create_map.\n"; + msg += "The generator was: " + config_name_ + "\n"; + msg += "Error when parsing create_map function. "; + if (errcode == LUA_ERRSYNTAX) { + msg += "There was a syntax error:\n"; + } else { + msg += "There was a memory error:\n"; + } + msg += lua_tostring(mState_, -1); + throw mapgen_exception(msg); + } + } + { + int errcode = lua_pcall(mState_, 0, 1, 0); + if (errcode != LUA_OK) { + std::string msg = "Error when running lua_map_generator create_map.\n"; + msg += "The generator was: " + config_name_ + "\n"; + msg += "Error when running create_map function. "; + if (errcode == LUA_ERRRUN) { + msg += "There was a runtime error:\n"; + } else if (errcode == LUA_ERRERR) { + msg += "There was an error with the attached debugger:\n"; + } else { + msg += "There was a memory or garbage collection error:\n"; + } + msg += lua_tostring(mState_, -1); + throw mapgen_exception(msg); + } + } + if (!lua_isstring(mState_,-1)) { + std::string msg = "Error when running lua_map_generator create_map.\n"; + msg += "The generator was: " + config_name_ + "\n"; + msg += "create_map did not return a string, instead it returned '"; + msg += lua_typename(mState_, lua_type(mState_, -1)); + msg += "'"; + throw mapgen_exception(msg); + } + return lua_tostring(mState_, -1); +} diff --git a/src/generators/lua_map_generator.hpp b/src/generators/lua_map_generator.hpp new file mode 100644 index 00000000000..2f6a87784a7 --- /dev/null +++ b/src/generators/lua_map_generator.hpp @@ -0,0 +1,53 @@ +/* + Copyright (C) 2014 by Chris Beck + Part of the Battle for Wesnoth Project http://www.wesnoth.org/ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. + + See the COPYING file for more details. +*/ + +#ifndef LUA_MAP_GENERATOR_DEFINED +#define LUA_MAP_GENERATOR_DEFINED + +#include "map_generator.hpp" + +#include + +class config; +struct lua_State; + +// TODO: Add support for user configurability (via defining a gui2 dialog in lua) +// What's missing is that you need access to the 'wesnoth' object to call show dialog +// at the moment. + +class lua_map_generator : public map_generator { +public: + lua_map_generator(const config & cfg); + + ~lua_map_generator(); + + bool allow_user_config() const { return false; } + + std::string name() const { return "lua"; } + + std::string id() const { return id_; } + + std::string config_name() const { return config_name_; } + + virtual std::string create_map(); + +private: + std::string id_, config_name_; + + std::string create_map_; + + lua_State * mState_; +}; + +#endif diff --git a/src/generators/map_create.cpp b/src/generators/map_create.cpp index c0d10baebda..6520b5ae10c 100644 --- a/src/generators/map_create.cpp +++ b/src/generators/map_create.cpp @@ -18,11 +18,13 @@ #include "generators/cave_map_generator.hpp" #include "generators/yamg/ya_mapgen.hpp" #include "generators/default_map_generator.hpp" +#include "generators/lua_map_generator.hpp" #include "log.hpp" #include "scoped_resource.hpp" #include "serialization/string_utils.hpp" #include +#include static lg::log_domain log_config("config"); #define ERR_CF LOG_STREAM(err, log_config) @@ -35,6 +37,8 @@ map_generator* create_map_generator(const std::string& name, const config &cfg) return new cave_map_generator(cfg); } else if(name == "yamg") { return new ya_mapgen(cfg); + } else if(name == "lua") { + return new lua_map_generator(cfg); } else { return NULL; } @@ -50,8 +54,9 @@ std::string random_generate_map(const std::string& parms, const config &cfg) assert(!parameters.empty()); //we use parameters.front() in the next line. util::scoped_ptr generator(create_map_generator(parameters.front(),cfg)); if(generator == NULL) { - ERR_CF << "could not find map generator '" << parameters.front() << "'" << std::endl; - return std::string(); + std::stringstream ss; + ss << "could not find map generator '" << parameters.front() << "'"; + throw mapgen_exception(ss.str()); } parameters.erase(parameters.begin()); @@ -66,8 +71,9 @@ config random_generate_scenario(const std::string& parms, const config &cfg) assert(!parameters.empty()); //we use parameters.front() in the next line. util::scoped_ptr generator(create_map_generator(parameters.front(),cfg)); if(generator == NULL) { - ERR_CF << "could not find map generator '" << parameters.front() << "'" << std::endl; - return config(); + std::stringstream ss; + ss << "could not find map generator '" << parameters.front() << "'"; + throw mapgen_exception(ss.str()); } parameters.erase(parameters.begin()); diff --git a/src/wesnoth.cpp b/src/wesnoth.cpp index 09fc3c06e73..b18ba284292 100644 --- a/src/wesnoth.cpp +++ b/src/wesnoth.cpp @@ -86,6 +86,8 @@ #include "SDL_stdinc.h" // for SDL_putenv, Uint32 #include "SDL_timer.h" // for SDL_GetTicks +//#define NO_CATCH_AT_GAME_END + #ifdef _WIN32 #include #endif