This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
-MeshUpdateQueue::(at your option) any later version.
+(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
),
m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT, this),
m_device(device),
- camera_position(0,0,0),
- camera_direction(0,0,1),
m_server_ser_ver(SER_FMT_VER_INVALID),
m_inventory_updated(false),
m_time_of_day(0),
m_access_denied(false)
{
m_packetcounter_timer = 0.0;
- m_delete_unused_sectors_timer = 0.0;
+ //m_delete_unused_sectors_timer = 0.0;
m_connection_reinit_timer = 0.0;
m_avg_rtt_timer = 0.0;
m_playerpos_send_timer = 0.0;
m_packetcounter.clear();
}
}
+
+ // Get connection status
+ bool connected = connectedAndInitialized();
+#if 0
{
/*
Delete unused sectors
}
}
}
-
- bool connected = connectedAndInitialized();
+#endif
if(connected == false)
{
// [0] u16 TOSERVER_INIT
// [2] u8 SER_FMT_VER_HIGHEST
// [3] u8[20] player_name
- // [23] u8[28] password
- SharedBuffer<u8> data(2+1+PLAYERNAME_SIZE+PASSWORD_SIZE);
+ // [23] u8[28] password (new in some version)
+ // [51] u16 client network protocol version (new in some version)
+ SharedBuffer<u8> data(2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2);
writeU16(&data[0], TOSERVER_INIT);
writeU8(&data[2], SER_FMT_VER_HIGHEST);
memset((char*)&data[3], 0, PLAYERNAME_SIZE);
snprintf((char*)&data[3], PLAYERNAME_SIZE, "%s", myplayer->getName());
- /*dstream<<"Client: password hash is \""<<m_password<<"\""
+ /*dstream<<"Client: sending initial password hash: \""<<m_password<<"\""
<<std::endl;*/
memset((char*)&data[23], 0, PASSWORD_SIZE);
snprintf((char*)&data[23], PASSWORD_SIZE, "%s", m_password.c_str());
+
+ // This should be incremented in each version
+ writeU16(&data[51], 1);
// Send as unreliable
Send(0, data, false);
Do stuff if connected
*/
+ /*
+ Run Map's timers and unload unused data
+ */
+ const float map_timer_and_unload_dtime = 5.25;
+ if(m_map_timer_and_unload_interval.step(dtime, map_timer_and_unload_dtime))
+ {
+ ScopeProfiler sp(&g_profiler, "Client: map timer and unload");
+ core::list<v3s16> deleted_blocks;
+ m_env.getMap().timerUpdate(map_timer_and_unload_dtime,
+ g_settings.getFloat("client_unload_unused_data_timeout"),
+ &deleted_blocks);
+
+ /*if(deleted_blocks.size() > 0)
+ dstream<<"Client: Unloaded "<<deleted_blocks.size()
+ <<" unused blocks"<<std::endl;*/
+
+ /*
+ Send info to server
+ NOTE: This loop is intentionally iterated the way it is.
+ */
+
+ core::list<v3s16>::Iterator i = deleted_blocks.begin();
+ core::list<v3s16> sendlist;
+ for(;;)
+ {
+ if(sendlist.size() == 255 || i == deleted_blocks.end())
+ {
+ if(sendlist.size() == 0)
+ break;
+ /*
+ [0] u16 command
+ [2] u8 count
+ [3] v3s16 pos_0
+ [3+6] v3s16 pos_1
+ ...
+ */
+ u32 replysize = 2+1+6*sendlist.size();
+ SharedBuffer<u8> reply(replysize);
+ writeU16(&reply[0], TOSERVER_DELETEDBLOCKS);
+ reply[2] = sendlist.size();
+ u32 k = 0;
+ for(core::list<v3s16>::Iterator
+ j = sendlist.begin();
+ j != sendlist.end(); j++)
+ {
+ writeV3S16(&reply[2+1+6*k], *j);
+ k++;
+ }
+ m_con.Send(PEER_ID_SERVER, 1, reply, true);
+
+ if(i == deleted_blocks.end())
+ break;
+
+ sendlist.clear();
+ }
+
+ sendlist.push_back(*i);
+ i++;
+ }
+ }
+
/*
Handle environment
*/
//TimeTaker envtimer("env step", m_device);
// Step environment
m_env.step(dtime);
-
- // Step active blocks
+
+ /*
+ Handle active blocks
+ NOTE: These old objects are DEPRECATED. TODO: Remove
+ */
for(core::map<v3s16, bool>::Iterator
i = m_active_blocks.getIterator();
i.atEnd() == false; i++)
{
v3s16 p = i.getNode()->getKey();
- MapBlock *block = NULL;
- try
- {
- block = m_env.getMap().getBlockNoCreate(p);
- block->stepObjects(dtime, false, m_env.getDayNightRatio());
- }
- catch(InvalidPositionException &e)
- {
- }
+ MapBlock *block = m_env.getMap().getBlockNoCreateNoEx(p);
+ if(block == NULL)
+ continue;
+
+ // Step MapBlockObjects
+ block->stepObjects(dtime, false, m_env.getDayNightRatio());
}
/*
*/
//m_env.getClientMap().updateMeshes(block->getPos(), getDayNightRatio());
-
/*
Add it to mesh update queue and set it to be acknowledged after update.
*/
/*
Read block objects
+ NOTE: Deprecated stuff here, TODO: Remove
*/
// Read active block count
for all added objects {
u16 id
u8 type
- u16 initialization data length
+ u32 initialization data length
string initialization data
}
*/
// get damage from falling on ground
m_ignore_damage_timer = 3.0;
}
+ else if(command == TOCLIENT_PLAYERITEM)
+ {
+ std::string datastring((char*)&data[2], datasize-2);
+ std::istringstream is(datastring, std::ios_base::binary);
+
+ u16 count = readU16(is);
+
+ for (u16 i = 0; i < count; ++i) {
+ u16 peer_id = readU16(is);
+ Player *player = m_env.getPlayer(peer_id);
+
+ if (player == NULL)
+ {
+ dout_client<<DTIME<<"Client: ignoring player item "
+ << deSerializeString(is)
+ << " for non-existing peer id " << peer_id
+ << std::endl;
+ continue;
+ } else if (player->isLocal()) {
+ dout_client<<DTIME<<"Client: ignoring player item "
+ << deSerializeString(is)
+ << " for local player" << std::endl;
+ continue;
+ } else {
+ InventoryList *inv = player->inventory.getList("main");
+ std::string itemstring(deSerializeString(is));
+ if (itemstring.empty()) {
+ inv->deleteItem(0);
+ dout_client<<DTIME
+ <<"Client: empty player item for peer "
+ << peer_id << std::endl;
+ } else {
+ std::istringstream iss(itemstring);
+ delete inv->changeItem(0, InventoryItem::deSerialize(iss));
+ dout_client<<DTIME<<"Client: player item for peer " << peer_id << ": ";
+ player->getWieldItem()->serialize(dout_client);
+ dout_client<<std::endl;
+ }
+ }
+ }
+ }
else
{
dout_client<<DTIME<<"WARNING: Client: Ignoring unknown command "
Send(0, data, false);
}
+void Client::sendPlayerItem(u16 item)
+{
+ Player *myplayer = m_env.getLocalPlayer();
+ if(myplayer == NULL)
+ return;
+
+ u16 our_peer_id = m_con.GetPeerID();
+
+ // Set peer id if not set already
+ if(myplayer->peer_id == PEER_ID_INEXISTENT)
+ myplayer->peer_id = our_peer_id;
+ // Check that an existing peer_id is the same as the connection's
+ assert(myplayer->peer_id == our_peer_id);
+
+ SharedBuffer<u8> data(2+2);
+ writeU16(&data[0], TOSERVER_PLAYERITEM);
+ writeU16(&data[2], item);
+
+ // Send as reliable
+ Send(0, data, true);
+}
+
void Client::removeNode(v3s16 p)
{
//JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
void Client::updateCamera(v3f pos, v3f dir)
{
m_env.getClientMap().updateCamera(pos, dir);
- camera_position = pos;
- camera_direction = dir;
+}
+
+void Client::renderPostFx()
+{
+ m_env.getClientMap().renderPostFx();
}
MapNode Client::getNode(v3s16 p)
return m_env.getMap().getNodeMetadata(p);
}
-v3f Client::getPlayerPosition()
+LocalPlayer* Client::getLocalPlayer()
+{
+ return m_env.getLocalPlayer();
+}
+
+v3f Client::getPlayerPosition(v3f *eye_position)
{
//JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
LocalPlayer *player = m_env.getLocalPlayer();
assert(player != NULL);
+ if (eye_position)
+ *eye_position = player->getEyePosition();
return player->getPosition();
}
player->control = control;
}
+void Client::selectPlayerItem(u16 item)
+{
+ LocalPlayer *player = m_env.getLocalPlayer();
+ assert(player != NULL);
+
+ player->wieldItem(item);
+
+ sendPlayerItem(item);
+}
+
// Returns true if the inventory of the local player has been
// updated from the server. If it is true, it is set to false.
bool Client::getLocalInventoryUpdated()