aboutsummaryrefslogtreecommitdiff
path: root/src/inventory.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/inventory.cpp')
-rw-r--r--src/inventory.cpp269
1 files changed, 185 insertions, 84 deletions
diff --git a/src/inventory.cpp b/src/inventory.cpp
index 4e897d9ff..d276e61c9 100644
--- a/src/inventory.cpp
+++ b/src/inventory.cpp
@@ -33,7 +33,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "log.h"
#include "nodedef.h"
#include "tooldef.h"
+#include "craftitemdef.h"
#include "gamedef.h"
+#include "scriptapi.h"
#include "strfnd.h"
/*
@@ -182,18 +184,52 @@ std::string InventoryItem::getItemString() {
return os.str();
}
-ServerActiveObject* InventoryItem::createSAO(ServerEnvironment *env, v3f pos)
+bool InventoryItem::dropOrPlace(ServerEnvironment *env,
+ ServerActiveObject *dropper,
+ v3f pos, bool place, s16 count)
{
/*
- Create an ItemSAO
+ Ensure that the block is loaded so that the item
+ can properly be added to the static list too
+ */
+ v3s16 blockpos = getNodeBlockPos(floatToInt(pos, BS));
+ MapBlock *block = env->getMap().emergeBlock(blockpos, false);
+ if(block==NULL)
+ {
+ infostream<<"InventoryItem::dropOrPlace(): FAIL: block not found: "
+ <<blockpos.X<<","<<blockpos.Y<<","<<blockpos.Z
+ <<std::endl;
+ return false;
+ }
+
+ /*
+ Take specified number of items,
+ but limit to getDropCount().
*/
- pos.Y -= BS*0.25; // let it drop a bit
- // Randomize a bit
- pos.X += BS*0.2*(float)myrand_range(-1000,1000)/1000.0;
- pos.Z += BS*0.2*(float)myrand_range(-1000,1000)/1000.0;
- // Create object
- ServerActiveObject *obj = new ItemSAO(env, pos, getItemString());
- return obj;
+ s16 dropcount = getDropCount();
+ if(count < 0 || count > dropcount)
+ count = dropcount;
+ if(count < 0 || count > getCount());
+ count = getCount();
+ if(count > 0)
+ {
+ /*
+ Create an ItemSAO
+ */
+ pos.Y -= BS*0.25; // let it drop a bit
+ // Randomize a bit
+ //pos.X += BS*0.2*(float)myrand_range(-1000,1000)/1000.0;
+ //pos.Z += BS*0.2*(float)myrand_range(-1000,1000)/1000.0;
+ // Create object
+ ServerActiveObject *obj = new ItemSAO(env, pos, getItemString());
+ // Add the object to the environment
+ env->addActiveObject(obj);
+ infostream<<"Dropped item"<<std::endl;
+
+ setCount(getCount() - count);
+ }
+
+ return getCount() < 1; // delete the item?
}
/*
@@ -307,75 +343,150 @@ video::ITexture * ToolItem::getImageRaw() const
#ifndef SERVER
video::ITexture * CraftItem::getImage() const
{
+ ICraftItemDefManager *cidef = m_gamedef->cidef();
ITextureSource *tsrc = m_gamedef->tsrc();
-
- std::string name = item_craft_get_image_name(m_subname, m_gamedef);
-
- // Get such a texture
- return tsrc->getTextureRaw(name);
+ std::string imagename = cidef->getImagename(m_subname);
+ return tsrc->getTextureRaw(imagename);
}
#endif
-ServerActiveObject* CraftItem::createSAO(ServerEnvironment *env, v3f pos)
+u16 CraftItem::getStackMax() const
{
- // Special cases
- ServerActiveObject *obj = item_craft_create_object(m_subname, env, pos);
- if(obj)
- return obj;
- // Default
- return InventoryItem::createSAO(env, pos);
+ ICraftItemDefManager *cidef = m_gamedef->cidef();
+ const CraftItemDefinition *def = cidef->getCraftItemDefinition(m_subname);
+ if(def == NULL)
+ return InventoryItem::getStackMax();
+ return def->stack_max;
}
-u16 CraftItem::getDropCount() const
+bool CraftItem::isUsable() const
{
- // Special cases
- s16 dc = item_craft_get_drop_count(m_subname, m_gamedef);
- if(dc != -1)
- return dc;
- // Default
- return InventoryItem::getDropCount();
+ ICraftItemDefManager *cidef = m_gamedef->cidef();
+ const CraftItemDefinition *def = cidef->getCraftItemDefinition(m_subname);
+ return def != NULL && def->usable;
}
bool CraftItem::isCookable() const
{
- return item_craft_is_cookable(m_subname, m_gamedef);
+ ICraftItemDefManager *cidef = m_gamedef->cidef();
+ const CraftItemDefinition *def = cidef->getCraftItemDefinition(m_subname);
+ return def != NULL && def->cookresult_item != "";
}
InventoryItem *CraftItem::createCookResult() const
{
- return item_craft_create_cook_result(m_subname, m_gamedef);
+ ICraftItemDefManager *cidef = m_gamedef->cidef();
+ const CraftItemDefinition *def = cidef->getCraftItemDefinition(m_subname);
+ if(def == NULL)
+ return InventoryItem::createCookResult();
+ std::istringstream is(def->cookresult_item, std::ios::binary);
+ return InventoryItem::deSerialize(is, m_gamedef);
}
float CraftItem::getCookTime() const
{
- return 3.0;
+ ICraftItemDefManager *cidef = m_gamedef->cidef();
+ const CraftItemDefinition *def = cidef->getCraftItemDefinition(m_subname);
+ if (def == NULL)
+ return InventoryItem::getCookTime();
+ return def->furnace_cooktime;
}
float CraftItem::getBurnTime() const
{
- if(m_subname == "lump_of_coal")
- return 40;
- return -1;
+ ICraftItemDefManager *cidef = m_gamedef->cidef();
+ const CraftItemDefinition *def = cidef->getCraftItemDefinition(m_subname);
+ if (def == NULL)
+ return InventoryItem::getBurnTime();
+ return def->furnace_burntime;
+}
+
+s16 CraftItem::getDropCount() const
+{
+ // Special cases
+ ICraftItemDefManager *cidef = m_gamedef->cidef();
+ const CraftItemDefinition *def = cidef->getCraftItemDefinition(m_subname);
+ if(def != NULL && def->dropcount >= 0)
+ return def->dropcount;
+ // Default
+ return InventoryItem::getDropCount();
+}
+
+bool CraftItem::areLiquidsPointable() const
+{
+ ICraftItemDefManager *cidef = m_gamedef->cidef();
+ const CraftItemDefinition *def = cidef->getCraftItemDefinition(m_subname);
+ return def != NULL && def->liquids_pointable;
}
-bool CraftItem::use(ServerEnvironment *env, ServerActiveObject *user)
+bool CraftItem::dropOrPlace(ServerEnvironment *env,
+ ServerActiveObject *dropper,
+ v3f pos, bool place, s16 count)
{
- if(!item_craft_is_eatable(m_subname, m_gamedef))
+ if(count == 0)
return false;
-
- u16 result_count = getCount() - 1; // Eat one at a time
- s16 hp_change = item_craft_eat_hp_change(m_subname, m_gamedef);
- s16 hp = user->getHP();
- hp += hp_change;
- if(hp < 0)
- hp = 0;
- user->setHP(hp);
-
- if(result_count < 1)
- return true;
-
- setCount(result_count);
- return false;
+
+ bool callback_exists = false;
+ bool result = false;
+
+ if(place)
+ {
+ result = scriptapi_craftitem_on_place_on_ground(
+ env->getLua(),
+ m_subname.c_str(), dropper, pos,
+ callback_exists);
+ }
+
+ // note: on_drop is fallback for on_place_on_ground
+
+ if(!callback_exists)
+ {
+ result = scriptapi_craftitem_on_drop(
+ env->getLua(),
+ m_subname.c_str(), dropper, pos,
+ callback_exists);
+ }
+
+ if(callback_exists)
+ {
+ // If the callback returned true, drop one item
+ if(result)
+ setCount(getCount() - 1);
+ return getCount() < 1;
+ }
+ else
+ {
+ // If neither on_place_on_ground (if place==true)
+ // nor on_drop exists, call the base implementation
+ return InventoryItem::dropOrPlace(env, dropper, pos, place, count);
+ }
+}
+
+bool CraftItem::use(ServerEnvironment *env,
+ ServerActiveObject *user,
+ const PointedThing& pointed)
+{
+ bool callback_exists = false;
+ bool result = false;
+
+ result = scriptapi_craftitem_on_use(
+ env->getLua(),
+ m_subname.c_str(), user, pointed,
+ callback_exists);
+
+ if(callback_exists)
+ {
+ // If the callback returned true, drop one item
+ if(result)
+ setCount(getCount() - 1);
+ return getCount() < 1;
+ }
+ else
+ {
+ // If neither on_place_on_ground (if place==true)
+ // nor on_drop exists, call the base implementation
+ return InventoryItem::use(env, user, pointed);
+ }
}
/*
@@ -1067,6 +1178,19 @@ IDropAction::IDropAction(std::istream &is)
void IDropAction::apply(InventoryContext *c, InventoryManager *mgr,
ServerEnvironment *env)
{
+ if(c->current_player == NULL){
+ infostream<<"IDropAction::apply(): FAIL: current_player is NULL"<<std::endl;
+ return;
+ }
+
+ // Do NOT cast directly to ServerActiveObject*, it breaks
+ // because of multiple inheritance.
+ ServerActiveObject *dropper =
+ static_cast<ServerActiveObject*>(
+ static_cast<ServerRemotePlayer*>(
+ c->current_player
+ ));
+
Inventory *inv_from = mgr->getInventory(c, from_inv);
if(!inv_from){
@@ -1086,7 +1210,8 @@ void IDropAction::apply(InventoryContext *c, InventoryManager *mgr,
<<", from_list=\""<<from_list<<"\""<<std::endl;
return;
}
- if(list_from->getItem(from_i) == NULL)
+ InventoryItem *item = list_from->getItem(from_i);
+ if(item == NULL)
{
infostream<<"IDropAction::apply(): FAIL: source item not found: "
<<"context=["<<describeC(c)<<"], from_inv=\""<<from_inv<<"\""
@@ -1095,43 +1220,19 @@ void IDropAction::apply(InventoryContext *c, InventoryManager *mgr,
return;
}
- v3f pos = c->current_player->getPosition();
+ v3f pos = dropper->getBasePosition();
pos.Y += 0.5*BS;
- v3s16 blockpos = getNodeBlockPos(floatToInt(pos, BS));
+
+ s16 count2 = count;
+ if(count2 == 0)
+ count2 = -1;
/*
- Ensure that the block is loaded so that the item
- can properly be added to the static list too
+ Drop the item
*/
- MapBlock *block = env->getMap().emergeBlock(blockpos, false);
- if(block==NULL)
- {
- infostream<<"IDropAction::apply(): FAIL: block not found: "
- <<blockpos.X<<","<<blockpos.Y<<","<<blockpos.Z
- <<std::endl;
- return;
- }
-
- // Take item from source list
- if(count == 0)
- count = list_from->getItem(from_i)->getDropCount();
- InventoryItem *item1 = list_from->takeItem(from_i, count);
-
- // Create an active object
- ServerActiveObject *obj = item1->createSAO(env, pos);
- if(obj == NULL)
- {
- infostream<<"IDropAction::apply(): item resulted in NULL object, "
- <<"not placing onto map"
- <<std::endl;
- }
- else
- {
- // Add the object to the environment
- env->addActiveObject(obj);
-
- infostream<<"Dropped object"<<std::endl;
- }
+ bool remove = item->dropOrPlace(env, dropper, pos, false, count2);
+ if(remove)
+ list_from->deleteItem(from_i);
mgr->inventoryModified(c, from_inv);