+ assert(m_env);
+
+ const float interval = 0.2;
+ if(m_move_interval.step(dtime, interval)==false)
+ return;
+ dtime = interval;
+
+ core::aabbox3d<f32> box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.);
+ collisionMoveResult moveresult;
+ // Apply gravity
+ m_speed_f += v3f(0, -dtime*9.81*BS, 0);
+ // Maximum movement without glitches
+ f32 pos_max_d = BS*0.25;
+ // Limit speed
+ if(m_speed_f.getLength()*dtime > pos_max_d)
+ m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);
+ v3f pos_f = getBasePosition();
+ v3f pos_f_old = pos_f;
+ v3f accel_f = v3f(0,0,0);
+ f32 stepheight = 0;
+ IGameDef *gamedef = m_env->getGameDef();
+ moveresult = collisionMoveSimple(&m_env->getMap(), gamedef,
+ pos_max_d, box, stepheight, dtime,
+ pos_f, m_speed_f, accel_f);
+
+ if(send_recommended == false)
+ return;
+
+ if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS)
+ {
+ setBasePosition(pos_f);
+ m_last_sent_position = pos_f;
+
+ std::ostringstream os(std::ios::binary);
+ // command (0 = update position)
+ writeU8(os, 0);
+ // pos
+ writeV3F1000(os, m_base_position);
+ // create message and add to list
+ ActiveObjectMessage aom(getId(), false, os.str());
+ m_messages_out.push_back(aom);
+ }
+ if(m_itemstring_changed)
+ {
+ m_itemstring_changed = false;
+
+ std::ostringstream os(std::ios::binary);
+ // command (1 = update itemstring)
+ writeU8(os, 1);
+ // itemstring
+ os<<serializeString(m_itemstring);
+ // create message and add to list
+ ActiveObjectMessage aom(getId(), false, os.str());
+ m_messages_out.push_back(aom);
+ }
+ }
+
+ std::string getClientInitializationData(u16 protocol_version)
+ {
+ std::ostringstream os(std::ios::binary);
+ // version
+ writeU8(os, 0);
+ // pos
+ writeV3F1000(os, m_base_position);
+ // itemstring
+ os<<serializeString(m_itemstring);
+ return os.str();
+ }
+
+ std::string getStaticData()
+ {
+ infostream<<__FUNCTION_NAME<<std::endl;
+ std::ostringstream os(std::ios::binary);
+ // version
+ writeU8(os, 0);
+ // itemstring
+ os<<serializeString(m_itemstring);
+ return os.str();
+ }
+
+ ItemStack createItemStack()
+ {
+ try{
+ IItemDefManager *idef = m_env->getGameDef()->idef();
+ ItemStack item;
+ item.deSerialize(m_itemstring, idef);
+ infostream<<__FUNCTION_NAME<<": m_itemstring=\""<<m_itemstring
+ <<"\" -> item=\""<<item.getItemString()<<"\""
+ <<std::endl;
+ return item;
+ }
+ catch(SerializationError &e)
+ {
+ infostream<<__FUNCTION_NAME<<": serialization error: "
+ <<"m_itemstring=\""<<m_itemstring<<"\""<<std::endl;
+ return ItemStack();
+ }
+ }
+
+ int punch(v3f dir,
+ const ToolCapabilities *toolcap,
+ ServerActiveObject *puncher,
+ float time_from_last_punch)
+ {
+ // Take item into inventory
+ ItemStack item = createItemStack();
+ Inventory *inv = puncher->getInventory();
+ if(inv != NULL)
+ {
+ std::string wieldlist = puncher->getWieldList();
+ ItemStack leftover = inv->addItem(wieldlist, item);
+ puncher->setInventoryModified();
+ if(leftover.empty())
+ {
+ m_removed = true;
+ }
+ else
+ {
+ m_itemstring = leftover.getItemString();
+ m_itemstring_changed = true;
+ }
+ }
+
+ return 0;
+ }
+
+
+private:
+ std::string m_itemstring;
+ bool m_itemstring_changed;
+ v3f m_speed_f;
+ v3f m_last_sent_position;
+ IntervalLimiter m_move_interval;
+};
+
+// Prototype (registers item for deserialization)
+ItemSAO proto_ItemSAO(NULL, v3f(0,0,0), "");
+
+ServerActiveObject* createItemSAO(ServerEnvironment *env, v3f pos,
+ const std::string itemstring)