aboutsummaryrefslogtreecommitdiff
path: root/src/game.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/game.cpp')
-rw-r--r--src/game.cpp594
1 files changed, 356 insertions, 238 deletions
diff --git a/src/game.cpp b/src/game.cpp
index 11e868a80..23f261cfd 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -40,7 +40,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "guiPasswordChange.h"
#include "guiVolumeChange.h"
#include "hud.h"
-#include "logoutputbuffer.h"
#include "mainmenumanager.h"
#include "mapblock.h"
#include "nodedef.h" // Needed for determining pointing to nodes
@@ -58,6 +57,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "util/pointedthing.h"
#include "version.h"
#include "minimap.h"
+#include "mapblock_mesh.h"
#include "sound.h"
@@ -176,19 +176,6 @@ struct LocalFormspecHandler : public TextDest {
}
}
- if (m_formname == "MT_CHAT_MENU") {
- assert(m_client != 0);
-
- if ((fields.find("btn_send") != fields.end()) ||
- (fields.find("quit") != fields.end())) {
- StringMap::const_iterator it = fields.find("f_text");
- if (it != fields.end())
- m_client->typeChatMessage(utf8_to_wide(it->second));
-
- return;
- }
- }
-
if (m_formname == "MT_DEATH_SCREEN") {
assert(m_client != 0);
@@ -286,23 +273,70 @@ inline bool isPointableNode(const MapNode &n,
(liquids_pointable && features.isLiquid());
}
+static inline void getNeighborConnectingFace(v3s16 p, INodeDefManager *nodedef,
+ ClientMap *map, MapNode n, u8 bitmask, u8 *neighbors)
+{
+ MapNode n2 = map->getNodeNoEx(p);
+ if (nodedef->nodeboxConnects(n, n2, bitmask))
+ *neighbors |= bitmask;
+}
+
+static inline u8 getNeighbors(v3s16 p, INodeDefManager *nodedef, ClientMap *map, MapNode n)
+{
+ u8 neighbors = 0;
+ const ContentFeatures &f = nodedef->get(n);
+ // locate possible neighboring nodes to connect to
+ if (f.drawtype == NDT_NODEBOX && f.node_box.type == NODEBOX_CONNECTED) {
+ v3s16 p2 = p;
+
+ p2.Y++;
+ getNeighborConnectingFace(p2, nodedef, map, n, 1, &neighbors);
+
+ p2 = p;
+ p2.Y--;
+ getNeighborConnectingFace(p2, nodedef, map, n, 2, &neighbors);
+
+ p2 = p;
+ p2.Z--;
+ getNeighborConnectingFace(p2, nodedef, map, n, 4, &neighbors);
+
+ p2 = p;
+ p2.X--;
+ getNeighborConnectingFace(p2, nodedef, map, n, 8, &neighbors);
+
+ p2 = p;
+ p2.Z++;
+ getNeighborConnectingFace(p2, nodedef, map, n, 16, &neighbors);
+
+ p2 = p;
+ p2.X++;
+ getNeighborConnectingFace(p2, nodedef, map, n, 32, &neighbors);
+ }
+
+ return neighbors;
+}
+
/*
Find what the player is pointing at
*/
-PointedThing getPointedThing(Client *client, v3f player_position,
- v3f camera_direction, v3f camera_position, core::line3d<f32> shootline,
- f32 d, bool liquids_pointable, bool look_for_object, v3s16 camera_offset,
- std::vector<aabb3f> &hilightboxes, ClientActiveObject *&selected_object)
+PointedThing getPointedThing(Client *client, Hud *hud, const v3f &player_position,
+ const v3f &camera_direction, const v3f &camera_position,
+ core::line3d<f32> shootline, f32 d, bool liquids_pointable,
+ bool look_for_object, const v3s16 &camera_offset,
+ ClientActiveObject *&selected_object)
{
PointedThing result;
- hilightboxes.clear();
+ std::vector<aabb3f> *selectionboxes = hud->getSelectionBoxes();
+ selectionboxes->clear();
+ static const bool show_entity_selectionbox = g_settings->getBool("show_entity_selectionbox");
+
selected_object = NULL;
INodeDefManager *nodedef = client->getNodeDefManager();
ClientMap &map = client->getEnv().getClientMap();
- f32 mindistance = BS * 1001;
+ f32 min_distance = BS * 1001;
// First try to find a pointed at active object
if (look_for_object) {
@@ -310,19 +344,20 @@ PointedThing getPointedThing(Client *client, v3f player_position,
camera_position, shootline);
if (selected_object != NULL) {
- if (selected_object->doShowSelectionBox()) {
+ if (show_entity_selectionbox &&
+ selected_object->doShowSelectionBox()) {
aabb3f *selection_box = selected_object->getSelectionBox();
// Box should exist because object was
// returned in the first place
assert(selection_box);
v3f pos = selected_object->getPosition();
- hilightboxes.push_back(aabb3f(
- selection_box->MinEdge + pos - intToFloat(camera_offset, BS),
- selection_box->MaxEdge + pos - intToFloat(camera_offset, BS)));
+ selectionboxes->push_back(aabb3f(
+ selection_box->MinEdge, selection_box->MaxEdge));
+ hud->setSelectionPos(pos, camera_offset);
}
- mindistance = (selected_object->getPosition() - camera_position).getLength();
+ min_distance = (selected_object->getPosition() - camera_position).getLength();
result.type = POINTEDTHING_OBJECT;
result.object_id = selected_object->getId();
@@ -331,14 +366,13 @@ PointedThing getPointedThing(Client *client, v3f player_position,
// That didn't work, try to find a pointed at node
-
v3s16 pos_i = floatToInt(player_position, BS);
/*infostream<<"pos_i=("<<pos_i.X<<","<<pos_i.Y<<","<<pos_i.Z<<")"
<<std::endl;*/
s16 a = d;
- s16 ystart = pos_i.Y + 0 - (camera_direction.Y < 0 ? a : 1);
+ s16 ystart = pos_i.Y - (camera_direction.Y < 0 ? a : 1);
s16 zstart = pos_i.Z - (camera_direction.Z < 0 ? a : 1);
s16 xstart = pos_i.X - (camera_direction.X < 0 ? a : 1);
s16 yend = pos_i.Y + 1 + (camera_direction.Y > 0 ? a : 1);
@@ -355,82 +389,139 @@ PointedThing getPointedThing(Client *client, v3f player_position,
if (xend == 32767)
xend = 32766;
- for (s16 y = ystart; y <= yend; y++)
- for (s16 z = zstart; z <= zend; z++)
+ v3s16 pointed_pos(0, 0, 0);
+
+ for (s16 y = ystart; y <= yend; y++) {
+ for (s16 z = zstart; z <= zend; z++) {
for (s16 x = xstart; x <= xend; x++) {
MapNode n;
bool is_valid_position;
+ v3s16 p(x, y, z);
- n = map.getNodeNoEx(v3s16(x, y, z), &is_valid_position);
- if (!is_valid_position)
+ n = map.getNodeNoEx(p, &is_valid_position);
+ if (!is_valid_position) {
continue;
-
- if (!isPointableNode(n, client, liquids_pointable))
+ }
+ if (!isPointableNode(n, client, liquids_pointable)) {
continue;
+ }
- std::vector<aabb3f> boxes = n.getSelectionBoxes(nodedef);
+ std::vector<aabb3f> boxes;
+ n.getSelectionBoxes(nodedef, &boxes, getNeighbors(p, nodedef, &map, n));
v3s16 np(x, y, z);
v3f npf = intToFloat(np, BS);
-
for (std::vector<aabb3f>::const_iterator
i = boxes.begin();
- i != boxes.end(); i++) {
+ i != boxes.end(); ++i) {
aabb3f box = *i;
box.MinEdge += npf;
box.MaxEdge += npf;
- for (u16 j = 0; j < 6; j++) {
- v3s16 facedir = g_6dirs[j];
- aabb3f facebox = box;
-
- f32 d = 0.001 * BS;
-
- if (facedir.X > 0)
- facebox.MinEdge.X = facebox.MaxEdge.X - d;
- else if (facedir.X < 0)
- facebox.MaxEdge.X = facebox.MinEdge.X + d;
- else if (facedir.Y > 0)
- facebox.MinEdge.Y = facebox.MaxEdge.Y - d;
- else if (facedir.Y < 0)
- facebox.MaxEdge.Y = facebox.MinEdge.Y + d;
- else if (facedir.Z > 0)
- facebox.MinEdge.Z = facebox.MaxEdge.Z - d;
- else if (facedir.Z < 0)
- facebox.MaxEdge.Z = facebox.MinEdge.Z + d;
-
- v3f centerpoint = facebox.getCenter();
- f32 distance = (centerpoint - camera_position).getLength();
-
- if (distance >= mindistance)
- continue;
-
- if (!facebox.intersectsWithLine(shootline))
- continue;
-
- v3s16 np_above = np + facedir;
-
- result.type = POINTEDTHING_NODE;
- result.node_undersurface = np;
- result.node_abovesurface = np_above;
- mindistance = distance;
-
- hilightboxes.clear();
-
- if (!g_settings->getBool("enable_node_highlighting")) {
- for (std::vector<aabb3f>::const_iterator
- i2 = boxes.begin();
- i2 != boxes.end(); i2++) {
- aabb3f box = *i2;
- box.MinEdge += npf + v3f(-d, -d, -d) - intToFloat(camera_offset, BS);
- box.MaxEdge += npf + v3f(d, d, d) - intToFloat(camera_offset, BS);
- hilightboxes.push_back(box);
- }
- }
+ v3f centerpoint = box.getCenter();
+ f32 distance = (centerpoint - camera_position).getLength();
+ if (distance >= min_distance) {
+ continue;
+ }
+ if (!box.intersectsWithLine(shootline)) {
+ continue;
}
+ result.type = POINTEDTHING_NODE;
+ min_distance = distance;
+ pointed_pos = np;
+ }
+ }
+ }
+ }
+
+ if (result.type == POINTEDTHING_NODE) {
+ f32 d = 0.001 * BS;
+ MapNode n = map.getNodeNoEx(pointed_pos);
+ v3f npf = intToFloat(pointed_pos, BS);
+ std::vector<aabb3f> boxes;
+ n.getSelectionBoxes(nodedef, &boxes, getNeighbors(pointed_pos, nodedef, &map, n));
+ f32 face_min_distance = 1000 * BS;
+ for (std::vector<aabb3f>::const_iterator
+ i = boxes.begin();
+ i != boxes.end(); ++i) {
+ aabb3f box = *i;
+ box.MinEdge += npf;
+ box.MaxEdge += npf;
+ for (u16 j = 0; j < 6; j++) {
+ v3s16 facedir = g_6dirs[j];
+ aabb3f facebox = box;
+ if (facedir.X > 0) {
+ facebox.MinEdge.X = facebox.MaxEdge.X - d;
+ } else if (facedir.X < 0) {
+ facebox.MaxEdge.X = facebox.MinEdge.X + d;
+ } else if (facedir.Y > 0) {
+ facebox.MinEdge.Y = facebox.MaxEdge.Y - d;
+ } else if (facedir.Y < 0) {
+ facebox.MaxEdge.Y = facebox.MinEdge.Y + d;
+ } else if (facedir.Z > 0) {
+ facebox.MinEdge.Z = facebox.MaxEdge.Z - d;
+ } else if (facedir.Z < 0) {
+ facebox.MaxEdge.Z = facebox.MinEdge.Z + d;
}
- } // for coords
+ v3f centerpoint = facebox.getCenter();
+ f32 distance = (centerpoint - camera_position).getLength();
+ if (distance >= face_min_distance)
+ continue;
+ if (!facebox.intersectsWithLine(shootline))
+ continue;
+ result.node_abovesurface = pointed_pos + facedir;
+ face_min_distance = distance;
+ }
+ }
+ selectionboxes->clear();
+ for (std::vector<aabb3f>::const_iterator
+ i = boxes.begin();
+ i != boxes.end(); ++i) {
+ aabb3f box = *i;
+ box.MinEdge += v3f(-d, -d, -d);
+ box.MaxEdge += v3f(d, d, d);
+ selectionboxes->push_back(box);
+ }
+ hud->setSelectionPos(intToFloat(pointed_pos, BS), camera_offset);
+ result.node_undersurface = pointed_pos;
+ }
+
+ // Update selection mesh light level and vertex colors
+ if (selectionboxes->size() > 0) {
+ v3f pf = hud->getSelectionPos();
+ v3s16 p = floatToInt(pf, BS);
+
+ // Get selection mesh light level
+ MapNode n = map.getNodeNoEx(p);
+ u16 node_light = getInteriorLight(n, -1, nodedef);
+ u16 light_level = node_light;
+ for (u8 i = 0; i < 6; i++) {
+ n = map.getNodeNoEx(p + g_6dirs[i]);
+ node_light = getInteriorLight(n, -1, nodedef);
+ if (node_light > light_level)
+ light_level = node_light;
+ }
+
+ video::SColor c = MapBlock_LightColor(255, light_level, 0);
+ u8 day = c.getRed();
+ u8 night = c.getGreen();
+ u32 daynight_ratio = client->getEnv().getDayNightRatio();
+ finalColorBlend(c, day, night, daynight_ratio);
+
+ // Modify final color a bit with time
+ u32 timer = porting::getTimeMs() % 5000;
+ float timerf = (float)(irr::core::PI * ((timer / 2500.0) - 0.5));
+ float sin_r = 0.08 * sin(timerf);
+ float sin_g = 0.08 * sin(timerf + irr::core::PI * 0.5);
+ float sin_b = 0.08 * sin(timerf + irr::core::PI);
+ c.setRed(core::clamp(core::round32(c.getRed() * (0.8 + sin_r)), 0, 255));
+ c.setGreen(core::clamp(core::round32(c.getGreen() * (0.8 + sin_g)), 0, 255));
+ c.setBlue(core::clamp(core::round32(c.getBlue() * (0.8 + sin_b)), 0, 255));
+
+ // Set mesh final color
+ hud->setSelectionMeshColor(c);
+ }
return result;
}
@@ -490,7 +581,7 @@ private:
color(color)
{}
};
- std::vector<Piece> m_log;
+ std::deque<Piece> m_log;
public:
u32 m_log_max_size;
@@ -513,12 +604,12 @@ public:
{
std::map<std::string, Meta> m_meta;
- for (std::vector<Piece>::const_iterator k = m_log.begin();
- k != m_log.end(); k++) {
+ for (std::deque<Piece>::const_iterator k = m_log.begin();
+ k != m_log.end(); ++k) {
const Piece &piece = *k;
for (Profiler::GraphValues::const_iterator i = piece.values.begin();
- i != piece.values.end(); i++) {
+ i != piece.values.end(); ++i) {
const std::string &id = i->first;
const float &value = i->second;
std::map<std::string, Meta>::iterator j =
@@ -550,7 +641,7 @@ public:
u32 next_color_i = 0;
for (std::map<std::string, Meta>::iterator i = m_meta.begin();
- i != m_meta.end(); i++) {
+ i != m_meta.end(); ++i) {
Meta &meta = i->second;
video::SColor color(255, 200, 200, 200);
@@ -566,7 +657,7 @@ public:
s32 meta_i = 0;
for (std::map<std::string, Meta>::const_iterator i = m_meta.begin();
- i != m_meta.end(); i++) {
+ i != m_meta.end(); ++i) {
const std::string &id = i->first;
const Meta &meta = i->second;
s32 x = x_left;
@@ -601,8 +692,8 @@ public:
float lastscaledvalue = 0.0;
bool lastscaledvalue_exists = false;
- for (std::vector<Piece>::const_iterator j = m_log.begin();
- j != m_log.end(); j++) {
+ for (std::deque<Piece>::const_iterator j = m_log.begin();
+ j != m_log.end(); ++j) {
const Piece &piece = *j;
float value = 0;
bool value_exists = false;
@@ -871,15 +962,18 @@ public:
services->setPixelShaderConstant("yawVec", (irr::f32 *)&minimap_yaw_vec, 3);
// Uniform sampler layers
- int layer0 = 0;
- int layer1 = 1;
- int layer2 = 2;
// before 1.8 there isn't a "integer interface", only float
#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8)
+ f32 layer0 = 0;
+ f32 layer1 = 1;
+ f32 layer2 = 2;
services->setPixelShaderConstant("baseTexture" , (irr::f32 *)&layer0, 1);
services->setPixelShaderConstant("normalTexture" , (irr::f32 *)&layer1, 1);
services->setPixelShaderConstant("textureFlags" , (irr::f32 *)&layer2, 1);
#else
+ s32 layer0 = 0;
+ s32 layer1 = 1;
+ s32 layer2 = 2;
services->setPixelShaderConstant("baseTexture" , (irr::s32 *)&layer0, 1);
services->setPixelShaderConstant("normalTexture" , (irr::s32 *)&layer1, 1);
services->setPixelShaderConstant("textureFlags" , (irr::s32 *)&layer2, 1);
@@ -1040,27 +1134,6 @@ static inline void create_formspec_menu(GUIFormSpecMenu **cur_formspec,
#define SIZE_TAG "size[11,5.5,true]" // Fixed size on desktop
#endif
-static void show_chat_menu(GUIFormSpecMenu **cur_formspec,
- InventoryManager *invmgr, IGameDef *gamedef,
- IWritableTextureSource *tsrc, IrrlichtDevice *device,
- Client *client, std::string text)
-{
- std::string formspec =
- FORMSPEC_VERSION_STRING
- SIZE_TAG
- "field[3,2.35;6,0.5;f_text;;" + text + "]"
- "button_exit[4,3;3,0.5;btn_send;" + wide_to_utf8(wstrgettext("Proceed")) + "]"
- ;
-
- /* Create menu */
- /* Note: FormspecFormSource and LocalFormspecHandler
- * are deleted by guiFormSpecMenu */
- FormspecFormSource *fs_src = new FormspecFormSource(formspec);
- LocalFormspecHandler *txt_dst = new LocalFormspecHandler("MT_CHAT_MENU", client);
-
- create_formspec_menu(cur_formspec, invmgr, gamedef, tsrc, device, fs_src, txt_dst, NULL);
-}
-
static void show_deathscreen(GUIFormSpecMenu **cur_formspec,
InventoryManager *invmgr, IGameDef *gamedef,
IWritableTextureSource *tsrc, IrrlichtDevice *device, Client *client)
@@ -1089,32 +1162,32 @@ static void show_pause_menu(GUIFormSpecMenu **cur_formspec,
bool singleplayermode)
{
#ifdef __ANDROID__
- std::string control_text = wide_to_utf8(wstrgettext("Default Controls:\n"
- "No menu visible:\n"
- "- single tap: button activate\n"
- "- double tap: place/use\n"
- "- slide finger: look around\n"
- "Menu/Inventory visible:\n"
- "- double tap (outside):\n"
- " -->close\n"
- "- touch stack, touch slot:\n"
- " --> move stack\n"
- "- touch&drag, tap 2nd finger\n"
- " --> place single item to slot\n"
- ));
+ std::string control_text = strgettext("Default Controls:\n"
+ "No menu visible:\n"
+ "- single tap: button activate\n"
+ "- double tap: place/use\n"
+ "- slide finger: look around\n"
+ "Menu/Inventory visible:\n"
+ "- double tap (outside):\n"
+ " -->close\n"
+ "- touch stack, touch slot:\n"
+ " --> move stack\n"
+ "- touch&drag, tap 2nd finger\n"
+ " --> place single item to slot\n"
+ );
#else
- std::string control_text = wide_to_utf8(wstrgettext("Default Controls:\n"
- "- WASD: move\n"
- "- Space: jump/climb\n"
- "- Shift: sneak/go down\n"
- "- Q: drop item\n"
- "- I: inventory\n"
- "- Mouse: turn/look\n"
- "- Mouse left: dig/punch\n"
- "- Mouse right: place/use\n"
- "- Mouse wheel: select item\n"
- "- T: chat\n"
- ));
+ std::string control_text = strgettext("Default Controls:\n"
+ "- WASD: move\n"
+ "- Space: jump/climb\n"
+ "- Shift: sneak/go down\n"
+ "- Q: drop item\n"
+ "- I: inventory\n"
+ "- Mouse: turn/look\n"
+ "- Mouse left: dig/punch\n"
+ "- Mouse right: place/use\n"
+ "- Mouse wheel: select item\n"
+ "- T: chat\n"
+ );
#endif
float ypos = singleplayermode ? 0.5 : 0.1;
@@ -1122,23 +1195,23 @@ static void show_pause_menu(GUIFormSpecMenu **cur_formspec,
os << FORMSPEC_VERSION_STRING << SIZE_TAG
<< "button_exit[4," << (ypos++) << ";3,0.5;btn_continue;"
- << wide_to_utf8(wstrgettext("Continue")) << "]";
+ << strgettext("Continue") << "]";
if (!singleplayermode) {
os << "button_exit[4," << (ypos++) << ";3,0.5;btn_change_password;"
- << wide_to_utf8(wstrgettext("Change Password")) << "]";
+ << strgettext("Change Password") << "]";
}
#ifndef __ANDROID__
os << "button_exit[4," << (ypos++) << ";3,0.5;btn_sound;"
- << wide_to_utf8(wstrgettext("Sound Volume")) << "]";
+ << strgettext("Sound Volume") << "]";
os << "button_exit[4," << (ypos++) << ";3,0.5;btn_key_config;"
- << wide_to_utf8(wstrgettext("Change Keys")) << "]";
+ << strgettext("Change Keys") << "]";
#endif
os << "button_exit[4," << (ypos++) << ";3,0.5;btn_exit_menu;"
- << wide_to_utf8(wstrgettext("Exit to Menu")) << "]";
+ << strgettext("Exit to Menu") << "]";
os << "button_exit[4," << (ypos++) << ";3,0.5;btn_exit_os;"
- << wide_to_utf8(wstrgettext("Exit to OS")) << "]"
+ << strgettext("Exit to OS") << "]"
<< "textarea[7.5,0.25;3.9,6.25;;" << control_text << ";]"
<< "textarea[0.4,0.25;3.5,6;;" << PROJECT_NAME_C "\n"
<< g_build_info << "\n"
@@ -1163,7 +1236,7 @@ static void updateChat(Client &client, f32 dtime, bool show_debug,
ChatBackend &chat_backend, gui::IGUIStaticText *guitext_chat)
{
// Add chat log output for errors to be shown in chat
- static LogOutputBuffer chat_log_error_buf(LMT_ERROR);
+ static LogOutputBuffer chat_log_error_buf(g_logger, LL_ERROR);
// Get new messages from error log buffer
while (!chat_log_error_buf.empty()) {
@@ -1235,6 +1308,7 @@ struct KeyCache {
KEYMAP_ID_JUMP,
KEYMAP_ID_SPECIAL1,
KEYMAP_ID_SNEAK,
+ KEYMAP_ID_AUTORUN,
// Other
KEYMAP_ID_DROP,
@@ -1287,6 +1361,8 @@ void KeyCache::populate()
key[KEYMAP_ID_SPECIAL1] = getKeySetting("keymap_special1");
key[KEYMAP_ID_SNEAK] = getKeySetting("keymap_sneak");
+ key[KEYMAP_ID_AUTORUN] = getKeySetting("keymap_autorun");
+
key[KEYMAP_ID_DROP] = getKeySetting("keymap_drop");
key[KEYMAP_ID_INVENTORY] = getKeySetting("keymap_inventory");
key[KEYMAP_ID_CHAT] = getKeySetting("keymap_chat");
@@ -1488,12 +1564,13 @@ protected:
void dropSelectedItem();
void openInventory();
- void openConsole();
+ void openConsole(float height, const wchar_t *line=NULL);
void toggleFreeMove(float *statustext_time);
void toggleFreeMoveAlt(float *statustext_time, float *jump_timer);
void toggleFast(float *statustext_time);
void toggleNoClip(float *statustext_time);
void toggleCinematic(float *statustext_time);
+ void toggleAutorun(float *statustext_time);
void toggleChat(float *statustext_time, bool *flag);
void toggleHud(float *statustext_time, bool *flag);
@@ -1519,9 +1596,9 @@ protected:
void updateCamera(VolatileRunFlags *flags, u32 busy_time, f32 dtime,
float time_from_last_punch);
void updateSound(f32 dtime);
- void processPlayerInteraction(std::vector<aabb3f> &highlight_boxes,
- GameRunData *runData, f32 dtime, bool show_hud,
+ void processPlayerInteraction(GameRunData *runData, f32 dtime, bool show_hud,
bool show_debug);
+ void handlePointingAtNothing(GameRunData *runData, const ItemStack &playerItem);
void handlePointingAtNode(GameRunData *runData,
const PointedThing &pointed, const ItemDefinition &playeritem_def,
const ToolCapabilities &playeritem_toolcap, f32 dtime);
@@ -1531,8 +1608,7 @@ protected:
void handleDigging(GameRunData *runData, const PointedThing &pointed,
const v3s16 &nodepos, const ToolCapabilities &playeritem_toolcap,
f32 dtime);
- void updateFrame(std::vector<aabb3f> &highlight_boxes, ProfilerGraph *graph,
- RunStats *stats, GameRunData *runData,
+ void updateFrame(ProfilerGraph *graph, RunStats *stats, GameRunData *runData,
f32 dtime, const VolatileRunFlags &flags, const CameraOrientation &cam);
void updateGui(float *statustext_time, const RunStats &stats,
const GameRunData& runData, f32 dtime, const VolatileRunFlags &flags,
@@ -1548,6 +1624,10 @@ protected:
static void settingChangedCallback(const std::string &setting_name, void *data);
void readSettings();
+#ifdef __ANDROID__
+ void handleAndroidChatInput();
+#endif
+
private:
InputHandler *input;
@@ -1626,7 +1706,6 @@ private:
* a later release.
*/
bool m_cache_doubletap_jump;
- bool m_cache_enable_node_highlighting;
bool m_cache_enable_clouds;
bool m_cache_enable_particles;
bool m_cache_enable_fog;
@@ -1635,8 +1714,8 @@ private:
#ifdef __ANDROID__
bool m_cache_hold_aux1;
+ bool m_android_chat_open;
#endif
-
};
Game::Game() :
@@ -1664,8 +1743,6 @@ Game::Game() :
{
g_settings->registerChangedCallback("doubletap_jump",
&settingChangedCallback, this);
- g_settings->registerChangedCallback("enable_node_highlighting",
- &settingChangedCallback, this);
g_settings->registerChangedCallback("enable_clouds",
&settingChangedCallback, this);
g_settings->registerChangedCallback("enable_particles",
@@ -1715,8 +1792,6 @@ Game::~Game()
g_settings->deregisterChangedCallback("doubletap_jump",
&settingChangedCallback, this);
- g_settings->deregisterChangedCallback("enable_node_highlighting",
- &settingChangedCallback, this);
g_settings->deregisterChangedCallback("enable_clouds",
&settingChangedCallback, this);
g_settings->deregisterChangedCallback("enable_particles",
@@ -1803,8 +1878,6 @@ void Game::run()
&runData.fog_range,
client));
- std::vector<aabb3f> highlight_boxes;
-
set_light_table(g_settings->getFloat("display_gamma"));
#ifdef __ANDROID__
@@ -1812,7 +1885,9 @@ void Game::run()
&& client->checkPrivilege("fast");
#endif
- while (device->run() && !(*kill || g_gamecallback->shutdown_requested)) {
+ while (device->run()
+ && !(*kill || g_gamecallback->shutdown_requested
+ || (server && server->getShutdownRequested()))) {
/* Must be called immediately after a device->run() call because it
* uses device->getTimer()->getTime()
@@ -1852,17 +1927,23 @@ void Game::run()
updateCamera(&flags, draw_times.busy_time, dtime,
runData.time_from_last_punch);
updateSound(dtime);
- processPlayerInteraction(highlight_boxes, &runData, dtime,
- flags.show_hud, flags.show_debug);
- updateFrame(highlight_boxes, &graph, &stats, &runData, dtime,
- flags, cam_view);
+ processPlayerInteraction(&runData, dtime, flags.show_hud,
+ flags.show_debug);
+ updateFrame(&graph, &stats, &runData, dtime, flags, cam_view);
updateProfilerGraphs(&graph);
+
+ // Update if minimap has been disabled by the server
+ flags.show_minimap &= !client->isMinimapDisabledByServer();
}
}
void Game::shutdown()
{
+ if (g_settings->get("3d_mode") == "pageflip") {
+ driver->setRenderTarget(irr::video::ERT_STEREO_BOTH_BUFFERS);
+ }
+
showOverlayMessage(wgettext("Shutting down..."), 0, 0, false);
if (clouds)
@@ -2044,6 +2125,7 @@ bool Game::createClient(const std::string &playername,
camera = new Camera(smgr, *draw_control, gamedef);
if (!camera || !camera->successfullyCreated(*error_message))
return false;
+ client->setCamera(camera);
/* Clouds
*/
@@ -2147,7 +2229,7 @@ bool Game::initGui()
// Chat backend and console
gui_chat_console = new GUIChatConsole(guienv, guienv->getRootGUIElement(),
- -1, chat_backend, client);
+ -1, chat_backend, client, &g_menumgr);
if (!gui_chat_console) {
*error_message = "Could not allocate memory for chat console";
errorstream << *error_message << std::endl;
@@ -2166,7 +2248,7 @@ bool Game::initGui()
#ifdef HAVE_TOUCHSCREENGUI
if (g_touchscreengui)
- g_touchscreengui->init(texture_src, porting::getDisplayDensity());
+ g_touchscreengui->init(texture_src);
#endif
@@ -2562,7 +2644,17 @@ void Game::processUserInput(VolatileRunFlags *flags,
|| noMenuActive() == false
|| guienv->hasFocus(gui_chat_console)) {
input->clear();
+#ifdef HAVE_TOUCHSCREENGUI
+ g_touchscreengui->hide();
+#endif
+ }
+#ifdef HAVE_TOUCHSCREENGUI
+ else if (g_touchscreengui) {
+ /* on touchscreengui step may generate own input events which ain't
+ * what we want in case we just did clear them */
+ g_touchscreengui->step(dtime);
}
+#endif
if (!guienv->hasFocus(gui_chat_console) && gui_chat_console->isOpen()) {
gui_chat_console->closeConsoleAtOnce();
@@ -2571,18 +2663,11 @@ void Game::processUserInput(VolatileRunFlags *flags,
// Input handler step() (used by the random input generator)
input->step(dtime);
-#ifdef HAVE_TOUCHSCREENGUI
-
- if (g_touchscreengui) {
- g_touchscreengui->step(dtime);
- }
-
-#endif
#ifdef __ANDROID__
-
- if (current_formspec != 0)
+ if (current_formspec != NULL)
current_formspec->getAndroidUIInput();
-
+ else
+ handleAndroidChatInput();
#endif
// Increase timer for double tap of "keymap_jump"
@@ -2613,19 +2698,21 @@ void Game::processKeyboardInput(VolatileRunFlags *flags,
if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_DROP])) {
dropSelectedItem();
+ } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_AUTORUN])) {
+ toggleAutorun(statustext_time);
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_INVENTORY])) {
openInventory();
} else if (input->wasKeyDown(EscapeKey) || input->wasKeyDown(CancelKey)) {
- show_pause_menu(&current_formspec, client, gamedef, texture_src, device,
- simple_singleplayer_mode);
+ if (!gui_chat_console->isOpenInhibited()) {
+ show_pause_menu(&current_formspec, client, gamedef,
+ texture_src, device, simple_singleplayer_mode);
+ }
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_CHAT])) {
- show_chat_menu(&current_formspec, client, gamedef, texture_src, device,
- client, "");
+ openConsole(0.2, L"");
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_CMD])) {
- show_chat_menu(&current_formspec, client, gamedef, texture_src, device,
- client, "/");
+ openConsole(0.2, L"/");
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_CONSOLE])) {
- openConsole();
+ openConsole(1);
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_FREEMOVE])) {
toggleFreeMove(statustext_time);
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_JUMP])) {
@@ -2660,19 +2747,19 @@ void Game::processKeyboardInput(VolatileRunFlags *flags,
decreaseViewRange(statustext_time);
} else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_RANGESELECT])) {
toggleFullViewRange(statustext_time);
- } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_QUICKTUNE_NEXT]))
+ } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_QUICKTUNE_NEXT])) {
quicktune->next();
- else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_QUICKTUNE_PREV]))
+ } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_QUICKTUNE_PREV])) {
quicktune->prev();
- else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_QUICKTUNE_INC]))
+ } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_QUICKTUNE_INC])) {
quicktune->inc();
- else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_QUICKTUNE_DEC]))
+ } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_QUICKTUNE_DEC])) {
quicktune->dec();
- else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_DEBUG_STACKS])) {
+ } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_DEBUG_STACKS])) {
// Print debug stacks
dstream << "-----------------------------------------"
<< std::endl;
- dstream << DTIME << "Printing debug stacks:" << std::endl;
+ dstream << "Printing debug stacks:" << std::endl;
dstream << "-----------------------------------------"
<< std::endl;
debug_stacks_print();
@@ -2768,15 +2855,32 @@ void Game::openInventory()
}
-void Game::openConsole()
+void Game::openConsole(float height, const wchar_t *line)
{
- if (!gui_chat_console->isOpenInhibited()) {
- // Open up to over half of the screen
- gui_chat_console->openConsole(0.6);
- guienv->setFocus(gui_chat_console);
+#ifdef __ANDROID__
+ porting::showInputDialog(gettext("ok"), "", "", 2);
+ m_android_chat_open = true;
+#else
+ if (gui_chat_console->isOpenInhibited())
+ return;
+ gui_chat_console->openConsole(height);
+ if (line) {
+ gui_chat_console->setCloseOnEnter(true);
+ gui_chat_console->replaceAndAddToHistory(line);
}
+#endif
}
+#ifdef __ANDROID__
+void Game::handleAndroidChatInput()
+{
+ if (m_android_chat_open && porting::getInputDialogState() == 0) {
+ std::string text = porting::getInputDialogValue();
+ client->typeChatMessage(utf8_to_wide(text));
+ }
+}
+#endif
+
void Game::toggleFreeMove(float *statustext_time)
{
@@ -2842,6 +2946,16 @@ void Game::toggleCinematic(float *statustext_time)
statustext = msg[cinematic];
}
+// Add WoW-style autorun by toggling continuous forward.
+void Game::toggleAutorun(float *statustext_time)
+{
+ static const wchar_t *msg[] = { L"autorun disabled", L"autorun enabled" };
+ bool autorun_enabled = !g_settings->getBool("continuous_forward");
+ g_settings->set("continuous_forward", bool_to_cstr(autorun_enabled));
+
+ *statustext_time = 0;
+ statustext = msg[autorun_enabled ? 1 : 0];
+}
void Game::toggleChat(float *statustext_time, bool *flag)
{
@@ -2860,8 +2974,6 @@ void Game::toggleHud(float *statustext_time, bool *flag)
*flag = !*flag;
*statustext_time = 0;
statustext = msg[*flag];
- if (g_settings->getBool("enable_node_highlighting"))
- client->setHighlighted(client->getHighlighted(), *flag);
}
void Game::toggleMinimap(float *statustext_time, bool *flag,
@@ -2982,10 +3094,10 @@ void Game::toggleProfiler(float *statustext_time, u32 *profiler_current_page,
void Game::increaseViewRange(float *statustext_time)
{
- s16 range = g_settings->getS16("viewing_range_nodes_min");
+ s16 range = g_settings->getS16("viewing_range");
s16 range_new = range + 10;
- g_settings->set("viewing_range_nodes_min", itos(range_new));
- statustext = utf8_to_wide("Minimum viewing range changed to "
+ g_settings->set("viewing_range", itos(range_new));
+ statustext = utf8_to_wide("Viewing range changed to "
+ itos(range_new));
*statustext_time = 0;
}
@@ -2993,14 +3105,14 @@ void Game::increaseViewRange(float *statustext_time)
void Game::decreaseViewRange(float *statustext_time)
{
- s16 range = g_settings->getS16("viewing_range_nodes_min");
+ s16 range = g_settings->getS16("viewing_range");
s16 range_new = range - 10;
- if (range_new < 0)
- range_new = range;
+ if (range_new < 20)
+ range_new = 20;
- g_settings->set("viewing_range_nodes_min", itos(range_new));
- statustext = utf8_to_wide("Minimum viewing range changed to "
+ g_settings->set("viewing_range", itos(range_new));
+ statustext = utf8_to_wide("Viewing range changed to "
+ itos(range_new));
*statustext_time = 0;
}
@@ -3447,8 +3559,8 @@ void Game::updateSound(f32 dtime)
}
-void Game::processPlayerInteraction(std::vector<aabb3f> &highlight_boxes,
- GameRunData *runData, f32 dtime, bool show_hud, bool show_debug)
+void Game::processPlayerInteraction(GameRunData *runData,
+ f32 dtime, bool show_hud, bool show_debug)
{
LocalPlayer *player = client->getEnv().getLocalPlayer();
@@ -3506,25 +3618,17 @@ void Game::processPlayerInteraction(std::vector<aabb3f> &highlight_boxes,
PointedThing pointed = getPointedThing(
// input
- client, player_position, camera_direction,
+ client, hud, player_position, camera_direction,
camera_position, shootline, d,
playeritem_def.liquids_pointable,
!runData->ldown_for_dig,
camera_offset,
// output
- highlight_boxes,
runData->selected_object);
if (pointed != runData->pointed_old) {
infostream << "Pointing at " << pointed.dump() << std::endl;
-
- if (m_cache_enable_node_highlighting) {
- if (pointed.type == POINTEDTHING_NODE) {
- client->setHighlighted(pointed.node_undersurface, show_hud);
- } else {
- client->setHighlighted(pointed.node_undersurface, false);
- }
- }
+ hud->updateSelectionMesh(camera_offset);
}
/*
@@ -3548,6 +3652,7 @@ void Game::processPlayerInteraction(std::vector<aabb3f> &highlight_boxes,
infostream << "Pointing away from node"
<< " (stopped digging)" << std::endl;
runData->digging = false;
+ hud->updateSelectionMesh(camera_offset);
}
}
@@ -3585,6 +3690,8 @@ void Game::processPlayerInteraction(std::vector<aabb3f> &highlight_boxes,
} else if (input->getLeftState()) {
// When button is held down in air, show continuous animation
runData->left_punch = true;
+ } else if (input->getRightClicked()) {
+ handlePointingAtNothing(runData, playeritem);
}
runData->pointed_old = pointed;
@@ -3600,6 +3707,15 @@ void Game::processPlayerInteraction(std::vector<aabb3f> &highlight_boxes,
}
+void Game::handlePointingAtNothing(GameRunData *runData, const ItemStack &playerItem)
+{
+ infostream << "Right Clicked in Air" << std::endl;
+ PointedThing fauxPointed;
+ fauxPointed.type = POINTEDTHING_NOTHING;
+ client->interact(5, fauxPointed);
+}
+
+
void Game::handlePointingAtNode(GameRunData *runData,
const PointedThing &pointed, const ItemDefinition &playeritem_def,
const ToolCapabilities &playeritem_toolcap, f32 dtime)
@@ -3615,7 +3731,7 @@ void Game::handlePointingAtNode(GameRunData *runData,
NodeMetadata *meta = map.getNodeMetadata(nodepos);
if (meta) {
- infotext = utf8_to_wide(meta->getString("infotext"));
+ infotext = unescape_enriched(utf8_to_wide(meta->getString("infotext")));
} else {
MapNode n = map.getNodeNoEx(nodepos);
@@ -3671,11 +3787,15 @@ void Game::handlePointingAtNode(GameRunData *runData,
} else {
soundmaker->m_player_rightpunch_sound =
SimpleSoundSpec();
- }
- if (playeritem_def.node_placement_prediction == "" ||
- nodedef_manager->get(map.getNodeNoEx(nodepos)).rightclickable)
- client->interact(3, pointed); // Report to server
+ if (playeritem_def.node_placement_prediction == "" ||
+ nodedef_manager->get(map.getNodeNoEx(nodepos)).rightclickable) {
+ client->interact(3, pointed); // Report to server
+ } else {
+ soundmaker->m_player_rightpunch_sound =
+ playeritem_def.sound_place_failed;
+ }
+ }
}
}
}
@@ -3687,10 +3807,15 @@ void Game::handlePointingAtObject(GameRunData *runData,
const v3f &player_position,
bool show_debug)
{
- infotext = utf8_to_wide(runData->selected_object->infoText());
+ infotext = unescape_enriched(
+ utf8_to_wide(runData->selected_object->infoText()));
- if (infotext == L"" && show_debug) {
- infotext = utf8_to_wide(runData->selected_object->debugInfoText());
+ if (show_debug) {
+ if (infotext != L"") {
+ infotext += L"\n";
+ }
+ infotext += unescape_enriched(utf8_to_wide(
+ runData->selected_object->debugInfoText()));
}
if (input->getLeftState()) {
@@ -3854,9 +3979,9 @@ void Game::handleDigging(GameRunData *runData,
}
-void Game::updateFrame(std::vector<aabb3f> &highlight_boxes,
- ProfilerGraph *graph, RunStats *stats, GameRunData *runData,
- f32 dtime, const VolatileRunFlags &flags, const CameraOrientation &cam)
+void Game::updateFrame(ProfilerGraph *graph, RunStats *stats,
+ GameRunData *runData, f32 dtime, const VolatileRunFlags &flags,
+ const CameraOrientation &cam)
{
LocalPlayer *player = client->getEnv().getLocalPlayer();
@@ -3867,12 +3992,7 @@ void Game::updateFrame(std::vector<aabb3f> &highlight_boxes,
if (draw_control->range_all) {
runData->fog_range = 100000 * BS;
} else {
- runData->fog_range = draw_control->wanted_range * BS
- + 0.0 * MAP_BLOCKSIZE * BS;
- runData->fog_range = MYMIN(
- runData->fog_range,
- (draw_control->farthest_drawn + 20) * BS);
- runData->fog_range *= 0.9;
+ runData->fog_range = 0.9 * draw_control->wanted_range * BS;
}
/*
@@ -4048,7 +4168,7 @@ void Game::updateFrame(std::vector<aabb3f> &highlight_boxes,
}
draw_scene(driver, smgr, *camera, *client, player, *hud, *mapper,
- guienv, highlight_boxes, screensize, skycolor, flags.show_hud,
+ guienv, screensize, skycolor, flags.show_hud,
flags.show_minimap);
/*
@@ -4328,7 +4448,6 @@ void Game::settingChangedCallback(const std::string &setting_name, void *data)
void Game::readSettings()
{
m_cache_doubletap_jump = g_settings->getBool("doubletap_jump");
- m_cache_enable_node_highlighting = g_settings->getBool("enable_node_highlighting");
m_cache_enable_clouds = g_settings->getBool("enable_clouds");
m_cache_enable_particles = g_settings->getBool("enable_particles");
m_cache_enable_fog = g_settings->getBool("enable_fog");
@@ -4420,4 +4539,3 @@ void the_game(bool *kill,
errorstream << "ModError: " << error_message << std::endl;
}
}
-