-- Called when object is punched
function TNT:on_punch(hitter)
print("TNT:on_punch()")
+ self.object:remove()
+ hitter:add_to_inventory("CraftItem testobject1 1")
end
-- Called when object is right-clicked
}
}
-void ItemSAO::rightClick(Player *player)
+void ItemSAO::punch(ServerActiveObject *puncher)
+{
+ InventoryItem *item = createInventoryItem();
+ bool fits = puncher->addToInventory(item);
+ if(fits)
+ m_removed = true;
+ else
+ delete item;
+}
+
+void ItemSAO::rightClick(ServerActiveObject *clicker)
{
infostream<<__FUNCTION_NAME<<std::endl;
InventoryItem *item = createInventoryItem();
if(item == NULL)
return;
- bool to_be_deleted = item->use(m_env, player);
+ bool to_be_deleted = item->use(m_env, clicker);
if(to_be_deleted)
m_removed = true;
// Reflect changes to the item here
m_inventorystring = item->getItemString();
- delete item;
+ delete item; // Delete temporary item
}
/*
return os.str();
}
-InventoryItem* RatSAO::createPickedUpItem()
+void RatSAO::punch(ServerActiveObject *puncher)
{
std::istringstream is("CraftItem rat 1", std::ios_base::binary);
InventoryItem *item = InventoryItem::deSerialize(is);
- return item;
+ bool fits = puncher->addToInventory(item);
+ if(fits)
+ m_removed = true;
+ else
+ delete item;
}
/*
return os.str();
}
-u16 Oerkki1SAO::punch(const std::string &toolname, v3f dir,
- const std::string &playername)
+void Oerkki1SAO::punch(ServerActiveObject *puncher)
{
+ v3f dir = (getBasePosition() - puncher->getBasePosition()).normalize();
+
+ std::string toolname = "";
+ InventoryItem *item = puncher->getWieldedItem();
+ if(item && (std::string)item->getName() == "ToolItem"){
+ ToolItem *titem = (ToolItem*)item;
+ toolname = titem->getToolName();
+ }
+
m_speed_f += dir*12*BS;
u16 amount = 5;
if(toolname == "SteelPick")
amount = 7;
doDamage(amount);
- return 65536/100;
+
+ puncher->damageWieldedItem(65536/100);
}
void Oerkki1SAO::doDamage(u16 d)
}
}
-u16 MobV2SAO::punch(const std::string &toolname, v3f dir,
- const std::string &playername)
+void MobV2SAO::punch(ServerActiveObject *puncher)
{
- assert(m_env);
+ v3f dir = (getBasePosition() - puncher->getBasePosition()).normalize();
+
+ std::string toolname = "";
+ InventoryItem *item = puncher->getWieldedItem();
+ if(item && (std::string)item->getName() == "ToolItem"){
+ ToolItem *titem = (ToolItem*)item;
+ toolname = titem->getToolName();
+ }
+
+ // A quick hack; SAO description is player name for player
+ std::string playername = puncher->getDescription();
+
Map *map = &m_env->getMap();
actionstream<<playername<<" punches mob id="<<m_id
if(toolname == "SteelPick")
amount = 3;
doDamage(amount);
- return 65536/100;
+
+ puncher->damageWieldedItem(65536/100);
}
bool MobV2SAO::isPeaceful()
return item;
}
-u16 LuaEntitySAO::punch(const std::string &toolname, v3f dir,
- const std::string &playername)
+void LuaEntitySAO::punch(ServerActiveObject *puncher)
{
- return 0;
+ if(!m_registered)
+ return;
+ lua_State *L = m_env->getLua();
+ scriptapi_luaentity_punch(L, m_id, puncher);
}
-void LuaEntitySAO::rightClick(Player *player)
+void LuaEntitySAO::rightClick(ServerActiveObject *clicker)
{
if(!m_registered)
return;
lua_State *L = m_env->getLua();
- scriptapi_luaentity_rightclick_player(L, m_id, player->getName());
+ scriptapi_luaentity_rightclick(L, m_id, clicker);
}
void LuaEntitySAO::setPos(v3f pos)
std::string getClientInitializationData();
std::string getStaticData();
InventoryItem* createInventoryItem();
- InventoryItem* createPickedUpItem(){return createInventoryItem();}
- void rightClick(Player *player);
-
+ void punch(ServerActiveObject *puncher);
+ void rightClick(ServerActiveObject *clicker);
float getMinimumSavedMovement(){ return 0.1*BS; }
private:
std::string m_inventorystring;
void step(float dtime, bool send_recommended);
std::string getClientInitializationData();
std::string getStaticData();
- InventoryItem* createPickedUpItem();
+ void punch(ServerActiveObject *puncher);
private:
bool m_is_active;
IntervalLimiter m_inactive_interval;
std::string getClientInitializationData();
std::string getStaticData();
InventoryItem* createPickedUpItem(){return NULL;}
- u16 punch(const std::string &toolname, v3f dir,
- const std::string &playername);
+ void punch(ServerActiveObject *puncher);
bool isPeaceful(){return false;}
private:
void doDamage(u16 d);
std::string getClientInitializationData();
void step(float dtime, bool send_recommended);
InventoryItem* createPickedUpItem(){return NULL;}
- u16 punch(const std::string &toolname, v3f dir,
- const std::string &playername);
+ void punch(ServerActiveObject *puncher);
bool isPeaceful();
private:
void sendPosition();
std::string getClientInitializationData();
std::string getStaticData();
InventoryItem* createPickedUpItem();
- u16 punch(const std::string &toolname, v3f dir,
- const std::string &playername);
- void rightClick(Player *player);
-
+ void punch(ServerActiveObject *puncher);
+ void rightClick(ServerActiveObject *clicker);
void setPos(v3f pos);
void moveTo(v3f pos, bool continuous);
float getMinimumSavedMovement();
return item_craft_create_cook_result(m_subname);
}
-bool CraftItem::use(ServerEnvironment *env, Player *player)
+bool CraftItem::use(ServerEnvironment *env, ServerActiveObject *user)
{
- if(item_craft_is_eatable(m_subname))
- {
- u16 result_count = getCount() - 1; // Eat one at a time
- s16 hp_change = item_craft_eat_hp_change(m_subname);
- if(player->hp + hp_change > 20)
- player->hp = 20;
- else
- player->hp += hp_change;
+ if(!item_craft_is_eatable(m_subname))
+ return false;
+
+ u16 result_count = getCount() - 1; // Eat one at a time
+ s16 hp_change = item_craft_eat_hp_change(m_subname);
+ s16 hp = user->getHP();
+ hp += hp_change;
+ if(hp < 0)
+ hp = 0;
+ user->setHP(hp);
+
+ if(result_count < 1)
+ return true;
- if(result_count < 1)
- return true;
- else
- setCount(result_count);
- }
+ setCount(result_count);
return false;
}
class ServerActiveObject;
class ServerEnvironment;
-class Player;
class InventoryItem
{
// Called when item is right-clicked when lying on ground.
// If returns true, item shall be deleted.
virtual bool use(ServerEnvironment *env,
- Player *player){return false;}
+ ServerActiveObject *user){return false;}
protected:
u16 m_count;
bool isCookable() const;
InventoryItem *createCookResult() const;
- bool use(ServerEnvironment *env, Player *player);
+ bool use(ServerEnvironment *env, ServerActiveObject *user);
/*
Special methods
inventory.deSerialize(is);
}
+/*
+ ServerRemotePlayer
+*/
+
+/* ServerActiveObject interface */
+
+InventoryItem* ServerRemotePlayer::getWieldedItem()
+{
+ InventoryList *list = inventory.getList("main");
+ if (list)
+ return list->getItem(m_selected_item);
+ return NULL;
+}
+void ServerRemotePlayer::damageWieldedItem(u16 amount)
+{
+ infostream<<"Damaging "<<getName()<<"'s wielded item for amount="
+ <<amount<<std::endl;
+ InventoryList *list = inventory.getList("main");
+ if(!list)
+ return;
+ InventoryItem *item = list->getItem(m_selected_item);
+ if(item && (std::string)item->getName() == "ToolItem"){
+ ToolItem *titem = (ToolItem*)item;
+ bool weared_out = titem->addWear(amount);
+ if(weared_out)
+ list->deleteItem(m_selected_item);
+ }
+}
+bool ServerRemotePlayer::addToInventory(InventoryItem *item)
+{
+ infostream<<"Adding "<<item->getName()<<" into "<<getName()
+ <<"'s inventory"<<std::endl;
+
+ InventoryList *ilist = inventory.getList("main");
+ if(ilist == NULL)
+ return false;
+
+ // In creative mode, just delete the item
+ if(g_settings->getBool("creative_mode")){
+ return false;
+ }
+
+ // Skip if inventory has no free space
+ if(ilist->roomForItem(item) == false)
+ {
+ infostream<<"Player inventory has no free space"<<std::endl;
+ return false;
+ }
+
+ // Add to inventory
+ InventoryItem *leftover = ilist->addItem(item);
+ assert(!leftover);
+
+ return true;
+}
+void ServerRemotePlayer::setHP(s16 hp_)
+{
+ hp = hp_;
+}
+s16 ServerRemotePlayer::getHP()
+{
+ return hp;
+}
+
/*
RemotePlayer
*/
Player::setPosition(position);
ServerActiveObject::setBasePosition(position);
}
+
+ /* ServerActiveObject interface */
- /*
- ServerActiveObject interface
- */
u8 getType() const
{return ACTIVEOBJECT_TYPE_PLAYER;}
+ virtual std::string getDescription(){return getName();}
+ // Returns a reference
+ virtual InventoryItem* getWieldedItem();
+ virtual void damageWieldedItem(u16 amount);
+ // If all fits, eats item and returns true. Otherwise returns false.
+ virtual bool addToInventory(InventoryItem *item);
+ virtual void setHP(s16 hp_);
+ virtual s16 getHP();
+
private:
};
// Exported functions
+ // garbage collector
+ static int gc_object(lua_State *L) {
+ ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1));
+ //infostream<<"ObjectRef::gc_object: o="<<o<<std::endl;
+ delete o;
+ return 0;
+ }
+
// remove(self)
static int l_remove(lua_State *L)
{
return 0;
}
- static int gc_object(lua_State *L) {
- //ObjectRef *o = checkobject(L, 1);
- ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1));
- //infostream<<"ObjectRef::gc_object: o="<<o<<std::endl;
- delete o;
- return 0;
+ // add_to_inventory(self, itemstring)
+ // returns: true if item was added, false otherwise
+ static int l_add_to_inventory(lua_State *L)
+ {
+ ObjectRef *ref = checkobject(L, 1);
+ luaL_checkstring(L, 2);
+ ServerActiveObject *co = getobject(ref);
+ if(co == NULL) return 0;
+ // itemstring
+ const char *itemstring = lua_tostring(L, 2);
+ infostream<<"ObjectRef::l_add_to_inventory(): id="<<co->getId()
+ <<" itemstring=\""<<itemstring<<"\""<<std::endl;
+ // Do it
+ std::istringstream is(itemstring, std::ios::binary);
+ InventoryItem *item = InventoryItem::deSerialize(is);
+ bool fits = co->addToInventory(item);
+ // Return
+ lua_pushboolean(L, fits);
+ return 1;
}
public:
method(ObjectRef, getpos),
method(ObjectRef, setpos),
method(ObjectRef, moveto),
+ method(ObjectRef, add_to_inventory),
{0,0}
};
+// Creates a new anonymous reference if id=0
+static void objectref_get_or_create(lua_State *L, ServerActiveObject *cobj)
+{
+ if(cobj->getId() == 0){
+ ObjectRef::create(L, cobj);
+ } else {
+ objectref_get(L, cobj->getId());
+ }
+}
+
/*
Main export function
*/
lua_setfield(L, -2, "env");
}
+#if 0
// Dump stack top with the dump2 function
static void dump2(lua_State *L, const char *name)
{
if(lua_pcall(L, 2, 0, 0))
script_error(L, "error: %s\n", lua_tostring(L, -1));
}
+#endif
/*
object_reference
script_error(L, "error running function 'step': %s\n", lua_tostring(L, -1));
}
-void scriptapi_luaentity_rightclick_player(lua_State *L, u16 id,
- const char *playername)
+// Calls entity:on_punch(ObjectRef puncher)
+void scriptapi_luaentity_punch(lua_State *L, u16 id,
+ ServerActiveObject *puncher)
{
realitycheck(L);
assert(lua_checkstack(L, 20));
luaentity_get(L, id);
int object = lua_gettop(L);
// State: object is at top of stack
- // Get step function
+ // Get function
+ lua_getfield(L, -1, "on_punch");
+ luaL_checktype(L, -1, LUA_TFUNCTION);
+ lua_pushvalue(L, object); // self
+ objectref_get_or_create(L, puncher); // Clicker reference
+ // Call with 2 arguments, 0 results
+ if(lua_pcall(L, 2, 0, 0))
+ script_error(L, "error running function 'on_punch': %s\n", lua_tostring(L, -1));
+}
+
+// Calls entity:on_rightclick(ObjectRef clicker)
+void scriptapi_luaentity_rightclick(lua_State *L, u16 id,
+ ServerActiveObject *clicker)
+{
+ realitycheck(L);
+ assert(lua_checkstack(L, 20));
+ //infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
+ StackUnroller stack_unroller(L);
+
+ // Get minetest.luaentities[id]
+ luaentity_get(L, id);
+ int object = lua_gettop(L);
+ // State: object is at top of stack
+ // Get function
lua_getfield(L, -1, "on_rightclick");
luaL_checktype(L, -1, LUA_TFUNCTION);
lua_pushvalue(L, object); // self
- // Call with 1 arguments, 0 results
- if(lua_pcall(L, 1, 0, 0))
- script_error(L, "error running function 'step': %s\n", lua_tostring(L, -1));
+ objectref_get_or_create(L, clicker); // Clicker reference
+ // Call with 2 arguments, 0 results
+ if(lua_pcall(L, 2, 0, 0))
+ script_error(L, "error running function 'on_rightclick': %s\n", lua_tostring(L, -1));
}
void scriptapi_luaentity_get_properties(lua_State *L, u16 id,
LuaEntityProperties *prop);
void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime);
-void scriptapi_luaentity_rightclick_player(lua_State *L, u16 id,
- const char *playername);
+void scriptapi_luaentity_punch(lua_State *L, u16 id,
+ ServerActiveObject *clicker);
+void scriptapi_luaentity_rightclick(lua_State *L, u16 id,
+ ServerActiveObject *clicker);
#endif
return;
//TODO: Check that object is reasonably close
+
+ // Get ServerRemotePlayer
+ ServerRemotePlayer *srp = (ServerRemotePlayer*)player;
+
+ // Update wielded item
+ srp->wieldItem(item_i);
- // Left click, pick object up (usually)
+ // Left click, pick/punch
if(button == 0)
{
+ actionstream<<player->getName()<<" punches object "
+ <<obj->getId()<<std::endl;
+
+ // Do stuff
+ obj->punch(srp);
+
+#if 0
/*
Try creating inventory item
*/
SendInventory(player->peer_id);
}
}
+#endif
}
// Right click, do something with object
if(button == 1)
actionstream<<player->getName()<<" right clicks object "
<<obj->getId()<<std::endl;
- // Track hp changes super-crappily
- u16 oldhp = player->hp;
-
// Do stuff
- obj->rightClick(player);
-
- // Send back stuff
- if(player->hp != oldhp)
- {
- SendPlayerHP(player);
- }
+ obj->rightClick(srp);
}
+
+ /*
+ Update player state to client
+ */
+ SendPlayerHP(player);
+ UpdateCrafting(player->peer_id);
+ SendInventory(player->peer_id);
}
else if(command == TOSERVER_GROUND_ACTION)
{
/*
Some more dynamic interface
*/
+
virtual void setPos(v3f pos)
{ setBasePosition(pos); }
// continuous: if true, object does not stop immediately at pos
// saving to disk may be omitted
virtual float getMinimumSavedMovement()
{ return 2.0*BS; }
+
+ virtual bool isPeaceful(){return true;}
+ virtual std::string getDescription(){return "SAO";}
+
/*
Step object in time.
Messages added to messages are sent to client over network.
*/
virtual std::string getStaticData(){return "";}
- /*
- Item that the player gets when this object is picked up.
- If NULL, object cannot be picked up.
- */
- virtual InventoryItem* createPickedUpItem(){return NULL;}
+ virtual void punch(ServerActiveObject *puncher){}
+ virtual void rightClick(ServerActiveObject *clicker){}
- /*
- If the object doesn't return an item, this will be called.
- Return value is tool wear.
- */
- virtual u16 punch(const std::string &toolname, v3f dir,
- const std::string &playername)
- {return 0;}
-
- /*
- */
- virtual void rightClick(Player *player){}
+ // Returns a reference
+ virtual InventoryItem* getWieldedItem()
+ { return NULL; }
+ virtual void damageWieldedItem(u16 amount)
+ {}
+ // If all fits, eats item and returns true. Otherwise returns false.
+ virtual bool addToInventory(InventoryItem *item)
+ {return false;}
+ virtual void setHP(s16 hp)
+ {}
+ virtual s16 getHP()
+ {return 0;}
- virtual bool isPeaceful(){return true;}
-
/*
Number of players which know about this object. Object won't be
deleted until this is 0 to keep the id preserved for the right