Allow both coordinate object and (x,y,z) as arguments to getTileBlock.

develop
Alexander Gavrilov 2012-05-02 12:50:05 +04:00
parent eadce95940
commit 28b5068382
5 changed files with 143 additions and 44 deletions

@ -779,9 +779,9 @@ Maps module
Returns a map block object for given x,y,z in local block coordinates. Returns a map block object for given x,y,z in local block coordinates.
* ``dfhack.maps.getTileBlock(coords)`` * ``dfhack.maps.getTileBlock(coords)``, or ``getTileBlock(x,y,z)``
Returns a map block object for given df::coord in local tile coordinates. Returns a map block object for given df::coord or x,y,z in local tile coordinates.
* ``dfhack.maps.getRegionBiome(region_coord2d)`` * ``dfhack.maps.getRegionBiome(region_coord2d)``

@ -1005,8 +1005,8 @@ Returns <em>false</em> in case of error.</p>
<li><p class="first"><tt class="docutils literal">dfhack.maps.getBlock(x,y,z)</tt></p> <li><p class="first"><tt class="docutils literal">dfhack.maps.getBlock(x,y,z)</tt></p>
<p>Returns a map block object for given x,y,z in local block coordinates.</p> <p>Returns a map block object for given x,y,z in local block coordinates.</p>
</li> </li>
<li><p class="first"><tt class="docutils literal">dfhack.maps.getTileBlock(coords)</tt></p> <li><p class="first"><tt class="docutils literal">dfhack.maps.getTileBlock(coords)</tt>, or <tt class="docutils literal">getTileBlock(x,y,z)</tt></p>
<p>Returns a map block object for given df::coord in local tile coordinates.</p> <p>Returns a map block object for given df::coord or x,y,z in local tile coordinates.</p>
</li> </li>
<li><p class="first"><tt class="docutils literal">dfhack.maps.getRegionBiome(region_coord2d)</tt></p> <li><p class="first"><tt class="docutils literal">dfhack.maps.getRegionBiome(region_coord2d)</tt></p>
<p>Returns the biome info struct for the given global map region.</p> <p>Returns the biome info struct for the given global map region.</p>
@ -1129,7 +1129,7 @@ from the size of the building.</p>
<li><p class="first"><tt class="docutils literal">dfhack.constructions.designateNew(pos,type,item_type,mat_index)</tt></p> <li><p class="first"><tt class="docutils literal">dfhack.constructions.designateNew(pos,type,item_type,mat_index)</tt></p>
<p>Designates a new construction at given position. If there already is <p>Designates a new construction at given position. If there already is
a planned but not completed construction there, changes its type. a planned but not completed construction there, changes its type.
Returns <em>true</em> or <em>false</em> if obstructed. Returns <em>true</em>, or <em>false</em> if obstructed.
Note that designated constructions are technically buildings.</p> Note that designated constructions are technically buildings.</p>
</li> </li>
</ul> </ul>

@ -520,8 +520,7 @@ static int dfhack_matinfo_matches(lua_State *state)
else if (lua_istable(state, 2)) else if (lua_istable(state, 2))
{ {
df::dfhack_material_category tmp; df::dfhack_material_category tmp;
if (!Lua::AssignDFObject(*Lua::GetOutput(state), state, &tmp, 2, false)) Lua::CheckDFObject(state, &tmp, 2, false);
lua_error(state);
lua_pushboolean(state, info.matches(tmp)); lua_pushboolean(state, info.matches(tmp));
} }
else else
@ -714,7 +713,6 @@ static const luaL_Reg dfhack_items_funcs[] = {
static const LuaWrapper::FunctionReg dfhack_maps_module[] = { static const LuaWrapper::FunctionReg dfhack_maps_module[] = {
WRAPN(getBlock, (df::map_block* (*)(int32_t,int32_t,int32_t))Maps::getBlock), WRAPN(getBlock, (df::map_block* (*)(int32_t,int32_t,int32_t))Maps::getBlock),
WRAPN(getTileBlock, (df::map_block* (*)(df::coord))Maps::getTileBlock),
WRAPM(Maps, getRegionBiome), WRAPM(Maps, getRegionBiome),
WRAPM(Maps, getGlobalInitFeature), WRAPM(Maps, getGlobalInitFeature),
WRAPM(Maps, getLocalInitFeature), WRAPM(Maps, getLocalInitFeature),
@ -722,7 +720,27 @@ static const LuaWrapper::FunctionReg dfhack_maps_module[] = {
{ NULL, NULL } { NULL, NULL }
}; };
static int maps_getTileBlock(lua_State *L)
{
df::map_block *block;
if (lua_gettop(L) == 1)
{
df::coord pos;
Lua::CheckDFObject(L, &pos, 1);
block = Maps::getTileBlock(pos);
}
else
{
block = Maps::getTileBlock(
luaL_checkint(L, 1), luaL_checkint(L, 2), luaL_checkint(L, 3)
);
}
Lua::PushDFObject(L, block);
return 1;
}
static const luaL_Reg dfhack_maps_funcs[] = { static const luaL_Reg dfhack_maps_funcs[] = {
{ "getTileBlock", maps_getTileBlock },
{ NULL, NULL } { NULL, NULL }
}; };

@ -84,7 +84,7 @@ void *DFHack::Lua::GetDFObject(lua_State *state, type_identity *type, int val_in
return get_object_internal(state, type, val_index, exact_type, false); return get_object_internal(state, type, val_index, exact_type, false);
} }
void *DFHack::Lua::CheckDFObject(lua_State *state, type_identity *type, int val_index, bool exact_type) static void check_valid_ptr_index(lua_State *state, int val_index)
{ {
if (lua_type(state, val_index) == LUA_TNONE) if (lua_type(state, val_index) == LUA_TNONE)
{ {
@ -93,23 +93,47 @@ void *DFHack::Lua::CheckDFObject(lua_State *state, type_identity *type, int val_
else else
luaL_error(state, "at index %d: pointer expected", val_index); luaL_error(state, "at index %d: pointer expected", val_index);
} }
}
if (lua_isnil(state, val_index)) static void dfhack_printerr(lua_State *S, const std::string &str);
return NULL;
void *rv = get_object_internal(state, type, val_index, exact_type, false); static void signal_typeid_error(color_ostream *out, lua_State *state,
type_identity *type, const char *msg,
int val_index, bool perr, bool signal)
{
std::string error = stl_sprintf(msg, type->getFullName().c_str());
if (!rv) if (signal)
{ {
std::string error = "invalid pointer type";
if (type)
error += "; expected: " + type->getFullName();
if (val_index > 0) if (val_index > 0)
luaL_argerror(state, val_index, error.c_str()); luaL_argerror(state, val_index, error.c_str());
else else
luaL_error(state, "at index %d: %s", val_index, error.c_str()); luaL_error(state, "at index %d: %s", val_index, error.c_str());
} }
else if (perr)
{
if (out)
out->printerr("%s", error.c_str());
else
dfhack_printerr(state, error);
}
else
lua_pushstring(state, error.c_str());
}
void *DFHack::Lua::CheckDFObject(lua_State *state, type_identity *type, int val_index, bool exact_type)
{
check_valid_ptr_index(state, val_index);
if (lua_isnil(state, val_index))
return NULL;
void *rv = get_object_internal(state, type, val_index, exact_type, false);
if (!rv)
signal_typeid_error(NULL, state, type, "invalid pointer type; expected: %s",
val_index, false, true);
return rv; return rv;
} }
@ -343,7 +367,7 @@ static void error_tostring(lua_State *L, bool keep_old = false)
} }
} }
static void report_error(lua_State *L, color_ostream *out = NULL) static void report_error(lua_State *L, color_ostream *out = NULL, bool pop = false)
{ {
error_tostring(L, true); error_tostring(L, true);
@ -355,7 +379,7 @@ static void report_error(lua_State *L, color_ostream *out = NULL)
else else
dfhack_printerr(L, msg); dfhack_printerr(L, msg);
lua_pop(L, 1); lua_pop(L, pop?2:1);
} }
static bool convert_to_exception(lua_State *L, int slevel, lua_State *thread = NULL) static bool convert_to_exception(lua_State *L, int slevel, lua_State *thread = NULL)
@ -544,10 +568,7 @@ bool DFHack::Lua::SafeCall(color_ostream &out, lua_State *L, int nargs, int nres
bool ok = lua_pcall(L, nargs, nres, base) == LUA_OK; bool ok = lua_pcall(L, nargs, nres, base) == LUA_OK;
if (!ok && perr) if (!ok && perr)
{ report_error(L, &out, true);
report_error(L, &out);
lua_pop(L, 1);
}
lua_remove(L, base); lua_remove(L, base);
set_dfhack_output(L, cur_out); set_dfhack_output(L, cur_out);
@ -658,10 +679,7 @@ int DFHack::Lua::SafeResume(color_ostream &out, lua_State *from, lua_State *thre
int rv = resume_helper(from, thread, nargs, nres); int rv = resume_helper(from, thread, nargs, nres);
if (!Lua::IsSuccess(rv) && perr) if (!Lua::IsSuccess(rv) && perr)
{ report_error(from, &out, true);
report_error(from, &out);
lua_pop(from, 1);
}
set_dfhack_output(from, cur_out); set_dfhack_output(from, cur_out);
@ -746,14 +764,64 @@ bool DFHack::Lua::Require(color_ostream &out, lua_State *state,
return true; return true;
} }
static bool doAssignDFObject(color_ostream *out, lua_State *state,
type_identity *type, void *target, int val_index,
bool exact, bool perr, bool signal)
{
if (signal)
check_valid_ptr_index(state, val_index);
if (lua_istable(state, val_index))
{
val_index = lua_absindex(state, val_index);
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_ASSIGN_NAME);
Lua::PushDFObject(state, type, target);
lua_pushvalue(state, val_index);
if (signal)
{
lua_call(state, 2, 0);
return true;
}
else
return Lua::SafeCall(*out, state, 2, 0, perr);
}
else if (!lua_isuserdata(state, val_index))
{
signal_typeid_error(out, state, type, "pointer to %s expected",
val_index, perr, signal);
return false;
}
else
{
void *in_ptr = Lua::GetDFObject(state, type, val_index, exact);
if (!in_ptr)
{
signal_typeid_error(out, state, type, "incompatible pointer type: %s expected",
val_index, perr, signal);
return false;
}
if (!type->copy(target, in_ptr))
{
signal_typeid_error(out, state, type, "no copy support for %s",
val_index, perr, signal);
return false;
}
return true;
}
}
bool DFHack::Lua::AssignDFObject(color_ostream &out, lua_State *state, bool DFHack::Lua::AssignDFObject(color_ostream &out, lua_State *state,
type_identity *type, void *target, int val_index, bool perr) type_identity *type, void *target, int val_index,
bool exact_type, bool perr)
{ {
val_index = lua_absindex(state, val_index); return doAssignDFObject(&out, state, type, target, val_index, exact_type, perr, false);
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_ASSIGN_NAME); }
PushDFObject(state, type, target);
lua_pushvalue(state, val_index); void DFHack::Lua::CheckDFObject(lua_State *state, type_identity *type,
return Lua::SafeCall(out, state, 2, 0, perr); void *target, int val_index, bool exact_type)
{
doAssignDFObject(NULL, state, type, target, val_index, exact_type, false, true);
} }
bool DFHack::Lua::SafeCallString(color_ostream &out, lua_State *state, const std::string &code, bool DFHack::Lua::SafeCallString(color_ostream &out, lua_State *state, const std::string &code,
@ -773,10 +841,7 @@ bool DFHack::Lua::SafeCallString(color_ostream &out, lua_State *state, const std
if (luaL_loadbuffer(state, code.data(), code.size(), debug_tag) != LUA_OK) if (luaL_loadbuffer(state, code.data(), code.size(), debug_tag) != LUA_OK)
{ {
if (perr) if (perr)
{ report_error(state, &out, true);
report_error(state, &out);
lua_pop(state, 1);
}
return false; return false;
} }
@ -1113,10 +1178,7 @@ static void do_invoke_event(lua_State *L, int argbase, int num_args, int errorfu
lua_pushvalue(L, argbase+i); lua_pushvalue(L, argbase+i);
if (lua_pcall(L, num_args, 0, errorfun) != LUA_OK) if (lua_pcall(L, num_args, 0, errorfun) != LUA_OK)
{ report_error(L, NULL, true);
report_error(L);
lua_pop(L, 1);
}
} }
static void dfhack_event_invoke(lua_State *L, int base, bool from_c) static void dfhack_event_invoke(lua_State *L, int base, bool from_c)

@ -109,7 +109,15 @@ namespace DFHack {namespace Lua {
* Return behavior is of SafeCall below. * Return behavior is of SafeCall below.
*/ */
DFHACK_EXPORT bool AssignDFObject(color_ostream &out, lua_State *state, DFHACK_EXPORT bool AssignDFObject(color_ostream &out, lua_State *state,
type_identity *type, void *target, int val_index, bool perr = true); type_identity *type, void *target, int val_index,
bool exact_type = false, bool perr = true);
/**
* Assign the value at val_index to the target of given identity using df.assign().
* Otherwise throws an error.
*/
DFHACK_EXPORT void CheckDFObject(lua_State *state, type_identity *type,
void *target, int val_index, bool exact_type = false);
/** /**
* Push the pointer onto the stack as a wrapped DF object of a specific type. * Push the pointer onto the stack as a wrapped DF object of a specific type.
@ -139,8 +147,19 @@ namespace DFHack {namespace Lua {
* Assign the value at val_index to the target using df.assign(). * Assign the value at val_index to the target using df.assign().
*/ */
template<class T> template<class T>
bool AssignDFObject(color_ostream &out, lua_State *state, T *target, int val_index, bool perr = true) { bool AssignDFObject(color_ostream &out, lua_State *state, T *target,
return AssignDFObject(out, state, df::identity_traits<T>::get(), target, val_index, perr); int val_index, bool exact_type = false, bool perr = true) {
return AssignDFObject(out, state, df::identity_traits<T>::get(),
target, val_index, exact_type, perr);
}
/**
* Assign the value at val_index to the target using df.assign().
* Throws in case of an error.
*/
template<class T>
void CheckDFObject(lua_State *state, T *target, int val_index, bool exact_type = false) {
CheckDFObject(state, df::identity_traits<T>::get(), target, val_index, exact_type);
} }
/** /**