51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include "client.h"
#include <iostream>
#include <algorithm>
-#include "clientserver.h"
+#include <sstream>
+#include <IFileSystem.h>
#include "jthread/jmutexautolock.h"
+#include "util/directiontables.h"
+#include "util/pointedthing.h"
+#include "util/serialize.h"
+#include "util/string.h"
+#include "strfnd.h"
+#include "client.h"
+#include "clientserver.h"
#include "main.h"
-#include <sstream>
#include "filesys.h"
#include "porting.h"
#include "mapsector.h"
#include "nodedef.h"
#include "itemdef.h"
#include "shader.h"
-#include <IFileSystem.h>
#include "base64.h"
#include "clientmap.h"
#include "clientmedia.h"
#include "sound.h"
-#include "util/string.h"
#include "IMeshCache.h"
#include "serialization.h"
-#include "util/serialize.h"
#include "config.h"
-#include "cmake_config_githash.h"
-#include "util/directiontables.h"
-#include "util/pointedthing.h"
#include "version.h"
+#include "drawscene.h"
+
+extern gui::IGUIEnvironment* guienv;
/*
QueuedMeshUpdate
MtEventManager *event,
bool ipv6
):
+ m_packetcounter_timer(0.0),
+ m_connection_reinit_timer(0.1),
+ m_avg_rtt_timer(0.0),
+ m_playerpos_send_timer(0.0),
+ m_ignore_damage_timer(0.0),
m_tsrc(tsrc),
m_shsrc(shsrc),
m_itemdef(itemdef),
m_inventory_updated(false),
m_inventory_from_server(NULL),
m_inventory_from_server_age(0.0),
+ m_show_hud(true),
m_animation_time(0),
m_crack_level(-1),
m_crack_pos(0,0,0),
m_removed_sounds_check_timer(0),
m_state(LC_Created)
{
- 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_ignore_damage_timer = 0.0;
-
/*
Add local player
*/
{
- Player *player = new LocalPlayer(this);
-
- player->updateName(playername);
+ Player *player = new LocalPlayer(this, playername);
m_env.addPlayer(player);
}
void Client::step(float dtime)
{
DSTACK(__FUNCTION_NAME);
-
+
// Limit a bit
if(dtime > 2.0)
dtime = 2.0;
-
+
if(m_ignore_damage_timer > dtime)
m_ignore_damage_timer -= dtime;
else
{
counter = 20.0;
- infostream<<"Client packetcounter (20s):"<<std::endl;
+ infostream << "Client packetcounter (" << m_packetcounter_timer
+ << "):"<<std::endl;
m_packetcounter.print(infostream);
m_packetcounter.clear();
}
}
}
#endif
-
- if(m_state == LC_Created)
+ // UGLY hack to fix 2 second startup delay caused by non existent
+ // server client startup synchronization in local server or singleplayer mode
+ static bool initial_step = true;
+ if (initial_step) {
+ initial_step = false;
+ }
+ else if(m_state == LC_Created)
{
float &counter = m_connection_reinit_timer;
counter -= dtime;
Player *myplayer = m_env.getLocalPlayer();
assert(myplayer != NULL);
-
// Send TOSERVER_INIT
// [0] u16 TOSERVER_INIT
// [2] u8 SER_FMT_VER_HIGHEST_READ
v2f align = readV2F1000(is);
v2f offset = readV2F1000(is);
v3f world_pos;
+ v2s32 size;
try{
world_pos = readV3F1000(is);
}catch(SerializationError &e) {};
+ try{
+ size = readV2S32(is);
+ } catch(SerializationError &e) {};
ClientEvent event;
event.type = CE_HUDADD;
event.hudadd.align = new v2f(align);
event.hudadd.offset = new v2f(offset);
event.hudadd.world_pos = new v3f(world_pos);
+ event.hudadd.size = new v2s32(size);
m_client_event_queue.push_back(event);
}
else if(command == TOCLIENT_HUDRM)
v2f v2fdata;
v3f v3fdata;
u32 intdata = 0;
+ v2s32 v2s32data;
std::string datastring((char *)&data[2], datasize - 2);
std::istringstream is(datastring, std::ios_base::binary);
sdata = deSerializeString(is);
else if (stat == HUD_STAT_WORLD_POS)
v3fdata = readV3F1000(is);
+ else if (stat == HUD_STAT_SIZE )
+ v2s32data = readV2S32(is);
else
intdata = readU32(is);
event.hudchange.v3fdata = new v3f(v3fdata);
event.hudchange.sdata = new std::string(sdata);
event.hudchange.data = intdata;
+ event.hudchange.v2s32data = new v2s32(v2s32data);
m_client_event_queue.push_back(event);
}
else if(command == TOCLIENT_HUD_SET_FLAGS)
LocalPlayer *player = m_env.getLocalPlayer();
assert(player != NULL);
- player->local_animations[0] = readV2F1000(is);
- player->local_animations[1] = readV2F1000(is);
- player->local_animations[2] = readV2F1000(is);
- player->local_animations[3] = readV2F1000(is);
+ player->local_animations[0] = readV2S32(is);
+ player->local_animations[1] = readV2S32(is);
+ player->local_animations[2] = readV2S32(is);
+ player->local_animations[3] = readV2S32(is);
player->local_animation_speed = readF1000(is);
}
+ else if(command == TOCLIENT_EYE_OFFSET)
+ {
+ std::string datastring((char *)&data[2], datasize - 2);
+ std::istringstream is(datastring, std::ios_base::binary);
+
+ LocalPlayer *player = m_env.getLocalPlayer();
+ assert(player != NULL);
+
+ player->eye_offset_first = readV3F1000(is);
+ player->eye_offset_third = readV3F1000(is);
+ }
else
{
infostream<<"Client: Ignoring unknown command "
// Write length
size_t messagesize = message.size();
- assert(messagesize <= 0xFFFF);
- writeU16(buf, (u16) (messagesize & 0xFF));
+ if (messagesize > 0xFFFF) {
+ messagesize = 0xFFFF;
+ }
+ writeU16(buf, (u16) messagesize);
os.write((char*)buf, 2);
// Write string
writeU8(os,VERSION_PATCH_ORIG);
writeU8(os,0);
- writeU16(os,strlen(CMAKE_VERSION_GITHASH));
- os.write(CMAKE_VERSION_GITHASH,strlen(CMAKE_VERSION_GITHASH));
+ writeU16(os,strlen(minetest_version_hash));
+ os.write(minetest_version_hash,strlen(minetest_version_hash));
// Make data buffer
std::string s = os.str();
return m_crack_level;
}
+void Client::setHighlighted(v3s16 pos, bool show_hud)
+{
+ m_show_hud = show_hud;
+ v3s16 old_highlighted_pos = m_highlighted_pos;
+ m_highlighted_pos = pos;
+ addUpdateMeshTaskForNode(old_highlighted_pos, false, true);
+ addUpdateMeshTaskForNode(m_highlighted_pos, false, true);
+}
+
void Client::setCrack(int level, v3s16 pos)
{
int old_crack_level = m_crack_level;
// Show locally
if (message[0] == L'/')
{
- m_chat_queue.push_back(
- (std::wstring)L"issued command: "+message);
+ m_chat_queue.push_back((std::wstring)L"issued command: " + message);
}
else
{
LocalPlayer *player = m_env.getLocalPlayer();
assert(player != NULL);
std::wstring name = narrow_to_wide(player->getName());
- m_chat_queue.push_back(
- (std::wstring)L"<"+name+L"> "+message);
+ m_chat_queue.push_back((std::wstring)L"<" + name + L"> " + message);
}
}
MapBlock *b = m_env.getMap().getBlockNoCreateNoEx(p);
if(b == NULL)
return;
-
+
/*
Create a task to update the mesh of the block
*/
-
+
MeshMakeData *data = new MeshMakeData(this);
-
+
{
//TimeTaker timer("data fill");
// Release: ~0ms
// Debug: 1-6ms, avg=2ms
data->fill(b);
data->setCrack(m_crack_level, m_crack_pos);
+ data->setHighlighted(m_highlighted_pos, m_show_hud);
data->setSmoothLighting(g_settings->getBool("smooth_lighting"));
}
-
+
// Add task to queue
m_mesh_update_thread.m_queue_in.addBlock(p, data, ack_to_server, urgent);
}
return 1.0; // downloader only exists when not yet done
}
-void draw_load_screen(const std::wstring &text,
- IrrlichtDevice* device, gui::IGUIFont* font,
- float dtime=0 ,int percent=0, bool clouds=true);
-
void Client::afterContentReceived(IrrlichtDevice *device, gui::IGUIFont* font)
{
infostream<<"Client::afterContentReceived() started"<<std::endl;
infostream<<"- Updating node aliases"<<std::endl;
m_nodedef->updateAliases(m_itemdef);
- // Update node textures
+ // Update node textures and assign shaders to each tile
infostream<<"- Updating node textures"<<std::endl;
- m_nodedef->updateTextures(m_tsrc);
+ m_nodedef->updateTextures(this);
// Preload item textures and meshes if configured to
if(g_settings->getBool("preload_item_visuals"))
{
verbosestream<<"Updating item textures and meshes"<<std::endl;
wchar_t* text = wgettext("Item textures...");
- draw_load_screen(text,device,font,0,0);
+ draw_load_screen(text, device, guienv, font, 0, 0);
std::set<std::string> names = m_itemdef->getAll();
size_t size = names.size();
size_t count = 0;
count++;
percent = count*100/size;
if (count%50 == 0) // only update every 50 item
- draw_load_screen(text,device,font,0,percent);
+ draw_load_screen(text, device, guienv, font, 0, percent);
}
delete[] text;
}
return m_con.getPeerStat(PEER_ID_SERVER,con::AVG_RTT);
}
+float Client::getCurRate(void)
+{
+ return ( m_con.getLocalStat(con::CUR_INC_RATE) +
+ m_con.getLocalStat(con::CUR_DL_RATE));
+}
+
+float Client::getAvgRate(void)
+{
+ return ( m_con.getLocalStat(con::AVG_INC_RATE) +
+ m_con.getLocalStat(con::AVG_DL_RATE));
+}
+
+void Client::makeScreenshot(IrrlichtDevice *device)
+{
+ irr::video::IVideoDriver *driver = device->getVideoDriver();
+ irr::video::IImage* const raw_image = driver->createScreenShot();
+ if (raw_image) {
+ irr::video::IImage* const image = driver->createImage(video::ECF_R8G8B8,
+ raw_image->getDimension());
+
+ if (image) {
+ raw_image->copyTo(image);
+ irr::c8 filename[256];
+ snprintf(filename, sizeof(filename), "%s" DIR_DELIM "screenshot_%u.png",
+ g_settings->get("screenshot_path").c_str(),
+ device->getTimer()->getRealTime());
+ std::stringstream sstr;
+ if (driver->writeImageToFile(image, filename)) {
+ sstr << "Saved screenshot to '" << filename << "'";
+ } else {
+ sstr << "Failed to save screenshot '" << filename << "'";
+ }
+ m_chat_queue.push_back(narrow_to_wide(sstr.str()));
+ infostream << sstr << std::endl;
+ image->drop();
+ }
+ raw_image->drop();
+ }
+}
+
// IGameDef interface
// Under envlock
IItemDefManager* Client::getItemDefManager()
{
return m_shsrc;
}
+scene::ISceneManager* Client::getSceneManager()
+{
+ return m_device->getSceneManager();
+}
u16 Client::allocateUnknownNodeId(const std::string &name)
{
errorstream<<"Client::allocateUnknownNodeId(): "