/*
Minetest-c55
Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
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
(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
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "client.h"
#include "utility.h"
#include <iostream>
#include "clientserver.h"
#include "jmutexautolock.h"
#include "main.h"
#include <sstream>
#include "porting.h"
void * ClientUpdateThread::Thread()
{
ThreadStarted();
DSTACK(__FUNCTION_NAME);
BEGIN_DEBUG_EXCEPTION_HANDLER
while(getRun())
{
m_client->asyncStep();
//m_client->updateSomeExpiredMeshes();
bool was = m_client->AsyncProcessData();
if(was == false)
sleep_ms(10);
}
END_DEBUG_EXCEPTION_HANDLER
return NULL;
}
Client::Client(
IrrlichtDevice *device,
const char *playername,
MapDrawControl &control):
m_thread(this),
m_env(new ClientMap(this, control,
device->getSceneManager()->getRootSceneNode(),
device->getSceneManager(), 666),
dout_client),
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_step_dtime(0.0),
m_inventory_updated(false),
m_time_of_day(0)
{
m_packetcounter_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_fetchblock_mutex.Init();
m_incoming_queue_mutex.Init();
m_env_mutex.Init();
m_con_mutex.Init();
m_step_dtime_mutex.Init();
m_thread.Start();
{
JMutexAutoLock envlock(m_env_mutex);
//m_env.getMap().StartUpdater();
Player *player = new LocalPlayer();
player->updateName(playername);
/*f32 y = BS*2 + BS*20;
player->setPosition(v3f(0, y, 0));*/
//player->setPosition(v3f(0, y, 30900*BS)); // DEBUG
m_env.addPlayer(player);
}
}
Client::~Client()
{
{
JMutexAutoLock conlock(m_con_mutex);
m_con.Disconnect();
}
m_thread.setRun(false);
while(m_thread.IsRunning())
sleep_ms(100);
}
void Client::connect(Address address)
{
DSTACK(__FUNCTION_NAME);
JMutexAutoLock lock(m_con_mutex);
m_con.setTimeoutMs(0);
m_con.Connect(address);
}
bool Client::connectedAndInitialized()
{
JMutexAutoLock lock(m_con_mutex);
if(m_con.Connected() == false)
return false;
if(m_server_ser_ver == SER_FMT_VER_INVALID)
return false;
return true;
}
void Client::step(float dtime)
{
DSTACK(__FUNCTION_NAME);
// Limit a bit
if(dtime > 2.0)
dtime = 2.0;
//dstream<<"Client steps "<<dtime<<std::endl;
{
//TimeTaker timer("ReceiveAll()", m_device);
// 0ms
ReceiveAll();
}
{
//TimeTaker timer("m_con_mutex + m_con.RunTimeouts()", m_device);
// 0ms
JMutexAutoLock lock(m_con_mutex);
m_con.RunTimeouts(dtime);
}
/*
Packet counter
*/
{
float &counter = m_packetcounter_timer;
counter -= dtime;
if(counter <= 0.0)
{
counter = 20.0;
dout_client<<"Client packetcounter (20s):"<<std::endl;
m_packetcounter.print(dout_client);
m_packetcounter.clear();
}
}
{
/*
Delete unused sectors
NOTE: This jams the game for a while because deleting sectors
clear caches
*/
float &counter = m_delete_unused_sectors_timer;
counter -= dtime;
if(counter <= 0.0)
{
// 3 minute interval
//counter = 180.0;
counter = 60.0;
JMutexAutoLock lock(m_env_mutex);
core::list<v3s16> deleted_blocks;
float delete_unused_sectors_timeout =
g_settings.getFloat("client_delete_unused_sectors_timeout");
// Delete sector blocks
/*u32 num = m_env.getMap().deleteUnusedSectors
(delete_unused_sectors_timeout,
true, &deleted_blocks);*/
// Delete whole sectors
u32 num = m_env.getMap().deleteUnusedSectors
(delete_unused_sectors_timeout,
false, &deleted_blocks);
if(num > 0)
{
/*dstream<<DTIME<<"Client: Deleted blocks of "<<num
<<" unused sectors"<<std::endl;*/
dstream<<DTIME<<"Client: Deleted "<<num
<<" unused sectors"<<std::endl;
/*
Send info to server
*/
// Env is locked so con can be locked.
JMutexAutoLock lock(m_con_mutex);
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;
|