+ char c = data[2+PASSWORD_SIZE+i];
+ if(c == 0)
+ break;
+ newpwd += c;
+ }
+
+ infostream<<"Server: Client requests a password change from "
+ <<"'"<<oldpwd<<"' to '"<<newpwd<<"'"<<std::endl;
+
+ std::string playername = player->getName();
+
+ if(m_authmanager.exists(playername) == false)
+ {
+ infostream<<"Server: playername not found in authmanager"<<std::endl;
+ // Wrong old password supplied!!
+ SendChatMessage(peer_id, L"playername not found in authmanager");
+ return;
+ }
+
+ std::string checkpwd = m_authmanager.getPassword(playername);
+
+ if(oldpwd != checkpwd)
+ {
+ infostream<<"Server: invalid old password"<<std::endl;
+ // Wrong old password supplied!!
+ SendChatMessage(peer_id, L"Invalid old password supplied. Password NOT changed.");
+ return;
+ }
+
+ actionstream<<player->getName()<<" changes password"<<std::endl;
+
+ m_authmanager.setPassword(playername, newpwd);
+
+ infostream<<"Server: password change successful for "<<playername
+ <<std::endl;
+ SendChatMessage(peer_id, L"Password change successful");
+ }
+ else if(command == TOSERVER_PLAYERITEM)
+ {
+ if (datasize < 2+2)
+ return;
+
+ u16 item = readU16(&data[2]);
+ srp->setWieldIndex(item);
+ SendWieldedItem(srp);
+ }
+ else if(command == TOSERVER_RESPAWN)
+ {
+ if(player->hp != 0)
+ return;
+
+ RespawnPlayer(player);
+
+ actionstream<<player->getName()<<" respawns at "
+ <<PP(player->getPosition()/BS)<<std::endl;
+
+ // ActiveObject is added to environment in AsyncRunStep after
+ // the previous addition has been succesfully removed
+ }
+ else if(command == TOSERVER_REQUEST_TEXTURES) {
+ std::string datastring((char*)&data[2], datasize-2);
+ std::istringstream is(datastring, std::ios_base::binary);
+
+
+ core::list<TextureRequest> tosend;
+ u16 numtextures = readU16(is);
+
+ infostream<<"Sending "<<numtextures<<" textures to "
+ <<getPlayerName(peer_id)<<std::endl;
+ verbosestream<<"TOSERVER_REQUEST_TEXTURES: "<<std::endl;
+
+ for(int i = 0; i < numtextures; i++) {
+ std::string name = deSerializeString(is);
+ tosend.push_back(TextureRequest(name));
+ verbosestream<<"TOSERVER_REQUEST_TEXTURES: requested texture "
+ <<name<<std::endl;
+ }
+
+ SendTexturesRequested(peer_id, tosend);
+
+ // Now the client should know about everything
+ // (definitions and textures)
+ getClient(peer_id)->definitions_sent = true;
+ }
+ else if(command == TOSERVER_INTERACT)
+ {
+ std::string datastring((char*)&data[2], datasize-2);
+ std::istringstream is(datastring, std::ios_base::binary);
+
+ /*
+ [0] u16 command
+ [2] u8 action
+ [3] u16 item
+ [5] u32 length of the next item
+ [9] serialized PointedThing
+ actions:
+ 0: start digging (from undersurface) or use
+ 1: stop digging (all parameters ignored)
+ 2: digging completed
+ 3: place block or item (to abovesurface)
+ 4: use item
+ */
+ u8 action = readU8(is);
+ u16 item_i = readU16(is);
+ std::istringstream tmp_is(deSerializeLongString(is), std::ios::binary);
+ PointedThing pointed;
+ pointed.deSerialize(tmp_is);
+
+ verbosestream<<"TOSERVER_INTERACT: action="<<(int)action<<", item="
+ <<item_i<<", pointed="<<pointed.dump()<<std::endl;
+
+ if(player->hp == 0)
+ {
+ verbosestream<<"TOSERVER_INTERACT: "<<srp->getName()
+ <<" tried to interact, but is dead!"<<std::endl;
+ return;
+ }
+
+ v3f player_pos = srp->m_last_good_position;
+
+ // Update wielded item
+ if(srp->getWieldIndex() != item_i)
+ {
+ srp->setWieldIndex(item_i);
+ SendWieldedItem(srp);
+ }
+
+ // Get pointed to node (undefined if not POINTEDTYPE_NODE)
+ v3s16 p_under = pointed.node_undersurface;
+ v3s16 p_above = pointed.node_abovesurface;
+
+ // Get pointed to object (NULL if not POINTEDTYPE_OBJECT)
+ ServerActiveObject *pointed_object = NULL;
+ if(pointed.type == POINTEDTHING_OBJECT)
+ {
+ pointed_object = m_env->getActiveObject(pointed.object_id);
+ if(pointed_object == NULL)
+ {
+ verbosestream<<"TOSERVER_INTERACT: "
+ "pointed object is NULL"<<std::endl;
+ return;
+ }
+
+ }
+
+ v3f pointed_pos_under = player_pos;
+ v3f pointed_pos_above = player_pos;
+ if(pointed.type == POINTEDTHING_NODE)
+ {
+ pointed_pos_under = intToFloat(p_under, BS);
+ pointed_pos_above = intToFloat(p_above, BS);
+ }
+ else if(pointed.type == POINTEDTHING_OBJECT)
+ {
+ pointed_pos_under = pointed_object->getBasePosition();
+ pointed_pos_above = pointed_pos_under;
+ }
+
+ /*
+ Check that target is reasonably close
+ (only when digging or placing things)
+ */
+ if(action == 0 || action == 2 || action == 3)
+ {
+ float d = player_pos.getDistanceFrom(pointed_pos_under);
+ float max_d = BS * 14; // Just some large enough value
+ if(d > max_d){
+ actionstream<<"Player "<<player->getName()
+ <<" tried to access "<<pointed.dump()
+ <<" from too far: "
+ <<"d="<<d<<", max_d="<<max_d
+ <<". ignoring."<<std::endl;
+ // Re-send block to revert change on client-side
+ RemoteClient *client = getClient(peer_id);
+ v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
+ client->SetBlockNotSent(blockpos);
+ // Do nothing else
+ return;
+ }
+ }
+
+ /*
+ Make sure the player is allowed to do it
+ */
+ if((getPlayerPrivs(player) & PRIV_INTERACT) == 0)
+ {
+ infostream<<"Ignoring interaction from player "<<player->getName()
+ <<" because privileges are "<<getPlayerPrivs(player)
+ <<std::endl;
+ return;
+ }
+
+ /*
+ 0: start digging or punch object
+ */
+ if(action == 0)
+ {
+ if(pointed.type == POINTEDTHING_NODE)
+ {
+ /*
+ NOTE: This can be used in the future to check if
+ somebody is cheating, by checking the timing.
+ */
+ MapNode n(CONTENT_IGNORE);
+ try
+ {
+ n = m_env->getMap().getNode(p_under);
+ }
+ catch(InvalidPositionException &e)
+ {
+ infostream<<"Server: Not punching: Node not found."
+ <<" Adding block to emerge queue."
+ <<std::endl;
+ m_emerge_queue.addBlock(peer_id,
+ getNodeBlockPos(p_above), BLOCK_EMERGE_FLAG_FROMDISK);
+ }
+ if(n.getContent() != CONTENT_IGNORE)
+ scriptapi_node_on_punch(m_lua, p_under, n, srp);
+ }
+ else if(pointed.type == POINTEDTHING_OBJECT)
+ {
+ // Skip if object has been removed
+ if(pointed_object->m_removed)
+ return;
+
+ actionstream<<player->getName()<<" punches object "
+ <<pointed.object_id<<": "
+ <<pointed_object->getDescription()<<std::endl;
+
+ ItemStack punchitem = srp->getWieldedItem();
+ ToolCapabilities toolcap =
+ punchitem.getToolCapabilities(m_itemdef);
+ v3f dir = (pointed_object->getBasePosition() -
+ (srp->getPosition() + srp->getEyeOffset())
+ ).normalize();
+ pointed_object->punch(dir, &toolcap, srp,
+ srp->m_time_from_last_punch);
+ srp->m_time_from_last_punch = 0;
+ }
+
+ } // action == 0
+
+ /*
+ 1: stop digging
+ */
+ else if(action == 1)
+ {
+ } // action == 1
+
+ /*
+ 2: Digging completed
+ */
+ else if(action == 2)
+ {
+ // Only complete digging of nodes
+ if(pointed.type == POINTEDTHING_NODE)
+ {
+ MapNode n(CONTENT_IGNORE);
+ try
+ {
+ n = m_env->getMap().getNode(p_under);
+ }
+ catch(InvalidPositionException &e)
+ {
+ infostream<<"Server: Not finishing digging: Node not found."
+ <<" Adding block to emerge queue."
+ <<std::endl;
+ m_emerge_queue.addBlock(peer_id,
+ getNodeBlockPos(p_above), BLOCK_EMERGE_FLAG_FROMDISK);
+ }
+ if(n.getContent() != CONTENT_IGNORE)
+ scriptapi_node_on_dig(m_lua, p_under, n, srp);
+ }
+ } // action == 2
+
+ /*
+ 3: place block or right-click object
+ */
+ else if(action == 3)
+ {
+ ItemStack item = srp->getWieldedItem();