aboutsummaryrefslogtreecommitdiff
path: root/src/client/game.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/game.cpp')
-rw-r--r--src/client/game.cpp385
1 files changed, 200 insertions, 185 deletions
diff --git a/src/client/game.cpp b/src/client/game.cpp
index 10c3a7ceb..5bfe55e66 100644
--- a/src/client/game.cpp
+++ b/src/client/game.cpp
@@ -68,6 +68,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "util/pointedthing.h"
#include "util/quicktune_shortcutter.h"
#include "irrlicht_changes/static_text.h"
+#include "irr_ptr.h"
#include "version.h"
#include "script/scripting_client.h"
#include "hud.h"
@@ -152,7 +153,7 @@ Game::~Game()
delete itemdef_manager;
delete draw_control;
- extendedResourceCleanup();
+ clearTextureNameCache();
g_settings->deregisterChangedCallback("doubletap_jump",
&settingChangedCallback, this);
@@ -190,6 +191,7 @@ Game::~Game()
bool Game::startup(bool *kill,
InputHandler *input,
+ RenderingEngine *rendering_engine,
const GameStartData &start_data,
std::string &error_message,
bool *reconnect,
@@ -197,21 +199,21 @@ bool Game::startup(bool *kill,
{
// "cache"
- this->device = RenderingEngine::get_raw_device();
+ m_rendering_engine = rendering_engine;
+ device = m_rendering_engine->get_raw_device();
this->kill = kill;
this->error_message = &error_message;
- this->reconnect_requested = reconnect;
+ reconnect_requested = reconnect;
this->input = input;
this->chat_backend = chat_backend;
- this->simple_singleplayer_mode = start_data.isSinglePlayer();
+ simple_singleplayer_mode = start_data.isSinglePlayer();
input->keycache.populate();
driver = device->getVideoDriver();
- smgr = RenderingEngine::get_scene_manager();
+ smgr = m_rendering_engine->get_scene_manager();
- RenderingEngine::get_scene_manager()->getParameters()->
- setAttribute(scene::OBJ_LOADER_IGNORE_MATERIAL_FILES, true);
+ smgr->getParameters()->setAttribute(scene::OBJ_LOADER_IGNORE_MATERIAL_FILES, true);
// Reinit runData
runData = GameRunData();
@@ -232,7 +234,7 @@ bool Game::startup(bool *kill,
if (!createClient(start_data))
return false;
- RenderingEngine::initialize(client, hud);
+ m_rendering_engine->initialize(client, hud);
return true;
}
@@ -249,7 +251,7 @@ void Game::run()
Profiler::GraphValues dummyvalues;
g_profiler->graphGet(dummyvalues);
- draw_times.last_time = RenderingEngine::get_timer_time();
+ draw_times.last_time = m_rendering_engine->get_timer_time();
set_light_table(g_settings->getFloat("display_gamma"));
@@ -261,12 +263,12 @@ void Game::run()
irr::core::dimension2d<u32> previous_screen_size(g_settings->getU16("screen_w"),
g_settings->getU16("screen_h"));
- while (RenderingEngine::run()
+ while (m_rendering_engine->run()
&& !(*kill || g_gamecallback->shutdown_requested
|| (server && server->isShutdownRequested()))) {
const irr::core::dimension2d<u32> &current_screen_size =
- RenderingEngine::get_video_driver()->getScreenSize();
+ m_rendering_engine->get_video_driver()->getScreenSize();
// Verify if window size has changed and save it if it's the case
// Ensure evaluating settings->getBool after verifying screensize
// First condition is cheaper
@@ -279,7 +281,7 @@ void Game::run()
}
// Calculate dtime =
- // RenderingEngine::run() from this iteration
+ // m_rendering_engine->run() from this iteration
// + Sleep time until the wanted FPS are reached
limitFps(&draw_times, &dtime);
@@ -328,7 +330,7 @@ void Game::run()
void Game::shutdown()
{
- RenderingEngine::finalize();
+ m_rendering_engine->finalize();
#if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR <= 8
if (g_settings->get("3d_mode") == "pageflip") {
driver->setRenderTarget(irr::video::ERT_STEREO_BOTH_BUFFERS);
@@ -487,7 +489,7 @@ bool Game::createClient(const GameStartData &start_data)
{
showOverlayMessage(N_("Creating client..."), 0, 10);
- draw_control = new MapDrawControl;
+ draw_control = new MapDrawControl();
if (!draw_control)
return false;
@@ -528,7 +530,7 @@ bool Game::createClient(const GameStartData &start_data)
/* Camera
*/
- camera = new Camera(*draw_control, client);
+ camera = new Camera(*draw_control, client, m_rendering_engine);
if (!camera->successfullyCreated(*error_message))
return false;
client->setCamera(camera);
@@ -540,7 +542,7 @@ bool Game::createClient(const GameStartData &start_data)
/* Skybox
*/
- sky = new Sky(-1, texture_src, shader_src);
+ sky = new Sky(-1, m_rendering_engine, texture_src, shader_src);
scsf->setSky(sky);
skybox = NULL; // This is used/set later on in the main run loop
@@ -562,16 +564,28 @@ bool Game::createClient(const GameStartData &start_data)
std::wstring str = utf8_to_wide(PROJECT_NAME_C);
str += L" ";
str += utf8_to_wide(g_version_hash);
+ {
+ const wchar_t *text = nullptr;
+ if (simple_singleplayer_mode)
+ text = wgettext("Singleplayer");
+ else
+ text = wgettext("Multiplayer");
+ str += L" [";
+ str += text;
+ str += L"]";
+ delete text;
+ }
str += L" [";
str += L"Minetest Hackclient";
str += L"]";
+
device->setWindowCaption(str.c_str());
LocalPlayer *player = client->getEnv().getLocalPlayer();
player->hurt_tilt_timer = 0;
player->hurt_tilt_strength = 0;
- hud = new Hud(guienv, client, player, &player->inventory);
+ hud = new Hud(client, player, &player->inventory);
mapper = client->getMinimap();
@@ -662,7 +676,7 @@ bool Game::connectToServer(const GameStartData &start_data,
start_data.password, start_data.address,
*draw_control, texture_src, shader_src,
itemdef_manager, nodedef_manager, sound, eventmgr,
- connect_address.isIPv6(), m_game_ui.get());
+ m_rendering_engine, connect_address.isIPv6(), m_game_ui.get());
client->m_simple_singleplayer_mode = simple_singleplayer_mode;
@@ -684,9 +698,9 @@ bool Game::connectToServer(const GameStartData &start_data,
f32 dtime;
f32 wait_time = 0; // in seconds
- fps_control.last_time = RenderingEngine::get_timer_time();
+ fps_control.last_time = m_rendering_engine->get_timer_time();
- while (RenderingEngine::run()) {
+ while (m_rendering_engine->run()) {
limitFps(&fps_control, &dtime);
@@ -723,7 +737,7 @@ bool Game::connectToServer(const GameStartData &start_data,
if (client->m_is_registration_confirmation_state) {
if (registration_confirmation_shown) {
// Keep drawing the GUI
- RenderingEngine::draw_menu_scene(guienv, dtime, true);
+ m_rendering_engine->draw_menu_scene(guienv, dtime, true);
} else {
registration_confirmation_shown = true;
(new GUIConfirmRegistration(guienv, guienv->getRootGUIElement(), -1,
@@ -733,7 +747,7 @@ bool Game::connectToServer(const GameStartData &start_data,
} else {
wait_time += dtime;
// Only time out if we aren't waiting for the server we started
- if (!start_data.isSinglePlayer() && wait_time > 10) {
+ if (!start_data.address.empty() && wait_time > 10) {
*error_message = "Connection timed out.";
errorstream << *error_message << std::endl;
break;
@@ -759,9 +773,9 @@ bool Game::getServerContent(bool *aborted)
FpsControl fps_control = { 0 };
f32 dtime; // in seconds
- fps_control.last_time = RenderingEngine::get_timer_time();
+ fps_control.last_time = m_rendering_engine->get_timer_time();
- while (RenderingEngine::run()) {
+ while (m_rendering_engine->run()) {
limitFps(&fps_control, &dtime);
@@ -799,13 +813,13 @@ bool Game::getServerContent(bool *aborted)
if (!client->itemdefReceived()) {
const wchar_t *text = wgettext("Item definitions...");
progress = 25;
- RenderingEngine::draw_load_screen(text, guienv, texture_src,
+ m_rendering_engine->draw_load_screen(text, guienv, texture_src,
dtime, progress);
delete[] text;
} else if (!client->nodedefReceived()) {
const wchar_t *text = wgettext("Node definitions...");
progress = 30;
- RenderingEngine::draw_load_screen(text, guienv, texture_src,
+ m_rendering_engine->draw_load_screen(text, guienv, texture_src,
dtime, progress);
delete[] text;
} else {
@@ -832,7 +846,7 @@ bool Game::getServerContent(bool *aborted)
}
progress = 30 + client->mediaReceiveProgress() * 35 + 0.5;
- RenderingEngine::draw_load_screen(utf8_to_wide(message.str()), guienv,
+ m_rendering_engine->draw_load_screen(utf8_to_wide(message.str()), guienv,
texture_src, dtime, progress);
}
}
@@ -1149,6 +1163,8 @@ void Game::processKeyInput()
toggleCinematic();
} else if (wasKeyDown(KeyType::SCREENSHOT)) {
client->makeScreenshot();
+ } else if (wasKeyDown(KeyType::TOGGLE_BLOCK_BOUNDS)) {
+ hud->toggleBlockBounds();
} else if (wasKeyDown(KeyType::TOGGLE_HUD)) {
m_game_ui->toggleHud();
} else if (wasKeyDown(KeyType::MINIMAP)) {
@@ -1263,8 +1279,8 @@ void Game::openInventory()
|| !client->getScript()->on_inventory_open(fs_src->m_client->getInventory(inventoryloc))) {
TextDest *txt_dst = new TextDestPlayerInventory(client);
auto *&formspec = m_game_ui->updateFormspec("");
- GUIFormSpecMenu::create(formspec, client, &input->joystick, fs_src,
- txt_dst, client->getFormspecPrepend(), sound);
+ GUIFormSpecMenu::create(formspec, client, m_rendering_engine->get_gui_env(),
+ &input->joystick, fs_src, txt_dst, client->getFormspecPrepend(), sound);
formspec->setFormSpec(fs_src->getForm(), inventoryloc);
}
@@ -1604,7 +1620,6 @@ void Game::checkZoomEnabled()
m_game_ui->showTranslatedStatusText("Zoom currently disabled by game or mod");
}
-
void Game::updateCameraDirection(CameraOrientation *cam, float dtime)
{
if ((device->isWindowActive() && device->isWindowFocused()
@@ -1640,6 +1655,18 @@ void Game::updateCameraDirection(CameraOrientation *cam, float dtime)
}
}
+// Get the factor to multiply with sensitivity to get the same mouse/joystick
+// responsiveness independently of FOV.
+f32 Game::getSensitivityScaleFactor() const
+{
+ f32 fov_y = client->getCamera()->getFovY();
+
+ // Multiply by a constant such that it becomes 1.0 at 72 degree FOV and
+ // 16:9 aspect ratio to minimize disruption of existing sensitivity
+ // settings.
+ return tan(fov_y / 2.0f) * 1.3763818698f;
+}
+
void Game::updateCameraOrientation(CameraOrientation *cam, float dtime)
{
#ifdef HAVE_TOUCHSCREENGUI
@@ -1655,8 +1682,9 @@ void Game::updateCameraOrientation(CameraOrientation *cam, float dtime)
dist.Y = -dist.Y;
}
- cam->camera_yaw -= dist.X * m_cache_mouse_sensitivity;
- cam->camera_pitch += dist.Y * m_cache_mouse_sensitivity;
+ f32 sens_scale = getSensitivityScaleFactor();
+ cam->camera_yaw -= dist.X * m_cache_mouse_sensitivity * sens_scale;
+ cam->camera_pitch += dist.Y * m_cache_mouse_sensitivity * sens_scale;
if (dist.X != 0 || dist.Y != 0)
input->setMousePos(center.X, center.Y);
@@ -1665,7 +1693,8 @@ void Game::updateCameraOrientation(CameraOrientation *cam, float dtime)
#endif
if (m_cache_enable_joysticks) {
- f32 c = m_cache_joystick_frustum_sensitivity * (1.f / 32767.f) * dtime;
+ f32 sens_scale = getSensitivityScaleFactor();
+ f32 c = m_cache_joystick_frustum_sensitivity * (1.f / 32767.f) * dtime * sens_scale;
cam->camera_yaw -= input->joystick.getAxisWithoutDead(JA_FRUSTUM_HORIZONTAL) * c;
cam->camera_pitch += input->joystick.getAxisWithoutDead(JA_FRUSTUM_VERTICAL) * c;
}
@@ -1688,7 +1717,7 @@ void Game::updatePlayerControl(const CameraOrientation &cam)
input->isKeyDown(KeyType::LEFT),
input->isKeyDown(KeyType::RIGHT),
isKeyDown(KeyType::JUMP),
- isKeyDown(KeyType::SPECIAL1),
+ isKeyDown(KeyType::AUX1),
isKeyDown(KeyType::SNEAK),
isKeyDown(KeyType::ZOOM),
isKeyDown(KeyType::DIG),
@@ -1705,7 +1734,7 @@ void Game::updatePlayerControl(const CameraOrientation &cam)
( (u32)(isKeyDown(KeyType::LEFT) & 0x1) << 2) |
( (u32)(isKeyDown(KeyType::RIGHT) & 0x1) << 3) |
( (u32)(isKeyDown(KeyType::JUMP) & 0x1) << 4) |
- ( (u32)(isKeyDown(KeyType::SPECIAL1) & 0x1) << 5) |
+ ( (u32)(isKeyDown(KeyType::AUX1) & 0x1) << 5) |
( (u32)(isKeyDown(KeyType::SNEAK) & 0x1) << 6) |
( (u32)(isKeyDown(KeyType::DIG) & 0x1) << 7) |
( (u32)(isKeyDown(KeyType::PLACE) & 0x1) << 8) |
@@ -1754,6 +1783,9 @@ inline void Game::step(f32 *dtime)
if (can_be_and_is_paused) { // This is for a singleplayer server
*dtime = 0; // No time passes
} else {
+ if (simple_singleplayer_mode && !paused_animated_nodes.empty())
+ resumeAnimation();
+
if (server)
server->step(*dtime);
@@ -1761,6 +1793,33 @@ inline void Game::step(f32 *dtime)
}
}
+static void pauseNodeAnimation(PausedNodesList &paused, scene::ISceneNode *node) {
+ if (!node)
+ return;
+ for (auto &&child: node->getChildren())
+ pauseNodeAnimation(paused, child);
+ if (node->getType() != scene::ESNT_ANIMATED_MESH)
+ return;
+ auto animated_node = static_cast<scene::IAnimatedMeshSceneNode *>(node);
+ float speed = animated_node->getAnimationSpeed();
+ if (!speed)
+ return;
+ paused.push_back({grab(animated_node), speed});
+ animated_node->setAnimationSpeed(0.0f);
+}
+
+void Game::pauseAnimation()
+{
+ pauseNodeAnimation(paused_animated_nodes, smgr->getRootSceneNode());
+}
+
+void Game::resumeAnimation()
+{
+ for (auto &&pair: paused_animated_nodes)
+ pair.first->setAnimationSpeed(pair.second);
+ paused_animated_nodes.clear();
+}
+
const ClientEventHandler Game::clientEventHandler[CLIENTEVENT_MAX] = {
{&Game::handleClientEvent_None},
{&Game::handleClientEvent_PlayerDamage},
@@ -1794,14 +1853,18 @@ void Game::handleClientEvent_PlayerDamage(ClientEvent *event, CameraOrientation
// Damage flash and hurt tilt are not used at death
if (client->getHP() > 0) {
- runData.damage_flash += 95.0f + 3.2f * event->player_damage.amount;
- runData.damage_flash = MYMIN(runData.damage_flash, 127.0f);
-
LocalPlayer *player = client->getEnv().getLocalPlayer();
+ f32 hp_max = player->getCAO() ?
+ player->getCAO()->getProperties()->hp_max : PLAYER_MAX_HP_DEFAULT;
+ f32 damage_ratio = event->player_damage.amount / hp_max;
+
+ runData.damage_flash += 95.0f + 64.f * damage_ratio;
+ runData.damage_flash = MYMIN(runData.damage_flash, 127.0f);
+
player->hurt_tilt_timer = 1.5f;
player->hurt_tilt_strength =
- rangelim(event->player_damage.amount / 4.0f, 1.0f, 4.0f);
+ rangelim(damage_ratio * 5.0f, 1.0f, 4.0f);
}
// Play damage sound
@@ -1845,8 +1908,8 @@ void Game::handleClientEvent_ShowFormSpec(ClientEvent *event, CameraOrientation
new TextDestPlayerInventory(client, *(event->show_formspec.formname));
auto *&formspec = m_game_ui->updateFormspec(*(event->show_formspec.formname));
- GUIFormSpecMenu::create(formspec, client, &input->joystick,
- fs_src, txt_dst, client->getFormspecPrepend(), sound);
+ GUIFormSpecMenu::create(formspec, client, m_rendering_engine->get_gui_env(),
+ &input->joystick, fs_src, txt_dst, client->getFormspecPrepend(), sound);
}
delete event->show_formspec.formspec;
@@ -1865,7 +1928,7 @@ void Game::handleClientEvent_ShowLocalFormSpec(ClientEvent *event, CameraOrienta
FormspecFormSource *fs_src = new FormspecFormSource(*event->show_formspec.formspec);
LocalFormspecHandler *txt_dst =
new LocalFormspecHandler(*event->show_formspec.formname, client);
- GUIFormSpecMenu::create(m_game_ui->getFormspecGUI(), client, &input->joystick,
+ GUIFormSpecMenu::create(m_game_ui->getFormspecGUI(), client, m_rendering_engine->get_gui_env(), &input->joystick,
fs_src, txt_dst, client->getFormspecPrepend(), sound);
}
@@ -1883,132 +1946,100 @@ void Game::handleClientEvent_HandleParticleEvent(ClientEvent *event,
void Game::handleClientEvent_HudAdd(ClientEvent *event, CameraOrientation *cam)
{
LocalPlayer *player = client->getEnv().getLocalPlayer();
- auto &hud_server_to_client = client->getHUDTranslationMap();
- u32 server_id = event->hudadd.server_id;
+ u32 server_id = event->hudadd->server_id;
// ignore if we already have a HUD with that ID
- auto i = hud_server_to_client.find(server_id);
- if (i != hud_server_to_client.end()) {
- delete event->hudadd.pos;
- delete event->hudadd.name;
- delete event->hudadd.scale;
- delete event->hudadd.text;
- delete event->hudadd.align;
- delete event->hudadd.offset;
- delete event->hudadd.world_pos;
- delete event->hudadd.size;
- delete event->hudadd.text2;
+ auto i = m_hud_server_to_client.find(server_id);
+ if (i != m_hud_server_to_client.end()) {
+ delete event->hudadd;
return;
}
HudElement *e = new HudElement;
- e->type = (HudElementType)event->hudadd.type;
- e->pos = *event->hudadd.pos;
- e->name = *event->hudadd.name;
- e->scale = *event->hudadd.scale;
- e->text = *event->hudadd.text;
- e->number = event->hudadd.number;
- e->item = event->hudadd.item;
- e->dir = event->hudadd.dir;
- e->align = *event->hudadd.align;
- e->offset = *event->hudadd.offset;
- e->world_pos = *event->hudadd.world_pos;
- e->size = *event->hudadd.size;
- e->z_index = event->hudadd.z_index;
- e->text2 = *event->hudadd.text2;
- hud_server_to_client[server_id] = player->addHud(e);
-
- delete event->hudadd.pos;
- delete event->hudadd.name;
- delete event->hudadd.scale;
- delete event->hudadd.text;
- delete event->hudadd.align;
- delete event->hudadd.offset;
- delete event->hudadd.world_pos;
- delete event->hudadd.size;
- delete event->hudadd.text2;
+ e->type = static_cast<HudElementType>(event->hudadd->type);
+ e->pos = event->hudadd->pos;
+ e->name = event->hudadd->name;
+ e->scale = event->hudadd->scale;
+ e->text = event->hudadd->text;
+ e->number = event->hudadd->number;
+ e->item = event->hudadd->item;
+ e->dir = event->hudadd->dir;
+ e->align = event->hudadd->align;
+ e->offset = event->hudadd->offset;
+ e->world_pos = event->hudadd->world_pos;
+ e->size = event->hudadd->size;
+ e->z_index = event->hudadd->z_index;
+ e->text2 = event->hudadd->text2;
+ m_hud_server_to_client[server_id] = player->addHud(e);
+
+ delete event->hudadd;
}
void Game::handleClientEvent_HudRemove(ClientEvent *event, CameraOrientation *cam)
{
LocalPlayer *player = client->getEnv().getLocalPlayer();
- HudElement *e = player->removeHud(event->hudrm.id);
- delete e;
+
+ auto i = m_hud_server_to_client.find(event->hudrm.id);
+ if (i != m_hud_server_to_client.end()) {
+ HudElement *e = player->removeHud(i->second);
+ delete e;
+ m_hud_server_to_client.erase(i);
+ }
+
}
void Game::handleClientEvent_HudChange(ClientEvent *event, CameraOrientation *cam)
{
LocalPlayer *player = client->getEnv().getLocalPlayer();
- u32 id = event->hudchange.id;
- HudElement *e = player->getHud(id);
+ HudElement *e = nullptr;
+
+ auto i = m_hud_server_to_client.find(event->hudchange->id);
+ if (i != m_hud_server_to_client.end()) {
+ e = player->getHud(i->second);
+ }
- if (e == NULL) {
- delete event->hudchange.v3fdata;
- delete event->hudchange.v2fdata;
- delete event->hudchange.sdata;
- delete event->hudchange.v2s32data;
+ if (e == nullptr) {
+ delete event->hudchange;
return;
}
- switch (event->hudchange.stat) {
- case HUD_STAT_POS:
- e->pos = *event->hudchange.v2fdata;
- break;
+#define CASE_SET(statval, prop, dataprop) \
+ case statval: \
+ e->prop = event->hudchange->dataprop; \
+ break
- case HUD_STAT_NAME:
- e->name = *event->hudchange.sdata;
- break;
+ switch (event->hudchange->stat) {
+ CASE_SET(HUD_STAT_POS, pos, v2fdata);
- case HUD_STAT_SCALE:
- e->scale = *event->hudchange.v2fdata;
- break;
+ CASE_SET(HUD_STAT_NAME, name, sdata);
- case HUD_STAT_TEXT:
- e->text = *event->hudchange.sdata;
- break;
+ CASE_SET(HUD_STAT_SCALE, scale, v2fdata);
- case HUD_STAT_NUMBER:
- e->number = event->hudchange.data;
- break;
+ CASE_SET(HUD_STAT_TEXT, text, sdata);
- case HUD_STAT_ITEM:
- e->item = event->hudchange.data;
- break;
+ CASE_SET(HUD_STAT_NUMBER, number, data);
- case HUD_STAT_DIR:
- e->dir = event->hudchange.data;
- break;
+ CASE_SET(HUD_STAT_ITEM, item, data);
- case HUD_STAT_ALIGN:
- e->align = *event->hudchange.v2fdata;
- break;
+ CASE_SET(HUD_STAT_DIR, dir, data);
- case HUD_STAT_OFFSET:
- e->offset = *event->hudchange.v2fdata;
- break;
+ CASE_SET(HUD_STAT_ALIGN, align, v2fdata);
- case HUD_STAT_WORLD_POS:
- e->world_pos = *event->hudchange.v3fdata;
- break;
+ CASE_SET(HUD_STAT_OFFSET, offset, v2fdata);
- case HUD_STAT_SIZE:
- e->size = *event->hudchange.v2s32data;
- break;
+ CASE_SET(HUD_STAT_WORLD_POS, world_pos, v3fdata);
- case HUD_STAT_Z_INDEX:
- e->z_index = event->hudchange.data;
- break;
+ CASE_SET(HUD_STAT_SIZE, size, v2s32data);
- case HUD_STAT_TEXT2:
- e->text2 = *event->hudchange.sdata;
- break;
+ CASE_SET(HUD_STAT_Z_INDEX, z_index, data);
+
+ CASE_SET(HUD_STAT_TEXT2, text2, sdata);
}
- delete event->hudchange.v3fdata;
- delete event->hudchange.v2fdata;
- delete event->hudchange.sdata;
- delete event->hudchange.v2s32data;
+#undef CASE_SET
+
+ delete event->hudchange;
}
void Game::handleClientEvent_SetSky(ClientEvent *event, CameraOrientation *cam)
@@ -2063,6 +2094,7 @@ void Game::handleClientEvent_SetSky(ClientEvent *event, CameraOrientation *cam)
"custom"
);
}
+
delete event->set_sky;
}
@@ -2563,9 +2595,10 @@ void Game::handlePointingAtNode(const PointedThing &pointed,
bool Game::nodePlacement(const ItemDefinition &selected_def,
const ItemStack &selected_item, const v3s16 &nodepos, const v3s16 &neighbourpos,
- const PointedThing &pointed, const NodeMetadata *meta)
+ const PointedThing &pointed, const NodeMetadata *meta, bool force)
{
- std::string prediction = selected_def.node_placement_prediction;
+ const auto &prediction = selected_def.node_placement_prediction;
+
const NodeDefManager *nodedef = client->ndef();
ClientMap &map = client->getEnv().getClientMap();
MapNode node;
@@ -2579,7 +2612,7 @@ bool Game::nodePlacement(const ItemDefinition &selected_def,
// formspec in meta
if (meta && !meta->getString("formspec").empty() && !input->isRandom()
- && !isKeyDown(KeyType::SNEAK)) {
+ && !isKeyDown(KeyType::SNEAK) && !force) {
// on_rightclick callbacks are called anyway
if (nodedef_manager->get(map.getNode(nodepos)).rightclickable)
client->interact(INTERACT_PLACE, pointed);
@@ -2594,8 +2627,8 @@ bool Game::nodePlacement(const ItemDefinition &selected_def,
TextDest *txt_dst = new TextDestNodeMetadata(nodepos, client);
auto *&formspec = m_game_ui->updateFormspec("");
- GUIFormSpecMenu::create(formspec, client, &input->joystick, fs_src,
- txt_dst, client->getFormspecPrepend(), sound);
+ GUIFormSpecMenu::create(formspec, client, m_rendering_engine->get_gui_env(),
+ &input->joystick, fs_src, txt_dst, client->getFormspecPrepend(), sound);
formspec->setFormSpec(meta->getString("formspec"), inventoryloc);
return false;
@@ -2603,7 +2636,7 @@ bool Game::nodePlacement(const ItemDefinition &selected_def,
// on_rightclick callback
if (prediction.empty() || (nodedef->get(node).rightclickable &&
- !isKeyDown(KeyType::SNEAK))) {
+ !isKeyDown(KeyType::SNEAK) && !force)) {
// Report to server
client->interact(INTERACT_PLACE, pointed);
return false;
@@ -2635,8 +2668,7 @@ bool Game::nodePlacement(const ItemDefinition &selected_def,
if (!found) {
errorstream << "Node placement prediction failed for "
- << selected_def.name << " (places "
- << prediction
+ << selected_def.name << " (places " << prediction
<< ") - Name not known" << std::endl;
// Handle this as if prediction was empty
// Report to server
@@ -2647,9 +2679,14 @@ bool Game::nodePlacement(const ItemDefinition &selected_def,
const ContentFeatures &predicted_f = nodedef->get(id);
// Predict param2 for facedir and wallmounted nodes
+ // Compare core.item_place_node() for what the server does
u8 param2 = 0;
- if (predicted_f.param_type_2 == CPT2_WALLMOUNTED ||
+ const u8 place_param2 = selected_def.place_param2;
+
+ if (place_param2) {
+ param2 = place_param2;
+ } else if (predicted_f.param_type_2 == CPT2_WALLMOUNTED ||
predicted_f.param_type_2 == CPT2_COLORED_WALLMOUNTED) {
v3s16 dir = nodepos - neighbourpos;
@@ -2660,9 +2697,7 @@ bool Game::nodePlacement(const ItemDefinition &selected_def,
} else {
param2 = dir.Z < 0 ? 5 : 4;
}
- }
-
- if (predicted_f.param_type_2 == CPT2_FACEDIR ||
+ } else if (predicted_f.param_type_2 == CPT2_FACEDIR ||
predicted_f.param_type_2 == CPT2_COLORED_FACEDIR) {
v3s16 dir = nodepos - floatToInt(client->getEnv().getLocalPlayer()->getPosition(), BS);
@@ -2673,11 +2708,9 @@ bool Game::nodePlacement(const ItemDefinition &selected_def,
}
}
- assert(param2 <= 5);
-
- //Check attachment if node is in group attached_node
- if (((ItemGroupList) predicted_f.groups)["attached_node"] != 0) {
- static v3s16 wallmounted_dirs[8] = {
+ // Check attachment if node is in group attached_node
+ if (itemgroup_get(predicted_f.groups, "attached_node") != 0) {
+ const static v3s16 wallmounted_dirs[8] = {
v3s16(0, 1, 0),
v3s16(0, -1, 0),
v3s16(1, 0, 0),
@@ -2702,11 +2735,11 @@ bool Game::nodePlacement(const ItemDefinition &selected_def,
}
// Apply color
- if ((predicted_f.param_type_2 == CPT2_COLOR
+ if (!place_param2 && (predicted_f.param_type_2 == CPT2_COLOR
|| predicted_f.param_type_2 == CPT2_COLORED_FACEDIR
|| predicted_f.param_type_2 == CPT2_COLORED_WALLMOUNTED)) {
- const std::string &indexstr = selected_item.metadata.getString(
- "palette_index", 0);
+ const auto &indexstr = selected_item.metadata.
+ getString("palette_index", 0);
if (!indexstr.empty()) {
s32 index = mystoi(indexstr);
if (predicted_f.param_type_2 == CPT2_COLOR) {
@@ -2746,11 +2779,10 @@ bool Game::nodePlacement(const ItemDefinition &selected_def,
soundmaker->m_player_rightpunch_sound = selected_def.sound_place_failed;
return false;
}
- } catch (InvalidPositionException &e) {
+ } catch (const InvalidPositionException &e) {
errorstream << "Node placement prediction failed for "
<< selected_def.name << " (places "
- << prediction
- << ") - Position not loaded" << std::endl;
+ << prediction << ") - Position not loaded" << std::endl;
soundmaker->m_player_rightpunch_sound = selected_def.sound_place_failed;
return false;
}
@@ -3158,7 +3190,7 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime,
} catch (SettingNotFoundException) {
}
#endif
- RenderingEngine::draw_scene(skycolor, m_game_ui->m_flags.show_hud,
+ m_rendering_engine->draw_scene(skycolor, m_game_ui->m_flags.show_hud,
m_game_ui->m_flags.show_minimap, draw_wield_tool, draw_crosshair);
/*
@@ -3297,7 +3329,7 @@ inline void Game::limitFps(FpsControl *fps_timings, f32 *dtime)
void Game::showOverlayMessage(const char *msg, float dtime, int percent, bool draw_clouds)
{
const wchar_t *wmsg = wgettext(msg);
- RenderingEngine::draw_load_screen(wmsg, guienv, texture_src, dtime, percent,
+ m_rendering_engine->draw_load_screen(wmsg, guienv, texture_src, dtime, percent,
draw_clouds);
delete[] wmsg;
}
@@ -3380,27 +3412,6 @@ bool Game::wasKeyReleased(GameKeyType k)
****************************************************************************/
/****************************************************************************/
-void Game::extendedResourceCleanup()
-{
- // Extended resource accounting
- infostream << "Irrlicht resources after cleanup:" << std::endl;
- infostream << "\tRemaining meshes : "
- << RenderingEngine::get_mesh_cache()->getMeshCount() << std::endl;
- infostream << "\tRemaining textures : "
- << driver->getTextureCount() << std::endl;
-
- for (unsigned int i = 0; i < driver->getTextureCount(); i++) {
- irr::video::ITexture *texture = driver->getTextureByIndex(i);
- infostream << "\t\t" << i << ":" << texture->getName().getPath().c_str()
- << std::endl;
- }
-
- clearTextureNameCache();
- infostream << "\tRemaining materials: "
- << driver-> getMaterialRendererCount()
- << " (note: irrlicht doesn't support removing renderers)" << std::endl;
-}
-
void Game::showDeathFormspec()
{
static std::string formspec_str =
@@ -3418,8 +3429,8 @@ void Game::showDeathFormspec()
LocalFormspecHandler *txt_dst = new LocalFormspecHandler("MT_DEATH_SCREEN", client);
auto *&formspec = m_game_ui->getFormspecGUI();
- GUIFormSpecMenu::create(formspec, client, &input->joystick,
- fs_src, txt_dst, client->getFormspecPrepend(), sound);
+ GUIFormSpecMenu::create(formspec, client, m_rendering_engine->get_gui_env(),
+ &input->joystick, fs_src, txt_dst, client->getFormspecPrepend(), sound);
formspec->setFocus("btn_respawn");
}
@@ -3560,10 +3571,13 @@ void Game::showPauseMenu()
LocalFormspecHandler *txt_dst = new LocalFormspecHandler("MT_PAUSE_MENU");
auto *&formspec = m_game_ui->getFormspecGUI();
- GUIFormSpecMenu::create(formspec, client, &input->joystick,
- fs_src, txt_dst, client->getFormspecPrepend(), sound);
+ GUIFormSpecMenu::create(formspec, client, m_rendering_engine->get_gui_env(),
+ &input->joystick, fs_src, txt_dst, client->getFormspecPrepend(), sound);
formspec->setFocus("btn_continue");
formspec->doPause = true;
+
+ if (simple_singleplayer_mode)
+ pauseAnimation();
}
/****************************************************************************/
@@ -3576,6 +3590,7 @@ Game *g_game;
void the_game(bool *kill,
InputHandler *input,
+ RenderingEngine *rendering_engine,
const GameStartData &start_data,
std::string &error_message,
ChatBackend &chat_backend,
@@ -3592,8 +3607,8 @@ void the_game(bool *kill,
try {
- if (game.startup(kill, input, start_data, error_message,
- reconnect_requested, &chat_backend)) {
+ if (game.startup(kill, input, rendering_engine, start_data,
+ error_message, reconnect_requested, &chat_backend)) {
game.run();
}