diff options
Diffstat (limited to 'src/client')
-rw-r--r-- | src/client/camera.cpp | 35 | ||||
-rw-r--r-- | src/client/camera.h | 47 | ||||
-rw-r--r-- | src/client/client.cpp | 16 | ||||
-rw-r--r-- | src/client/client.h | 10 | ||||
-rw-r--r-- | src/client/clientevent.h | 55 | ||||
-rw-r--r-- | src/client/clientmap.cpp | 45 | ||||
-rw-r--r-- | src/client/content_cao.cpp | 12 | ||||
-rw-r--r-- | src/client/game.cpp | 261 | ||||
-rw-r--r-- | src/client/guiscalingfilter.cpp | 2 | ||||
-rw-r--r-- | src/client/hud.cpp | 2 | ||||
-rw-r--r-- | src/client/inputhandler.cpp | 15 | ||||
-rw-r--r-- | src/client/inputhandler.h | 2 | ||||
-rw-r--r-- | src/client/joystick_controller.cpp | 6 | ||||
-rw-r--r-- | src/client/keys.h | 2 | ||||
-rw-r--r-- | src/client/mapblock_mesh.cpp | 6 | ||||
-rw-r--r-- | src/client/minimap.cpp | 11 | ||||
-rw-r--r-- | src/client/render/anaglyph.cpp | 2 | ||||
-rw-r--r-- | src/client/render/interlaced.cpp | 4 | ||||
-rw-r--r-- | src/client/renderingengine.cpp | 4 | ||||
-rw-r--r-- | src/client/shader.h | 5 | ||||
-rw-r--r-- | src/client/sky.cpp | 5 | ||||
-rw-r--r-- | src/client/sound_openal.cpp | 4 | ||||
-rw-r--r-- | src/client/tile.cpp | 11 | ||||
-rw-r--r-- | src/client/wieldmesh.cpp | 33 |
24 files changed, 332 insertions, 263 deletions
diff --git a/src/client/camera.cpp b/src/client/camera.cpp index 9a08254b4..5158d0dd1 100644 --- a/src/client/camera.cpp +++ b/src/client/camera.cpp @@ -79,6 +79,7 @@ Camera::Camera(MapDrawControl &draw_control, Client *client): m_cache_fov = std::fmax(g_settings->getFloat("fov"), 45.0f); m_arm_inertia = g_settings->getBool("arm_inertia"); m_nametags.clear(); + m_show_nametag_backgrounds = g_settings->getBool("show_nametag_backgrounds"); } Camera::~Camera() @@ -663,7 +664,7 @@ void Camera::wield(const ItemStack &item) void Camera::drawWieldedTool(irr::core::matrix4* translation) { // Clear Z buffer so that the wielded tool stays in front of world geometry - m_wieldmgr->getVideoDriver()->clearZBuffer(); + m_wieldmgr->getVideoDriver()->clearBuffers(video::ECBF_DEPTH); // Draw the wielded node (in a separate scene manager) scene::ICameraSceneNode* cam = m_wieldmgr->getActiveCamera(); @@ -696,18 +697,14 @@ void Camera::drawNametags() v2u32 screensize = driver->getScreenSize(); for (const Nametag *nametag : m_nametags) { - if (nametag->nametag_color.getAlpha() == 0) { - // Enforce hiding nametag, - // because if freetype is enabled, a grey - // shadow can remain. - continue; - } - v3f pos = nametag->parent_node->getAbsolutePosition() + nametag->nametag_pos * BS; + // Nametags are hidden in GenericCAO::updateNametag() + + v3f pos = nametag->parent_node->getAbsolutePosition() + nametag->pos * BS; f32 transformed_pos[4] = { pos.X, pos.Y, pos.Z, 1.0f }; trans.multiplyWith1x4Matrix(transformed_pos); if (transformed_pos[3] > 0) { std::wstring nametag_colorless = - unescape_translate(utf8_to_wide(nametag->nametag_text)); + unescape_translate(utf8_to_wide(nametag->text)); core::dimension2d<u32> textsize = font->getDimension( nametag_colorless.c_str()); f32 zDiv = transformed_pos[3] == 0.0f ? 1.0f : @@ -720,26 +717,22 @@ void Camera::drawNametags() core::rect<s32> size(0, 0, textsize.Width, textsize.Height); core::rect<s32> bg_size(-2, 0, textsize.Width+2, textsize.Height); - video::SColor textColor = nametag->nametag_color; - - bool darkBackground = textColor.getLuminance() > 186; - video::SColor backgroundColor = darkBackground - ? video::SColor(50, 50, 50, 50) - : video::SColor(50, 255, 255, 255); - driver->draw2DRectangle(backgroundColor, bg_size + screen_pos); + auto bgcolor = nametag->getBgColor(m_show_nametag_backgrounds); + if (bgcolor.getAlpha() != 0) + driver->draw2DRectangle(bgcolor, bg_size + screen_pos); font->draw( - translate_string(utf8_to_wide(nametag->nametag_text)).c_str(), - size + screen_pos, textColor); + translate_string(utf8_to_wide(nametag->text)).c_str(), + size + screen_pos, nametag->textcolor); } } } Nametag *Camera::addNametag(scene::ISceneNode *parent_node, - const std::string &nametag_text, video::SColor nametag_color, - const v3f &pos) + const std::string &text, video::SColor textcolor, + Optional<video::SColor> bgcolor, const v3f &pos) { - Nametag *nametag = new Nametag(parent_node, nametag_text, nametag_color, pos); + Nametag *nametag = new Nametag(parent_node, text, textcolor, bgcolor, pos); m_nametags.push_back(nametag); return nametag; } diff --git a/src/client/camera.h b/src/client/camera.h index 16a1961be..6fd8d9aa7 100644 --- a/src/client/camera.h +++ b/src/client/camera.h @@ -25,27 +25,47 @@ with this program; if not, write to the Free Software Foundation, Inc., #include <ICameraSceneNode.h> #include <ISceneNode.h> #include <list> +#include "util/Optional.h" class LocalPlayer; struct MapDrawControl; class Client; class WieldMeshSceneNode; -struct Nametag { +struct Nametag +{ + scene::ISceneNode *parent_node; + std::string text; + video::SColor textcolor; + Optional<video::SColor> bgcolor; + v3f pos; + Nametag(scene::ISceneNode *a_parent_node, - const std::string &a_nametag_text, - const video::SColor &a_nametag_color, - const v3f &a_nametag_pos): + const std::string &text, + const video::SColor &textcolor, + const Optional<video::SColor> &bgcolor, + const v3f &pos): parent_node(a_parent_node), - nametag_text(a_nametag_text), - nametag_color(a_nametag_color), - nametag_pos(a_nametag_pos) + text(text), + textcolor(textcolor), + bgcolor(bgcolor), + pos(pos) { } - scene::ISceneNode *parent_node; - std::string nametag_text; - video::SColor nametag_color; - v3f nametag_pos; + + video::SColor getBgColor(bool use_fallback) const + { + if (bgcolor) + return bgcolor.value(); + else if (!use_fallback) + return video::SColor(0, 0, 0, 0); + else if (textcolor.getLuminance() > 186) + // Dark background for light text + return video::SColor(50, 50, 50, 50); + else + // Light background for dark text + return video::SColor(50, 255, 255, 255); + } }; enum CameraMode {CAMERA_MODE_FIRST, CAMERA_MODE_THIRD, CAMERA_MODE_THIRD_FRONT}; @@ -164,8 +184,8 @@ public: } Nametag *addNametag(scene::ISceneNode *parent_node, - const std::string &nametag_text, video::SColor nametag_color, - const v3f &pos); + const std::string &text, video::SColor textcolor, + Optional<video::SColor> bgcolor, const v3f &pos); void removeNametag(Nametag *nametag); @@ -245,4 +265,5 @@ private: bool m_arm_inertia; std::list<Nametag *> m_nametags; + bool m_show_nametag_backgrounds; }; diff --git a/src/client/client.cpp b/src/client/client.cpp index ef4a3cdfc..0486bc0a9 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -663,12 +663,15 @@ bool Client::loadMedia(const std::string &data, const std::string &filename, io::IFileSystem *irrfs = RenderingEngine::get_filesystem(); video::IVideoDriver *vdrv = RenderingEngine::get_video_driver(); +#if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR > 8 + io::IReadFile *rfile = irrfs->createMemoryReadFile( + data.c_str(), data.size(), "_tempreadfile"); +#else // Silly irrlicht's const-incorrectness Buffer<char> data_rw(data.c_str(), data.size()); - - // Create an irrlicht memory file io::IReadFile *rfile = irrfs->createMemoryReadFile( *data_rw, data_rw.getSize(), "_tempreadfile"); +#endif FATAL_ERROR_IF(!rfile, "Could not create irrlicht memory file."); @@ -1914,13 +1917,20 @@ scene::IAnimatedMesh* Client::getMesh(const std::string &filename, bool cache) // Create the mesh, remove it from cache and return it // This allows unique vertex colors and other properties for each instance +#if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR > 8 + io::IReadFile *rfile = RenderingEngine::get_filesystem()->createMemoryReadFile( + data.c_str(), data.size(), filename.c_str()); +#else Buffer<char> data_rw(data.c_str(), data.size()); // Const-incorrect Irrlicht - io::IReadFile *rfile = RenderingEngine::get_filesystem()->createMemoryReadFile( + io::IReadFile *rfile = RenderingEngine::get_filesystem()->createMemoryReadFile( *data_rw, data_rw.getSize(), filename.c_str()); +#endif FATAL_ERROR_IF(!rfile, "Could not create/open RAM file"); scene::IAnimatedMesh *mesh = RenderingEngine::get_scene_manager()->getMesh(rfile); rfile->drop(); + if (!mesh) + return nullptr; mesh->grab(); if (!cache) RenderingEngine::get_mesh_cache()->removeMesh(mesh); diff --git a/src/client/client.h b/src/client/client.h index 25a1b97ba..da7f8e8a1 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -412,12 +412,7 @@ public: inline bool checkCSMRestrictionFlag(CSMRestrictionFlags flag) const { - return m_csm_restriction_flags & flag; - } - - inline std::unordered_map<u32, u32> &getHUDTranslationMap() - { - return m_hud_server_to_client; + return m_csm_restriction_flags & 0; } bool joinModChannel(const std::string &channel) override; @@ -556,9 +551,6 @@ private: // Relation of client id to object id std::unordered_map<int, u16> m_sounds_to_objects; - // Map server hud ids to client hud ids - std::unordered_map<u32, u32> m_hud_server_to_client; - // Privileges std::unordered_set<std::string> m_privileges; diff --git a/src/client/clientevent.h b/src/client/clientevent.h index 9bd31efce..2215aecbd 100644 --- a/src/client/clientevent.h +++ b/src/client/clientevent.h @@ -52,6 +52,31 @@ enum ClientEventType : u8 CLIENTEVENT_MAX, }; +struct ClientEventHudAdd +{ + u32 server_id; + u8 type; + v2f pos, scale; + std::string name; + std::string text, text2; + u32 number, item, dir; + v2f align, offset; + v3f world_pos; + v2s32 size; + s16 z_index; +}; + +struct ClientEventHudChange +{ + u32 id; + HudElementStat stat; + v2f v2fdata; + std::string sdata; + u32 data; + v3f v3fdata; + v2s32 v2s32data; +}; + struct ClientEvent { ClientEventType type; @@ -93,38 +118,12 @@ struct ClientEvent { u32 id; } delete_particlespawner; - struct - { - u32 server_id; - u8 type; - v2f *pos; - std::string *name; - v2f *scale; - std::string *text; - u32 number; - u32 item; - u32 dir; - v2f *align; - v2f *offset; - v3f *world_pos; - v2s32 *size; - s16 z_index; - std::string *text2; - } hudadd; + ClientEventHudAdd *hudadd; struct { u32 id; } hudrm; - struct - { - u32 id; - HudElementStat stat; - v2f *v2fdata; - std::string *sdata; - u32 data; - v3f *v3fdata; - v2s32 *v2s32data; - } hudchange; + ClientEventHudChange *hudchange; SkyboxParams *set_sky; struct { diff --git a/src/client/clientmap.cpp b/src/client/clientmap.cpp index b9e0cc2ce..be8343009 100644 --- a/src/client/clientmap.cpp +++ b/src/client/clientmap.cpp @@ -165,6 +165,9 @@ void ClientMap::updateDrawList() v3s16 p_blocks_max; getBlocksInViewRange(cam_pos_nodes, &p_blocks_min, &p_blocks_max); + // Read the vision range, unless unlimited range is enabled. + float range = m_control.range_all ? 1e7 : m_control.wanted_range; + // Number of blocks currently loaded by the client u32 blocks_loaded = 0; // Number of blocks with mesh in rendering range @@ -182,6 +185,7 @@ void ClientMap::updateDrawList() occlusion_culling_enabled = false; } + // Uncomment to debug occluded blocks in the wireframe mode // TODO: Include this as a flag for an extended debugging setting //if (occlusion_culling_enabled && m_control.show_wireframe) @@ -218,32 +222,34 @@ void ClientMap::updateDrawList() continue; } - float range = 100000 * BS; - if (!m_control.range_all) - range = m_control.wanted_range * BS; + v3s16 block_coord = block->getPos(); + v3s16 block_position = block->getPosRelative() + MAP_BLOCKSIZE / 2; - float d = 0.0; - if (!isBlockInSight(block->getPos(), camera_position, - camera_direction, camera_fov, range, &d)) - continue; + // First, perform a simple distance check, with a padding of one extra block. + if (!m_control.range_all && + block_position.getDistanceFrom(cam_pos_nodes) > range + MAP_BLOCKSIZE) + continue; // Out of range, skip. + // Keep the block alive as long as it is in range. + block->resetUsageTimer(); blocks_in_range_with_mesh++; - /* - Occlusion culling - */ + // Frustum culling + float d = 0.0; + if (!isBlockInSight(block_coord, camera_position, + camera_direction, camera_fov, range * BS, &d)) + continue; + + // Occlusion culling if ((!m_control.range_all && d > m_control.wanted_range * BS) || (occlusion_culling_enabled && isBlockOccluded(block, cam_pos_nodes))) { blocks_occlusion_culled++; continue; } - // This block is in range. Reset usage timer. - block->resetUsageTimer(); - // Add to set block->refGrab(); - m_drawlist[block->getPos()] = block; + m_drawlist[block_coord] = block; sector_blocks_drawn++; } // foreach sectorblocks @@ -282,8 +288,6 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) const u32 daynight_ratio = m_client->getEnv().getDayNightRatio(); const v3f camera_position = m_camera_position; - const v3f camera_direction = m_camera_direction; - const f32 camera_fov = m_camera_fov; /* Get all blocks and draw all visible ones @@ -310,11 +314,10 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) if (!block->mesh) continue; - float d = 0.0; - if (!isBlockInSight(block->getPos(), camera_position, - camera_direction, camera_fov, 100000 * BS, &d)) - continue; - + v3f block_pos_r = intToFloat(block->getPosRelative() + MAP_BLOCKSIZE / 2, BS); + float d = camera_position.getDistanceFrom(block_pos_r); + d = MYMAX(0,d - BLOCK_MAX_RADIUS); + // Mesh animation if (pass == scene::ESNRP_SOLID) { //MutexAutoLock lock(block->mesh_mutex); diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index c65977b44..97ae9afc4 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -934,7 +934,7 @@ void GenericCAO::updateNametag() if (m_is_local_player) // No nametag for local player return; - if (m_prop.nametag.empty()) { + if (m_prop.nametag.empty() || m_prop.nametag_color.getAlpha() == 0) { // Delete nametag if (m_nametag) { m_client->getCamera()->removeNametag(m_nametag); @@ -952,12 +952,14 @@ void GenericCAO::updateNametag() if (!m_nametag) { // Add nametag m_nametag = m_client->getCamera()->addNametag(node, - m_prop.nametag, m_prop.nametag_color, pos); + m_prop.nametag, m_prop.nametag_color, + m_prop.nametag_bgcolor, pos); } else { // Update nametag - m_nametag->nametag_text = m_prop.nametag; - m_nametag->nametag_color = m_prop.nametag_color; - m_nametag->nametag_pos = pos; + m_nametag->text = m_prop.nametag; + m_nametag->textcolor = m_prop.nametag_color; + m_nametag->bgcolor = m_prop.nametag_bgcolor; + m_nametag->pos = pos; } } diff --git a/src/client/game.cpp b/src/client/game.cpp index 3c58fb46f..31c782c51 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" @@ -425,6 +426,7 @@ class GameGlobalShaderConstantSetter : public IShaderConstantSetter CachedPixelShaderSetting<float, 3> m_camera_offset_pixel; CachedPixelShaderSetting<float, 3> m_camera_offset_vertex; CachedPixelShaderSetting<SamplerLayer_t> m_base_texture; + CachedPixelShaderSetting<SamplerLayer_t> m_normal_texture; Client *m_client; public: @@ -458,6 +460,7 @@ public: m_camera_offset_pixel("cameraOffset"), m_camera_offset_vertex("cameraOffset"), m_base_texture("baseTexture"), + m_normal_texture("normalTexture"), m_client(client) { g_settings->registerChangedCallback("enable_fog", settingsCallback, this); @@ -545,8 +548,9 @@ public: m_camera_offset_pixel.set(camera_offset_array, services); m_camera_offset_vertex.set(camera_offset_array, services); - SamplerLayer_t base_tex = 0; + SamplerLayer_t base_tex = 0, normal_tex = 1; m_base_texture.set(&base_tex, services); + m_normal_texture.set(&normal_tex, services); } }; @@ -647,6 +651,8 @@ struct ClientEventHandler THE GAME ****************************************************************************/ +using PausedNodesList = std::vector<std::pair<irr_ptr<scene::IAnimatedMeshSceneNode>, float>>; + /* This is not intended to be a public class. If a public class becomes * desirable then it may be better to create another 'wrapper' class that * hides most of the stuff in this class (nothing in this class is required @@ -796,6 +802,9 @@ private: void showDeathFormspec(); void showPauseMenu(); + void pauseAnimation(); + void resumeAnimation(); + // ClientEvent handlers void handleClientEvent_None(ClientEvent *event, CameraOrientation *cam); void handleClientEvent_PlayerDamage(ClientEvent *event, CameraOrientation *cam); @@ -823,6 +832,8 @@ private: const NodeMetadata *meta); static const ClientEventHandler clientEventHandler[CLIENTEVENT_MAX]; + f32 getSensitivityScaleFactor() const; + InputHandler *input = nullptr; Client *client = nullptr; @@ -856,6 +867,9 @@ private: Hud *hud = nullptr; Minimap *mapper = nullptr; + // Map server hud ids to client hud ids + std::unordered_map<u32, u32> m_hud_server_to_client; + GameRunData runData; Flags m_flags; @@ -870,6 +884,7 @@ private: std::string *error_message; bool *reconnect_requested; scene::ISceneNode *skybox; + PausedNodesList paused_animated_nodes; bool simple_singleplayer_mode; /* End 'cache' */ @@ -2331,7 +2346,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() @@ -2367,6 +2381,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 @@ -2382,8 +2408,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); @@ -2392,7 +2419,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; } @@ -2415,7 +2443,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), @@ -2432,7 +2460,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) | @@ -2481,6 +2509,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); @@ -2488,6 +2519,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}, @@ -2602,132 +2660,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; - if (e == NULL) { - delete event->hudchange.v3fdata; - delete event->hudchange.v2fdata; - delete event->hudchange.sdata; - delete event->hudchange.v2s32data; + 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 == 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) @@ -3279,7 +3305,8 @@ bool Game::nodePlacement(const ItemDefinition &selected_def, const ItemStack &selected_item, const v3s16 &nodepos, const v3s16 &neighbourpos, const PointedThing &pointed, const NodeMetadata *meta) { - 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; @@ -3349,8 +3376,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 @@ -3361,9 +3387,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; @@ -3374,9 +3405,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); @@ -3387,11 +3416,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), @@ -3416,11 +3443,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) { @@ -3460,11 +3487,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; } @@ -4218,6 +4244,9 @@ void Game::showPauseMenu() fs_src, txt_dst, client->getFormspecPrepend(), sound); formspec->setFocus("btn_continue"); formspec->doPause = true; + + if (simple_singleplayer_mode) + pauseAnimation(); } /****************************************************************************/ diff --git a/src/client/guiscalingfilter.cpp b/src/client/guiscalingfilter.cpp index 406c096e6..8c565a52f 100644 --- a/src/client/guiscalingfilter.cpp +++ b/src/client/guiscalingfilter.cpp @@ -129,7 +129,7 @@ video::ITexture *guiScalingResizeCached(video::IVideoDriver *driver, #endif // Convert the scaled image back into a texture. - scaled = driver->addTexture(scalename, destimg, NULL); + scaled = driver->addTexture(scalename, destimg); destimg->drop(); g_txrCache[scalename] = scaled; diff --git a/src/client/hud.cpp b/src/client/hud.cpp index 46736b325..74c1828e3 100644 --- a/src/client/hud.cpp +++ b/src/client/hud.cpp @@ -950,7 +950,7 @@ void drawItemStack( if (imesh && imesh->mesh) { scene::IMesh *mesh = imesh->mesh; - driver->clearZBuffer(); + driver->clearBuffers(video::ECBF_DEPTH); s32 delta = 0; if (rotation_kind < IT_ROT_NONE) { MeshTimeInfo &ti = rotation_time_infos[rotation_kind]; diff --git a/src/client/inputhandler.cpp b/src/client/inputhandler.cpp index 608a405a8..b7e70fa6c 100644 --- a/src/client/inputhandler.cpp +++ b/src/client/inputhandler.cpp @@ -35,7 +35,7 @@ void KeyCache::populate() key[KeyType::LEFT] = getKeySetting("keymap_left"); key[KeyType::RIGHT] = getKeySetting("keymap_right"); key[KeyType::JUMP] = getKeySetting("keymap_jump"); - key[KeyType::SPECIAL1] = getKeySetting("keymap_special1"); + key[KeyType::AUX1] = getKeySetting("keymap_aux1"); key[KeyType::SNEAK] = getKeySetting("keymap_sneak"); key[KeyType::DIG] = getKeySetting("keymap_dig"); key[KeyType::PLACE] = getKeySetting("keymap_place"); @@ -113,17 +113,12 @@ bool MyEventReceiver::OnEvent(const SEvent &event) if (event.EventType == irr::EET_KEY_INPUT_EVENT) { const KeyPress &keyCode = event.KeyInput; if (keysListenedFor[keyCode]) { - // If the key is being held down then the OS may - // send a continuous stream of keydown events. - // In this case, we don't want to let this - // stream reach the application as it will cause - // certain actions to repeat constantly. if (event.KeyInput.PressedDown) { - if (!IsKeyDown(keyCode)) { - keyWasDown.set(keyCode); + if (!IsKeyDown(keyCode)) keyWasPressed.set(keyCode); - } + keyIsDown.set(keyCode); + keyWasDown.set(keyCode); } else { if (IsKeyDown(keyCode)) keyWasReleased.set(keyCode); @@ -224,7 +219,7 @@ void RandomInputHandler::step(float dtime) { static RandomInputHandlerSimData rnd_data[] = { { "keymap_jump", 0.0f, 40 }, - { "keymap_special1", 0.0f, 40 }, + { "keymap_aux1", 0.0f, 40 }, { "keymap_forward", 0.0f, 40 }, { "keymap_left", 0.0f, 40 }, { "keymap_dig", 0.0f, 30 }, diff --git a/src/client/inputhandler.h b/src/client/inputhandler.h index 7487bbdc7..1fb4cf0ec 100644 --- a/src/client/inputhandler.h +++ b/src/client/inputhandler.h @@ -201,7 +201,7 @@ private: // The current state of keys KeyList keyIsDown; - // Whether a key was down + // Like keyIsDown but only reset when that key is read KeyList keyWasDown; // Whether a key has just been pressed diff --git a/src/client/joystick_controller.cpp b/src/client/joystick_controller.cpp index f61ae4ae6..919db5315 100644 --- a/src/client/joystick_controller.cpp +++ b/src/client/joystick_controller.cpp @@ -79,7 +79,7 @@ JoystickLayout create_default_layout() // Accessible without any modifier pressed JLO_B_PB(KeyType::JUMP, bm | 1 << 0, 1 << 0); - JLO_B_PB(KeyType::SPECIAL1, bm | 1 << 1, 1 << 1); + JLO_B_PB(KeyType::AUX1, bm | 1 << 1, 1 << 1); // Accessible with start button not pressed, but four pressed // TODO find usage for button 0 @@ -126,11 +126,11 @@ JoystickLayout create_xbox_layout() // 4 Buttons JLO_B_PB(KeyType::JUMP, 1 << 0, 1 << 0); // A/green JLO_B_PB(KeyType::ESC, 1 << 1, 1 << 1); // B/red - JLO_B_PB(KeyType::SPECIAL1, 1 << 2, 1 << 2); // X/blue + JLO_B_PB(KeyType::AUX1, 1 << 2, 1 << 2); // X/blue JLO_B_PB(KeyType::INVENTORY, 1 << 3, 1 << 3); // Y/yellow // Analog Sticks - JLO_B_PB(KeyType::SPECIAL1, 1 << 11, 1 << 11); // left + JLO_B_PB(KeyType::AUX1, 1 << 11, 1 << 11); // left JLO_B_PB(KeyType::SNEAK, 1 << 12, 1 << 12); // right // Triggers diff --git a/src/client/keys.h b/src/client/keys.h index 60a7a3c45..9f90da6b8 100644 --- a/src/client/keys.h +++ b/src/client/keys.h @@ -32,7 +32,7 @@ public: LEFT, RIGHT, JUMP, - SPECIAL1, + AUX1, SNEAK, AUTOFORWARD, DIG, diff --git a/src/client/mapblock_mesh.cpp b/src/client/mapblock_mesh.cpp index d78a86b2d..167e1e3ec 100644 --- a/src/client/mapblock_mesh.cpp +++ b/src/client/mapblock_mesh.cpp @@ -404,7 +404,7 @@ static void getNodeVertexDirs(const v3s16 &dir, v3s16 *vertex_dirs) static void getNodeTextureCoords(v3f base, const v3f &scale, const v3s16 &dir, float *u, float *v) { - if (dir.X > 0 || dir.Y > 0 || dir.Z < 0) + if (dir.X > 0 || dir.Y != 0 || dir.Z < 0) base -= scale; if (dir == v3s16(0,0,1)) { *u = -base.X - 1; @@ -422,8 +422,8 @@ static void getNodeTextureCoords(v3f base, const v3f &scale, const v3s16 &dir, f *u = base.X + 1; *v = -base.Z - 2; } else if (dir == v3s16(0,-1,0)) { - *u = base.X; - *v = base.Z; + *u = base.X + 1; + *v = base.Z + 1; } } diff --git a/src/client/minimap.cpp b/src/client/minimap.cpp index c6ccf86e8..dd810ee0a 100644 --- a/src/client/minimap.cpp +++ b/src/client/minimap.cpp @@ -304,7 +304,7 @@ void Minimap::setModeIndex(size_t index) data->mode = m_modes[index]; m_current_mode_index = index; } else { - data->mode = MinimapModeDef{MINIMAP_TYPE_OFF, N_("Minimap hidden"), 0, 0, ""}; + data->mode = MinimapModeDef{MINIMAP_TYPE_OFF, gettext("Minimap hidden"), 0, 0, ""}; m_current_mode_index = 0; } @@ -330,25 +330,26 @@ void Minimap::addMode(MinimapModeDef mode) if (mode.label == "") { switch (mode.type) { case MINIMAP_TYPE_OFF: - mode.label = N_("Minimap hidden"); + mode.label = gettext("Minimap hidden"); break; case MINIMAP_TYPE_SURFACE: - mode.label = N_("Minimap in surface mode, Zoom x%d"); + mode.label = gettext("Minimap in surface mode, Zoom x%d"); if (mode.map_size > 0) zoom = 256 / mode.map_size; break; case MINIMAP_TYPE_RADAR: - mode.label = N_("Minimap in radar mode, Zoom x%d"); + mode.label = gettext("Minimap in radar mode, Zoom x%d"); if (mode.map_size > 0) zoom = 512 / mode.map_size; break; case MINIMAP_TYPE_TEXTURE: - mode.label = N_("Minimap in texture mode"); + mode.label = gettext("Minimap in texture mode"); break; default: break; } } + // else: Custom labels need mod-provided client-side translation if (zoom >= 0) { char label_buf[1024]; diff --git a/src/client/render/anaglyph.cpp b/src/client/render/anaglyph.cpp index 9ba4464a2..153e77400 100644 --- a/src/client/render/anaglyph.cpp +++ b/src/client/render/anaglyph.cpp @@ -40,7 +40,7 @@ void RenderingCoreAnaglyph::setupMaterial(int color_mask) void RenderingCoreAnaglyph::useEye(bool right) { RenderingCoreStereo::useEye(right); - driver->clearZBuffer(); + driver->clearBuffers(video::ECBF_DEPTH); setupMaterial(right ? video::ECP_GREEN | video::ECP_BLUE : video::ECP_RED); } diff --git a/src/client/render/interlaced.cpp b/src/client/render/interlaced.cpp index ce8e92f21..3f79a8eb5 100644 --- a/src/client/render/interlaced.cpp +++ b/src/client/render/interlaced.cpp @@ -35,7 +35,11 @@ void RenderingCoreInterlaced::initMaterial() IShaderSource *s = client->getShaderSource(); mat.UseMipMaps = false; mat.ZBuffer = false; +#if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR > 8 + mat.ZWriteEnable = video::EZW_OFF; +#else mat.ZWriteEnable = false; +#endif u32 shader = s->getShader("3d_interlaced_merge", TILE_MATERIAL_BASIC); mat.MaterialType = s->getShaderInfo(shader).material; for (int k = 0; k < 3; ++k) { diff --git a/src/client/renderingengine.cpp b/src/client/renderingengine.cpp index 99ff8c1ee..4f59bbae3 100644 --- a/src/client/renderingengine.cpp +++ b/src/client/renderingengine.cpp @@ -118,6 +118,8 @@ RenderingEngine::RenderingEngine(IEventReceiver *receiver) } SIrrlichtCreationParameters params = SIrrlichtCreationParameters(); + if (g_logger.getTraceEnabled()) + params.LoggingLevel = irr::ELL_DEBUG; params.DriverType = driverType; params.WindowSize = core::dimension2d<u32>(screen_w, screen_h); params.Bits = bits; @@ -325,9 +327,11 @@ static bool getWindowHandle(irr::video::IVideoDriver *driver, HWND &hWnd) const video::SExposedVideoData exposedData = driver->getExposedVideoData(); switch (driver->getDriverType()) { +#if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 9 case video::EDT_DIRECT3D8: hWnd = reinterpret_cast<HWND>(exposedData.D3D8.HWnd); break; +#endif case video::EDT_DIRECT3D9: hWnd = reinterpret_cast<HWND>(exposedData.D3D9.HWnd); break; diff --git a/src/client/shader.h b/src/client/shader.h index 38ab76704..49a563115 100644 --- a/src/client/shader.h +++ b/src/client/shader.h @@ -96,9 +96,10 @@ public: if (has_been_set && std::equal(m_sent, m_sent + count, value)) return; if (is_pixel) - services->setPixelShaderConstant(m_name, value, count); + services->setPixelShaderConstant(services->getPixelShaderConstantID(m_name), value, count); else - services->setVertexShaderConstant(m_name, value, count); + services->setVertexShaderConstant(services->getVertexShaderConstantID(m_name), value, count); + std::copy(value, value + count, m_sent); has_been_set = true; } diff --git a/src/client/sky.cpp b/src/client/sky.cpp index 3a40321dd..caf695e7a 100644 --- a/src/client/sky.cpp +++ b/src/client/sky.cpp @@ -39,12 +39,13 @@ static video::SMaterial baseMaterial() { video::SMaterial mat; mat.Lighting = false; -#if ENABLE_GLES +#if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR > 8 mat.ZBuffer = video::ECFN_DISABLED; + mat.ZWriteEnable = video::EZW_OFF; #else + mat.ZWriteEnable = false; mat.ZBuffer = video::ECFN_NEVER; #endif - mat.ZWriteEnable = false; mat.AntiAliasing = 0; mat.TextureLayer[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE; mat.TextureLayer[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE; diff --git a/src/client/sound_openal.cpp b/src/client/sound_openal.cpp index f4e61f93e..8dceeede6 100644 --- a/src/client/sound_openal.cpp +++ b/src/client/sound_openal.cpp @@ -671,8 +671,8 @@ public: alSourcei(sound->source_id, AL_SOURCE_RELATIVE, false); alSource3f(sound->source_id, AL_POSITION, pos.X, pos.Y, pos.Z); - alSource3f(sound->source_id, AL_VELOCITY, 0, 0, 0); - alSourcef(sound->source_id, AL_REFERENCE_DISTANCE, 30.0); + alSource3f(sound->source_id, AL_VELOCITY, 0.0f, 0.0f, 0.0f); + alSourcef(sound->source_id, AL_REFERENCE_DISTANCE, 10.0f); } bool updateSoundGain(int id, float gain) diff --git a/src/client/tile.cpp b/src/client/tile.cpp index aad956ada..7e3901247 100644 --- a/src/client/tile.cpp +++ b/src/client/tile.cpp @@ -837,17 +837,16 @@ static video::IImage *createInventoryCubeImage( image = scaled; } sanity_check(image->getPitch() == 4 * size); - return reinterpret_cast<u32 *>(image->lock()); + return reinterpret_cast<u32 *>(image->getData()); }; auto free_image = [] (video::IImage *image) -> void { - image->unlock(); image->drop(); }; video::IImage *result = driver->createImage(video::ECF_A8R8G8B8, {cube_size, cube_size}); sanity_check(result->getPitch() == 4 * cube_size); result->fill(video::SColor(0x00000000u)); - u32 *target = reinterpret_cast<u32 *>(result->lock()); + u32 *target = reinterpret_cast<u32 *>(result->getData()); // Draws single cube face // `shade_factor` is face brightness, in range [0.0, 1.0] @@ -906,7 +905,6 @@ static video::IImage *createInventoryCubeImage( {0, 5}, {1, 5}, }); - result->unlock(); return result; } @@ -2224,9 +2222,14 @@ video::SColor TextureSource::getTextureAverageColor(const std::string &name) video::IVideoDriver *driver = RenderingEngine::get_video_driver(); video::SColor c(0, 0, 0, 0); video::ITexture *texture = getTexture(name); + if (!texture) + return c; video::IImage *image = driver->createImage(texture, core::position2d<s32>(0, 0), texture->getOriginalSize()); + if (!image) + return c; + u32 total = 0; u32 tR = 0; u32 tG = 0; diff --git a/src/client/wieldmesh.cpp b/src/client/wieldmesh.cpp index ad583210a..387eb17c3 100644 --- a/src/client/wieldmesh.cpp +++ b/src/client/wieldmesh.cpp @@ -294,7 +294,7 @@ void WieldMeshSceneNode::setExtruded(const std::string &imagename, } material.setFlag(video::EMF_ANISOTROPIC_FILTER, m_anisotropic_filter); // mipmaps cause "thin black line" artifacts -#if (IRRLICHT_VERSION_MAJOR >= 1 && IRRLICHT_VERSION_MINOR >= 8) || IRRLICHT_VERSION_MAJOR >= 2 +#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR >= 8) || IRRLICHT_VERSION_MAJOR >= 2 material.setFlag(video::EMF_USE_MIP_MAPS, false); #endif if (m_enable_shaders) { @@ -303,23 +303,26 @@ void WieldMeshSceneNode::setExtruded(const std::string &imagename, } } -scene::SMesh *createSpecialNodeMesh(Client *client, content_t id, std::vector<ItemPartColor> *colors, const ContentFeatures &f) +static scene::SMesh *createSpecialNodeMesh(Client *client, MapNode n, + std::vector<ItemPartColor> *colors, const ContentFeatures &f) { MeshMakeData mesh_make_data(client, false); MeshCollector collector; mesh_make_data.setSmoothLighting(false); MapblockMeshGenerator gen(&mesh_make_data, &collector); - u8 param2 = 0; - if (f.param_type_2 == CPT2_WALLMOUNTED || + + if (n.getParam2()) { + // keep it + } else if (f.param_type_2 == CPT2_WALLMOUNTED || f.param_type_2 == CPT2_COLORED_WALLMOUNTED) { if (f.drawtype == NDT_TORCHLIKE) - param2 = 1; + n.setParam2(1); else if (f.drawtype == NDT_SIGNLIKE || f.drawtype == NDT_NODEBOX || f.drawtype == NDT_MESH) - param2 = 4; + n.setParam2(4); } - gen.renderSingle(id, param2); + gen.renderSingle(n.getContent(), n.getParam2()); colors->clear(); scene::SMesh *mesh = new scene::SMesh(); @@ -413,9 +416,12 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che case NDT_LIQUID: setCube(f, def.wield_scale); break; - default: + default: { // Render non-trivial drawtypes like the actual node - mesh = createSpecialNodeMesh(client, id, &m_colors, f); + MapNode n(id); + n.setParam2(def.place_param2); + + mesh = createSpecialNodeMesh(client, n, &m_colors, f); changeToMesh(mesh); mesh->drop(); m_meshnode->setScale( @@ -423,6 +429,7 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che / (BS * f.visual_scale)); break; } + } u32 material_count = m_meshnode->getMaterialCount(); for (u32 i = 0; i < material_count; ++i) { @@ -585,12 +592,16 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result) result->buffer_colors.emplace_back(l0.has_color, l0.color); break; } - default: + default: { // Render non-trivial drawtypes like the actual node - mesh = createSpecialNodeMesh(client, id, &result->buffer_colors, f); + MapNode n(id); + n.setParam2(def.place_param2); + + mesh = createSpecialNodeMesh(client, n, &result->buffer_colors, f); scaleMesh(mesh, v3f(0.12, 0.12, 0.12)); break; } + } u32 mc = mesh->getMeshBufferCount(); for (u32 i = 0; i < mc; ++i) { |