#include "version.h"
#include "script/scripting_client.h"
#include "hud.h"
+#include "clientdynamicinfo.h"
#if USE_SOUND
#include "client/sound_openal.h"
CachedPixelShaderSetting<float> m_fog_distance;
CachedVertexShaderSetting<float> m_animation_timer_vertex;
CachedPixelShaderSetting<float> m_animation_timer_pixel;
+ CachedVertexShaderSetting<float> m_animation_timer_delta_vertex;
+ CachedPixelShaderSetting<float> m_animation_timer_delta_pixel;
CachedPixelShaderSetting<float, 3> m_day_light;
CachedPixelShaderSetting<float, 4> m_star_color;
CachedPixelShaderSetting<float, 3> m_eye_position_pixel;
CachedPixelShaderSetting<SamplerLayer_t> m_texture3;
CachedPixelShaderSetting<float, 2> m_texel_size0;
std::array<float, 2> m_texel_size0_values;
- CachedPixelShaderSetting<float> m_exposure_factor_pixel;
- float m_user_exposure_factor;
+ CachedStructPixelShaderSetting<float, 7> m_exposure_params_pixel;
+ float m_user_exposure_compensation;
bool m_bloom_enabled;
CachedPixelShaderSetting<float> m_bloom_intensity_pixel;
float m_bloom_intensity;
+ CachedPixelShaderSetting<float> m_bloom_strength_pixel;
+ float m_bloom_strength;
CachedPixelShaderSetting<float> m_bloom_radius_pixel;
float m_bloom_radius;
+ CachedPixelShaderSetting<float> m_saturation_pixel;
public:
void onSettingsChange(const std::string &name)
{
if (name == "enable_fog")
m_fog_enabled = g_settings->getBool("enable_fog");
- if (name == "exposure_factor")
- m_user_exposure_factor = g_settings->getFloat("exposure_factor", 0.1f, 10.0f);
+ if (name == "exposure_compensation")
+ m_user_exposure_compensation = g_settings->getFloat("exposure_compensation", -1.0f, 1.0f);
if (name == "bloom_intensity")
m_bloom_intensity = g_settings->getFloat("bloom_intensity", 0.01f, 1.0f);
+ if (name == "bloom_strength_factor")
+ m_bloom_strength = RenderingEngine::BASE_BLOOM_STRENGTH * g_settings->getFloat("bloom_strength_factor", 0.1f, 10.0f);
if (name == "bloom_radius")
- m_bloom_radius = g_settings->getFloat("bloom_radius", 1.0f, 64.0f);
+ m_bloom_radius = g_settings->getFloat("bloom_radius", 0.1f, 8.0f);
}
static void settingsCallback(const std::string &name, void *userdata)
m_fog_distance("fogDistance"),
m_animation_timer_vertex("animationTimer"),
m_animation_timer_pixel("animationTimer"),
+ m_animation_timer_delta_vertex("animationTimerDelta"),
+ m_animation_timer_delta_pixel("animationTimerDelta"),
m_day_light("dayLight"),
m_star_color("starColor"),
m_eye_position_pixel("eyePosition"),
m_texture2("texture2"),
m_texture3("texture3"),
m_texel_size0("texelSize0"),
- m_exposure_factor_pixel("exposureFactor"),
+ m_exposure_params_pixel("exposureParams",
+ std::array<const char*, 7> {
+ "luminanceMin", "luminanceMax", "exposureCorrection",
+ "speedDarkBright", "speedBrightDark", "centerWeightPower", "compensationFactor"
+ }),
m_bloom_intensity_pixel("bloomIntensity"),
- m_bloom_radius_pixel("bloomRadius")
+ m_bloom_strength_pixel("bloomStrength"),
+ m_bloom_radius_pixel("bloomRadius"),
+ m_saturation_pixel("saturation")
{
g_settings->registerChangedCallback("enable_fog", settingsCallback, this);
- g_settings->registerChangedCallback("exposure_factor", settingsCallback, this);
+ g_settings->registerChangedCallback("exposure_compensation", settingsCallback, this);
g_settings->registerChangedCallback("bloom_intensity", settingsCallback, this);
+ g_settings->registerChangedCallback("bloom_strength_factor", settingsCallback, this);
g_settings->registerChangedCallback("bloom_radius", settingsCallback, this);
+ g_settings->registerChangedCallback("saturation", settingsCallback, this);
m_fog_enabled = g_settings->getBool("enable_fog");
- m_user_exposure_factor = g_settings->getFloat("exposure_factor", 0.1f, 10.0f);
+ m_user_exposure_compensation = g_settings->getFloat("exposure_compensation", -1.0f, 1.0f);
m_bloom_enabled = g_settings->getBool("enable_bloom");
m_bloom_intensity = g_settings->getFloat("bloom_intensity", 0.01f, 1.0f);
- m_bloom_radius = g_settings->getFloat("bloom_radius", 1.0f, 64.0f);
+ m_bloom_strength = RenderingEngine::BASE_BLOOM_STRENGTH * g_settings->getFloat("bloom_strength_factor", 0.1f, 10.0f);
+ m_bloom_radius = g_settings->getFloat("bloom_radius", 0.1f, 8.0f);
}
~GameGlobalShaderConstantSetter()
m_animation_timer_vertex.set(&animation_timer_f, services);
m_animation_timer_pixel.set(&animation_timer_f, services);
+ float animation_timer_delta_f = (float)m_client->getEnv().getFrameTimeDelta() / 100000.f;
+ m_animation_timer_delta_vertex.set(&animation_timer_delta_f, services);
+ m_animation_timer_delta_pixel.set(&animation_timer_delta_f, services);
+
float eye_position_array[3];
v3f epos = m_client->getEnv().getLocalPlayer()->getEyePosition();
epos.getAs3Values(eye_position_array);
m_texel_size0.set(m_texel_size0_values.data(), services);
- float exposure_factor = RenderingEngine::DEFAULT_EXPOSURE_FACTOR * m_user_exposure_factor;
- if (std::isnan(exposure_factor))
- exposure_factor = RenderingEngine::DEFAULT_EXPOSURE_FACTOR;
- m_exposure_factor_pixel.set(&exposure_factor, services);
+ const AutoExposure &exposure_params = m_client->getEnv().getLocalPlayer()->getLighting().exposure;
+ std::array<float, 7> exposure_buffer = {
+ std::pow(2.0f, exposure_params.luminance_min),
+ std::pow(2.0f, exposure_params.luminance_max),
+ exposure_params.exposure_correction,
+ exposure_params.speed_dark_bright,
+ exposure_params.speed_bright_dark,
+ exposure_params.center_weight_power,
+ powf(2.f, m_user_exposure_compensation)
+ };
+ m_exposure_params_pixel.set(exposure_buffer.data(), services);
if (m_bloom_enabled) {
m_bloom_intensity_pixel.set(&m_bloom_intensity, services);
m_bloom_radius_pixel.set(&m_bloom_radius, services);
+ m_bloom_strength_pixel.set(&m_bloom_strength, services);
}
+ float saturation = m_client->getEnv().getLocalPlayer()->getLighting().saturation;
+ m_saturation_pixel.set(&saturation, services);
}
void onSetMaterial(const video::SMaterial &material)
float damage_flash;
float update_draw_list_timer;
+ float touch_blocks_timer;
f32 fog_range;
bool look_for_object, const v3s16 &camera_offset);
void handlePointingAtNothing(const ItemStack &playerItem);
void handlePointingAtNode(const PointedThing &pointed,
- const ItemStack &selected_item, const ItemStack &hand_item, f32 dtime);
+ const ItemStack &selected_item, const ItemStack &hand_item,
+ const ItemStack &place_item, f32 dtime);
void handlePointingAtObject(const PointedThing &pointed, const ItemStack &playeritem,
const v3f &player_position, bool show_debug);
void handleDigging(const PointedThing &pointed, const v3s16 &nodepos,
void updateChat(f32 dtime);
bool nodePlacement(const ItemDefinition &selected_def, const ItemStack &selected_item,
- const v3s16 &nodepos, const v3s16 &neighbourpos, const PointedThing &pointed,
+ const v3s16 &nodepos, const v3s16 &neighborpos, const PointedThing &pointed,
const NodeMetadata *meta);
static const ClientEventHandler clientEventHandler[CLIENTEVENT_MAX];
f32 getSensitivityScaleFactor() const;
+ ClientDynamicInfo getCurrentDynamicInfo() const;
InputHandler *input = nullptr;
Client *client = nullptr;
Server *server = nullptr;
+ ClientDynamicInfo client_display_info{};
+ float dynamic_info_send_timer = 0;
+
IWritableTextureSource *texture_src = nullptr;
IWritableShaderSource *shader_src = nullptr;
// this happens in pause menu in singleplayer
bool m_is_paused = false;
-#if IRRLICHT_VERSION_MT_REVISION < 5
- int m_reset_HW_buffer_counter = 0;
-#endif
-
#ifdef HAVE_TOUCHSCREENGUI
bool m_cache_hold_aux1;
bool m_touch_use_crosshair;
&& client->checkPrivilege("fast");
#endif
- irr::core::dimension2d<u32> previous_screen_size(g_settings->getU16("screen_w"),
+ v2u32 previous_screen_size(g_settings->getU16("screen_w"),
g_settings->getU16("screen_h"));
while (m_rendering_engine->run()
&& !(*kill || g_gamecallback->shutdown_requested
|| (server && server->isShutdownRequested()))) {
- const irr::core::dimension2d<u32> ¤t_screen_size =
- m_rendering_engine->get_video_driver()->getScreenSize();
+ // Calculate dtime =
+ // m_rendering_engine->run() from this iteration
+ // + Sleep time until the wanted FPS are reached
+ draw_times.limit(device, &dtime);
+
+ const auto current_dynamic_info = getCurrentDynamicInfo();
+ if (!current_dynamic_info.equal(client_display_info)) {
+ client_display_info = current_dynamic_info;
+ dynamic_info_send_timer = 0.2f;
+ }
+
+ if (dynamic_info_send_timer > 0) {
+ dynamic_info_send_timer -= dtime;
+ if (dynamic_info_send_timer <= 0) {
+ client->sendUpdateClientInfo(current_dynamic_info);
+ }
+ }
+
+ const auto ¤t_screen_size = current_dynamic_info.render_target_size;
+
// 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
if (previous_screen_size != current_screen_size &&
current_screen_size != irr::core::dimension2d<u32>(0,0) &&
g_settings->getBool("autosave_screensize")) {
- g_settings->setU16("screen_w", current_screen_size.Width);
- g_settings->setU16("screen_h", current_screen_size.Height);
+ g_settings->setU16("screen_w", current_screen_size.X);
+ g_settings->setU16("screen_h", current_screen_size.Y);
previous_screen_size = current_screen_size;
}
- // Calculate dtime =
- // m_rendering_engine->run() from this iteration
- // + Sleep time until the wanted FPS are reached
- draw_times.limit(device, &dtime);
-
// Prepare render data for next iteration
updateStats(&stats, draw_times, dtime);
processQueues();
m_game_ui->clearInfoText();
- hud->resizeHotbar();
-
updateProfilers(stats, draw_times, dtime);
processUserInput(dtime);
void Game::shutdown()
{
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);
- }
-#endif
+
auto formspec = m_game_ui->getFormspecGUI();
if (formspec)
formspec->quitMenu();
if (client->modsLoaded())
client->getScript()->on_camera_ready(camera);
client->setCamera(camera);
+#ifdef HAVE_TOUCHSCREENGUI
+ if (g_touchscreengui) {
+ g_touchscreengui->setUseCrosshair(!isNoCrosshairAllowed());
+ }
+#endif
/* Clouds
*/
if (g_gamecallback->changepassword_requested) {
(new GUIPasswordChange(guienv, guiroot, -1,
- &g_menumgr, client, texture_src))->drop();
+ &g_menumgr, client, texture_src))->drop();
g_gamecallback->changepassword_requested = false;
}
if (g_gamecallback->changevolume_requested) {
(new GUIVolumeChange(guienv, guiroot, -1,
- &g_menumgr, texture_src))->drop();
+ &g_menumgr, texture_src))->drop();
g_gamecallback->changevolume_requested = false;
}
if (g_gamecallback->keyconfig_requested) {
(new GUIKeyChangeMenu(guienv, guiroot, -1,
- &g_menumgr, texture_src))->drop();
+ &g_menumgr, texture_src))->drop();
g_gamecallback->keyconfig_requested = false;
}
} else if (wasKeyDown(KeyType::MINIMAP)) {
toggleMinimap(isKeyDown(KeyType::SNEAK));
} else if (wasKeyDown(KeyType::TOGGLE_CHAT)) {
- m_game_ui->toggleChat();
+ m_game_ui->toggleChat(client);
} else if (wasKeyDown(KeyType::TOGGLE_FOG)) {
toggleFog();
} else if (wasKeyDown(KeyType::TOGGLE_UPDATE_CAMERA)) {
/* Item selection using mouse wheel
*/
*new_playeritem = player->getWieldIndex();
-
s32 wheel = input->getMouseWheel();
u16 max_item = MYMIN(PLAYER_INVENTORY_SIZE - 1,
- player->hud_hotbar_itemcount - 1);
+ player->hud_hotbar_itemcount - 1);
s32 dir = wheel;
break;
}
}
+
+ // Clamp selection again in case it wasn't changed but max_item was
+ *new_playeritem = MYMIN(*new_playeritem, max_item);
}
void Game::updateCameraDirection(CameraOrientation *cam, float dtime)
{
+#ifndef __ANDROID__
+ if (isMenuActive())
+ device->getCursorControl()->setRelativeMode(false);
+ else
+ device->getCursorControl()->setRelativeMode(true);
+#endif
+
if ((device->isWindowActive() && device->isWindowFocused()
&& !isMenuActive()) || input->isRandom()) {
return tan(fov_y / 2.0f) * 1.3763818698f;
}
+ClientDynamicInfo Game::getCurrentDynamicInfo() const
+{
+ v2u32 screen_size = RenderingEngine::getWindowSize();
+ f32 density = RenderingEngine::getDisplayDensity();
+ f32 gui_scaling = g_settings->getFloat("gui_scaling") * density;
+ f32 hud_scaling = g_settings->getFloat("hud_scaling") * density;
+
+ return {
+ screen_size, gui_scaling, hud_scaling,
+ ClientDynamicInfo::calculateMaxFSSize(screen_size)
+ };
+}
+
void Game::updateCameraOrientation(CameraOrientation *cam, float dtime)
{
#ifdef HAVE_TOUCHSCREENGUI
);
}
+ // Orbit Tilt:
+ sky->setBodyOrbitTilt(event->set_sky->body_orbit_tilt);
+
delete event->set_sky;
}
// Update sound listener
v3s16 camera_offset = camera->getOffset();
sound->updateListener(camera->getCameraNode()->getPosition() + intToFloat(camera_offset, BS),
- v3f(0, 0, 0), // velocity
- camera->getDirection(),
- camera->getCameraNode()->getUpVector());
+ v3f(0, 0, 0), // velocity
+ camera->getDirection(),
+ camera->getCameraNode()->getUpVector());
bool mute_sound = g_settings->getBool("mute_sound");
if (mute_sound) {
Calculate what block is the crosshair pointing to
*/
- ItemStack selected_item, hand_item;
+ ItemStack selected_item, hand_item, offhand_item, place_item;
const ItemStack &tool_item = player->getWieldedItem(&selected_item, &hand_item);
const ItemDefinition &selected_def = selected_item.getDefinition(itemdef_manager);
!runData.btn_down_for_dig,
camera_offset);
+ player->getOffhandWieldedItem(&offhand_item, &place_item, itemdef_manager, pointed);
+
if (pointed != runData.pointed_old)
infostream << "Pointing at " << pointed.dump() << std::endl;
!client->getScript()->on_item_use(selected_item, pointed)))
client->interact(INTERACT_USE, pointed);
} else if (pointed.type == POINTEDTHING_NODE) {
- handlePointingAtNode(pointed, selected_item, hand_item, dtime);
+ handlePointingAtNode(pointed, selected_item, hand_item, place_item, dtime);
} else if (pointed.type == POINTEDTHING_OBJECT) {
v3f player_position = player->getPosition();
bool basic_debug_allowed = client->checkPrivilege("debug") || (player->hud_flags & HUD_FLAG_BASIC_DEBUG);
if (wasKeyPressed(KeyType::DIG) && client->modsLoaded())
client->getScript()->on_item_use(selected_item, pointed);
} else if (wasKeyPressed(KeyType::PLACE)) {
- handlePointingAtNothing(selected_item);
+ handlePointingAtNothing(place_item);
}
runData.pointed_old = pointed;
if (runData.punching || wasKeyPressed(KeyType::DIG))
- camera->setDigging(0); // dig animation
+ camera->setDigging(0, MAINHAND); // dig animation
input->clearWasKeyPressed();
input->clearWasKeyReleased();
{
std::vector<aabb3f> *selectionboxes = hud->getSelectionBoxes();
selectionboxes->clear();
- hud->setSelectedFaceNormal(v3f(0.0, 0.0, 0.0));
+ hud->setSelectedFaceNormal(v3f());
static thread_local const bool show_entity_selectionbox = g_settings->getBool(
"show_entity_selectionbox");
v3f pos = runData.selected_object->getPosition();
selectionboxes->push_back(aabb3f(selection_box));
hud->setSelectionPos(pos, camera_offset);
+ GenericCAO* gcao = dynamic_cast<GenericCAO*>(runData.selected_object);
+ if (gcao != nullptr && gcao->getProperties().rotate_selectionbox)
+ hud->setSelectionRotation(gcao->getSceneNode()->getAbsoluteTransformation().getRotationDegrees());
+ else
+ hud->setSelectionRotation(v3f());
}
+ hud->setSelectedFaceNormal(result.raw_intersection_normal);
} else if (result.type == POINTEDTHING_NODE) {
// Update selection boxes
MapNode n = map.getNode(result.node_undersurface);
}
hud->setSelectionPos(intToFloat(result.node_undersurface, BS),
camera_offset);
- hud->setSelectedFaceNormal(v3f(
- result.intersection_normal.X,
- result.intersection_normal.Y,
- result.intersection_normal.Z));
+ hud->setSelectionRotation(v3f());
+ hud->setSelectedFaceNormal(result.intersection_normal);
}
// Update selection mesh light level and vertex colors
void Game::handlePointingAtNode(const PointedThing &pointed,
- const ItemStack &selected_item, const ItemStack &hand_item, f32 dtime)
+ const ItemStack &selected_item, const ItemStack &hand_item,
+ const ItemStack &place_item, f32 dtime)
{
v3s16 nodepos = pointed.node_undersurface;
- v3s16 neighbourpos = pointed.node_abovesurface;
+ v3s16 neighborpos = pointed.node_abovesurface;
/*
Check information text of node
infostream << "Place button pressed while looking at ground" << std::endl;
// Placing animation (always shown for feedback)
- camera->setDigging(1);
+ if (place_item == selected_item)
+ camera->setDigging(1, MAINHAND);
+ else
+ camera->setDigging(1, OFFHAND);
soundmaker->m_player_rightpunch_sound = SimpleSoundSpec();
// make that happen
// And also set the sound and send the interact
// But first check for meta formspec and rightclickable
- auto &def = selected_item.getDefinition(itemdef_manager);
- bool placed = nodePlacement(def, selected_item, nodepos, neighbourpos,
+ auto &def = place_item.getDefinition(itemdef_manager);
+ bool placed = nodePlacement(def, place_item, nodepos, neighborpos,
pointed, meta);
if (placed && client->modsLoaded())
}
bool Game::nodePlacement(const ItemDefinition &selected_def,
- const ItemStack &selected_item, const v3s16 &nodepos, const v3s16 &neighbourpos,
+ const ItemStack &selected_item, const v3s16 &nodepos, const v3s16 &neighborpos,
const PointedThing &pointed, const NodeMetadata *meta)
{
const auto &prediction = selected_def.node_placement_prediction;
verbosestream << "Node placement prediction for "
<< selected_def.name << " is " << prediction << std::endl;
- v3s16 p = neighbourpos;
+ v3s16 p = neighborpos;
// Place inside node itself if buildable_to
MapNode n_under = map.getNode(nodepos, &is_valid_position);
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;
+ // Compare core.item_place_node() for what the server does with param2
+ MapNode predicted_node(id, 0, 0);
const u8 place_param2 = selected_def.place_param2;
if (place_param2) {
- param2 = place_param2;
+ predicted_node.setParam2(place_param2);
} else if (predicted_f.param_type_2 == CPT2_WALLMOUNTED ||
predicted_f.param_type_2 == CPT2_COLORED_WALLMOUNTED) {
- v3s16 dir = nodepos - neighbourpos;
+ v3s16 dir = nodepos - neighborpos;
if (abs(dir.Y) > MYMAX(abs(dir.X), abs(dir.Z))) {
- param2 = dir.Y < 0 ? 1 : 0;
+ predicted_node.setParam2(dir.Y < 0 ? 1 : 0);
} else if (abs(dir.X) > abs(dir.Z)) {
- param2 = dir.X < 0 ? 3 : 2;
+ predicted_node.setParam2(dir.X < 0 ? 3 : 2);
} else {
- param2 = dir.Z < 0 ? 5 : 4;
+ predicted_node.setParam2(dir.Z < 0 ? 5 : 4);
}
} 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);
if (abs(dir.X) > abs(dir.Z)) {
- param2 = dir.X < 0 ? 3 : 1;
+ predicted_node.setParam2(dir.X < 0 ? 3 : 1);
} else {
- param2 = dir.Z < 0 ? 2 : 0;
+ predicted_node.setParam2(dir.Z < 0 ? 2 : 0);
}
}
// 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),
- v3s16(-1, 0, 0),
- v3s16(0, 0, 1),
- v3s16(0, 0, -1),
- };
+ int an = itemgroup_get(predicted_f.groups, "attached_node");
+ if (an != 0) {
v3s16 pp;
- if (predicted_f.param_type_2 == CPT2_WALLMOUNTED ||
- predicted_f.param_type_2 == CPT2_COLORED_WALLMOUNTED)
- pp = p + wallmounted_dirs[param2];
- else
+ if (an == 3) {
pp = p + v3s16(0, -1, 0);
+ } else if (an == 4) {
+ pp = p + v3s16(0, 1, 0);
+ } else if (an == 2) {
+ if (predicted_f.param_type_2 == CPT2_FACEDIR ||
+ predicted_f.param_type_2 == CPT2_COLORED_FACEDIR ||
+ predicted_f.param_type_2 == CPT2_4DIR ||
+ predicted_f.param_type_2 == CPT2_COLORED_4DIR) {
+ pp = p + facedir_dirs[predicted_node.getFaceDir(nodedef)];
+ } else {
+ pp = p;
+ }
+ } else if (predicted_f.param_type_2 == CPT2_WALLMOUNTED ||
+ predicted_f.param_type_2 == CPT2_COLORED_WALLMOUNTED) {
+ pp = p + predicted_node.getWallMountedDir(nodedef);
+ } else {
+ pp = p + v3s16(0, -1, 0);
+ }
if (!nodedef->get(map.getNode(pp)).walkable) {
soundmaker->m_player_rightpunch_sound = selected_def.sound_place_failed;
if (!indexstr.empty()) {
s32 index = mystoi(indexstr);
if (predicted_f.param_type_2 == CPT2_COLOR) {
- param2 = index;
+ predicted_node.setParam2(index);
} else if (predicted_f.param_type_2 == CPT2_COLORED_WALLMOUNTED) {
// param2 = pure palette index + other
- param2 = (index & 0xf8) | (param2 & 0x07);
+ predicted_node.setParam2((index & 0xf8) | (predicted_node.getParam2() & 0x07));
} else if (predicted_f.param_type_2 == CPT2_COLORED_FACEDIR) {
// param2 = pure palette index + other
- param2 = (index & 0xe0) | (param2 & 0x1f);
+ predicted_node.setParam2((index & 0xe0) | (predicted_node.getParam2() & 0x1f));
} else if (predicted_f.param_type_2 == CPT2_COLORED_4DIR) {
// param2 = pure palette index + other
- param2 = (index & 0xfc) | (param2 & 0x03);
+ predicted_node.setParam2((index & 0xfc) | (predicted_node.getParam2() & 0x03));
}
}
}
// Add node to client map
- MapNode n(id, 0, param2);
-
try {
LocalPlayer *player = client->getEnv().getLocalPlayer();
- // Dont place node when player would be inside new node
+ // Don't place node when player would be inside new node
// NOTE: This is to be eventually implemented by a mod as client-side Lua
- if (!nodedef->get(n).walkable ||
+ if (!predicted_f.walkable ||
g_settings->getBool("enable_build_where_you_stand") ||
(client->checkPrivilege("noclip") && g_settings->getBool("noclip")) ||
- (nodedef->get(n).walkable &&
- neighbourpos != player->getStandingNodePos() + v3s16(0, 1, 0) &&
- neighbourpos != player->getStandingNodePos() + v3s16(0, 2, 0))) {
+ (predicted_f.walkable &&
+ neighborpos != player->getStandingNodePos() + v3s16(0, 1, 0) &&
+ neighborpos != player->getStandingNodePos() + v3s16(0, 2, 0))) {
// This triggers the required mesh update too
- client->addNode(p, n);
+ client->addNode(p, predicted_node);
// Report to server
client->interact(INTERACT_PLACE, pointed);
// A node is predicted, also play a sound
client->setCrack(-1, nodepos);
}
- camera->setDigging(0); // Dig animation
+ camera->setDigging(0, MAINHAND); // Dig animation
}
void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime,
direct_brightness = client->getEnv().getClientMap()
.getBackgroundBrightness(MYMIN(runData.fog_range * 1.2, 60 * BS),
daynight_ratio, (int)(old_brightness * 255.5), &sunlight_seen)
- / 255.0;
+ / 255.0;
}
float time_of_day_smooth = runData.time_of_day_smooth;
if (client->updateWieldedItem()) {
// Update wielded tool
- ItemStack selected_item, hand_item;
+ ItemStack selected_item, hand_item, offhand_item;
ItemStack &tool_item = player->getWieldedItem(&selected_item, &hand_item);
- camera->wield(tool_item);
+ camera->wield(tool_item, MAINHAND);
+ player->getOffhandWieldedItem(&offhand_item, nullptr, itemdef_manager, PointedThing());
+ camera->wield(offhand_item, OFFHAND);
}
/*
changed much
*/
runData.update_draw_list_timer += dtime;
+ runData.touch_blocks_timer += dtime;
+
+ bool draw_list_updated = false;
float update_draw_list_delta = 0.2f;
runData.update_draw_list_timer = 0;
client->getEnv().getClientMap().updateDrawList();
runData.update_draw_list_last_cam_dir = camera_direction;
+ draw_list_updated = true;
+ }
+
+ if (runData.touch_blocks_timer > update_draw_list_delta && !draw_list_updated) {
+ client->getEnv().getClientMap().touchMapBlocks();
+ runData.touch_blocks_timer = 0;
}
if (RenderingEngine::get_shadow_renderer()) {
/*
==================== End scene ====================
*/
-#if IRRLICHT_VERSION_MT_REVISION < 5
- if (++m_reset_HW_buffer_counter > 500) {
- /*
- Periodically remove all mesh HW buffers.
-
- Work around for a quirk in Irrlicht where a HW buffer is only
- released after 20000 iterations (triggered from endScene()).
-
- Without this, all loaded but unused meshes will retain their HW
- buffers for at least 5 minutes, at which point looking up the HW buffers
- becomes a bottleneck and the framerate drops (as much as 30%).
-
- Tests showed that numbers between 50 and 1000 are good, so picked 500.
- There are no other public Irrlicht APIs that allow interacting with the
- HW buffers without tracking the status of every individual mesh.
-
- The HW buffers for _visible_ meshes will be reinitialized in the next frame.
- */
- infostream << "Game::updateFrame(): Removing all HW buffers." << std::endl;
- driver->removeAllHardwareBuffers();
- m_reset_HW_buffer_counter = 0;
- }
-#endif
driver->endScene();
m_cache_enable_fog = g_settings->getBool("enable_fog");
m_cache_mouse_sensitivity = g_settings->getFloat("mouse_sensitivity", 0.001f, 10.0f);
m_cache_joystick_frustum_sensitivity = std::max(g_settings->getFloat("joystick_frustum_sensitivity"), 0.001f);
- m_repeat_place_time = g_settings->getFloat("repeat_place_time", 0.25f, 2.0);
+ m_repeat_place_time = g_settings->getFloat("repeat_place_time", 0.16f, 2.0);
m_cache_enable_noclip = g_settings->getBool("noclip");
m_cache_enable_free_move = g_settings->getBool("free_move");