mirror of https://github.com/minetest/minetest.git
Merge 2f4f5a31b0
into d767ab0890
This commit is contained in:
commit
a137dc601f
|
@ -47,11 +47,6 @@ gui::IGUIEnvironment *guienv = nullptr;
|
||||||
gui::IGUIStaticText *guiroot = nullptr;
|
gui::IGUIStaticText *guiroot = nullptr;
|
||||||
MainMenuManager g_menumgr;
|
MainMenuManager g_menumgr;
|
||||||
|
|
||||||
bool isMenuActive()
|
|
||||||
{
|
|
||||||
return g_menumgr.menuCount() != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Passed to menus to allow disconnecting and exiting
|
// Passed to menus to allow disconnecting and exiting
|
||||||
MainGameCallback *g_gamecallback = nullptr;
|
MainGameCallback *g_gamecallback = nullptr;
|
||||||
|
|
||||||
|
@ -74,13 +69,20 @@ ClientLauncher::~ClientLauncher()
|
||||||
{
|
{
|
||||||
delete input;
|
delete input;
|
||||||
|
|
||||||
delete receiver;
|
|
||||||
|
|
||||||
delete g_fontengine;
|
delete g_fontengine;
|
||||||
|
g_fontengine = nullptr;
|
||||||
delete g_gamecallback;
|
delete g_gamecallback;
|
||||||
|
g_gamecallback = nullptr;
|
||||||
|
|
||||||
|
guiroot = nullptr;
|
||||||
|
guienv = nullptr;
|
||||||
|
assert(g_menumgr.menuCount() == 0);
|
||||||
|
|
||||||
delete m_rendering_engine;
|
delete m_rendering_engine;
|
||||||
|
|
||||||
|
// delete event receiver only after all Irrlicht stuff is gone
|
||||||
|
delete receiver;
|
||||||
|
|
||||||
#if USE_SOUND
|
#if USE_SOUND
|
||||||
g_sound_manager_singleton.reset();
|
g_sound_manager_singleton.reset();
|
||||||
#endif
|
#endif
|
||||||
|
@ -103,10 +105,8 @@ bool ClientLauncher::run(GameStartData &start_data, const Settings &cmd_args)
|
||||||
g_sound_manager_singleton = createSoundManagerSingleton();
|
g_sound_manager_singleton = createSoundManagerSingleton();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!init_engine()) {
|
if (!init_engine())
|
||||||
errorstream << "Could not initialize game engine." << std::endl;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_rendering_engine->get_video_driver()) {
|
if (!m_rendering_engine->get_video_driver()) {
|
||||||
errorstream << "Could not initialize video driver." << std::endl;
|
errorstream << "Could not initialize video driver." << std::endl;
|
||||||
|
@ -129,7 +129,6 @@ bool ClientLauncher::run(GameStartData &start_data, const Settings &cmd_args)
|
||||||
init_guienv(guienv);
|
init_guienv(guienv);
|
||||||
|
|
||||||
g_fontengine = new FontEngine(guienv);
|
g_fontengine = new FontEngine(guienv);
|
||||||
FATAL_ERROR_IF(!g_fontengine, "Font engine creation failed.");
|
|
||||||
|
|
||||||
// Create the menu clouds
|
// Create the menu clouds
|
||||||
// This is only global so it can be used by RenderingEngine::draw_load_screen().
|
// This is only global so it can be used by RenderingEngine::draw_load_screen().
|
||||||
|
@ -258,6 +257,13 @@ bool ClientLauncher::run(GameStartData &start_data, const Settings &cmd_args)
|
||||||
}
|
}
|
||||||
} // Menu-game loop
|
} // Menu-game loop
|
||||||
|
|
||||||
|
// If profiler was enabled print it one last time
|
||||||
|
if (g_settings->getFloat("profiler_print_interval") > 0) {
|
||||||
|
infostream << "Profiler:" << std::endl;
|
||||||
|
g_profiler->print(infostream);
|
||||||
|
g_profiler->clear();
|
||||||
|
}
|
||||||
|
|
||||||
assert(g_menucloudsmgr->getReferenceCount() == 1);
|
assert(g_menucloudsmgr->getReferenceCount() == 1);
|
||||||
g_menucloudsmgr->drop();
|
g_menucloudsmgr->drop();
|
||||||
g_menucloudsmgr = nullptr;
|
g_menucloudsmgr = nullptr;
|
||||||
|
@ -294,8 +300,12 @@ void ClientLauncher::init_args(GameStartData &start_data, const Settings &cmd_ar
|
||||||
bool ClientLauncher::init_engine()
|
bool ClientLauncher::init_engine()
|
||||||
{
|
{
|
||||||
receiver = new MyEventReceiver();
|
receiver = new MyEventReceiver();
|
||||||
m_rendering_engine = new RenderingEngine(receiver);
|
try {
|
||||||
return m_rendering_engine->get_raw_device() != nullptr;
|
m_rendering_engine = new RenderingEngine(receiver);
|
||||||
|
} catch (std::exception &e) {
|
||||||
|
errorstream << e.what() << std::endl;
|
||||||
|
}
|
||||||
|
return !!m_rendering_engine;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientLauncher::init_input()
|
void ClientLauncher::init_input()
|
||||||
|
|
|
@ -33,6 +33,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "camera.h" // CameraModes
|
#include "camera.h" // CameraModes
|
||||||
#include "collision.h"
|
#include "collision.h"
|
||||||
#include "content_cso.h"
|
#include "content_cso.h"
|
||||||
|
#include "clientobject.h"
|
||||||
#include "environment.h"
|
#include "environment.h"
|
||||||
#include "itemdef.h"
|
#include "itemdef.h"
|
||||||
#include "localplayer.h"
|
#include "localplayer.h"
|
||||||
|
@ -218,14 +219,15 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
// Prototype
|
// Prototype
|
||||||
TestCAO proto_TestCAO(NULL, NULL);
|
static TestCAO proto_TestCAO(nullptr, nullptr);
|
||||||
|
|
||||||
TestCAO::TestCAO(Client *client, ClientEnvironment *env):
|
TestCAO::TestCAO(Client *client, ClientEnvironment *env):
|
||||||
ClientActiveObject(0, client, env),
|
ClientActiveObject(0, client, env),
|
||||||
m_node(NULL),
|
m_node(NULL),
|
||||||
m_position(v3f(0,10*BS,0))
|
m_position(v3f(0,10*BS,0))
|
||||||
{
|
{
|
||||||
ClientActiveObject::registerType(getType(), create);
|
if (!client)
|
||||||
|
ClientActiveObject::registerType(getType(), create);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<ClientActiveObject> TestCAO::create(Client *client, ClientEnvironment *env)
|
std::unique_ptr<ClientActiveObject> TestCAO::create(Client *client, ClientEnvironment *env)
|
||||||
|
@ -322,8 +324,6 @@ void TestCAO::processMessage(const std::string &data)
|
||||||
GenericCAO
|
GenericCAO
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "clientobject.h"
|
|
||||||
|
|
||||||
GenericCAO::GenericCAO(Client *client, ClientEnvironment *env):
|
GenericCAO::GenericCAO(Client *client, ClientEnvironment *env):
|
||||||
ClientActiveObject(0, client, env)
|
ClientActiveObject(0, client, env)
|
||||||
{
|
{
|
||||||
|
@ -2082,4 +2082,4 @@ void GenericCAO::updateMeshCulling()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prototype
|
// Prototype
|
||||||
GenericCAO proto_GenericCAO(NULL, NULL);
|
static GenericCAO proto_GenericCAO(nullptr, nullptr);
|
||||||
|
|
|
@ -27,16 +27,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "irrlicht_changes/CGUITTFont.h"
|
#include "irrlicht_changes/CGUITTFont.h"
|
||||||
#include "util/numeric.h" // rangelim
|
#include "util/numeric.h" // rangelim
|
||||||
|
|
||||||
/** maximum size distance for getting a "similar" font size */
|
|
||||||
#define MAX_FONT_SIZE_OFFSET 10
|
|
||||||
|
|
||||||
/** reference to access font engine, has to be initialized by main */
|
/** reference to access font engine, has to be initialized by main */
|
||||||
FontEngine* g_fontengine = NULL;
|
FontEngine *g_fontengine = nullptr;
|
||||||
|
|
||||||
/** callback to be used on change of font size setting */
|
/** callback to be used on change of font size setting */
|
||||||
static void font_setting_changed(const std::string &name, void *userdata)
|
static void font_setting_changed(const std::string &name, void *userdata)
|
||||||
{
|
{
|
||||||
g_fontengine->readSettings();
|
if (g_fontengine)
|
||||||
|
g_fontengine->readSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -226,7 +224,7 @@ gui::IGUIFont *FontEngine::initFont(const FontSpec &spec)
|
||||||
u16 divisible_by = g_settings->getU16(setting_prefix + "font_size_divisible_by");
|
u16 divisible_by = g_settings->getU16(setting_prefix + "font_size_divisible_by");
|
||||||
if (divisible_by > 1) {
|
if (divisible_by > 1) {
|
||||||
size = std::max<u32>(
|
size = std::max<u32>(
|
||||||
std::round((double)size / divisible_by) * divisible_by, divisible_by);
|
std::round((float)size / divisible_by) * divisible_by, divisible_by);
|
||||||
}
|
}
|
||||||
|
|
||||||
sanity_check(size != 0);
|
sanity_check(size != 0);
|
||||||
|
|
|
@ -1132,9 +1132,11 @@ void Game::run()
|
||||||
FpsControl draw_times;
|
FpsControl draw_times;
|
||||||
f32 dtime; // in seconds
|
f32 dtime; // in seconds
|
||||||
|
|
||||||
/* Clear the profiler */
|
// Clear the profiler
|
||||||
Profiler::GraphValues dummyvalues;
|
{
|
||||||
g_profiler->graphGet(dummyvalues);
|
Profiler::GraphValues dummyvalues;
|
||||||
|
g_profiler->graphPop(dummyvalues);
|
||||||
|
}
|
||||||
|
|
||||||
draw_times.reset();
|
draw_times.reset();
|
||||||
|
|
||||||
|
@ -1902,7 +1904,8 @@ void Game::updateProfilers(const RunStats &stats, const FpsControl &draw_times,
|
||||||
g_settings->getFloat("profiler_print_interval");
|
g_settings->getFloat("profiler_print_interval");
|
||||||
bool print_to_log = true;
|
bool print_to_log = true;
|
||||||
|
|
||||||
if (profiler_print_interval == 0) {
|
// Update game UI anyway but don't log
|
||||||
|
if (profiler_print_interval <= 0) {
|
||||||
print_to_log = false;
|
print_to_log = false;
|
||||||
profiler_print_interval = 3;
|
profiler_print_interval = 3;
|
||||||
}
|
}
|
||||||
|
@ -1917,12 +1920,12 @@ void Game::updateProfilers(const RunStats &stats, const FpsControl &draw_times,
|
||||||
g_profiler->clear();
|
g_profiler->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update update graphs
|
// Update graphs
|
||||||
g_profiler->graphAdd("Time non-rendering [us]",
|
g_profiler->graphAdd("Time non-rendering [us]",
|
||||||
draw_times.busy_time - stats.drawtime);
|
draw_times.busy_time - stats.drawtime);
|
||||||
|
|
||||||
g_profiler->graphAdd("Sleep [us]", draw_times.sleep_time);
|
g_profiler->graphAdd("Sleep [us]", draw_times.sleep_time);
|
||||||
g_profiler->graphAdd("FPS", 1.0f / dtime);
|
|
||||||
|
g_profiler->graphSet("FPS", 1.0f / dtime);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::updateStats(RunStats *stats, const FpsControl &draw_times,
|
void Game::updateStats(RunStats *stats, const FpsControl &draw_times,
|
||||||
|
@ -4229,7 +4232,7 @@ void Game::updateClouds(float dtime)
|
||||||
inline void Game::updateProfilerGraphs(ProfilerGraph *graph)
|
inline void Game::updateProfilerGraphs(ProfilerGraph *graph)
|
||||||
{
|
{
|
||||||
Profiler::GraphValues values;
|
Profiler::GraphValues values;
|
||||||
g_profiler->graphGet(values);
|
g_profiler->graphPop(values);
|
||||||
graph->put(values);
|
graph->put(values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,12 +29,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
* converting textures back into images repeatedly, and some don't even
|
* converting textures back into images repeatedly, and some don't even
|
||||||
* allow it at all.
|
* allow it at all.
|
||||||
*/
|
*/
|
||||||
std::map<io::path, video::IImage *> g_imgCache;
|
static std::map<io::path, video::IImage *> g_imgCache;
|
||||||
|
|
||||||
/* Maintain a static cache of all pre-scaled textures. These need to be
|
/* Maintain a static cache of all pre-scaled textures. These need to be
|
||||||
* cleared as well when the cached images.
|
* cleared as well when the cached images.
|
||||||
*/
|
*/
|
||||||
std::map<io::path, video::ITexture *> g_txrCache;
|
static std::map<io::path, video::ITexture *> g_txrCache;
|
||||||
|
|
||||||
/* Manually insert an image into the cache, useful to avoid texture-to-image
|
/* Manually insert an image into the cache, useful to avoid texture-to-image
|
||||||
* conversion whenever we can intercept it.
|
* conversion whenever we can intercept it.
|
||||||
|
|
|
@ -355,12 +355,11 @@ const KeyPress CancelKey("KEY_CANCEL");
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// A simple cache for quicker lookup
|
// A simple cache for quicker lookup
|
||||||
std::unordered_map<std::string, KeyPress> g_key_setting_cache;
|
static std::unordered_map<std::string, KeyPress> g_key_setting_cache;
|
||||||
|
|
||||||
KeyPress getKeySetting(const char *settingname)
|
KeyPress getKeySetting(const char *settingname)
|
||||||
{
|
{
|
||||||
std::unordered_map<std::string, KeyPress>::iterator n;
|
auto n = g_key_setting_cache.find(settingname);
|
||||||
n = g_key_setting_cache.find(settingname);
|
|
||||||
if (n != g_key_setting_cache.end())
|
if (n != g_key_setting_cache.end())
|
||||||
return n->second;
|
return n->second;
|
||||||
|
|
||||||
|
|
|
@ -253,8 +253,11 @@ RenderingEngine::RenderingEngine(IEventReceiver *receiver)
|
||||||
|
|
||||||
RenderingEngine::~RenderingEngine()
|
RenderingEngine::~RenderingEngine()
|
||||||
{
|
{
|
||||||
|
sanity_check(s_singleton == this);
|
||||||
|
|
||||||
core.reset();
|
core.reset();
|
||||||
m_device->closeDevice();
|
m_device->closeDevice();
|
||||||
|
m_device->drop();
|
||||||
s_singleton = nullptr;
|
s_singleton = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,10 +281,7 @@ void RenderingEngine::removeMesh(const scene::IMesh* mesh)
|
||||||
void RenderingEngine::cleanupMeshCache()
|
void RenderingEngine::cleanupMeshCache()
|
||||||
{
|
{
|
||||||
auto mesh_cache = m_device->getSceneManager()->getMeshCache();
|
auto mesh_cache = m_device->getSceneManager()->getMeshCache();
|
||||||
while (mesh_cache->getMeshCount() != 0) {
|
mesh_cache->clear();
|
||||||
if (scene::IAnimatedMesh *mesh = mesh_cache->getMeshByIndex(0))
|
|
||||||
mesh_cache->removeMesh(mesh);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RenderingEngine::setupTopLevelWindow()
|
bool RenderingEngine::setupTopLevelWindow()
|
||||||
|
|
|
@ -46,7 +46,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
/*
|
/*
|
||||||
A cache from shader name to shader path
|
A cache from shader name to shader path
|
||||||
*/
|
*/
|
||||||
MutexedMap<std::string, std::string> g_shadername_to_path_cache;
|
static MutexedMap<std::string, std::string> g_shadername_to_path_cache;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Gets the path to a shader by first checking if the file
|
Gets the path to a shader by first checking if the file
|
||||||
|
|
|
@ -191,7 +191,7 @@ private:
|
||||||
scene::IMesh *m_cube;
|
scene::IMesh *m_cube;
|
||||||
};
|
};
|
||||||
|
|
||||||
ExtrusionMeshCache *g_extrusion_mesh_cache = NULL;
|
static ExtrusionMeshCache *g_extrusion_mesh_cache = nullptr;
|
||||||
|
|
||||||
|
|
||||||
WieldMeshSceneNode::WieldMeshSceneNode(scene::ISceneManager *mgr, s32 id, bool lighting):
|
WieldMeshSceneNode::WieldMeshSceneNode(scene::ISceneManager *mgr, s32 id, bool lighting):
|
||||||
|
|
|
@ -70,7 +70,7 @@ enum EmergeAction {
|
||||||
EMERGE_GENERATED,
|
EMERGE_GENERATED,
|
||||||
};
|
};
|
||||||
|
|
||||||
const static std::string emergeActionStrs[] = {
|
constexpr const char *emergeActionStrs[] = {
|
||||||
"cancelled",
|
"cancelled",
|
||||||
"errored",
|
"errored",
|
||||||
"from_memory",
|
"from_memory",
|
||||||
|
|
|
@ -26,10 +26,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
class BaseException : public std::exception
|
class BaseException : public std::exception
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BaseException(const std::string &s) throw(): m_s(s) {}
|
BaseException(const std::string &s) noexcept: m_s(s) {}
|
||||||
~BaseException() throw() = default;
|
~BaseException() throw() = default;
|
||||||
|
|
||||||
virtual const char * what() const throw()
|
virtual const char * what() const noexcept
|
||||||
{
|
{
|
||||||
return m_s.c_str();
|
return m_s.c_str();
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,14 +23,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
enum TimePrecision
|
|
||||||
{
|
|
||||||
PRECISION_SECONDS,
|
|
||||||
PRECISION_MILLI,
|
|
||||||
PRECISION_MICRO,
|
|
||||||
PRECISION_NANO
|
|
||||||
};
|
|
||||||
|
|
||||||
inline struct tm mt_localtime()
|
inline struct tm mt_localtime()
|
||||||
{
|
{
|
||||||
// initialize the time zone on first invocation
|
// initialize the time zone on first invocation
|
||||||
|
|
|
@ -80,7 +80,7 @@ public:
|
||||||
return mm && mm->preprocessEvent(event);
|
return mm && mm->preprocessEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 menuCount()
|
size_t menuCount() const
|
||||||
{
|
{
|
||||||
return m_stack.size();
|
return m_stack.size();
|
||||||
}
|
}
|
||||||
|
@ -95,12 +95,16 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: why isn't this private?
|
||||||
std::list<gui::IGUIElement*> m_stack;
|
std::list<gui::IGUIElement*> m_stack;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern MainMenuManager g_menumgr;
|
extern MainMenuManager g_menumgr;
|
||||||
|
|
||||||
extern bool isMenuActive();
|
static inline bool isMenuActive()
|
||||||
|
{
|
||||||
|
return g_menumgr.menuCount() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
class MainGameCallback : public IGameCallback
|
class MainGameCallback : public IGameCallback
|
||||||
{
|
{
|
||||||
|
@ -138,7 +142,8 @@ public:
|
||||||
keyconfig_changed = true;
|
keyconfig_changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void showOpenURLDialog(const std::string &url) override {
|
void showOpenURLDialog(const std::string &url) override
|
||||||
|
{
|
||||||
show_open_url_dialog = url;
|
show_open_url_dialog = url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -215,21 +215,22 @@ void MapBlock::expireIsAirCache()
|
||||||
|
|
||||||
// List relevant id-name pairs for ids in the block using nodedef
|
// List relevant id-name pairs for ids in the block using nodedef
|
||||||
// Renumbers the content IDs (starting at 0 and incrementing)
|
// Renumbers the content IDs (starting at 0 and incrementing)
|
||||||
|
// Note that there's no technical reason why we *have to* renumber the IDs,
|
||||||
|
// but we do it anyway as it also helps compressability.
|
||||||
static void getBlockNodeIdMapping(NameIdMapping *nimap, MapNode *nodes,
|
static void getBlockNodeIdMapping(NameIdMapping *nimap, MapNode *nodes,
|
||||||
const NodeDefManager *nodedef)
|
const NodeDefManager *nodedef)
|
||||||
{
|
{
|
||||||
// The static memory requires about 65535 * sizeof(int) RAM in order to be
|
// The static memory requires about 65535 * 2 bytes RAM in order to be
|
||||||
// sure we can handle all content ids. But it's absolutely worth it as it's
|
// sure we can handle all content ids. But it's absolutely worth it as it's
|
||||||
// a speedup of 4 for one of the major time consuming functions on storing
|
// a speedup of 4 for one of the major time consuming functions on storing
|
||||||
// mapblocks.
|
// mapblocks.
|
||||||
thread_local std::unique_ptr<content_t[]> mapping;
|
thread_local std::unique_ptr<content_t[]> mapping;
|
||||||
static_assert(sizeof(content_t) == 2, "content_t must be 16-bit");
|
static_assert(sizeof(content_t) == 2, "content_t must be 16-bit");
|
||||||
if (!mapping)
|
if (!mapping)
|
||||||
mapping = std::make_unique<content_t[]>(USHRT_MAX + 1);
|
mapping = std::make_unique<content_t[]>(CONTENT_MAX + 1);
|
||||||
|
|
||||||
memset(mapping.get(), 0xFF, (USHRT_MAX + 1) * sizeof(content_t));
|
memset(mapping.get(), 0xFF, (CONTENT_MAX + 1) * sizeof(content_t));
|
||||||
|
|
||||||
std::unordered_set<content_t> unknown_contents;
|
|
||||||
content_t id_counter = 0;
|
content_t id_counter = 0;
|
||||||
for (u32 i = 0; i < MapBlock::nodecount; i++) {
|
for (u32 i = 0; i < MapBlock::nodecount; i++) {
|
||||||
content_t global_id = nodes[i].getContent();
|
content_t global_id = nodes[i].getContent();
|
||||||
|
@ -243,21 +244,13 @@ static void getBlockNodeIdMapping(NameIdMapping *nimap, MapNode *nodes,
|
||||||
id = id_counter++;
|
id = id_counter++;
|
||||||
mapping[global_id] = id;
|
mapping[global_id] = id;
|
||||||
|
|
||||||
const ContentFeatures &f = nodedef->get(global_id);
|
const auto &name = nodedef->get(global_id).name;
|
||||||
const std::string &name = f.name;
|
nimap->set(id, name);
|
||||||
if (name.empty())
|
|
||||||
unknown_contents.insert(global_id);
|
|
||||||
else
|
|
||||||
nimap->set(id, name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the MapNode
|
// Update the MapNode
|
||||||
nodes[i].setContent(id);
|
nodes[i].setContent(id);
|
||||||
}
|
}
|
||||||
for (u16 unknown_content : unknown_contents) {
|
|
||||||
errorstream << "getBlockNodeIdMapping(): IGNORING ERROR: "
|
|
||||||
<< "Name for node id " << unknown_content << " not known" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Correct ids in the block to match nodedef based on names.
|
// Correct ids in the block to match nodedef based on names.
|
||||||
|
|
|
@ -708,15 +708,17 @@ Buffer<u8> MapNode::serializeBulk(int version,
|
||||||
|
|
||||||
Buffer<u8> databuf(nodecount * (content_width + params_width));
|
Buffer<u8> databuf(nodecount * (content_width + params_width));
|
||||||
|
|
||||||
u32 start1 = content_width * nodecount;
|
// Writing to the buffer linearly is faster
|
||||||
u32 start2 = (content_width + 1) * nodecount;
|
u8 *p = &databuf[0];
|
||||||
|
for (u32 i = 0; i < nodecount; i++, p += 2)
|
||||||
|
writeU16(p, nodes[i].param0);
|
||||||
|
|
||||||
|
for (u32 i = 0; i < nodecount; i++, p++)
|
||||||
|
writeU8(p, nodes[i].param1);
|
||||||
|
|
||||||
|
for (u32 i = 0; i < nodecount; i++, p++)
|
||||||
|
writeU8(p, nodes[i].param2);
|
||||||
|
|
||||||
// Serialize content
|
|
||||||
for (u32 i = 0; i < nodecount; i++) {
|
|
||||||
writeU16(&databuf[i * 2], nodes[i].param0);
|
|
||||||
writeU8(&databuf[start1 + i], nodes[i].param1);
|
|
||||||
writeU8(&databuf[start2 + i], nodes[i].param2);
|
|
||||||
}
|
|
||||||
return databuf;
|
return databuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,8 +21,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <set>
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <cassert>
|
||||||
#include "irrlichttypes_bloated.h"
|
#include "irrlichttypes_bloated.h"
|
||||||
|
|
||||||
typedef std::unordered_map<u16, std::string> IdToNameMap;
|
typedef std::unordered_map<u16, std::string> IdToNameMap;
|
||||||
|
@ -42,6 +42,7 @@ public:
|
||||||
|
|
||||||
void set(u16 id, const std::string &name)
|
void set(u16 id, const std::string &name)
|
||||||
{
|
{
|
||||||
|
assert(!name.empty());
|
||||||
m_id_to_name[id] = name;
|
m_id_to_name[id] = name;
|
||||||
m_name_to_id[name] = id;
|
m_name_to_id[name] = id;
|
||||||
}
|
}
|
||||||
|
@ -67,8 +68,7 @@ public:
|
||||||
}
|
}
|
||||||
bool getName(u16 id, std::string &result) const
|
bool getName(u16 id, std::string &result) const
|
||||||
{
|
{
|
||||||
IdToNameMap::const_iterator i;
|
auto i = m_id_to_name.find(id);
|
||||||
i = m_id_to_name.find(id);
|
|
||||||
if (i == m_id_to_name.end())
|
if (i == m_id_to_name.end())
|
||||||
return false;
|
return false;
|
||||||
result = i->second;
|
result = i->second;
|
||||||
|
@ -76,8 +76,7 @@ public:
|
||||||
}
|
}
|
||||||
bool getId(const std::string &name, u16 &result) const
|
bool getId(const std::string &name, u16 &result) const
|
||||||
{
|
{
|
||||||
NameToIdMap::const_iterator i;
|
auto i = m_name_to_id.find(name);
|
||||||
i = m_name_to_id.find(name);
|
|
||||||
if (i == m_name_to_id.end())
|
if (i == m_name_to_id.end())
|
||||||
return false;
|
return false;
|
||||||
result = i->second;
|
result = i->second;
|
||||||
|
|
|
@ -1098,7 +1098,7 @@ enum NetProtoCompressionMode {
|
||||||
NETPROTO_COMPRESSION_NONE = 0,
|
NETPROTO_COMPRESSION_NONE = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
const static std::string accessDeniedStrings[SERVER_ACCESSDENIED_MAX] = {
|
constexpr const char *accessDeniedStrings[SERVER_ACCESSDENIED_MAX] = {
|
||||||
"Invalid password",
|
"Invalid password",
|
||||||
"Your client sent something the server didn't expect. Try reconnecting or updating your client.",
|
"Your client sent something the server didn't expect. Try reconnecting or updating your client.",
|
||||||
"The server is running in simple singleplayer mode. You cannot connect.",
|
"The server is running in simple singleplayer mode. You cannot connect.",
|
||||||
|
|
|
@ -33,7 +33,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "irrlichttypes.h" // u64
|
#include "irrlichttypes.h" // u64
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "gettime.h"
|
#include "util/timetaker.h" // TimePrecision
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#define SWPRINTF_CHARSTRING L"%S"
|
#define SWPRINTF_CHARSTRING L"%S"
|
||||||
|
|
145
src/profiler.cpp
145
src/profiler.cpp
|
@ -22,40 +22,37 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
|
||||||
static Profiler main_profiler;
|
static Profiler main_profiler;
|
||||||
Profiler *g_profiler = &main_profiler;
|
Profiler *g_profiler = &main_profiler;
|
||||||
ScopeProfiler::ScopeProfiler(
|
|
||||||
Profiler *profiler, const std::string &name, ScopeProfilerType type) :
|
ScopeProfiler::ScopeProfiler(Profiler *profiler, const std::string &name,
|
||||||
m_profiler(profiler),
|
ScopeProfilerType type, TimePrecision prec) :
|
||||||
m_name(name), m_type(type)
|
m_profiler(profiler),
|
||||||
|
m_name(name), m_type(type), m_precision(prec)
|
||||||
{
|
{
|
||||||
m_name.append(" [ms]");
|
m_name.append(" [").append(TimePrecision_units[prec]).append("]");
|
||||||
if (m_profiler)
|
m_time1 = porting::getTime(prec);
|
||||||
m_timer = new TimeTaker(m_name, nullptr, PRECISION_MILLI);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ScopeProfiler::~ScopeProfiler()
|
ScopeProfiler::~ScopeProfiler()
|
||||||
{
|
{
|
||||||
if (!m_timer)
|
if (!m_profiler)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
float duration_ms = m_timer->stop(true);
|
float duration = porting::getTime(m_precision) - m_time1;
|
||||||
float duration = duration_ms;
|
|
||||||
if (m_profiler) {
|
switch (m_type) {
|
||||||
switch (m_type) {
|
case SPT_ADD:
|
||||||
case SPT_ADD:
|
m_profiler->add(m_name, duration);
|
||||||
m_profiler->add(m_name, duration);
|
break;
|
||||||
break;
|
case SPT_AVG:
|
||||||
case SPT_AVG:
|
m_profiler->avg(m_name, duration);
|
||||||
m_profiler->avg(m_name, duration);
|
break;
|
||||||
break;
|
case SPT_GRAPH_ADD:
|
||||||
case SPT_GRAPH_ADD:
|
m_profiler->graphAdd(m_name, duration);
|
||||||
m_profiler->graphAdd(m_name, duration);
|
break;
|
||||||
break;
|
case SPT_MAX:
|
||||||
case SPT_MAX:
|
m_profiler->max(m_name, duration);
|
||||||
m_profiler->max(m_name, duration);
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
delete m_timer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Profiler::Profiler()
|
Profiler::Profiler()
|
||||||
|
@ -66,92 +63,68 @@ Profiler::Profiler()
|
||||||
void Profiler::add(const std::string &name, float value)
|
void Profiler::add(const std::string &name, float value)
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(m_mutex);
|
MutexAutoLock lock(m_mutex);
|
||||||
{
|
|
||||||
/* No average shall have been used; mark add/max used as -2 */
|
auto it = m_data.find(name);
|
||||||
std::map<std::string, int>::iterator n = m_avgcounts.find(name);
|
if (it == m_data.end()) {
|
||||||
if (n == m_avgcounts.end()) {
|
// mark with special value for checking
|
||||||
m_avgcounts[name] = -2;
|
m_data.emplace(name, DataPair{value, -SPT_ADD});
|
||||||
} else {
|
} else {
|
||||||
if (n->second == -1)
|
assert(it->second.avgcount == -SPT_ADD);
|
||||||
n->second = -2;
|
it->second.value += value;
|
||||||
assert(n->second == -2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{
|
|
||||||
std::map<std::string, float>::iterator n = m_data.find(name);
|
|
||||||
if (n == m_data.end())
|
|
||||||
m_data[name] = value;
|
|
||||||
else
|
|
||||||
n->second += value;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Profiler::max(const std::string &name, float value)
|
void Profiler::max(const std::string &name, float value)
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(m_mutex);
|
MutexAutoLock lock(m_mutex);
|
||||||
{
|
|
||||||
/* No average shall have been used; mark add/max used as -2 */
|
auto it = m_data.find(name);
|
||||||
auto n = m_avgcounts.find(name);
|
if (it == m_data.end()) {
|
||||||
if (n == m_avgcounts.end()) {
|
// mark with special value for checking
|
||||||
m_avgcounts[name] = -2;
|
m_data.emplace(name, DataPair{value, -SPT_MAX});
|
||||||
} else {
|
} else {
|
||||||
if (n->second == -1)
|
assert(it->second.avgcount == -SPT_MAX);
|
||||||
n->second = -2;
|
it->second.value = std::max(value, it->second.value);
|
||||||
assert(n->second == -2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto n = m_data.find(name);
|
|
||||||
if (n == m_data.end())
|
|
||||||
m_data[name] = value;
|
|
||||||
else if (value > n->second)
|
|
||||||
n->second = value;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Profiler::avg(const std::string &name, float value)
|
void Profiler::avg(const std::string &name, float value)
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(m_mutex);
|
MutexAutoLock lock(m_mutex);
|
||||||
int &count = m_avgcounts[name];
|
|
||||||
|
|
||||||
assert(count != -2);
|
auto it = m_data.find(name);
|
||||||
count = MYMAX(count, 0) + 1;
|
if (it == m_data.end()) {
|
||||||
m_data[name] += value;
|
m_data.emplace(name, DataPair{value, 1});
|
||||||
|
} else {
|
||||||
|
assert(it->second.avgcount >= 1);
|
||||||
|
it->second.value += value;
|
||||||
|
it->second.avgcount++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Profiler::clear()
|
void Profiler::clear()
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(m_mutex);
|
MutexAutoLock lock(m_mutex);
|
||||||
for (auto &it : m_data) {
|
for (auto &it : m_data)
|
||||||
it.second = 0;
|
it.second = DataPair();
|
||||||
}
|
|
||||||
m_avgcounts.clear();
|
|
||||||
m_start_time = porting::getTimeMs();
|
m_start_time = porting::getTimeMs();
|
||||||
}
|
}
|
||||||
|
|
||||||
float Profiler::getValue(const std::string &name) const
|
float Profiler::getValue(const std::string &name) const
|
||||||
{
|
{
|
||||||
auto numerator = m_data.find(name);
|
auto it = m_data.find(name);
|
||||||
if (numerator == m_data.end())
|
if (it == m_data.end())
|
||||||
return 0.f;
|
return 0;
|
||||||
|
return it->second.getValue();
|
||||||
auto denominator = m_avgcounts.find(name);
|
|
||||||
if (denominator != m_avgcounts.end()) {
|
|
||||||
if (denominator->second >= 1)
|
|
||||||
return numerator->second / denominator->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
return numerator->second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Profiler::getAvgCount(const std::string &name) const
|
int Profiler::getAvgCount(const std::string &name) const
|
||||||
{
|
{
|
||||||
auto n = m_avgcounts.find(name);
|
auto it = m_data.find(name);
|
||||||
|
if (it == m_data.end())
|
||||||
if (n != m_avgcounts.end() && n->second >= 1)
|
return 1;
|
||||||
return n->second;
|
int denominator = it->second.avgcount;
|
||||||
|
return denominator >= 1 ? denominator : 1;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 Profiler::getElapsedMs() const
|
u64 Profiler::getElapsedMs() const
|
||||||
|
@ -204,6 +177,6 @@ void Profiler::getPage(GraphValues &o, u32 page, u32 pagecount)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
o[i.first] = i.second / getAvgCount(i.first);
|
o[i.first] = i.second.getValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,54 +58,71 @@ public:
|
||||||
void getPage(GraphValues &o, u32 page, u32 pagecount);
|
void getPage(GraphValues &o, u32 page, u32 pagecount);
|
||||||
|
|
||||||
|
|
||||||
|
void graphSet(const std::string &id, float value)
|
||||||
|
{
|
||||||
|
MutexAutoLock lock(m_mutex);
|
||||||
|
m_graphvalues[id] = value;
|
||||||
|
}
|
||||||
void graphAdd(const std::string &id, float value)
|
void graphAdd(const std::string &id, float value)
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(m_mutex);
|
MutexAutoLock lock(m_mutex);
|
||||||
std::map<std::string, float>::iterator i =
|
auto it = m_graphvalues.find(id);
|
||||||
m_graphvalues.find(id);
|
if (it == m_graphvalues.end())
|
||||||
if(i == m_graphvalues.end())
|
m_graphvalues.emplace(id, value);
|
||||||
m_graphvalues[id] = value;
|
|
||||||
else
|
else
|
||||||
i->second += value;
|
it->second += value;
|
||||||
}
|
}
|
||||||
void graphGet(GraphValues &result)
|
void graphPop(GraphValues &result)
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(m_mutex);
|
MutexAutoLock lock(m_mutex);
|
||||||
result = m_graphvalues;
|
assert(result.empty());
|
||||||
m_graphvalues.clear();
|
std::swap(result, m_graphvalues);
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove(const std::string& name)
|
void remove(const std::string& name)
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(m_mutex);
|
MutexAutoLock lock(m_mutex);
|
||||||
m_avgcounts.erase(name);
|
|
||||||
m_data.erase(name);
|
m_data.erase(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct DataPair {
|
||||||
|
float value = 0;
|
||||||
|
int avgcount = 0;
|
||||||
|
|
||||||
|
inline float getValue() const {
|
||||||
|
return avgcount >= 1 ? (value / avgcount) : value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
std::mutex m_mutex;
|
std::mutex m_mutex;
|
||||||
std::map<std::string, float> m_data;
|
std::map<std::string, DataPair> m_data;
|
||||||
std::map<std::string, int> m_avgcounts;
|
|
||||||
std::map<std::string, float> m_graphvalues;
|
std::map<std::string, float> m_graphvalues;
|
||||||
u64 m_start_time;
|
u64 m_start_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ScopeProfilerType{
|
enum ScopeProfilerType : u8
|
||||||
SPT_ADD,
|
{
|
||||||
|
SPT_ADD = 1,
|
||||||
SPT_AVG,
|
SPT_AVG,
|
||||||
SPT_GRAPH_ADD,
|
SPT_GRAPH_ADD,
|
||||||
SPT_MAX
|
SPT_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Note: this class should be kept lightweight.
|
||||||
|
|
||||||
class ScopeProfiler
|
class ScopeProfiler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ScopeProfiler(Profiler *profiler, const std::string &name,
|
ScopeProfiler(Profiler *profiler, const std::string &name,
|
||||||
ScopeProfilerType type = SPT_ADD);
|
ScopeProfilerType type = SPT_ADD,
|
||||||
|
TimePrecision precision = PRECISION_MILLI);
|
||||||
~ScopeProfiler();
|
~ScopeProfiler();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Profiler *m_profiler = nullptr;
|
Profiler *m_profiler = nullptr;
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
TimeTaker *m_timer = nullptr;
|
u64 m_time1;
|
||||||
enum ScopeProfilerType m_type;
|
ScopeProfilerType m_type;
|
||||||
|
TimePrecision m_precision;
|
||||||
};
|
};
|
||||||
|
|
|
@ -4096,10 +4096,9 @@ void dedicated_server_loop(Server &server, bool &kill)
|
||||||
/*
|
/*
|
||||||
Profiler
|
Profiler
|
||||||
*/
|
*/
|
||||||
if (profiler_print_interval != 0) {
|
if (profiler_print_interval > 0) {
|
||||||
if(m_profiler_interval.step(steplen, profiler_print_interval))
|
if (m_profiler_interval.step(steplen, profiler_print_interval)) {
|
||||||
{
|
infostream << "Profiler:" << std::endl;
|
||||||
infostream<<"Profiler:"<<std::endl;
|
|
||||||
g_profiler->print(infostream);
|
g_profiler->print(infostream);
|
||||||
g_profiler->clear();
|
g_profiler->clear();
|
||||||
}
|
}
|
||||||
|
@ -4112,6 +4111,12 @@ void dedicated_server_loop(Server &server, bool &kill)
|
||||||
ServerList::sendAnnounce(ServerList::AA_DELETE,
|
ServerList::sendAnnounce(ServerList::AA_DELETE,
|
||||||
server.m_bind_addr.getPort());
|
server.m_bind_addr.getPort());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (profiler_print_interval > 0) {
|
||||||
|
infostream << "Profiler:" << std::endl;
|
||||||
|
g_profiler->print(infostream);
|
||||||
|
g_profiler->clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -115,7 +115,7 @@ static TestAuthDatabase g_test_instance;
|
||||||
void TestAuthDatabase::runTests(IGameDef *gamedef)
|
void TestAuthDatabase::runTests(IGameDef *gamedef)
|
||||||
{
|
{
|
||||||
// fixed directory, for persistence
|
// fixed directory, for persistence
|
||||||
thread_local const std::string test_dir = getTestTempDirectory();
|
const std::string test_dir = getTestTempDirectory();
|
||||||
|
|
||||||
// Each set of tests is run twice for each database type:
|
// Each set of tests is run twice for each database type:
|
||||||
// one where we reuse the same AuthDatabase object (to test local caching),
|
// one where we reuse the same AuthDatabase object (to test local caching),
|
||||||
|
|
|
@ -36,7 +36,7 @@ public:
|
||||||
void testFlagDesc();
|
void testFlagDesc();
|
||||||
|
|
||||||
static const char *config_text_before;
|
static const char *config_text_before;
|
||||||
static const std::string config_text_after;
|
static const char *config_text_after;
|
||||||
};
|
};
|
||||||
|
|
||||||
static TestSettings g_test_instance;
|
static TestSettings g_test_instance;
|
||||||
|
@ -76,7 +76,7 @@ const char *TestSettings::config_text_before =
|
||||||
"zoop = true\n"
|
"zoop = true\n"
|
||||||
"[dummy_eof_end_tag]\n";
|
"[dummy_eof_end_tag]\n";
|
||||||
|
|
||||||
const std::string TestSettings::config_text_after =
|
const char *TestSettings::config_text_after =
|
||||||
u8"leet = 1337\n"
|
u8"leet = 1337\n"
|
||||||
"leetleet = 13371337\n"
|
"leetleet = 13371337\n"
|
||||||
"leetleet_neg = -13371337\n"
|
"leetleet_neg = -13371337\n"
|
||||||
|
|
|
@ -31,6 +31,7 @@ std::string QuicktuneValue::getString()
|
||||||
}
|
}
|
||||||
return "<invalid type>";
|
return "<invalid type>";
|
||||||
}
|
}
|
||||||
|
|
||||||
void QuicktuneValue::relativeAdd(float amount)
|
void QuicktuneValue::relativeAdd(float amount)
|
||||||
{
|
{
|
||||||
switch(type){
|
switch(type){
|
||||||
|
@ -48,24 +49,16 @@ void QuicktuneValue::relativeAdd(float amount)
|
||||||
|
|
||||||
static std::map<std::string, QuicktuneValue> g_values;
|
static std::map<std::string, QuicktuneValue> g_values;
|
||||||
static std::vector<std::string> g_names;
|
static std::vector<std::string> g_names;
|
||||||
std::mutex *g_mutex = NULL;
|
static std::mutex g_mutex;
|
||||||
|
|
||||||
static void makeMutex()
|
const std::vector<std::string> &getQuicktuneNames()
|
||||||
{
|
|
||||||
if(!g_mutex){
|
|
||||||
g_mutex = new std::mutex();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string> getQuicktuneNames()
|
|
||||||
{
|
{
|
||||||
return g_names;
|
return g_names;
|
||||||
}
|
}
|
||||||
|
|
||||||
QuicktuneValue getQuicktuneValue(const std::string &name)
|
QuicktuneValue getQuicktuneValue(const std::string &name)
|
||||||
{
|
{
|
||||||
makeMutex();
|
MutexAutoLock lock(g_mutex);
|
||||||
MutexAutoLock lock(*g_mutex);
|
|
||||||
std::map<std::string, QuicktuneValue>::iterator i = g_values.find(name);
|
std::map<std::string, QuicktuneValue>::iterator i = g_values.find(name);
|
||||||
if(i == g_values.end()){
|
if(i == g_values.end()){
|
||||||
QuicktuneValue val;
|
QuicktuneValue val;
|
||||||
|
@ -77,17 +70,15 @@ QuicktuneValue getQuicktuneValue(const std::string &name)
|
||||||
|
|
||||||
void setQuicktuneValue(const std::string &name, const QuicktuneValue &val)
|
void setQuicktuneValue(const std::string &name, const QuicktuneValue &val)
|
||||||
{
|
{
|
||||||
makeMutex();
|
MutexAutoLock lock(g_mutex);
|
||||||
MutexAutoLock lock(*g_mutex);
|
|
||||||
g_values[name] = val;
|
g_values[name] = val;
|
||||||
g_values[name].modified = true;
|
g_values[name].modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateQuicktuneValue(const std::string &name, QuicktuneValue &val)
|
void updateQuicktuneValue(const std::string &name, QuicktuneValue &val)
|
||||||
{
|
{
|
||||||
makeMutex();
|
MutexAutoLock lock(g_mutex);
|
||||||
MutexAutoLock lock(*g_mutex);
|
auto i = g_values.find(name);
|
||||||
std::map<std::string, QuicktuneValue>::iterator i = g_values.find(name);
|
|
||||||
if(i == g_values.end()){
|
if(i == g_values.end()){
|
||||||
g_values[name] = val;
|
g_values[name] = val;
|
||||||
g_names.push_back(name);
|
g_names.push_back(name);
|
||||||
|
|
|
@ -74,7 +74,7 @@ struct QuicktuneValue
|
||||||
void relativeAdd(float amount);
|
void relativeAdd(float amount);
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<std::string> getQuicktuneNames();
|
const std::vector<std::string> &getQuicktuneNames();
|
||||||
QuicktuneValue getQuicktuneValue(const std::string &name);
|
QuicktuneValue getQuicktuneValue(const std::string &name);
|
||||||
void setQuicktuneValue(const std::string &name, const QuicktuneValue &val);
|
void setQuicktuneValue(const std::string &name, const QuicktuneValue &val);
|
||||||
|
|
||||||
|
|
|
@ -291,7 +291,7 @@ inline v3f readV3F32(const u8 *data)
|
||||||
|
|
||||||
inline void writeU8(u8 *data, u8 i)
|
inline void writeU8(u8 *data, u8 i)
|
||||||
{
|
{
|
||||||
data[0] = (i >> 0) & 0xFF;
|
data[0] = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void writeS8(u8 *data, s8 i)
|
inline void writeS8(u8 *data, s8 i)
|
||||||
|
|
|
@ -23,12 +23,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
|
||||||
TimeTaker::TimeTaker(const std::string &name, u64 *result, TimePrecision prec)
|
void TimeTaker::start()
|
||||||
{
|
{
|
||||||
m_name = name;
|
m_time1 = porting::getTime(m_precision);
|
||||||
m_result = result;
|
|
||||||
m_precision = prec;
|
|
||||||
m_time1 = porting::getTime(prec);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 TimeTaker::stop(bool quiet)
|
u64 TimeTaker::stop(bool quiet)
|
||||||
|
@ -39,15 +36,8 @@ u64 TimeTaker::stop(bool quiet)
|
||||||
(*m_result) += dtime;
|
(*m_result) += dtime;
|
||||||
} else {
|
} else {
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
static const char* const units[] = {
|
|
||||||
"s" /* PRECISION_SECONDS */,
|
|
||||||
"ms" /* PRECISION_MILLI */,
|
|
||||||
"us" /* PRECISION_MICRO */,
|
|
||||||
"ns" /* PRECISION_NANO */,
|
|
||||||
};
|
|
||||||
infostream << m_name << " took "
|
infostream << m_name << " took "
|
||||||
<< dtime << units[m_precision]
|
<< dtime << TimePrecision_units[m_precision] << std::endl;
|
||||||
<< std::endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_running = false;
|
m_running = false;
|
||||||
|
|
|
@ -19,18 +19,43 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
#include "irrlichttypes.h"
|
#include "irrlichttypes.h"
|
||||||
#include "gettime.h"
|
|
||||||
|
enum TimePrecision : s8
|
||||||
|
{
|
||||||
|
PRECISION_SECONDS,
|
||||||
|
PRECISION_MILLI,
|
||||||
|
PRECISION_MICRO,
|
||||||
|
PRECISION_NANO,
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr const char *TimePrecision_units[] = {
|
||||||
|
"s" /* PRECISION_SECONDS */,
|
||||||
|
"ms" /* PRECISION_MILLI */,
|
||||||
|
"us" /* PRECISION_MICRO */,
|
||||||
|
"ns" /* PRECISION_NANO */,
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TimeTaker
|
TimeTaker
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Note: this class should be kept lightweight
|
||||||
|
|
||||||
class TimeTaker
|
class TimeTaker
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TimeTaker(const std::string &name, u64 *result=nullptr,
|
TimeTaker(const std::string &name, u64 *result = nullptr,
|
||||||
TimePrecision prec=PRECISION_MILLI);
|
TimePrecision prec = PRECISION_MILLI)
|
||||||
|
{
|
||||||
|
if (result)
|
||||||
|
m_result = result;
|
||||||
|
else
|
||||||
|
m_name = name;
|
||||||
|
m_precision = prec;
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
~TimeTaker()
|
~TimeTaker()
|
||||||
{
|
{
|
||||||
|
@ -42,9 +67,11 @@ public:
|
||||||
u64 getTimerTime();
|
u64 getTimerTime();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void start();
|
||||||
|
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
|
u64 *m_result = nullptr;
|
||||||
u64 m_time1;
|
u64 m_time1;
|
||||||
bool m_running = true;
|
bool m_running = true;
|
||||||
TimePrecision m_precision;
|
TimePrecision m_precision;
|
||||||
u64 *m_result = nullptr;
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue