Пример #1
0
/**
 * Gets the parsed field of a vconfig object (_index metamethod).
 * Special fields __literal, __shallow_literal, __parsed, and
 * __shallow_parsed, return Lua tables.
 */
static int impl_vconfig_get(lua_State *L)
{
	vconfig *v = static_cast<vconfig *>(lua_touserdata(L, 1));

	if (lua_isnumber(L, 2))
	{
		vconfig::all_children_iterator i = v->ordered_begin();
		unsigned len = std::distance(i, v->ordered_end());
		unsigned pos = lua_tointeger(L, 2) - 1;
		if (pos >= len) return 0;
		std::advance(i, pos);

		lua_createtable(L, 2, 0);
		lua_pushstring(L, i.get_key().c_str());
		lua_rawseti(L, -2, 1);
		luaW_pushvconfig(L, vconfig(i.get_child()));
		lua_rawseti(L, -2, 2);
		return 1;
	}

	char const *m = luaL_checkstring(L, 2);
	if (strcmp(m, "__literal") == 0) {
		luaW_pushconfig(L, v->get_config());
		return 1;
	}
	if (strcmp(m, "__parsed") == 0) {
		luaW_pushconfig(L, v->get_parsed_config());
		return 1;
	}

	bool shallow_literal = strcmp(m, "__shallow_literal") == 0;
	if (shallow_literal || strcmp(m, "__shallow_parsed") == 0)
	{
		lua_newtable(L);
		BOOST_FOREACH(const config::attribute &a, v->get_config().attribute_range()) {
			if (shallow_literal)
				luaW_pushscalar(L, a.second);
			else
				luaW_pushscalar(L, v->expand(a.first));
			lua_setfield(L, -2, a.first.c_str());
		}
		vconfig::all_children_iterator i = v->ordered_begin(),
			i_end = v->ordered_end();
		if (shallow_literal) {
			i.disable_insertion();
			i_end.disable_insertion();
		}
		for (int j = 1; i != i_end; ++i, ++j)
		{
			lua_createtable(L, 2, 0);
			lua_pushstring(L, i.get_key().c_str());
			lua_rawseti(L, -2, 1);
			luaW_pushvconfig(L, i.get_child());
			lua_rawseti(L, -2, 2);
			lua_rawseti(L, -2, j);
		}
		return 1;
	}
Пример #2
0
/**
 * Gets some data on a unit type (__index metamethod).
 * - Arg 1: table containing an "id" field.
 * - Arg 2: string containing the name of the property.
 * - Ret 1: something containing the attribute.
 */
static int impl_unit_type_get(lua_State *L)
{
    char const *m = luaL_checkstring(L, 2);
    lua_pushstring(L, "id");
    lua_rawget(L, 1);
    const unit_type *utp = unit_types.find(lua_tostring(L, -1));
    if (!utp) return luaL_argerror(L, 1, "unknown unit type");
    unit_type const &ut = *utp;

    // Find the corresponding attribute.
    return_tstring_attrib("name", ut.type_name());
    return_int_attrib("max_hitpoints", ut.hitpoints());
    return_int_attrib("max_moves", ut.movement());
    return_int_attrib("max_experience", ut.experience_needed());
    return_int_attrib("cost", ut.cost());
    return_int_attrib("level", ut.level());
    return_int_attrib("recall_cost", ut.recall_cost());
    return_cfgref_attrib("__cfg", ut.get_cfg());
    if (strcmp(m, "traits") == 0) {
        lua_newtable(L);
        BOOST_FOREACH(const config& trait, ut.possible_traits()) {
            const std::string& id = trait["id"];
            lua_pushlstring(L, id.c_str(), id.length());
            luaW_pushconfig(L, trait);
            lua_rawset(L, -3);
        }
        return 1;
    }
Пример #3
0
void lua_kernel_base::run_lua_tag(const config& cfg)
{
	int nArgs = 0;
	if (const config& args = cfg.child("args")) {
		luaW_pushconfig(this->mState, args);
		++nArgs;
	}
	this->run(cfg["code"].str().c_str(), cfg["name"].str(), nArgs);
}
static int impl_context_accessor(lua_State * L, std::shared_ptr<lua_context_backend> backend, plugins_context::accessor_function func)
{
	if (!backend->valid) {
		luaL_error(L , "Error, you tried to use an invalid context object in a lua thread");
	}

	if(lua_gettop(L)) {
		config temp;
		if(!luaW_toconfig(L, 1, temp)) {
			luaL_argerror(L, 1, "Error, tried to parse a config but some fields were invalid");
		}
		luaW_pushconfig(L, func(temp));
		return 1;
	} else {
		luaW_pushconfig(L, func(config()));
		return 1;
	}
}
Пример #5
0
/**
 * Returns a clone (deep copy) of the passed config, which can be either a normal config or a vconfig
 * If it is a vconfig, the underlying config is also cloned.
 * - Arg 1: a config
 * - Ret: the cloned config
 */
static int intf_clone_wml(lua_State* L)
{
	const vconfig* vcfg = nullptr;
	const config& cfg = luaW_checkconfig(L, 1, vcfg);
	if(vcfg) {
		config clone_underlying = vcfg->get_config();
		vconfig clone(clone_underlying);
		luaW_pushvconfig(L, clone);
	} else {
		luaW_pushconfig(L, cfg);
	}
	return 1;
}
Пример #6
0
void lua_ai_context::set_persistent_data(const config &cfg)
{
	int top = lua_gettop(L);

	lua_pushlightuserdata(L, static_cast<void *>(const_cast<char *>(&aisKey)));
	lua_rawget(L, LUA_REGISTRYINDEX);
	lua_rawgeti(L, -1, num_);

	luaW_pushconfig(L, cfg);
	lua_setfield(L, -2, "data");

	lua_settop(L, top);
}
Пример #7
0
/**
 * Parses a WML string into a config; does not preprocess or validate
 * - Arg 1: WML string
 * - Ret: config
 */
static int intf_parse_wml(lua_State* L)
{
	std::string wml = luaL_checkstring(L, 1);
	std::string schema_path = luaL_optstring(L, 2, "");
	std::shared_ptr<schema_validation::schema_validator> validator;
	if(!schema_path.empty()) {
		validator.reset(new schema_validation::schema_validator(filesystem::get_wml_location(schema_path)));
		validator->set_create_exceptions(false); // Don't crash if there's an error, just go ahead anyway
	}
	config result;
	read(result, wml, validator.get());
	luaW_pushconfig(L, result);
	return 1;
}
Пример #8
0
/**
 * Gets some data on a unit type (__index metamethod).
 * - Arg 1: table containing an "id" field.
 * - Arg 2: string containing the name of the property.
 * - Ret 1: something containing the attribute.
 */
static int impl_unit_type_get(lua_State *L)
{
	const unit_type& ut = luaW_checkunittype(L, 1);
	char const *m = luaL_checkstring(L, 2);

	// Find the corresponding attribute.
	return_tstring_attrib("name", ut.type_name());
	return_string_attrib("id", ut.id());
	return_string_attrib("alignment", ut.alignment().to_string());
	return_string_attrib("race", ut.race_id());
	return_int_attrib("max_hitpoints", ut.hitpoints());
	return_int_attrib("max_moves", ut.movement());
	return_int_attrib("max_experience", ut.experience_needed());
	return_int_attrib("cost", ut.cost());
	return_int_attrib("level", ut.level());
	return_int_attrib("recall_cost", ut.recall_cost());
	return_cfgref_attrib("__cfg", ut.get_cfg());
	if (strcmp(m, "traits") == 0) {
		lua_newtable(L);
		for (const config& trait : ut.possible_traits()) {
			const std::string& id = trait["id"];
			lua_pushlstring(L, id.c_str(), id.length());
			luaW_pushconfig(L, trait);
			lua_rawset(L, -3);
		}
		return 1;
	}
	if (strcmp(m, "abilities") == 0) {
		lua_push(L, ut.get_ability_list());
		return 1;
	}
	if (strcmp(m, "attacks") == 0) {
		push_unit_attacks_table(L, 1);
		return 1;
	}
	// TODO: Should this only exist for base units?
	if(strcmp(m, "variations") == 0) {
		*new(L) const unit_type* = &ut;
		luaL_setmetatable(L, UnitTypeTable);
		return 1;
	}
	return 0;
}
Пример #9
0
/**
 * Loads a WML file into a config
 * - Arg 1: WML file path
 * - Arg 2: (optional) Array of preprocessor defines, or false to skip preprocessing (true is also valid)
 * - Arg 3: (optional) Path to a schema file for validation (omit for no validation)
 * - Ret: config
 */
static int intf_load_wml(lua_State* L)
{
	std::string file = luaL_checkstring(L, 1);
	bool preprocess = true;
	preproc_map defines_map;
	if(lua_type(L, 2) == LUA_TBOOLEAN) {
		preprocess = luaW_toboolean(L, 2);
	} else if(lua_type(L, 2) == LUA_TTABLE || lua_type(L, 2) == LUA_TUSERDATA) {
		lua_len(L, 2);
		int n = lua_tonumber(L, -1);
		lua_pop(L, 1);
		for(int i = 0; i < n; i++) {
			lua_geti(L, 2, i);
			if(!lua_isstring(L, -1)) {
				return luaL_argerror(L, 2, "expected bool or array of strings");
			}
			std::string define = lua_tostring(L, -1);
			lua_pop(L, 1);
			if(!define.empty()) {
				defines_map.emplace(define, preproc_define(define));
			}
		}
	} else if(!lua_isnoneornil(L, 2)) {
		return luaL_argerror(L, 2, "expected bool or array of strings");
	}
	std::string schema_path = luaL_optstring(L, 3, "");
	std::shared_ptr<schema_validation::schema_validator> validator;
	if(!schema_path.empty()) {
		validator.reset(new schema_validation::schema_validator(filesystem::get_wml_location(schema_path)));
		validator->set_create_exceptions(false); // Don't crash if there's an error, just go ahead anyway
	}
	std::string wml_file = filesystem::get_wml_location(file);
	filesystem::scoped_istream stream;
	config result;
	if(preprocess) {
		stream = preprocess_file(wml_file, &defines_map);
	} else {
		stream.reset(new std::ifstream(wml_file));
	}
	read(result, *stream, validator.get());
	luaW_pushconfig(L, result);
	return 1;
}
Пример #10
0
void lua_ai_action_handler::handle(config &cfg, bool configOut, lua_object_ptr l_obj)
{
	int initial_top = lua_gettop(L);//get the old stack size

	// Load the user function from the registry.
	lua_pushlightuserdata(L, static_cast<void *>(const_cast<char *>(&aisKey)));//stack size is now 1 [-1: ais_table key]
	lua_rawget(L, LUA_REGISTRYINDEX);//stack size is still 1 [-1: ais_table]
	lua_rawgeti(L, -1, num_);//stack size is 2 [-1: ai_action  -2: ais_table]
	lua_remove(L, -2);//stack size is 1 [-1: ai_action]
	//load the lua ai context as a parameter
	context_.load();//stack size is 2 [-1: ai_context -2: ai_action]

	if (!configOut)
	{
		luaW_pushconfig(L, cfg);
		luaW_pcall(L, 2, 0, true);
	}
	else if (luaW_pcall(L, 1, 5, true)) // @note for Crab: how much nrets should we actually have here
	{				    // there were 2 initially, but aspects like recruitment pattern
		l_obj->store(L, initial_top + 1); // return a lot of results
	}

	lua_settop(L, initial_top);//empty stack
}
Пример #11
0
void mapgen_lua_kernel::run_generator(const char * prog, const config & generator)
{
	load_string(prog, boost::bind(&lua_kernel_base::throw_exception, this, _1, _2));
	luaW_pushconfig(mState, generator);
	protected_call(1, 1, boost::bind(&lua_kernel_base::throw_exception, this, _1, _2));
}
Пример #12
0
	typename boost::enable_if<typename boost::is_same<T, config>::type, void>::type lua_push(lua_State *L, const config& val)
	{
		luaW_pushconfig(L, val);
	}
Пример #13
0
static int cfun_ai_get_leader_goal(lua_State *L)
{
	config goal = get_readonly_context(L).get_leader_goal();
	luaW_pushconfig(L, goal);
	return 1;
}
application_lua_kernel::request_list application_lua_kernel::thread::run_script(const plugins_context & ctxt, const std::vector<plugins_manager::event> & queue)
{
	// There are two possibilities: (1) this is the first execution, and the C function is the only thing on the stack
	// (2) this is a subsequent execution, and there is nothing on the stack.
	// Either way we push the arguments to the function and call resume.

	// First we have to create the event table, by concatenating the event queue into a table.
	lua_newtable(T_); //this will be the event table
	for (std::size_t i = 0; i < queue.size(); ++i) {
		lua_newtable(T_);
		lua_pushstring(T_, queue[i].name.c_str());
		lua_rawseti(T_, -2, 1);
		luaW_pushconfig(T_, queue[i].data);
		lua_rawseti(T_, -2, 2);
		lua_rawseti(T_, -2, i+1);
	}

	// Now we have to create the context object. It is arranged as a table of boost functions.
	std::shared_ptr<lua_context_backend> this_context_backend = std::make_shared<lua_context_backend> (lua_context_backend());
	lua_newtable(T_); // this will be the context table
	for (const std::string & key : ctxt.callbacks_ | boost::adaptors::map_keys ) {
		lua_pushstring(T_, key.c_str());
		lua_cpp::push_function(T_, std::bind(&impl_context_backend, _1, this_context_backend, key));
		lua_settable(T_, -3);
	}

	// Now we have to create the info object (context accessors). It is arranged as a table of boost functions.
	lua_newtable(T_); // this will be the info table
	lua_pushstring(T_, "name");
	lua_pushstring(T_, ctxt.name_.c_str());
	lua_settable(T_, -3);
	for (const plugins_context::accessor_list::value_type & v : ctxt.accessors_) {
		const std::string & key = v.first;
		const plugins_context::accessor_function & func = v.second;
		lua_pushstring(T_, key.c_str());
		lua_cpp::push_function(T_, std::bind(&impl_context_accessor, _1, this_context_backend, func));
		lua_settable(T_, -3);
	}

	// Now we resume the function, calling the coroutine with the three arguments (events, context, info).
	lua_resume(T_, nullptr, 3);

	started_ = true;

	this_context_backend->valid = false; //invalidate the context object for lua

	if (lua_status(T_) != LUA_YIELD) {
		LOG_LUA << "Thread status = '" << lua_status(T_) << "'\n";
		if (lua_status(T_) != LUA_OK) {
			std::stringstream ss;
			ss << "encountered a";
			switch(lua_status(T_)) {
				case LUA_ERRSYNTAX:
					ss << " syntax ";
					break;
				case LUA_ERRRUN:
					ss << " runtime ";
					break;
				case LUA_ERRERR:
					ss << " error-handler ";
					break;
				default:
					ss << " ";
					break;
			}
			ss << "error:\n" << lua_tostring(T_, -1) << "\n";
			ERR_LUA << ss.str() << std::endl;
		}
	}

	application_lua_kernel::request_list results;

	for (const plugins_manager::event & req : this_context_backend->requests) {
		results.push_back(std::bind(ctxt.callbacks_.find(req.name)->second, req.data));
		//results.emplace_back(ctxt.callbacks_.find(req.name)->second, req.data);
	}
	return results;
}