From 9eaf93d41d6745b877f8f52cf54b21050abefda1 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Wed, 25 Jul 2012 02:36:54 +0300 Subject: Detached inventory callbacks and reworked node metadata callbacks --- src/inventorymanager.cpp | 365 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 255 insertions(+), 110 deletions(-) (limited to 'src/inventorymanager.cpp') diff --git a/src/inventorymanager.cpp b/src/inventorymanager.cpp index 1369cb0d7..5412a5dca 100644 --- a/src/inventorymanager.cpp +++ b/src/inventorymanager.cpp @@ -41,25 +41,25 @@ std::string InventoryLocation::dump() const void InventoryLocation::serialize(std::ostream &os) const { - switch(type){ - case InventoryLocation::UNDEFINED: - os<<"undefined"; - break; - case InventoryLocation::CURRENT_PLAYER: - os<<"current_player"; - break; - case InventoryLocation::PLAYER: - os<<"player:"<getItem(from_i).count; + + int src_can_take_count = 0xffff; + int dst_can_put_count = 0xffff; - // Handle node metadata move - if(from_inv.type == InventoryLocation::NODEMETA && - to_inv.type == InventoryLocation::NODEMETA && - from_inv.p != to_inv.p) + /* Query detached inventories */ + + // Move occurs in the same detached inventory + if(from_inv.type == InventoryLocation::DETACHED && + to_inv.type == InventoryLocation::DETACHED && + from_inv.name == to_inv.name) { - errorstream<<"Directly moving items between two nodes is " - <<"disallowed."<getEnv()->getLua(); + src_can_take_count = scriptapi_detached_inventory_allow_move( + L, from_inv.name, from_list, from_i, + to_list, to_i, try_take_count, player); + dst_can_put_count = src_can_take_count; + } + else + { + // Destination is detached + if(to_inv.type == InventoryLocation::DETACHED) + { + lua_State *L = player->getEnv()->getLua(); + ItemStack src_item = list_from->getItem(from_i); + src_item.count = try_take_count; + dst_can_put_count = scriptapi_detached_inventory_allow_put( + L, to_inv.name, to_list, to_i, src_item, player); + } + // Source is detached + if(from_inv.type == InventoryLocation::DETACHED) + { + lua_State *L = player->getEnv()->getLua(); + src_can_take_count = scriptapi_detached_inventory_allow_take( + L, from_inv.name, from_list, from_i, try_take_count, player); + } } - else if(from_inv.type == InventoryLocation::NODEMETA && + + /* Query node metadata inventories */ + + // Both endpoints are nodemeta + // Move occurs in the same nodemeta inventory + if(from_inv.type == InventoryLocation::NODEMETA && to_inv.type == InventoryLocation::NODEMETA && from_inv.p == to_inv.p) { lua_State *L = player->getEnv()->getLua(); - int count0 = count; - if(count0 == 0) - count0 = list_from->getItem(from_i).count; - infostream<getDescription()<<" moving "<getEnv()->getLua(); - int count0 = count; - if(count0 == 0) - count0 = list_from->getItem(from_i).count; - infostream<getDescription()<<" taking "<addItem(to_i, return_stack); - list_to->addItem(return_stack); // Force return of everything - } - // Handle node metadata offer - else if(to_inv.type == InventoryLocation::NODEMETA) - { - lua_State *L = player->getEnv()->getLua(); - int count0 = count; - if(count0 == 0) - count0 = list_from->getItem(from_i).count; - ItemStack offer_stack = list_from->takeItem(from_i, count0); - infostream<getDescription()<<" offering " - <addItem(from_i, reject_stack); - list_from->addItem(reject_stack); // Force return of everything - } - // Handle regular move + src_can_take_count = scriptapi_nodemeta_inventory_allow_move( + L, from_inv.p, from_list, from_i, + to_list, to_i, try_take_count, player); + dst_can_put_count = src_can_take_count; + } else { - /* - This performs the actual movement - - If something is wrong (source item is empty, destination is the - same as source), nothing happens - */ - list_from->moveItem(from_i, list_to, to_i, count); - - infostream<<"IMoveAction::apply(): moved " + // Destination is nodemeta + if(to_inv.type == InventoryLocation::NODEMETA) + { + lua_State *L = player->getEnv()->getLua(); + ItemStack src_item = list_from->getItem(from_i); + src_item.count = try_take_count; + dst_can_put_count = scriptapi_nodemeta_inventory_allow_put( + L, to_inv.p, to_list, to_i, src_item, player); + } + // Source is nodemeta + if(from_inv.type == InventoryLocation::NODEMETA) + { + lua_State *L = player->getEnv()->getLua(); + src_can_take_count = scriptapi_nodemeta_inventory_allow_take( + L, from_inv.p, from_list, from_i, try_take_count, player); + } + } + + /* Modify count according to collected data */ + int new_count = try_take_count; + if(new_count > src_can_take_count) + new_count = src_can_take_count; + if(new_count > dst_can_put_count) + new_count = dst_can_put_count; + + /* If no items will be moved, don't go further */ + if(new_count == 0) + { + infostream<<"IMoveAction::apply(): move was completely disallowed: " <<" count="<changeItem(from_i, ItemStack()); - else - item1 = list_from->takeItem(from_i, count); + lua_State *L = player->getEnv()->getLua(); + src_can_take_count = scriptapi_nodemeta_inventory_allow_take( + L, from_inv.p, from_list, from_i, take_count, player); } - // Drop the item and apply the returned ItemStack - ItemStack item2 = item1; - if(scriptapi_item_on_drop(player->getEnv()->getLua(), item2, player, + if(src_can_take_count < take_count) + take_count = src_can_take_count; + + int actually_dropped_count = 0; + + // Drop the item + ItemStack item1 = list_from->getItem(from_i); + if(scriptapi_item_on_drop(player->getEnv()->getLua(), item1, player, player->getBasePosition() + v3f(0,1,0))) { - if(g_settings->getBool("creative_mode") == true - && from_inv.type == InventoryLocation::PLAYER) - item2 = item1; // creative mode + actually_dropped_count = take_count - item1.count; + + if(actually_dropped_count == 0){ + infostream<<"Actually dropped no items"<addItem(from_i, item2); + // Don't remove from inventory in creative mode + if(g_settings->getBool("creative_mode") == true + && from_inv.type == InventoryLocation::PLAYER){ + } + else{ + // Take item from source list + ItemStack item2 = list_from->takeItem(from_i, actually_dropped_count); - // Unless we have put the same amount back as we took in the first place, - // set inventory modified flag - if(item2.count != item1.count) + if(item2.count != actually_dropped_count) + errorstream<<"Could not take dropped count of items"<setInventoryModified(from_inv); + } } infostream<<"IDropAction::apply(): dropped " @@ -409,6 +534,26 @@ void IDropAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame <<" list=\""<