aboutsummaryrefslogtreecommitdiff
path: root/games/devtest/mods/testnodes/textures/testnodes_palette_full.png
blob: e0a5f8b349809a6a6d3febdca04f93a5b09ddebd (plain)
ofshex dumpascii
0000 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 00 10 00 00 00 10 08 02 00 00 00 90 91 68 .PNG........IHDR...............h
0020 36 00 00 01 ff 49 44 41 54 78 01 3d 92 27 94 15 31 14 86 73 93 e9 7d 77 9f c7 d0 24 cd a2 30 f4 6....IDATx.=.'..1..s..}w...$..0.
0040 a2 51 74 90 38 9a c6 81 03 87 42 52 24 5d 51 2c 38 aa 42 6f 9b de 27 e1 cf bc 73 78 e7 9e ff 7d .Qt.8.....BR$]Q,8.Bo..'...sx...}
0060 f9 ee f4 5c 1a 8c 3f 69 22 b6 57 78 9a f0 8d 35 91 ce 90 ae 88 ed 18 c9 37 16 02 5d 2d 63 be bd ...\..?i".Wx...5........7..]-c..
0080 02 e6 94 6c 6f 45 b9 8a 33 19 e6 53 5c a8 28 93 51 2e 57 b6 27 64 9c 4f 51 a6 e2 1c 46 ad 6e 0e ...loE..3..S\.(.Q.W.'d.OQ...F.n.
00a0 61 ce 20 e9 cf ae 2f a5 47 55 40 b8 52 e5 f3 22 a4 32 e4 a5 cf cb 80 65 b1 81 d4 cb 80 17 be a8 a...../.GU@.R..".2.....e........
00c0 90 21 d1 fe af df 9c 4e 06 85 f2 6a 39 17 f3 1a f0 14 e6 d2 6d a4 5f 2b b7 66 7e 2d dd 5a 86 85 .!.....N...j9.......m._+.f~-.Z..
00e0 ee d2 87 23 cf 5b 9b d7 3e b5 0e 75 36 b5 2e 61 89 ac 3c de d9 0c b2 71 78 e7 68 53 7b ac 33 89 ...#.[..>..u6..a..<....qx.hS{.3.
0100 ce bd 7c 69 8c ca ee 98 dd 49 b3 57 76 cf cc 01 a9 cc 9e 39 ad b4 00 03 b3 7a 00 b3 3a e5 f4 8a ..|i.....I.Wv......9.....z..:...
0120 9e 5c 7c 34 98 34 1a 34 19 6c 14 34 9a 3a 07 a4 41 ba 66 89 d6 7c 0c 9b 04 a3 9b 0f 1f 70 49 a4 .\|4.4.4.l.4.:..A.f..|.......pI.
0140 94 90 8a 4f c4 95 22 c9 f8 b2 14 e3 93 82 81 27 a4 5e 32 ba 7d ff 1e 16 a4 d8 5c 00 02 e0 f7 5f ...O.."........'.^2.}.....\...._
0160 6a c6 b5 f0 87 16 e4 e3 1b 37 24 d7 f7 95 82 4d ba 38 72 59 52 10 12 2d cd 00 ce a5 a1 e8 fc d3 j........7$....M.8rYR..-........
0180 cb 78 4b 73 d4 2f 07 98 df 72 c9 33 cc c6 18 99 09 3f 32 7c 1e 7a 7d ec 58 6f b2 ce c6 47 a4 65 .xKs./...r.3.....?2|.z}.Xo...G.e
01a0 e1 53 b6 00 87 75 16 f5 b3 6f 5c f8 e5 31 8c 0e 7f 3a e9 62 77 5a e5 56 d2 af 66 68 26 b7 26 b7 .S...u...o\..1...:.bwZ.V..fh&.&.
01c0 95 f0 7e 25 01 d8 2f b7 d1 de ea 18 fd d8 bb 17 97 ac f4 2c 88 da 57 25 46 c0 a7 3c e2 48 c8 4a ..~%../............,..W%F..<.H.J
01e0 2f 19 20 0f 39 46 03 40 3b fe 1e c2 5c 84 85 9a 07 4e 05 25 12 93 22 61 56 d3 49 03 86 af 54 41 /...9F.@;...\....N.%.."aV.I...TA
0200 3e 85 25 1e 81 61 e7 1d 3c e5 c6 c2 c8 22 9e c5 94 25 48 0c b3 d8 5c f0 3c 16 29 64 32 4b 18 0c >.%..a..<...."...%H...\.<.)d2K..
0220 7f 28 fe 01 e3 d4 5b 4f 64 ca fa 3f 00 00 00 00 49 45 4e 44 ae 42 60 82 .(....[Od..?....IEND.B`.
ref='#n147'>147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543
/*
Minetest
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 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; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include "lua_api/l_inventory.h"
#include "lua_api/l_internal.h"
#include "lua_api/l_item.h"
#include "common/c_converter.h"
#include "common/c_content.h"
#include "server.h"
#include "remoteplayer.h"

/*
	InvRef
*/
InvRef* InvRef::checkobject(lua_State *L, int narg)
{
	luaL_checktype(L, narg, LUA_TUSERDATA);
	void *ud = luaL_checkudata(L, narg, className);
	if(!ud) luaL_typerror(L, narg, className);
	return *(InvRef**)ud;  // unbox pointer
}

Inventory* InvRef::getinv(lua_State *L, InvRef *ref)
{
	return getServer(L)->getInventory(ref->m_loc);
}

InventoryList* InvRef::getlist(lua_State *L, InvRef *ref,
		const char *listname)
{
	NO_MAP_LOCK_REQUIRED;
	Inventory *inv = getinv(L, ref);
	if(!inv)
		return NULL;
	return inv->getList(listname);
}

void InvRef::reportInventoryChange(lua_State *L, InvRef *ref)
{
	// Inform other things that the inventory has changed
	getServer(L)->setInventoryModified(ref->m_loc);
}

// Exported functions

// garbage collector
int InvRef::gc_object(lua_State *L) {
	InvRef *o = *(InvRef **)(lua_touserdata(L, 1));
	delete o;
	return 0;
}

// is_empty(self, listname) -> true/false
int InvRef::l_is_empty(lua_State *L)
{
	NO_MAP_LOCK_REQUIRED;
	InvRef *ref = checkobject(L, 1);
	const char *listname = luaL_checkstring(L, 2);
	InventoryList *list = getlist(L, ref, listname);
	if(list && list->getUsedSlots() > 0){
		lua_pushboolean(L, false);
	} else {
		lua_pushboolean(L, true);
	}
	return 1;
}

// get_size(self, listname)
int InvRef::l_get_size(lua_State *L)
{
	NO_MAP_LOCK_REQUIRED;
	InvRef *ref = checkobject(L, 1);
	const char *listname = luaL_checkstring(L, 2);
	InventoryList *list = getlist(L, ref, listname);
	if(list){
		lua_pushinteger(L, list->getSize());
	} else {
		lua_pushinteger(L, 0);
	}
	return 1;
}

// get_width(self, listname)
int InvRef::l_get_width(lua_State *L)
{
	NO_MAP_LOCK_REQUIRED;
	InvRef *ref = checkobject(L, 1);
	const char *listname = luaL_checkstring(L, 2);
	InventoryList *list = getlist(L, ref, listname);
	if(list){
		lua_pushinteger(L, list->getWidth());
	} else {
		lua_pushinteger(L, 0);
	}
	return 1;
}

// set_size(self, listname, size)
int InvRef::l_set_size(lua_State *L)
{
	NO_MAP_LOCK_REQUIRED;
	InvRef *ref = checkobject(L, 1);
	const char *listname = luaL_checkstring(L, 2);

	int newsize = luaL_checknumber(L, 3);
	if (newsize < 0) {
		lua_pushboolean(L, false);
		return 1;
	}

	Inventory *inv = getinv(L, ref);
	if(inv == NULL){
		lua_pushboolean(L, false);
		return 1;
	}
	if(newsize == 0){
		inv->deleteList(listname);
		reportInventoryChange(L, ref);
		lua_pushboolean(L, true);
		return 1;
	}
	InventoryList *list = inv->getList(listname);
	if(list){
		list->setSize(newsize);
	} else {
		list = inv->addList(listname, newsize);
		if (!list)
		{
			lua_pushboolean(L, false);
			return 1;
		}
	}
	reportInventoryChange(L, ref);
	lua_pushboolean(L, true);
	return 1;
}

// set_width(self, listname, size)
int InvRef::l_set_width(lua_State *L)
{
	NO_MAP_LOCK_REQUIRED;
	InvRef *ref = checkobject(L, 1);
	const char *listname = luaL_checkstring(L, 2);
	int newwidth = luaL_checknumber(L, 3);
	Inventory *inv = getinv(L, ref);
	if(inv == NULL){
		return 0;
	}
	InventoryList *list = inv->getList(listname);
	if(list){
		list->setWidth(newwidth);
	} else {
		return 0;
	}
	reportInventoryChange(L, ref);
	return 0;
}

// get_stack(self, listname, i) -> itemstack
int InvRef::l_get_stack(lua_State *L)
{
	NO_MAP_LOCK_REQUIRED;
	InvRef *ref = checkobject(L, 1);
	const char *listname = luaL_checkstring(L, 2);
	int i = luaL_checknumber(L, 3) - 1;
	InventoryList *list = getlist(L, ref, listname);
	ItemStack item;
	if(list != NULL && i >= 0 && i < (int) list->getSize())
		item = list->getItem(i);
	LuaItemStack::create(L, item);
	return 1;
}

// set_stack(self, listname, i, stack) -> true/false
int InvRef::l_set_stack(lua_State *L)
{
	NO_MAP_LOCK_REQUIRED;
	InvRef *ref = checkobject(L, 1);
	const char *listname = luaL_checkstring(L, 2);
	int i = luaL_checknumber(L, 3) - 1;
	ItemStack newitem = read_item(L, 4, getServer(L)->idef());
	InventoryList *list = getlist(L, ref, listname);
	if(list != NULL && i >= 0 && i < (int) list->getSize()){
		list->changeItem(i, newitem);
		reportInventoryChange(L, ref);
		lua_pushboolean(L, true);
	} else {
		lua_pushboolean(L, false);
	}
	return 1;
}

// get_list(self, listname) -> list or nil
int InvRef::l_get_list(lua_State *L)
{
	NO_MAP_LOCK_REQUIRED;
	InvRef *ref = checkobject(L, 1);
	const char *listname = luaL_checkstring(L, 2);
	Inventory *inv = getinv(L, ref);
	if(inv){
		push_inventory_list(L, inv, listname);
	} else {
		lua_pushnil(L);
	}
	return 1;
}

// set_list(self, listname, list)
int InvRef::l_set_list(lua_State *L)
{
	NO_MAP_LOCK_REQUIRED;
	InvRef *ref = checkobject(L, 1);
	const char *listname = luaL_checkstring(L, 2);
	Inventory *inv = getinv(L, ref);
	if(inv == NULL){
		return 0;
	}
	InventoryList *list = inv->getList(listname);
	if(list)
		read_inventory_list(L, 3, inv, listname,
				getServer(L), list->getSize());
	else
		read_inventory_list(L, 3, inv, listname, getServer(L));
	reportInventoryChange(L, ref);
	return 0;
}

// get_lists(self) -> list of InventoryLists
int InvRef::l_get_lists(lua_State *L)
{
	NO_MAP_LOCK_REQUIRED;
	InvRef *ref = checkobject(L, 1);
	Inventory *inv = getinv(L, ref);
	if (!inv) {
		return 0;
	}
	std::vector<const InventoryList*> lists = inv->getLists();
	std::vector<const InventoryList*>::iterator iter = lists.begin();
	lua_createtable(L, 0, lists.size());
	for (; iter != lists.end(); iter++) {
		const char* name = (*iter)->getName().c_str();
		lua_pushstring(L, name);
		push_inventory_list(L, inv, name);
		lua_rawset(L, -3);
	}
	return 1;
}

// set_lists(self, lists)
int InvRef::l_set_lists(lua_State *L)
{
	NO_MAP_LOCK_REQUIRED;
	InvRef *ref = checkobject(L, 1);
	Inventory *inv = getinv(L, ref);
	if (!inv) {
		return 0;
	}

	// Make a temporary inventory in case reading fails
	Inventory *tempInv(inv);
	tempInv->clear();

	Server *server = getServer(L);

	lua_pushnil(L);
	while (lua_next(L, 2)) {
		const char *listname = lua_tostring(L, -2);
		read_inventory_list(L, -1, tempInv, listname, server);
		lua_pop(L, 1);
	}
	inv = tempInv;
	return 0;
}

// add_item(self, listname, itemstack or itemstring or table or nil) -> itemstack
// Returns the leftover stack
int InvRef::l_add_item(lua_State *L)
{
	NO_MAP_LOCK_REQUIRED;
	InvRef *ref = checkobject(L, 1);
	const char *listname = luaL_checkstring(L, 2);
	ItemStack item = read_item(L, 3, getServer(L)->idef());
	InventoryList *list = getlist(L, ref, listname);
	if(list){
		ItemStack leftover = list->addItem(item);
		if(leftover.count != item.count)
			reportInventoryChange(L, ref);
		LuaItemStack::create(L, leftover);
	} else {
		LuaItemStack::create(L, item);
	}
	return 1;
}

// room_for_item(self, listname, itemstack or itemstring or table or nil) -> true/false
// Returns true if the item completely fits into the list
int InvRef::l_room_for_item(lua_State *L)
{
	NO_MAP_LOCK_REQUIRED;
	InvRef *ref = checkobject(L, 1);
	const char *listname = luaL_checkstring(L, 2);
	ItemStack item = read_item(L, 3, getServer(L)->idef());
	InventoryList *list = getlist(L, ref, listname);
	if(list){
		lua_pushboolean(L, list->roomForItem(item));
	} else {
		lua_pushboolean(L, false);
	}
	return 1;
}

// contains_item(self, listname, itemstack or itemstring or table or nil, [match_meta]) -> true/false
// Returns true if the list contains the given count of the given item
int InvRef::l_contains_item(lua_State *L)
{
	NO_MAP_LOCK_REQUIRED;
	InvRef *ref = checkobject(L, 1);
	const char *listname = luaL_checkstring(L, 2);
	ItemStack item = read_item(L, 3, getServer(L)->idef());
	InventoryList *list = getlist(L, ref, listname);
	bool match_meta = false;
	if (lua_isboolean(L, 4))
		match_meta = lua_toboolean(L, 4);
	if (list) {
		lua_pushboolean(L, list->containsItem(item, match_meta));
	} else {
		lua_pushboolean(L, false);
	}
	return 1;
}

// remove_item(self, listname, itemstack or itemstring or table or nil) -> itemstack
// Returns the items that were actually removed
int InvRef::l_remove_item(lua_State *L)
{
	NO_MAP_LOCK_REQUIRED;
	InvRef *ref = checkobject(L, 1);
	const char *listname = luaL_checkstring(L, 2);
	ItemStack item = read_item(L, 3, getServer(L)->idef());
	InventoryList *list = getlist(L, ref, listname);
	if(list){
		ItemStack removed = list->removeItem(item);
		if(!removed.empty())
			reportInventoryChange(L, ref);
		LuaItemStack::create(L, removed);
	} else {
		LuaItemStack::create(L, ItemStack());
	}
	return 1;
}

// get_location() -> location (like get_inventory(location))
int InvRef::l_get_location(lua_State *L)
{
	NO_MAP_LOCK_REQUIRED;
	InvRef *ref = checkobject(L, 1);
	const InventoryLocation &loc = ref->m_loc;
	switch(loc.type){
	case InventoryLocation::PLAYER:
		lua_newtable(L);
		lua_pushstring(L, "player");
		lua_setfield(L, -2, "type");
		lua_pushstring(L, loc.name.c_str());
		lua_setfield(L, -2, "name");
		return 1;
	case InventoryLocation::NODEMETA:
		lua_newtable(L);
		lua_pushstring(L, "node");
		lua_setfield(L, -2, "type");
		push_v3s16(L, loc.p);
		lua_setfield(L, -2, "pos");
		return 1;
	case InventoryLocation::DETACHED:
		lua_newtable(L);
		lua_pushstring(L, "detached");
		lua_setfield(L, -2, "type");
		lua_pushstring(L, loc.name.c_str());
		lua_setfield(L, -2, "name");
		return 1;
	case InventoryLocation::UNDEFINED:
	case InventoryLocation::CURRENT_PLAYER:
		break;
	}
	lua_newtable(L);
	lua_pushstring(L, "undefined");
	lua_setfield(L, -2, "type");
	return 1;
}


InvRef::InvRef(const InventoryLocation &loc):
	m_loc(loc)
{
}

// Creates an InvRef and leaves it on top of stack
// Not callable from Lua; all references are created on the C side.
void InvRef::create(lua_State *L, const InventoryLocation &loc)
{
	NO_MAP_LOCK_REQUIRED;
	InvRef *o = new InvRef(loc);
	*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
	luaL_getmetatable(L, className);
	lua_setmetatable(L, -2);
}
void InvRef::createPlayer(lua_State *L, RemotePlayer *player)
{
	NO_MAP_LOCK_REQUIRED;
	InventoryLocation loc;
	loc.setPlayer(player->getName());
	create(L, loc);
}
void InvRef::createNodeMeta(lua_State *L, v3s16 p)
{
	InventoryLocation loc;
	loc.setNodeMeta(p);
	create(L, loc);
}

void InvRef::Register(lua_State *L)
{
	lua_newtable(L);
	int methodtable = lua_gettop(L);
	luaL_newmetatable(L, className);
	int metatable = lua_gettop(L);

	lua_pushliteral(L, "__metatable");
	lua_pushvalue(L, methodtable);
	lua_settable(L, metatable);  // hide metatable from Lua getmetatable()

	lua_pushliteral(L, "__index");
	lua_pushvalue(L, methodtable);
	lua_settable(L, metatable);

	lua_pushliteral(L, "__gc");
	lua_pushcfunction(L, gc_object);
	lua_settable(L, metatable);

	lua_pop(L, 1);  // drop metatable

	luaL_openlib(L, 0, methods, 0);  // fill methodtable
	lua_pop(L, 1);  // drop methodtable

	// Cannot be created from Lua
	//lua_register(L, className, create_object);
}

const char InvRef::className[] = "InvRef";
const luaL_Reg InvRef::methods[] = {
	luamethod(InvRef, is_empty),
	luamethod(InvRef, get_size),
	luamethod(InvRef, set_size),
	luamethod(InvRef, get_width),
	luamethod(InvRef, set_width),
	luamethod(InvRef, get_stack),
	luamethod(InvRef, set_stack),
	luamethod(InvRef, get_list),
	luamethod(InvRef, set_list),
	luamethod(InvRef, get_lists),
	luamethod(InvRef, set_lists),
	luamethod(InvRef, add_item),
	luamethod(InvRef, room_for_item),
	luamethod(InvRef, contains_item),
	luamethod(InvRef, remove_item),
	luamethod(InvRef, get_location),
	{0,0}
};

// get_inventory(location)
int ModApiInventory::l_get_inventory(lua_State *L)
{
	InventoryLocation loc;

	std::string type = checkstringfield(L, 1, "type");

	if(type == "node"){
		MAP_LOCK_REQUIRED;