aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/auth.cpp22
-rw-r--r--src/auth.h2
-rw-r--r--src/base64.cpp7
-rw-r--r--src/client.cpp6
-rw-r--r--src/defaultsettings.cpp3
-rw-r--r--src/environment.cpp52
-rw-r--r--src/environment.h1
-rw-r--r--src/game.cpp19
-rw-r--r--src/guiPasswordChange.cpp28
-rw-r--r--src/guiPasswordChange.h26
-rw-r--r--src/main.cpp34
-rw-r--r--src/main.h4
-rw-r--r--src/map.cpp6
-rw-r--r--src/map.h6
-rw-r--r--src/mapblock.cpp92
-rw-r--r--src/nodemetadata.cpp155
-rw-r--r--src/profiler.h131
-rw-r--r--src/server.cpp215
-rw-r--r--src/server.h15
-rw-r--r--src/servercommand.cpp29
-rw-r--r--src/servercommand.h28
-rw-r--r--src/servermain.cpp3
-rw-r--r--src/utility.cpp8
-rw-r--r--src/utility.h3
24 files changed, 674 insertions, 221 deletions
diff --git a/src/auth.cpp b/src/auth.cpp
index 49985e697..5d61243c6 100644
--- a/src/auth.cpp
+++ b/src/auth.cpp
@@ -77,7 +77,8 @@ u64 stringToPrivs(std::string str)
}
AuthManager::AuthManager(const std::string &authfilepath):
- m_authfilepath(authfilepath)
+ m_authfilepath(authfilepath),
+ m_modified(false)
{
m_mutex.Init();
@@ -138,6 +139,8 @@ void AuthManager::load()
ad.privs = privs;
m_authdata[name] = ad;
}
+
+ m_modified = false;
}
void AuthManager::save()
@@ -162,6 +165,8 @@ void AuthManager::save()
AuthData ad = i.getNode()->getValue();
os<<name<<":"<<ad.pwd<<":"<<privsToString(ad.privs)<<"\n";
}
+
+ m_modified = false;
}
bool AuthManager::exists(const std::string &username)
@@ -180,6 +185,8 @@ void AuthManager::set(const std::string &username, AuthData ad)
JMutexAutoLock lock(m_mutex);
m_authdata[username] = ad;
+
+ m_modified = true;
}
void AuthManager::add(const std::string &username)
@@ -187,6 +194,8 @@ void AuthManager::add(const std::string &username)
JMutexAutoLock lock(m_mutex);
m_authdata[username] = AuthData();
+
+ m_modified = true;
}
std::string AuthManager::getPassword(const std::string &username)
@@ -214,6 +223,8 @@ void AuthManager::setPassword(const std::string &username,
AuthData ad = n->getValue();
ad.pwd = password;
n->setValue(ad);
+
+ m_modified = true;
}
u64 AuthManager::getPrivs(const std::string &username)
@@ -240,5 +251,14 @@ void AuthManager::setPrivs(const std::string &username, u64 privs)
AuthData ad = n->getValue();
ad.privs = privs;
n->setValue(ad);
+
+ m_modified = true;
}
+bool AuthManager::isModified()
+{
+ JMutexAutoLock lock(m_mutex);
+ return m_modified;
+}
+
+
diff --git a/src/auth.h b/src/auth.h
index 472409d46..62dced2a3 100644
--- a/src/auth.h
+++ b/src/auth.h
@@ -89,10 +89,12 @@ public:
const std::string &password);
u64 getPrivs(const std::string &username);
void setPrivs(const std::string &username, u64 privs);
+ bool isModified();
private:
JMutex m_mutex;
std::string m_authfilepath;
core::map<std::string, AuthData> m_authdata;
+ bool m_modified;
};
#endif
diff --git a/src/base64.cpp b/src/base64.cpp
index 2a863d161..0dfba5013 100644
--- a/src/base64.cpp
+++ b/src/base64.cpp
@@ -71,9 +71,10 @@ std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_
for (j = 0; (j < i + 1); j++)
ret += base64_chars[char_array_4[j]];
-
- while((i++ < 3))
- ret += '=';
+
+ // Don't pad it with =
+ /*while((i++ < 3))
+ ret += '=';*/
}
diff --git a/src/client.cpp b/src/client.cpp
index 79bbd8021..e494056f2 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -306,8 +306,14 @@ void Client::step(float dtime)
SharedBuffer<u8> data(2+1+PLAYERNAME_SIZE+PASSWORD_SIZE);
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<<"\""
+ <<std::endl;*/
+
+ memset((char*)&data[23], 0, PASSWORD_SIZE);
snprintf((char*)&data[23], PASSWORD_SIZE, "%s", m_password.c_str());
// Send as unreliable
diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp
index 6fcdc1dbb..73f22a7f7 100644
--- a/src/defaultsettings.cpp
+++ b/src/defaultsettings.cpp
@@ -74,12 +74,13 @@ void set_default_settings()
g_settings.setDefault("give_initial_stuff", "false");
g_settings.setDefault("default_password", "");
g_settings.setDefault("default_privs", "build, shout");
+ g_settings.setDefault("profiler_print_interval", "0");
g_settings.setDefault("objectdata_interval", "0.2");
g_settings.setDefault("active_object_range", "2");
g_settings.setDefault("max_simultaneous_block_sends_per_client", "1");
//g_settings.setDefault("max_simultaneous_block_sends_per_client", "2");
- g_settings.setDefault("max_simultaneous_block_sends_server_total", "4");
+ g_settings.setDefault("max_simultaneous_block_sends_server_total", "8");
g_settings.setDefault("max_block_send_distance", "8");
g_settings.setDefault("max_block_generate_distance", "8");
g_settings.setDefault("time_send_interval", "20");
diff --git a/src/environment.cpp b/src/environment.cpp
index 36c754d57..f5f20d0e5 100644
--- a/src/environment.cpp
+++ b/src/environment.cpp
@@ -729,6 +729,16 @@ void ServerEnvironment::step(float dtime)
// Activate stored objects
activateObjects(block);
+ // Run node metadata
+ bool changed = block->m_node_metadata.step((float)dtime_s);
+ if(changed)
+ {
+ MapEditEvent event;
+ event.type = MEET_BLOCK_NODE_METADATA_CHANGED;
+ event.p = p;
+ m_map->dispatchEvent(&event);
+ }
+
// TODO: Do something
// TODO: Implement usage of ActiveBlockModifier
@@ -762,8 +772,10 @@ void ServerEnvironment::step(float dtime)
/*
Mess around in active blocks
*/
- if(m_active_blocks_test_interval.step(dtime, 10.0))
+ if(m_active_blocks_nodemetadata_interval.step(dtime, 1.0))
{
+ float dtime = 1.0;
+
for(core::map<v3s16, bool>::Iterator
i = m_active_blocks.m_list.getIterator();
i.atEnd()==false; i++)
@@ -779,7 +791,38 @@ void ServerEnvironment::step(float dtime)
// Set current time as timestamp
block->setTimestamp(m_game_time);
+
+ // Run node metadata
+ bool changed = block->m_node_metadata.step(dtime);
+ if(changed)
+ {
+ MapEditEvent event;
+ event.type = MEET_BLOCK_NODE_METADATA_CHANGED;
+ event.p = p;
+ m_map->dispatchEvent(&event);
+ }
+ }
+ }
+ if(m_active_blocks_test_interval.step(dtime, 10.0))
+ {
+ //float dtime = 10.0;
+
+ for(core::map<v3s16, bool>::Iterator
+ i = m_active_blocks.m_list.getIterator();
+ i.atEnd()==false; i++)
+ {
+ v3s16 p = i.getNode()->getKey();
+ /*dstream<<"Server: Block ("<<p.X<<","<<p.Y<<","<<p.Z
+ <<") being handled"<<std::endl;*/
+
+ MapBlock *block = m_map->getBlockNoCreateNoEx(p);
+ if(block==NULL)
+ continue;
+
+ // Set current time as timestamp
+ block->setTimestamp(m_game_time);
+
/*
Do stuff!
@@ -801,8 +844,11 @@ void ServerEnvironment::step(float dtime)
{
v3s16 p = p0 + block->getPosRelative();
MapNode n = block->getNodeNoEx(p0);
- // Test something:
- // Convert mud under proper lighting to grass
+
+ /*
+ Test something:
+ Convert mud under proper lighting to grass
+ */
if(n.d == CONTENT_MUD)
{
if(myrand()%20 == 0)
diff --git a/src/environment.h b/src/environment.h
index f5cce5933..b4f2a64ca 100644
--- a/src/environment.h
+++ b/src/environment.h
@@ -246,6 +246,7 @@ private:
ActiveBlockList m_active_blocks;
IntervalLimiter m_active_blocks_management_interval;
IntervalLimiter m_active_blocks_test_interval;
+ IntervalLimiter m_active_blocks_nodemetadata_interval;
// Time from the beginning of the game in seconds.
// Incremented in step().
u32 m_game_time;
diff --git a/src/game.cpp b/src/game.cpp
index 6932b45f1..e8e6cb71f 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -903,6 +903,10 @@ void the_game(
bool first_loop_after_window_activation = true;
+ // TODO: Convert the static interval timers to these
+ // Interval limiter for profiler
+ IntervalLimiter m_profiler_interval;
+
// Time is in milliseconds
// NOTE: getRealTime() causes strange problems in wine (imprecision?)
// NOTE: So we have to use getTime() and call run()s between them
@@ -1090,6 +1094,21 @@ void the_game(
}
/*
+ Profiler
+ */
+ float profiler_print_interval =
+ g_settings.getFloat("profiler_print_interval");
+ if(profiler_print_interval != 0)
+ {
+ if(m_profiler_interval.step(0.030, profiler_print_interval))
+ {
+ dstream<<"Profiler:"<<std::endl;
+ g_profiler.print(dstream);
+ g_profiler.clear();
+ }
+ }
+
+ /*
Direct handling of user input
*/
diff --git a/src/guiPasswordChange.cpp b/src/guiPasswordChange.cpp
index 98b11b432..ec1cd029a 100644
--- a/src/guiPasswordChange.cpp
+++ b/src/guiPasswordChange.cpp
@@ -1,21 +1,19 @@
/*
-Minetest-c55
-Copyright (C) 2010-11 celeron55, Perttu Ahola <celeron55@gmail.com>
+Part of Minetest-c55
+Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
Copyright (C) 2011 Ciaran Gultnieks <ciaran@ciarang.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.
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "guiPasswordChange.h"
diff --git a/src/guiPasswordChange.h b/src/guiPasswordChange.h
index defac3113..1748baade 100644
--- a/src/guiPasswordChange.h
+++ b/src/guiPasswordChange.h
@@ -1,21 +1,19 @@
/*
-Minetest-c55
+Part of Minetest-c55
Copyright (C) 2010-11 celeron55, Perttu Ahola <celeron55@gmail.com>
Copyright (C) 2011 Ciaran Gultnieks <ciaran@ciarang.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.
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef GUIPASSWORDCHANGE_HEADER
diff --git a/src/main.cpp b/src/main.cpp
index 3d342e596..2cde3b302 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -215,6 +215,8 @@ FIXME: Server sometimes goes into some infinite PeerNotFoundException loop
FIXME: The new optimized map sending doesn't sometimes send enough blocks
from big caves and such
+* Take player's walking direction into account in GetNextBlocks
+
Environment:
------------
@@ -308,6 +310,9 @@ Making it more portable:
Stuff to do before release:
---------------------------
+Fixes to the current release:
+-----------------------------
+
Stuff to do after release:
---------------------------
- Make sure server handles removing grass when a block is placed (etc)
@@ -386,6 +391,9 @@ Settings g_settings;
// This is located in defaultsettings.cpp
extern void set_default_settings();
+// Global profiler
+Profiler g_profiler;
+
/*
Random stuff
*/
@@ -436,7 +444,14 @@ std::ostream *derr_client_ptr = &dstream;
class TimeGetter
{
public:
- TimeGetter(IrrlichtDevice *device):
+ virtual u32 getTime() = 0;
+};
+
+// A precise irrlicht one
+class IrrlichtTimeGetter: public TimeGetter
+{
+public:
+ IrrlichtTimeGetter(IrrlichtDevice *device):
m_device(device)
{}
u32 getTime()
@@ -448,8 +463,18 @@ public:
private:
IrrlichtDevice *m_device;
};
+// Not so precise one which works without irrlicht
+class SimpleTimeGetter: public TimeGetter
+{
+public:
+ u32 getTime()
+ {
+ return porting::getTimeMs();
+ }
+};
// A pointer to a global instance of the time getter
+// TODO: why?
TimeGetter *g_timegetter = NULL;
u32 getTimeMs()
@@ -1208,6 +1233,9 @@ int main(int argc, char *argv[])
{
DSTACK("Dedicated server branch");
+ // Create time getter
+ g_timegetter = new SimpleTimeGetter();
+
// Create server
Server server(map_dir.c_str());
server.start(port);
@@ -1290,7 +1318,7 @@ int main(int argc, char *argv[])
device = device;
// Create time getter
- g_timegetter = new TimeGetter(device);
+ g_timegetter = new IrrlichtTimeGetter(device);
// Create game callback for menus
g_gamecallback = new MainGameCallback(device);
@@ -1497,6 +1525,8 @@ int main(int argc, char *argv[])
g_settings.set("creative_mode", itos(menudata.creative_mode));
g_settings.set("enable_damage", itos(menudata.enable_damage));
+ // NOTE: These are now checked server side; no need to do it
+ // here, so let's not do it here.
/*// Check for valid parameters, restart menu if invalid.
if(playername == "")
{
diff --git a/src/main.h b/src/main.h
index fcf150f87..450525c26 100644
--- a/src/main.h
+++ b/src/main.h
@@ -28,6 +28,10 @@ extern Settings g_settings;
#include "tile.h"
extern ITextureSource *g_texturesource;
+// Global profiler
+#include "profiler.h"
+extern Profiler g_profiler;
+
// Debug streams
#include <fstream>
diff --git a/src/map.cpp b/src/map.cpp
index a49de3c46..f9809e9fd 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -5692,9 +5692,9 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
p_nodes_min.Y / MAP_BLOCKSIZE - 1,
p_nodes_min.Z / MAP_BLOCKSIZE - 1);
v3s16 p_blocks_max(
- p_nodes_max.X / MAP_BLOCKSIZE + 1,
- p_nodes_max.Y / MAP_BLOCKSIZE + 1,
- p_nodes_max.Z / MAP_BLOCKSIZE + 1);
+ p_nodes_max.X / MAP_BLOCKSIZE,
+ p_nodes_max.Y / MAP_BLOCKSIZE,
+ p_nodes_max.Z / MAP_BLOCKSIZE);
u32 vertex_count = 0;
diff --git a/src/map.h b/src/map.h
index 09154547c..6f7ac0d3b 100644
--- a/src/map.h
+++ b/src/map.h
@@ -46,8 +46,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define MAPTYPE_CLIENT 2
enum MapEditEventType{
+ // Node added (changed from air or something else to something)
MEET_ADDNODE,
+ // Node removed (changed to air)
MEET_REMOVENODE,
+ // Node metadata of block changed (not knowing which node exactly)
+ // p stores block coordinate
+ MEET_BLOCK_NODE_METADATA_CHANGED,
+ // Anything else
MEET_OTHER
};
diff --git a/src/mapblock.cpp b/src/mapblock.cpp
index c448ef236..e31596b9c 100644
--- a/src/mapblock.cpp
+++ b/src/mapblock.cpp
@@ -540,10 +540,10 @@ void updateFastFaceRow(
v3s16 p_next;
- bool next_makes_face;
+ bool next_makes_face = false;
v3s16 next_p_corrected;
v3s16 next_face_dir_corrected;
- u8 next_lights[4];
+ u8 next_lights[4] = {0,0,0,0};
TileSpec next_tile;
// If at last position, there is nothing to compare to and
@@ -729,63 +729,90 @@ private:
core::array<PreMeshBuffer> m_prebuffers;
};
+// Create a cuboid.
+// material - the material to use (for all 6 faces)
+// collector - the MeshCollector for the resulting polygons
+// pa - texture atlas pointer for the material
+// c - vertex colour - used for all
+// pos - the position of the centre of the cuboid
+// rz,ry,rz - the radius of the cuboid in each dimension
+// txc - texture coordinates - this is a list of texture coordinates
+// for the opposite corners of each face - therefore, there
+// should be (2+2)*6=24 values in the list. Alternatively, pass
+// NULL to use the entire texture for each face. The order of
+// the faces in the list is top-backi-right-front-left-bottom
+// If you specified 0,0,1,1 for each face, that would be the
+// same as passing NULL.
void makeCuboid(video::SMaterial &material, MeshCollector *collector,
AtlasPointer* pa, video::SColor &c,
- v3f &pos, f32 rx, f32 ry, f32 rz)
+ v3f &pos, f32 rx, f32 ry, f32 rz, f32* txc)
{
+ f32 tu0=pa->x0();
+ f32 tu1=pa->x1();
+ f32 tv0=pa->y0();
+ f32 tv1=pa->y1();
+ f32 txus=tu1-tu0;
+ f32 txvs=tv1-tv0;
+
video::S3DVertex v[4] =
{
- video::S3DVertex(0,0,0, 0,0,0, c,
- pa->x0(), pa->y1()),
- video::S3DVertex(0,0,0, 0,0,0, c,
- pa->x1(), pa->y1()),
- video::S3DVertex(0,0,0, 0,0,0, c,
- pa->x1(), pa->y0()),
- video::S3DVertex(0,0,0, 0,0,0, c,
- pa->x0(), pa->y0())
+ video::S3DVertex(0,0,0, 0,0,0, c, tu0, tv1),
+ video::S3DVertex(0,0,0, 0,0,0, c, tu1, tv1),
+ video::S3DVertex(0,0,0, 0,0,0, c, tu1, tv0),
+ video::S3DVertex(0,0,0, 0,0,0, c, tu0, tv0)
};
for(int i=0;i<6;i++)
{
switch(i)
{
- case 0:
+ case 0: // top
v[0].Pos.X=-rx; v[0].Pos.Y= ry; v[0].Pos.Z=-rz;
v[1].Pos.X=-rx; v[1].Pos.Y= ry; v[1].Pos.Z= rz;
v[2].Pos.X= rx; v[2].Pos.Y= ry; v[2].Pos.Z= rz;
v[3].Pos.X= rx; v[3].Pos.Y= ry, v[3].Pos.Z=-rz;
break;
- case 1:
+ case 1: // back
v[0].Pos.X=-rx; v[0].Pos.Y= ry; v[0].Pos.Z=-rz;
v[1].Pos.X= rx; v[1].Pos.Y= ry; v[1].Pos.Z=-rz;
v[2].Pos.X= rx; v[2].Pos.Y=-ry; v[2].Pos.Z=-rz;
v[3].Pos.X=-rx; v[3].Pos.Y=-ry, v[3].Pos.Z=-rz;
break;
- case 2:
+ case 2: //right
v[0].Pos.X= rx; v[0].Pos.Y= ry; v[0].Pos.Z=-rz;
v[1].Pos.X= rx; v[1].Pos.Y= ry; v[1].Pos.Z= rz;
v[2].Pos.X= rx; v[2].Pos.Y=-ry; v[2].Pos.Z= rz;
v[3].Pos.X= rx; v[3].Pos.Y=-ry, v[3].Pos.Z=-rz;
break;
- case 3:
+ case 3: // front
v[0].Pos.X= rx; v[0].Pos.Y= ry; v[0].Pos.Z= rz;
v[1].Pos.X=-rx; v[1].Pos.Y= ry; v[1].Pos.Z= rz;
v[2].Pos.X=-rx; v[2].Pos.Y=-ry; v[2].Pos.Z= rz;
v[3].Pos.X= rx; v[3].Pos.Y=-ry, v[3].Pos.Z= rz;
break;
- case 4:
+ case 4: // left
v[0].Pos.X=-rx; v[0].Pos.Y= ry; v[0].Pos.Z= rz;
v[1].Pos.X=-rx; v[1].Pos.Y= ry; v[1].Pos.Z=-rz;
v[2].Pos.X=-rx; v[2].Pos.Y=-ry; v[2].Pos.Z=-rz;
v[3].Pos.X=-rx; v[3].Pos.Y=-ry, v[3].Pos.Z= rz;
break;
- case 5:
+ case 5: // bottom
v[0].Pos.X= rx; v[0].Pos.Y=-ry; v[0].Pos.Z= rz;
v[1].Pos.X=-rx; v[1].Pos.Y=-ry; v[1].Pos.Z= rz;
v[2].Pos.X=-rx; v[2].Pos.Y=-ry; v[2].Pos.Z=-rz;
v[3].Pos.X= rx; v[3].Pos.Y=-ry, v[3].Pos.Z=-rz;
break;
}
+
+ if(txc!=NULL)
+ {
+ v[0].TCoords.X=tu0+txus*txc[0]; v[0].TCoords.Y=tv0+txvs*txc[3];
+ v[1].TCoords.X=tu0+txus*txc[2]; v[1].TCoords.Y=tv0+txvs*txc[3];
+ v[2].TCoords.X=tu0+txus*txc[2]; v[2].TCoords.Y=tv0+txvs*txc[1];
+ v[3].TCoords.X=tu0+txus*txc[0]; v[3].TCoords.Y=tv0+txvs*txc[1];
+ txc+=4;
+ }
+
for(u16 i=0; i<4; i++)
v[i].Pos += pos;
u16 indices[] = {0,1,2,2,3,0};
@@ -1569,9 +1596,16 @@ scene::SMesh* makeMapBlockMesh(MeshMakeData *data)
// The post - always present
v3f pos = intToFloat(p+blockpos_nodes, BS);
+ f32 postuv[24]={
+ 0.4,0.4,0.6,0.6,
+ 0.35,0,0.65,1,
+ 0.35,0,0.65,1,
+ 0.35,0,0.65,1,
+ 0.35,0,0.65,1,
+ 0.4,0.4,0.6,0.6};
makeCuboid(material_wood, &collector,
&pa_wood, c, pos,
- post_rad,BS/2,post_rad);
+ post_rad,BS/2,post_rad, postuv);
// Now a section of fence, +X, if there's a post there
v3s16 p2 = p;
@@ -1582,14 +1616,21 @@ scene::SMesh* makeMapBlockMesh(MeshMakeData *data)
pos = intToFloat(p+blockpos_nodes, BS);
pos.X += BS/2;
pos.Y += BS/4;
+ f32 xrailuv[24]={
+ 0,0.4,1,0.6,
+ 0,0.4,1,0.6,
+ 0,0.4,1,0.6,
+ 0,0.4,1,0.6,
+ 0,0.4,1,0.6,
+ 0,0.4,1,0.6};
makeCuboid(material_wood, &collector,
&pa_wood, c, pos,
- bar_len,bar_rad,bar_rad);
+ bar_len,bar_rad,bar_rad, xrailuv);
pos.Y -= BS/2;
makeCuboid(material_wood, &collector,
&pa_wood, c, pos,
- bar_len,bar_rad,bar_rad);
+ bar_len,bar_rad,bar_rad, xrailuv);
}
// Now a section of fence, +Z, if there's a post there
@@ -1601,13 +1642,20 @@ scene::SMesh* makeMapBlockMesh(MeshMakeData *data)
pos = intToFloat(p+blockpos_nodes, BS);
pos.Z += BS/2;
pos.Y += BS/4;
+ f32 zrailuv[24]={
+ 0,0.4,1,0.6,
+ 0,0.4,1,0.6,
+ 0,0.4,1,0.6,
+ 0,0.4,1,0.6,
+ 0,0.4,1,0.6,
+ 0,0.4,1,0.6};
makeCuboid(material_wood, &collector,
&pa_wood, c, pos,
- bar_rad,bar_rad,bar_len);
+ bar_rad,bar_rad,bar_len, zrailuv);
pos.Y -= BS/2;
makeCuboid(material_wood, &collector,
&pa_wood, c, pos,
- bar_rad,bar_rad,bar_len);
+ bar_rad,bar_rad,bar_len, zrailuv);
}
diff --git a/src/nodemetadata.cpp b/src/nodemetadata.cpp
index 308a33854..f9468e4fa 100644
--- a/src/nodemetadata.cpp
+++ b/src/nodemetadata.cpp
@@ -268,91 +268,100 @@ void FurnaceNodeMetadata::inventoryModified()
}
bool FurnaceNodeMetadata::step(float dtime)
{
+ if(dtime > 60.0)
+ dstream<<"Furnace stepping a long time ("<<dtime<<")"<<std::endl;
// Update at a fixed frequency
- const float interval = 0.5;
+ const float interval = 2.0;
m_step_accumulator += dtime;
- if(m_step_accumulator < interval)
- return false;
- m_step_accumulator -= interval;
- dtime = interval;
-
- //dstream<<"Furnace step dtime="<<dtime<<std::endl;
-
- InventoryList *dst_list = m_inventory->getList("dst");
- assert(dst_list);
-
- InventoryList *src_list = m_inventory->getList("src");
- assert(src_list);
- InventoryItem *src_item = src_list->getItem(0);
-
- // Start only if there are free slots in dst, so that it can
- // accomodate any result item
- if(dst_list->getFreeSlots() > 0 && src_item && src_item->isCookable())
- {
- m_src_totaltime = 3;
- }
- else
+ bool changed = false;
+ while(m_step_accumulator > interval)
{
- m_src_time = 0;
- m_src_totaltime = 0;
- }
+ m_step_accumulator -= interval;
+ dtime = interval;
- if(m_fuel_time < m_fuel_totaltime)
- {
- //dstream<<"Furnace is active"<<std::endl;
- m_fuel_time += dtime;
- m_src_time += dtime;
- if(m_src_time >= m_src_totaltime && m_src_totaltime > 0.001
- && src_item)
+ //dstream<<"Furnace step dtime="<<dtime<<std::endl;
+
+ InventoryList *dst_list = m_inventory->getList("dst");
+ assert(dst_list);
+
+ InventoryList *src_list = m_inventory->getList("src");
+ assert(src_list);
+ InventoryItem *src_item = src_list->getItem(0);
+
+ // Start only if there are free slots in dst, so that it can
+ // accomodate any result item
+ if(dst_list->getFreeSlots() > 0 && src_item && src_item->isCookable())
+ {
+ m_src_totaltime = 3;
+ }
+ else
{
- InventoryItem *cookresult = src_item->createCookResult();
- dst_list->addItem(cookresult);
- src_list->decrementMaterials(1);
m_src_time = 0;
m_src_totaltime = 0;
}
- return true;
- }
-
- if(src_item == NULL || m_src_totaltime < 0.001)
- {
- return false;
- }
-
- bool changed = false;
- //dstream<<"Furnace is out of fuel"<<std::endl;
+ if(m_fuel_time < m_fuel_totaltime)
+ {
+ //dstream<<"Furnace is active"<<std::endl;
+ m_fuel_time += dtime;
+ m_src_time += dtime;
+ if(m_src_time >= m_src_totaltime && m_src_totaltime > 0.001
+ && src_item)
+ {
+ InventoryItem *cookresult = src_item->createCookResult();
+ dst_list->addItem(cookresult);
+ src_list->decrementMaterials(1);
+ m_src_time = 0;
+ m_src_totaltime = 0;
+ }
+ changed = true;
+ continue;
+ }
+
+ if(src_item == NULL || m_src_totaltime < 0.001)
+ {
+ continue;
+ }
+
+ //dstream<<"Furnace is out of fuel"<<std::endl;
- InventoryList *fuel_list = m_inventory->getList("fuel");
- assert(fuel_list);
- InventoryItem *fuel_item = fuel_list->getItem(0);
+ InventoryList *fuel_list = m_inventory->getList("fuel");
+ assert(fuel_list);
+ InventoryItem *fuel_item = fuel_list->getItem(0);
- if(ItemSpec(ITEM_MATERIAL, CONTENT_TREE).checkItem(fuel_item))
- {
- m_fuel_totaltime = 10;
- m_fuel_time = 0;
- fuel_list->decrementMaterials(1);
- changed = true;
- }
- else if(ItemSpec(ITEM_MATERIAL, CONTENT_WOOD).checkItem(fuel_item))
- {
- m_fuel_totaltime = 5;
- m_fuel_time = 0;
- fuel_list->decrementMaterials(1);
- changed = true;
- }
- else if(ItemSpec(ITEM_CRAFT, "lump_of_coal").checkItem(fuel_item))
- {
- m_fuel_totaltime = 10;
- m_fuel_time = 0;
- fuel_list->decrementMaterials(1);
- changed = true;
- }
- else
- {
- //dstream<<"No fuel found"<<std::endl;
+ if(ItemSpec(ITEM_MATERIAL, CONTENT_TREE).checkItem(fuel_item))
+ {
+ m_fuel_totaltime = 30;
+ m_fuel_time = 0;
+ fuel_list->decrementMaterials(1);
+ changed = true;
+ }
+ else if(ItemSpec(ITEM_MATERIAL, CONTENT_WOOD).checkItem(fuel_item))
+ {
+ m_fuel_totaltime = 30/4;
+ m_fuel_time = 0;
+ fuel_list->decrementMaterials(1);
+ changed = true;
+ }
+ else if(ItemSpec(ITEM_CRAFT, "Stick").checkItem(fuel_item))
+ {
+ m_fuel_totaltime = 30/4/4;
+ m_fuel_time = 0;
+ fuel_list->decrementMaterials(1);
+ changed = true;
+ }
+ else if(ItemSpec(ITEM_CRAFT, "lump_of_coal").checkItem(fuel_item))
+ {
+ m_fuel_totaltime = 40;
+ m_fuel_time = 0;
+ fuel_list->decrementMaterials(1);
+ changed = true;
+ }
+ else
+ {
+ //dstream<<"No fuel found"<<std::endl;
+ }
}
-
return changed;
}
diff --git a/src/profiler.h b/src/profiler.h
new file mode 100644
index 000000000..a30e34a7c
--- /dev/null
+++ b/src/profiler.h
@@ -0,0 +1,131 @@
+/*
+Minetest-c55
+Copyright (C) 2011 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.
+*/
+
+#ifndef PROFILER_HEADER
+#define PROFILER_HEADER
+
+#include "common_irrlicht.h"
+#include <string>
+#include "utility.h"
+#include <jmutex.h>
+#include <jmutexautolock.h>
+
+/*
+ Time profiler
+*/
+
+class Profiler
+{
+public:
+ Profiler()
+ {
+ m_mutex.Init();
+ }
+
+ void add(const std::string &name, u32 duration)
+ {
+ JMutexAutoLock lock(m_mutex);
+ core::map<std::string, u32>::Node *n = m_data.find(name);
+ if(n == NULL)
+ {
+ m_data[name] = duration;
+ }
+ else
+ {
+ n->setValue(n->getValue()+duration);
+ }
+ }
+
+ void clear()
+ {
+ JMutexAutoLock lock(m_mutex);
+ for(core::map<std::string, u32>::Iterator
+ i = m_data.getIterator();
+ i.atEnd() == false; i++)
+ {
+ i.getNode()->setValue(0);
+ }
+ }
+
+ void print(std::ostream &o)
+ {
+ JMutexAutoLock lock(m_mutex);
+ for(core::map<std::string, u32>::Iterator
+ i = m_data.getIterator();
+ i.atEnd() == false; i++)
+ {
+ std::string name = i.getNode()->getKey();
+ o<<name<<": ";
+ s32 clampsize = 40;
+ s32 space = clampsize-name.size();
+ for(s32 j=0; j<space; j++)
+ {
+ if(j%2 == 0 && j < space - 1)
+ o<<"-";
+ else
+ o<<" ";
+ }
+ o<<i.getNode()->getValue();
+ o<<std::endl;
+ }
+ }
+
+private:
+ JMutex m_mutex;
+ core::map<std::string, u32> m_data;
+};
+
+class ScopeProfiler
+{
+public:
+ ScopeProfiler(Profiler *profiler, const std::string &name):
+ m_profiler(profiler),
+ m_name(name),
+ m_timer(NULL)
+ {
+ if(m_profiler)
+ m_timer = new TimeTaker(m_name.c_str());
+ }
+ // name is copied
+ ScopeProfiler(Profiler *profiler, const char *name):
+ m_profiler(profiler),
+ m_name(name),
+ m_timer(NULL)
+ {
+ if(m_profiler)
+ m_timer = new TimeTaker(m_name.c_str());
+ }
+ ~ScopeProfiler()
+ {
+ if(m_timer)
+ {
+ u32 duration = m_timer->stop(true);
+ if(m_profiler)
+ m_profiler->add(m_name, duration);
+ delete m_timer;
+ }
+ }
+private:
+ Profiler *m_profiler;
+ std::string m_name;
+ TimeTaker *m_timer;
+};
+
+#endif
+
diff --git a/src/server.cpp b/src/server.cpp
index 56874c46c..96fcc0d07 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -312,11 +312,14 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
TimeTaker timer("RemoteClient::GetNextBlocks", &timer_result);*/
// Increment timers
- m_nearest_unsent_reset_timer += dtime;
m_nothing_to_send_pause_timer -= dtime;
if(m_nothing_to_send_pause_timer >= 0)
+ {
+ // Keep this reset
+ m_nearest_unsent_reset_timer = 0;
return;
+ }
// Won't send anything if already sending
if(m_blocks_sending.size() >= g_settings.getU16
@@ -326,14 +329,21 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
return;
}
+ //TimeTaker timer("RemoteClient::GetNextBlocks");
+
Player *player = server->m_env.getPlayer(peer_id);
assert(player != NULL);
v3f playerpos = player->getPosition();
v3f playerspeed = player->getSpeed();
+ v3f playerspeeddir(0,0,0);
+ if(playerspeed.getLength() > 1.0*BS)
+ playerspeeddir = playerspeed / playerspeed.getLength();
+ // Predict to next block
+ v3f playerpos_predicted = playerpos + playerspeeddir*MAP_BLOCKSIZE*BS;
- v3s16 center_nodepos = floatToInt(playerpos, BS);
+ v3s16 center_nodepos = floatToInt(playerpos_predicted, BS);
v3s16 center = getNodeBlockPos(center_nodepos);
@@ -344,6 +354,9 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
camera_dir.rotateYZBy(player->getPitch());
camera_dir.rotateXZBy(player->getYaw());
+ /*dstream<<"camera_dir=("<<camera_dir.X<<","<<camera_dir.Y<<","
+ <<camera_dir.Z<<")"<<std::endl;*/
+
/*
Get the starting value of the block finder radius.
*/
@@ -356,11 +369,18 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
/*dstream<<"m_nearest_unsent_reset_timer="
<<m_nearest_unsent_reset_timer<<std::endl;*/
- if(m_nearest_unsent_reset_timer > 5.0)
+
+ // This has to be incremented only when the nothing to send pause
+ // is not active
+ m_nearest_unsent_reset_timer += dtime;
+
+ // Reset periodically to avoid possible bugs or other mishaps
+ if(m_nearest_unsent_reset_timer > 10.0)
{
m_nearest_unsent_reset_timer = 0;
m_nearest_unsent_d = 0;
- //dstream<<"Resetting m_nearest_unsent_d"<<std::endl;
+ /*dstream<<"Resetting m_nearest_unsent_d for "
+ <<server->getPlayerName(peer_id)<<std::endl;*/
}
//s16 last_nearest_unsent_d = m_nearest_unsent_d;
@@ -402,11 +422,22 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
s16 d_max = g_settings.getS16("max_block_send_distance");
s16 d_max_gen = g_settings.getS16("max_block_generate_distance");
+ // Don't loop very much at a time
+ if(d_max > d_start+1)
+ d_max = d_start+1;
+ /*if(d_max_gen > d_start+2)
+ d_max_gen = d_start+2;*/
+
//dstream<<"Starting from "<<d_start<<std::endl;
bool sending_something = false;
- for(s16 d = d_start; d <= d_max; d++)
+ bool no_blocks_found_for_sending = true;
+
+ bool queue_is_full = false;
+
+ s16 d;
+ for(d = d_start; d <= d_max; d++)
{
//dstream<<"RemoteClient::SendBlocks(): d="<<d<<std::endl;
@@ -451,7 +482,10 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
// Don't select too many blocks for sending
if(num_blocks_selected >= max_simul_dynamic)
- goto queue_full;
+ {
+ queue_is_full = true;
+ goto queue_full_break;
+ }
// Don't send blocks that are currently being transferred
if(m_blocks_sending.find(p) != NULL)
@@ -513,6 +547,8 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
}
#endif
+ //dstream<<"d="<<d<<std::endl;
+
/*
Don't generate or send if not in sight
*/
@@ -527,7 +563,9 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
*/
{
if(m_blocks_sent.find(p) != NULL)
+ {
continue;
+ }
}
/*
@@ -539,11 +577,14 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
bool block_is_invalid = false;
if(block != NULL)
{
+ // Block is dummy if data doesn't exist.
+ // It means it has been not found from disk and not generated
if(block->isDummy())
{
surely_not_found_on_disk = true;
}
-
+
+ // Block is valid if lighting is up-to-date and data exists
if(block->isValid() == false)
{
block_is_invalid = true;
@@ -564,8 +605,8 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
If block is not close, don't send it unless it is near
ground level.
- Block is not near ground level if night-time mesh
- doesn't differ from day-time mesh.
+ Block is near ground level if night-time mesh
+ differs from day-time mesh.
*/
if(d > 3)
{
@@ -586,14 +627,16 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
}
/*
- Record the lowest d from which a a block has been
+ Record the lowest d from which a block has been
found being not sent and possibly to exist
*/
- if(new_nearest_unsent_d == -1 || d < new_nearest_unsent_d)
+ if(no_blocks_found_for_sending)
{
if(generate == true)
new_nearest_unsent_d = d;
}
+
+ no_blocks_found_for_sending = false;
/*
Add inexistent block to emerge queue.
@@ -633,20 +676,30 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
sending_something = true;
}
}
-queue_full:
+queue_full_break:
- if(new_nearest_unsent_d != -1)
+ //dstream<<"Stopped at "<<d<<std::endl;
+
+ if(no_blocks_found_for_sending)
{
- m_nearest_unsent_d = new_nearest_unsent_d;
+ if(queue_is_full == false)
+ new_nearest_unsent_d = d;
}
+ if(new_nearest_unsent_d != -1)
+ m_nearest_unsent_d = new_nearest_unsent_d;
+
if(sending_something == false)
{
m_nothing_to_send_counter++;
- if(m_nothing_to_send_counter >= 3)
+ if((s16)m_nothing_to_send_counter >=
+ g_settings.getS16("max_block_send_distance"))
{
// Pause time in seconds
- m_nothing_to_send_pause_timer = 2.0;
+ m_nothing_to_send_pause_timer = 1.0;
+ /*dstream<<"nothing to send to "
+ <<server->getPlayerName(peer_id)
+ <<" (d="<<d<<")"<<std::endl;*/
}
}
else
@@ -1130,12 +1183,16 @@ void Server::AsyncRunStep()
dtime = m_step_dtime;
}
- // Send blocks to clients
- SendBlocks(dtime);
+ {
+ ScopeProfiler sp(&g_profiler, "Server: selecting and sending "
+ "blocks to clients");
+ // Send blocks to clients
+ SendBlocks(dtime);
+ }
if(dtime < 0.001)
return;
-
+
//dstream<<"Server steps "<<dtime<<std::endl;
//dstream<<"Server::AsyncRunStep(): dtime="<<dtime<<std::endl;
@@ -1196,12 +1253,14 @@ void Server::AsyncRunStep()
{
// Process connection's timeouts
JMutexAutoLock lock2(m_con_mutex);
+ ScopeProfiler sp(&g_profiler, "Server: connection timeout processing");
m_con.RunTimeouts(dtime);
}
{
// This has to be called so that the client list gets synced
// with the peer list of the connection
+ ScopeProfiler sp(&g_profiler, "Server: peer change handling");
handlePeerChanges();
}
@@ -1209,6 +1268,7 @@ void Server::AsyncRunStep()
// Step environment
// This also runs Map's timers
JMutexAutoLock lock(m_env_mutex);
+ ScopeProfiler sp(&g_profiler, "Server: environment step");
m_env.step(dtime);
}
@@ -1225,7 +1285,9 @@ void Server::AsyncRunStep()
m_liquid_transform_timer -= 1.00;
JMutexAutoLock lock(m_env_mutex);
-
+
+ ScopeProfiler sp(&g_profiler, "Server: liquid transform");
+
core::map<v3s16, MapBlock*> modified_blocks;
m_env.getMap().transformLiquids(modified_blocks);
#if 0
@@ -1298,10 +1360,11 @@ void Server::AsyncRunStep()
*/
{
//dstream<<"Server: Checking added and deleted active objects"<<std::endl;
-
JMutexAutoLock envlock(m_env_mutex);
JMutexAutoLock conlock(m_con_mutex);
-
+
+ ScopeProfiler sp(&g_profiler, "Server: checking added and deleted objects");
+
// Radius inside which objects are active
s16 radius = 32;
@@ -1446,6 +1509,8 @@ void Server::AsyncRunStep()
JMutexAutoLock envlock(m_env_mutex);
JMutexAutoLock conlock(m_con_mutex);
+ ScopeProfiler sp(&g_profiler, "Server: sending object messages");
+
// Key = object id
// Value = data sent by object
core::map<u16, core::list<ActiveObjectMessage>* > buffered_messages;
@@ -1572,6 +1637,11 @@ void Server::AsyncRunStep()
dstream<<"Server: MEET_REMOVENODE"<<std::endl;
sendRemoveNode(event->p, event->already_known_by_peer);
}
+ else if(event->type == MEET_BLOCK_NODE_METADATA_CHANGED)
+ {
+ dstream<<"Server: MEET_BLOCK_NODE_METADATA_CHANGED"<<std::endl;
+ setBlockNotSent(event->p);
+ }
else if(event->type == MEET_OTHER)
{
dstream<<"WARNING: Server: MEET_OTHER not implemented"
@@ -1598,6 +1668,9 @@ void Server::AsyncRunStep()
{
JMutexAutoLock lock1(m_env_mutex);
JMutexAutoLock lock2(m_con_mutex);
+
+ ScopeProfiler sp(&g_profiler, "Server: sending mbo positions");
+
SendObjectData(counter);
counter = 0.0;
@@ -1606,15 +1679,20 @@ void Server::AsyncRunStep()
/*
Step node metadata
+ TODO: Move to ServerEnvironment and utilize active block stuff
*/
- {
+ /*{
//TimeTaker timer("Step node metadata");
JMutexAutoLock envlock(m_env_mutex);
JMutexAutoLock conlock(m_con_mutex);
-
+
+ ScopeProfiler sp(&g_profiler, "Server: stepping node metadata");
+
core::map<v3s16, MapBlock*> changed_blocks;
m_env.getMap().nodeMetadataStep(dtime, changed_blocks);
+
+ // Use setBlockNotSent
for(core::map<v3s16, MapBlock*>::Iterator
i = changed_blocks.getIterator();
@@ -1630,7 +1708,7 @@ void Server::AsyncRunStep()
client->SetBlockNotSent(block->getPos());
}
}
- }
+ }*/
/*
Trigger emergethread (it somehow gets to a non-triggered but
@@ -1655,8 +1733,11 @@ void Server::AsyncRunStep()
{
counter = 0.0;
+ ScopeProfiler sp(&g_profiler, "Server: saving stuff");
+
// Auth stuff
- m_authmanager.save();
+ if(m_authmanager.isModified())
+ m_authmanager.save();
// Map
JMutexAutoLock lock(m_env_mutex);
@@ -1842,7 +1923,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
checkpwd = g_settings.get("default_password");
}
- if(password != checkpwd)
+ if(password != checkpwd && checkpwd != "")
{
derr_server<<DTIME<<"Server: peer_id="<<peer_id
<<": supplied invalid password for "
@@ -3581,6 +3662,17 @@ void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id,
}
}
+void Server::setBlockNotSent(v3s16 p)
+{
+ for(core::map<u16, RemoteClient*>::Iterator
+ i = m_clients.getIterator();
+ i.atEnd()==false; i++)
+ {
+ RemoteClient *client = i.getNode()->getValue();
+ client->SetBlockNotSent(p);
+ }
+}
+
void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver)
{
DSTACK(__FUNCTION_NAME);
@@ -3646,20 +3738,24 @@ void Server::SendBlocks(float dtime)
core::array<PrioritySortedBlockTransfer> queue;
s32 total_sending = 0;
-
- for(core::map<u16, RemoteClient*>::Iterator
- i = m_clients.getIterator();
- i.atEnd() == false; i++)
+
{
- RemoteClient *client = i.getNode()->getValue();
- assert(client->peer_id == i.getNode()->getKey());
+ ScopeProfiler sp(&g_profiler, "Server: selecting blocks for sending");
- total_sending += client->SendingCount();
-
- if(client->serialization_version == SER_FMT_VER_INVALID)
- continue;
-
- client->GetNextBlocks(this, dtime, queue);
+ for(core::map<u16, RemoteClient*>::Iterator
+ i = m_clients.getIterator();
+ i.atEnd() == false; i++)
+ {
+ RemoteClient *client = i.getNode()->getValue();
+ assert(client->peer_id == i.getNode()->getKey());
+
+ total_sending += client->SendingCount();
+
+ if(client->serialization_version == SER_FMT_VER_INVALID)
+ continue;
+
+ client->GetNextBlocks(this, dtime, queue);
+ }
}
// Sort.
@@ -4531,25 +4627,48 @@ void dedicated_server_loop(Server &server, bool &kill)
{
DSTACK(__FUNCTION_NAME);
- std::cout<<DTIME<<std::endl;
- std::cout<<"========================"<<std::endl;
- std::cout<<"Running dedicated server"<<std::endl;
- std::cout<<"========================"<<std::endl;
- std::cout<<std::endl;
+ dstream<<DTIME<<std::endl;
+ dstream<<"========================"<<std::endl;
+ dstream<<"Running dedicated server"<<std::endl;
+ dstream<<"========================"<<std::endl;
+ dstream<<std::endl;
+
+ IntervalLimiter m_profiler_interval;
for(;;)
{
// This is kind of a hack but can be done like this
// because server.step() is very light
- sleep_ms(30);
+ {
+ ScopeProfiler sp(&g_profiler, "dedicated server sleep");
+ sleep_ms(30);
+ }
server.step(0.030);
if(server.getShutdownRequested() || kill)
{
- std::cout<<DTIME<<" dedicated_server_loop(): Quitting."<<std::endl;
+ dstream<<DTIME<<" dedicated_server_loop(): Quitting."<<std::endl;
break;
}
+ /*
+ Profiler
+ */
+ float profiler_print_interval =
+ g_settings.getFloat("profiler_print_interval");
+ if(profiler_print_interval != 0)
+ {
+ if(m_profiler_interval.step(0.030, profiler_print_interval))
+ {
+ dstream<<"Profiler:"<<std::endl;
+ g_profiler.print(dstream);
+ g_profiler.clear();
+ }
+ }
+
+ /*
+ Player info
+ */
static int counter = 0;
counter--;
if(counter <= 0)
@@ -4562,10 +4681,10 @@ void dedicated_server_loop(Server &server, bool &kill)
u32 sum = PIChecksum(list);
if(sum != sum_old)
{
- std::cout<<DTIME<<"Player info:"<<std::endl;
+ dstream<<DTIME<<"Player info:"<<std::endl;
for(i=list.begin(); i!=list.end(); i++)
{
- i->PrintLine(&std::cout);
+ i->PrintLine(&dstream);
}
}
sum_old = sum;
diff --git a/src/server.h b/src/server.h
index 7b73e476c..791ecdec7 100644
--- a/src/server.h
+++ b/src/server.h
@@ -480,15 +480,17 @@ private:
Additionally, if far_players!=NULL, players further away than
far_d_nodes are ignored and their peer_ids are added to far_players
*/
+ // Envlock and conlock should be locked when calling these
void sendRemoveNode(v3s16 p, u16 ignore_id=0,
core::list<u16> *far_players=NULL, float far_d_nodes=100);
void sendAddNode(v3s16 p, MapNode n, u16 ignore_id=0,
core::list<u16> *far_players=NULL, float far_d_nodes=100);
+ void setBlockNotSent(v3s16 p);
// Environment and Connection must be locked when called
void SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver);
- // Sends blocks to clients
+ // Sends blocks to clients (locks env and con on its own)
void SendBlocks(float dtime);
/*
@@ -500,6 +502,15 @@ private:
// When called, connection mutex should be locked
RemoteClient* getClient(u16 peer_id);
+ // When called, environment mutex should be locked
+ std::string getPlayerName(u16 peer_id)
+ {
+ Player *player = m_env.getPlayer(peer_id);
+ if(player == NULL)
+ return "[id="+itos(peer_id);
+ return player->getName();
+ }
+
/*
Get a player from memory or creates one.
If player is already connected, return NULL
@@ -627,6 +638,8 @@ private:
*/
u16 m_ignore_map_edit_events_peer_id;
+ Profiler *m_profiler;
+
friend class EmergeThread;
friend class RemoteClient;
};
diff --git a/src/servercommand.cpp b/src/servercommand.cpp
index e05578b39..333e29084 100644
--- a/src/servercommand.cpp
+++ b/src/servercommand.cpp
@@ -1,24 +1,21 @@
/*
-Minetest-c55
-Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
+Part of Minetest-c55
+Copyright (C) 2010-11 celeron55, Perttu Ahola <celeron55@gmail.com>
Copyright (C) 2011 Ciaran Gultnieks <ciaran@ciarang.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.
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-
#include "servercommand.h"
#include "utility.h"
diff --git a/src/servercommand.h b/src/servercommand.h
index 058fbe65b..9013bc2a6 100644
--- a/src/servercommand.h
+++ b/src/servercommand.h
@@ -1,21 +1,19 @@
/*
-Minetest-c55
-Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
+Part of Minetest-c55
+Copyright (C) 2010-11 celeron55, Perttu Ahola <celeron55@gmail.com>
Copyright (C) 2011 Ciaran Gultnieks <ciaran@ciarang.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.
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef SERVERCOMMAND_HEADER
diff --git a/src/servermain.cpp b/src/servermain.cpp
index f3b17000c..f83e2ae76 100644
--- a/src/servermain.cpp
+++ b/src/servermain.cpp
@@ -79,6 +79,9 @@ Settings g_settings;
extern void set_default_settings();
+// Global profiler
+Profiler g_profiler;
+
// A dummy thing
ITextureSource *g_texturesource = NULL;
diff --git a/src/utility.cpp b/src/utility.cpp
index 186881c5a..0721100cb 100644
--- a/src/utility.cpp
+++ b/src/utility.cpp
@@ -229,10 +229,10 @@ std::string translatePassword(std::string playername, std::wstring password)
if(password.length() == 0)
return "";
- std::string slt=playername + wide_to_narrow(password);
- SHA1 *sha1 = new SHA1();
- sha1->addBytes(slt.c_str(), slt.length());
- unsigned char *digest = sha1->getDigest();
+ std::string slt = playername + wide_to_narrow(password);
+ SHA1 sha1;
+ sha1.addBytes(slt.c_str(), slt.length());
+ unsigned char *digest = sha1.getDigest();
std::string pwd = base64_encode(digest, 20);
free(digest);
return pwd;
diff --git a/src/utility.h b/src/utility.h
index f18d31278..534aea483 100644
--- a/src/utility.h
+++ b/src/utility.h
@@ -244,6 +244,9 @@ inline f32 readF1000(std::istream &is)
{
char buf[2];
is.read(buf, 2);
+ // TODO: verify if this gets rid of the valgrind warning
+ //if(is.gcount() != 2)
+ // return 0;
return readF1000((u8*)buf);
}