# so see a full list at https://content.minetest.net/help/content_flags/
contentdb_flag_blacklist (ContentDB Flag Blacklist) string nonfree, desktop_default
+ # Maximum number of concurrent downloads. Downloads exceeding this limit will be queued.
+ contentdb_max_concurrent_downloads (ContentDB Max Concurrent Downloads) int 3
++
+[Cheat Menu]
+
+# Font to use for cheat menu
+cheat_menu_font (MenuFont) enum FM_Mono FM_Standard,FM_Mono,FM_Fallback,FM_Simple,FM_SimpleMono,FM_MaxMode,FM_Unspecified
+
+# (RGB value)
+cheat_menu_bg_color (Cell background color) v3f 255, 145, 88
+
+cheat_menu_bg_color_alpha (Cell background color alpha) int 192
+
+# (RGB value)
+cheat_menu_active_bg_color (Active cell background color) v3f 255, 87, 53
+
+cheat_menu_active_bg_color_alpha (Active cell background color alpha) int 192
+
+# (RGB value)
+cheat_menu_font_color (Font color) v3f 0, 0, 0
+
+cheat_menu_font_color_alpha (Font color alpha) int 255
+
+# (RGB value)
+cheat_menu_selected_font_color (Selected font color) v3f 255, 252, 88
+
+cheat_menu_selected_font_color_alpha (Selected font color alpha) int 255
+
+[Cheats]
+
+fullbright (Fullbright) bool false
+
+xray (XRay) bool false
+
+xray_nodes (XRay Nodes) string default:stone,mcl_core:stone
+
+priv_bypass (PrivBypass) bool true
+
+fastdig (FastDig) bool false
+
+fastplace (FastPlace) bool false
+
+autodig (AutoDig) bool false
+
+autoplace (AutoPlace) bool false
+
+prevent_natural_damage (NoFallDamage) bool true
+
+freecam (Freecam) bool false
+
+killaura (Killaura) bool false
+
+no_hurt_cam (NoHurtCam) bool false
+
+increase_tool_range (IncreasedRange) bool true
+
+increase_tool_range_plus (IncreasedRangePlus) bool true
+
+hud_flags_bypass (HUDBypass) bool true
+
+antiknockback (AntiKnockback) bool false
+
+entity_speed (GodMode) bool false
+
+jesus (Jesus) bool false
+
+instant_break (InstantBreak) bool false
+
+no_night (BrightNight) bool false
+
+coords (Coords) bool false
+
+point_liquids (PointLiquids) bool false
+
+log_particles (ParticleExploit) bool false
+
+spamclick (FastHit) bool false
+
+no_force_rotate (NoForceRotate) bool false
+
+enable_tracers (Tracers) bool false
+
+enable_esp (ESP) bool false
+
+no_slow (NoSlow) bool false
+
+ignore_status_messages (IgnoreStatus) bool true
+
+mark_deathmessages (Deathmessages) bool true
+
+autosneak (AutoSneak) bool false
+
+autoeject (AutoEject) bool false
+
+eject_items (AutoEject Items) string
+
+autotool (AutoTool) bool false
+
+autorespawn (AutoRespawn) bool false
+
+next_item (NextItem) bool false
+
+scaffold (Scaffold) bool false
+
+scaffold_plus (ScaffoldPlus) bool false
+
+block_water (BlockWater) bool false
+
+autotnt (PlaceOnTop) bool false
+
+replace (Replace) bool false
+
+crystal_pvp (CrystalPvP) bool false
+
+autototem (AutoTotem) bool false
+
+dont_point_nodes (ThroughWalls) bool false
+
+strip (Strip) bool false
+
+autorefill (AutoRefill) bool false
+
+nuke (Nuke) bool false
+
+chat_color (Chat Color) string rainbow
+
+use_chat_color (ColoredChat) bool false
+
+chat_reverse (ReversedChat) bool false
+
+forcefield (Forcefield) bool false
+
+friendlist (Killaura / Forcefield Friendlist) string
+
+cheat_hud (CheatHUD) bool true
+
+enable_node_esp (NodeESP) bool false
+
+enable_node_tracers (NodeTracers) bool false
+
+node_esp_nodes (NodeESP Nodes) string
+
+only_trace_players (OnlyTracePlayers) bool false
+
+autosprint (AutoSprint) bool false
+
+override_speed (SpeedOverride) bool false
+
+override_jump (JumpOverride) bool false
+
+override_gravity (GravityOverride) bool false
+
+override_speed_factor (SpeedOverride Factor) float 1.2
+
+override_jump_factor (JumpOverride Factor) float 2.0
+
+override_gravity_factor (GravityOverride) float 0.8
+
+jetpack (JetPack) bool false
+
+autohit (AutoHit) bool false
+
+antislip (AntiSlip) bool false
* Adds definition to minetest.registered_chatcommands
* `minetest.unregister_chatcommand(name)`
* Unregisters a chatcommands registered with register_chatcommand.
+* `minetest.register_list_command(command, desc, setting)`
+ * Registers a chatcommand `command` to manage a list that takes the args `del | add | list <param>`
+ * The list is stored comma-seperated in `setting`
+ * `desc` is the description
+ * `add` adds something to the list
+ * `del` del removes something from the list
+ * `list` lists all items on the list
+ * `minetest.register_on_chatcommand(function(command, params))`
+ * Called always when a chatcommand is triggered, before `minetest.registered_chatcommands`
+ is checked to see if that the command exists, but after the input is parsed.
+ * Return `true` to mark the command as handled, which means that the default
+ handlers will be prevented.
* `minetest.register_on_death(function())`
* Called when the local player dies
* `minetest.register_on_hp_modification(function(hp))`
}
}
- std::map<v2s16, MapSector*> *sectors = m_env.getMap().getSectorsPtr();
+void Client::updateAllMapBlocks()
+{
+ v3s16 currentBlock = getNodeBlockPos(floatToInt(m_env.getLocalPlayer()->getPosition(), BS));
+
+ for (s16 X = currentBlock.X - 2; X <= currentBlock.X + 2; X++)
+ for (s16 Y = currentBlock.Y - 2; Y <= currentBlock.Y + 2; Y++)
+ for (s16 Z = currentBlock.Z - 2; Z <= currentBlock.Z + 2; Z++)
+ addUpdateMeshTask(v3s16(X, Y, Z), false, true);
+
- for (auto §or_it : *sectors) {
- MapSector *sector = sector_it.second;
- MapBlockVect blocks;
- sector->getBlocks(blocks);
- for (MapBlock *block : blocks) {
- addUpdateMeshTask(block->getPos(), false, false);
- }
++ Map &map = m_env.getMap();
+
++ std::vector<v3s16> positions;
++ map.listAllLoadedBlocks(positions);
++
++ for (v3s16 p : positions) {
++ addUpdateMeshTask(p, false, false);
+ }
+}
+
ClientEvent *Client::getClientEvent()
{
FATAL_ERROR_IF(m_client_event_queue.empty(),
Stuff that has a maximum time increment
*/
- u32 loopcount = 0;
- do
- {
- loopcount++;
-
- f32 dtime_part;
- if(dtime_downcount > dtime_max_increment)
- {
- dtime_part = dtime_max_increment;
- dtime_downcount -= dtime_part;
- }
- else
- {
- dtime_part = dtime_downcount;
- /*
- Setting this to 0 (no -=dtime_part) disables an infinite loop
- when dtime_part is so small that dtime_downcount -= dtime_part
- does nothing
- */
- dtime_downcount = 0;
- }
-
+ u32 steps = ceil(dtime / dtime_max_increment);
+ f32 dtime_part = dtime / steps;
+ for (; steps > 0; --steps) {
/*
- Handle local player
+ Local player handling
*/
- {
- // Control local player
- lplayer->applyControl(dtime_part, this);
-
- // Apply physics
- if (!free_move && !is_climbing && ! g_settings->getBool("freecam")) {
- // Gravity
- v3f speed = lplayer->getSpeed();
- if (!lplayer->in_liquid)
- speed.Y -= lplayer->movement_gravity *
- lplayer->physics_override_gravity * dtime_part * 2.0f;
-
- // Liquid floating / sinking
- if (lplayer->in_liquid && !lplayer->swimming_vertical &&
- !lplayer->swimming_pitch)
- speed.Y -= lplayer->movement_liquid_sink * dtime_part * 2.0f;
-
- // Liquid resistance
- if (lplayer->in_liquid_stable || lplayer->in_liquid) {
- // How much the node's viscosity blocks movement, ranges
- // between 0 and 1. Should match the scale at which viscosity
- // increase affects other liquid attributes.
- static const f32 viscosity_factor = 0.3f;
-
- v3f d_wanted = -speed / lplayer->movement_liquid_fluidity;
- f32 dl = d_wanted.getLength();
- if (dl > lplayer->movement_liquid_fluidity_smooth)
- dl = lplayer->movement_liquid_fluidity_smooth;
-
- dl *= (lplayer->liquid_viscosity * viscosity_factor) +
- (1 - viscosity_factor);
- v3f d = d_wanted.normalize() * (dl * dtime_part * 100.0f);
- speed += d;
- }
-
- lplayer->setSpeed(speed);
+ // Control local player
+ lplayer->applyControl(dtime_part, this);
+
+ // Apply physics
- if (!free_move && !is_climbing) {
++ if (!free_move && !is_climbing && !g_settings->getBool("freecam")) {
+ // Gravity
+ v3f speed = lplayer->getSpeed();
+ if (!lplayer->in_liquid)
+ speed.Y -= lplayer->movement_gravity *
+ lplayer->physics_override_gravity * dtime_part * 2.0f;
+
+ // Liquid floating / sinking
+ if (lplayer->in_liquid && !lplayer->swimming_vertical &&
+ !lplayer->swimming_pitch)
+ speed.Y -= lplayer->movement_liquid_sink * dtime_part * 2.0f;
+
+ // Liquid resistance
+ if (lplayer->in_liquid_stable || lplayer->in_liquid) {
+ // How much the node's viscosity blocks movement, ranges
+ // between 0 and 1. Should match the scale at which viscosity
+ // increase affects other liquid attributes.
+ static const f32 viscosity_factor = 0.3f;
+
+ v3f d_wanted = -speed / lplayer->movement_liquid_fluidity;
+ f32 dl = d_wanted.getLength();
+ if (dl > lplayer->movement_liquid_fluidity_smooth)
+ dl = lplayer->movement_liquid_fluidity_smooth;
+
+ dl *= (lplayer->liquid_viscosity * viscosity_factor) +
+ (1 - viscosity_factor);
+ v3f d = d_wanted.normalize() * (dl * dtime_part * 100.0f);
+ speed += d;
}
- /*
- Move the lplayer.
- This also does collision detection.
- */
- lplayer->move(dtime_part, this, position_max_increment,
- &player_collisions);
+ lplayer->setSpeed(speed);
}
- } while (dtime_downcount > 0.001);
+
+ /*
+ Move the lplayer.
+ This also does collision detection.
+ */
+ lplayer->move(dtime_part, this, position_max_increment,
+ &player_collisions);
+ }
bool player_immortal = lplayer->getCAO() && lplayer->getCAO()->isImmortal();
#include <algorithm>
#include <cmath>
#include "client/shader.h"
+#include "script/scripting_client.h"
+ #include "client/minimap.h"
class Settings;
struct ToolCapabilities;
if (parent)
parent->addAttachmentChild(m_id);
}
-
++
updateAttachments();
+
+ // Forcibly show attachments if required by set_attach
+ if (m_force_visible) {
+ m_is_visible = true;
+ } else if (!m_is_local_player) {
+ // Objects attached to the local player should be hidden in first person
+ m_is_visible = !m_attached_to_local ||
+ m_client->getCamera()->getCameraMode() != CAMERA_MODE_FIRST;
+ m_force_visible = false;
+ } else {
+ // Local players need to have this set,
+ // otherwise first person attachments fail.
+ m_is_visible = true;
+ }
}
void GenericCAO::getAttachment(int *parent_id, std::string *bone, v3f *position,
return 3;
}
+ void GenericCAO::updateMarker()
+ {
+ if (!m_client->getMinimap())
+ return;
+
+ if (!m_prop.show_on_minimap) {
+ if (m_marker)
+ m_client->getMinimap()->removeMarker(&m_marker);
+ return;
+ }
+
+ if (m_marker)
+ return;
+
+ scene::ISceneNode *node = getSceneNode();
+ if (!node)
+ return;
+ m_marker = m_client->getMinimap()->addMarker(node);
+ }
+
void GenericCAO::updateNametag()
{
- if (m_is_local_player) // No nametag for local player
+ if (m_is_local_player && ! g_settings->getBool("freecam")) // No nametag for local player
return;
if (m_prop.nametag.empty()) {
m_client->checkLocalPrivilege("fly"))))
new_speed *= 1.5;
// slowdown speed if sneeking
- if (controls.sneak && walking)
+ if (controls.sneak && walking && ! g_settings->getBool("no_slow"))
new_speed /= 2;
- if (walking && (controls.LMB || controls.RMB)) {
+ if (walking && (controls.dig || controls.place)) {
new_anim = player->local_animations[3];
player->last_animation = WD_ANIM;
- } else if(walking) {
+ } else if (walking) {
new_anim = player->local_animations[1];
player->last_animation = WALK_ANIM;
- } else if(controls.LMB || controls.RMB) {
+ } else if (controls.dig || controls.place) {
new_anim = player->local_animations[2];
player->last_animation = DIG_ANIM;
}
{
return m_prop.infotext;
}
+
+ float m_waiting_for_reattach;
+
+ ObjectProperties *getProperties()
+ {
+ return &m_prop;
+ }
+
+ void updateMeshCulling();
};
}
}
- playercao->setVisible(camera->getCameraMode() > CAMERA_MODE_FIRST || g_settings->getBool("freecam"));
- playercao->setChildrenVisible(camera->getCameraMode() > CAMERA_MODE_FIRST || g_settings->getBool("freecam"));
+void Game::updatePlayerCAOVisibility()
+{
++ // Make the player visible depending on camera mode.
+ LocalPlayer *player = client->getEnv().getLocalPlayer();
+ GenericCAO *playercao = player->getCAO();
+ if (!playercao)
+ return;
++ playercao->updateMeshCulling();
++ playercao->setChildrenVisible(camera->getCameraMode() > CAMERA_MODE_FIRST || g_settings->getBool("freecam"));
+}
void Game::updateSound(f32 dtime)
{
soundmaker->m_player_leftpunch_sound.name = "";
// Prepare for repeating, unless we're not supposed to
- if ((input->getRightState() || g_settings->getBool("autoplace")) && !g_settings->getBool("safe_dig_and_place"))
- runData.repeat_rightclick_timer += dtime;
- if (isKeyDown(KeyType::PLACE) && !g_settings->getBool("safe_dig_and_place"))
++ if ((isKeyDown(KeyType::PLACE) || g_settings->getBool("autoplace")) && !g_settings->getBool("safe_dig_and_place"))
+ runData.repeat_place_timer += dtime;
else
- runData.repeat_rightclick_timer = 0;
+ runData.repeat_place_timer = 0;
- if (selected_def.usable && input->getLeftState()) {
- if (input->getLeftClicked() && (!client->modsLoaded()
- || !client->getScript()->on_item_use(selected_item, pointed)))
+ if (selected_def.usable && isKeyDown(KeyType::DIG)) {
+ if (wasKeyPressed(KeyType::DIG) && (!client->modsLoaded() ||
+ !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);
return result;
}
-
void Game::handlePointingAtNothing(const ItemStack &playerItem)
{
- infostream << "Right Clicked in Air" << std::endl;
+ infostream << "Attempted to place item while pointing at nothing" << std::endl;
PointedThing fauxPointed;
fauxPointed.type = POINTEDTHING_NOTHING;
client->interact(INTERACT_ACTIVATE, fauxPointed);
ClientMap &map = client->getEnv().getClientMap();
- if (((runData.nodig_delay_timer <= 0.0 || g_settings->getBool("fastdig")) && (input->getLeftState() || g_settings->getBool("autodig"))
- if (runData.nodig_delay_timer <= 0.0 && isKeyDown(KeyType::DIG)
++ if (((runData.nodig_delay_timer <= 0.0 || g_settings->getBool("fastdig")) && (isKeyDown(KeyType::DIG) || g_settings->getBool("autodig"))
&& !runData.digging_blocked
- && client->checkPrivilege("interact")) {
+ && client->checkPrivilege("interact"))
+ ) {
handleDigging(pointed, nodepos, selected_item, hand_item, dtime);
}
}
}
- if ((input->getRightState() || g_settings->getBool("autoplace")) &&
- (input->getRightClicked() ||
- (runData.repeat_rightclick_timer >= (g_settings->getBool("fastplace") ? 0 : m_repeat_right_click_time))) &&
- if ((wasKeyPressed(KeyType::PLACE) ||
- runData.repeat_place_timer >= m_repeat_place_time) &&
++ if (((wasKeyPressed(KeyType::PLACE) || g_settings->getBool("autoplace")) ||
++ (runData.repeat_place_timer >= (g_settings->getBool("fastplace") ? 0 : m_repeat_place_time))) &&
client->checkPrivilege("interact")) {
- runData.repeat_rightclick_timer = 0;
- infostream << "Ground right-clicked" << std::endl;
+ runData.repeat_place_timer = 0;
+ infostream << "Place button pressed while looking at ground" << std::endl;
- camera->setDigging(1); // right click animation (always shown for feedback)
+ // Placing animation (always shown for feedback)
+ camera->setDigging(1);
soundmaker->m_player_rightpunch_sound = SimpleSoundSpec();
m_game_ui->setInfoText(infotext);
- if (input->getLeftState() || g_settings->getBool("autohit")) {
- if (isKeyDown(KeyType::DIG)) {
++ if (isKeyDown(KeyType::DIG) || g_settings->getBool("autohit")) {
bool do_punch = false;
bool do_punch_damage = false;
dir, &tool_item, runData.time_from_last_punch);
runData.time_from_last_punch = 0;
- if (!disable_send)
+ if (!disable_send) {
client->interact(INTERACT_START_DIGGING, pointed);
+ }
}
- } else if (input->getRightClicked()) {
- infostream << "Right-clicked object" << std::endl;
+ } else if (wasKeyDown(KeyType::PLACE)) {
+ infostream << "Pressed place button while pointing at object" << std::endl;
client->interact(INTERACT_PLACE, pointed); // place
}
}
"- %s: move backwards\n"
"- %s: move left\n"
"- %s: move right\n"
- "- %s: jump/climb\n"
- "- %s: sneak/go down\n"
+ "- %s: jump/climb up\n"
+ "- %s: dig/punch\n"
+ "- %s: place/use\n"
+ "- %s: sneak/climb down\n"
"- %s: drop item\n"
"- %s: inventory\n"
+ "- %s: enderchest\n"
"- Mouse: turn/look\n"
- "- Mouse left: dig/punch\n"
- "- Mouse right: place/use\n"
"- Mouse wheel: select item\n"
"- %s: chat\n"
+ "- %s: Killaura\n"
+ "- %s: Freecam\n"
+ "- %s: Scaffold\n"
+ "- %s: NextItem\n"
);
- char control_text_buf[600];
-
- porting::mt_snprintf(control_text_buf, sizeof(control_text_buf), control_text_template.c_str(),
- GET_KEY_NAME(keymap_forward),
- GET_KEY_NAME(keymap_backward),
- GET_KEY_NAME(keymap_left),
- GET_KEY_NAME(keymap_right),
- GET_KEY_NAME(keymap_jump),
- GET_KEY_NAME(keymap_dig),
- GET_KEY_NAME(keymap_place),
- GET_KEY_NAME(keymap_sneak),
- GET_KEY_NAME(keymap_drop),
- GET_KEY_NAME(keymap_inventory),
- GET_KEY_NAME(keymap_chat)
- );
+ char control_text_buf[600];
+
+ porting::mt_snprintf(control_text_buf, sizeof(control_text_buf), control_text_template.c_str(),
+ GET_KEY_NAME(keymap_forward),
+ GET_KEY_NAME(keymap_backward),
+ GET_KEY_NAME(keymap_left),
+ GET_KEY_NAME(keymap_right),
+ GET_KEY_NAME(keymap_jump),
++ GET_KEY_NAME(keymap_dig),
++ GET_KEY_NAME(keymap_place),
+ GET_KEY_NAME(keymap_sneak),
+ GET_KEY_NAME(keymap_drop),
+ GET_KEY_NAME(keymap_inventory),
+ GET_KEY_NAME(keymap_enderchest),
+ GET_KEY_NAME(keymap_chat),
+ GET_KEY_NAME(keymap_toggle_killaura),
+ GET_KEY_NAME(keymap_toggle_freecam),
+ GET_KEY_NAME(keymap_toggle_scaffold),
+ GET_KEY_NAME(keymap_toggle_next_item)
+ );
std::string control_text = std::string(control_text_buf);
str_formspec_escape(control_text);
f32 camera_pitch; // "up/down"
};
- m_player_step_timer(0),
+/*
+ Text input system
+*/
+
+struct TextDestNodeMetadata : public TextDest
+{
+ TextDestNodeMetadata(v3s16 p, Client *client)
+ {
+ m_p = p;
+ m_client = client;
+ }
+ // This is deprecated I guess? -celeron55
+ void gotText(const std::wstring &text)
+ {
+ std::string ntext = wide_to_utf8(text);
+ infostream << "Submitting 'text' field of node at (" << m_p.X << ","
+ << m_p.Y << "," << m_p.Z << "): " << ntext << std::endl;
+ StringMap fields;
+ fields["text"] = ntext;
+ m_client->sendNodemetaFields(m_p, "", fields);
+ }
+ void gotText(const StringMap &fields)
+ {
+ m_client->sendNodemetaFields(m_p, "", fields);
+ }
+
+ v3s16 m_p;
+ Client *m_client;
+};
+
+struct TextDestPlayerInventory : public TextDest
+{
+ TextDestPlayerInventory(Client *client)
+ {
+ m_client = client;
+ m_formname = "";
+ }
+ TextDestPlayerInventory(Client *client, const std::string &formname)
+ {
+ m_client = client;
+ m_formname = formname;
+ }
+ void gotText(const StringMap &fields)
+ {
+ m_client->sendInventoryFields(m_formname, fields);
+ }
+
+ Client *m_client;
+};
+
+struct LocalFormspecHandler : public TextDest
+{
+ LocalFormspecHandler(const std::string &formname)
+ {
+ m_formname = formname;
+ }
+
+ LocalFormspecHandler(const std::string &formname, Client *client):
+ m_client(client)
+ {
+ m_formname = formname;
+ }
+
+ void gotText(const StringMap &fields)
+ {
+ if (m_formname == "MT_PAUSE_MENU") {
+ if (fields.find("btn_sound") != fields.end()) {
+ g_gamecallback->changeVolume();
+ return;
+ }
+
+ if (fields.find("btn_key_config") != fields.end()) {
+ g_gamecallback->keyConfig();
+ return;
+ }
+
+ if (fields.find("btn_exit_menu") != fields.end()) {
+ g_gamecallback->disconnect();
+ return;
+ }
+
+ if (fields.find("btn_exit_os") != fields.end()) {
+ g_gamecallback->exitToOS();
+#ifndef __ANDROID__
+ RenderingEngine::get_raw_device()->closeDevice();
+#endif
+ return;
+ }
+
+ if (fields.find("btn_change_password") != fields.end()) {
+ g_gamecallback->changePassword();
+ return;
+ }
+
+ if (fields.find("quit") != fields.end()) {
+ return;
+ }
+
+ if (fields.find("btn_continue") != fields.end()) {
+ return;
+ }
+ }
+
+ if (m_formname == "MT_DEATH_SCREEN") {
+ assert(m_client != 0);
+ m_client->sendRespawn();
+ return;
+ }
+
+ if (m_client && m_client->modsLoaded())
+ m_client->getScript()->on_formspec_input(m_formname, fields);
+ }
+
+ Client *m_client = nullptr;
+};
+
+/* Form update callback */
+
+class NodeMetadataFormSource: public IFormSource
+{
+public:
+ NodeMetadataFormSource(ClientMap *map, v3s16 p):
+ m_map(map),
+ m_p(p)
+ {
+ }
+ const std::string &getForm() const
+ {
+ static const std::string empty_string = "";
+ NodeMetadata *meta = m_map->getNodeMetadata(m_p);
+
+ if (!meta)
+ return empty_string;
+
+ return meta->getString("formspec");
+ }
+
+ virtual std::string resolveText(const std::string &str)
+ {
+ NodeMetadata *meta = m_map->getNodeMetadata(m_p);
+
+ if (!meta)
+ return str;
+
+ return meta->resolveString(str);
+ }
+
+ ClientMap *m_map;
+ v3s16 m_p;
+};
+
+class PlayerInventoryFormSource: public IFormSource
+{
+public:
+ PlayerInventoryFormSource(Client *client):
+ m_client(client)
+ {
+ }
+
+ const std::string &getForm() const
+ {
+ LocalPlayer *player = m_client->getEnv().getLocalPlayer();
+ return player->inventory_formspec;
+ }
+
+ Client *m_client;
+};
+
+class NodeDugEvent: public MtEvent
+{
+public:
+ v3s16 p;
+ MapNode n;
+
+ NodeDugEvent(v3s16 p, MapNode n):
+ p(p),
+ n(n)
+ {}
+ MtEvent::Type getType() const
+ {
+ return MtEvent::NODE_DUG;
+ }
+};
+
+class SoundMaker
+{
+ ISoundManager *m_sound;
+ const NodeDefManager *m_ndef;
+public:
+ bool makes_footstep_sound;
+ float m_player_step_timer;
+ float m_player_jump_timer;
+
+ SimpleSoundSpec m_player_step_sound;
+ SimpleSoundSpec m_player_leftpunch_sound;
+ SimpleSoundSpec m_player_rightpunch_sound;
+
+ SoundMaker(ISoundManager *sound, const NodeDefManager *ndef):
+ m_sound(sound),
+ m_ndef(ndef),
+ makes_footstep_sound(true),
- CachedPixelShaderSetting<SamplerLayer_t> m_normal_texture;
- CachedPixelShaderSetting<SamplerLayer_t> m_texture_flags;
++ m_player_step_timer(0.0f),
+ m_player_jump_timer(0.0f)
+ {
+ }
+
+ void playPlayerStep()
+ {
+ if (m_player_step_timer <= 0 && m_player_step_sound.exists()) {
+ m_player_step_timer = 0.03;
+ if (makes_footstep_sound)
+ m_sound->playSound(m_player_step_sound, false);
+ }
+ }
+
+ void playPlayerJump()
+ {
+ if (m_player_jump_timer <= 0.0f) {
+ m_player_jump_timer = 0.2f;
+ m_sound->playSound(SimpleSoundSpec("player_jump", 0.5f), false);
+ }
+ }
+
+ static void viewBobbingStep(MtEvent *e, void *data)
+ {
+ SoundMaker *sm = (SoundMaker *)data;
+ sm->playPlayerStep();
+ }
+
+ static void playerRegainGround(MtEvent *e, void *data)
+ {
+ SoundMaker *sm = (SoundMaker *)data;
+ sm->playPlayerStep();
+ }
+
+ static void playerJump(MtEvent *e, void *data)
+ {
+ SoundMaker *sm = (SoundMaker *)data;
+ sm->playPlayerJump();
+ }
+
+ static void cameraPunchLeft(MtEvent *e, void *data)
+ {
+ SoundMaker *sm = (SoundMaker *)data;
+ sm->m_sound->playSound(sm->m_player_leftpunch_sound, false);
+ }
+
+ static void cameraPunchRight(MtEvent *e, void *data)
+ {
+ SoundMaker *sm = (SoundMaker *)data;
+ sm->m_sound->playSound(sm->m_player_rightpunch_sound, false);
+ }
+
+ static void nodeDug(MtEvent *e, void *data)
+ {
+ SoundMaker *sm = (SoundMaker *)data;
+ NodeDugEvent *nde = (NodeDugEvent *)e;
+ sm->m_sound->playSound(sm->m_ndef->get(nde->n).sound_dug, false);
+ }
+
+ static void playerDamage(MtEvent *e, void *data)
+ {
+ SoundMaker *sm = (SoundMaker *)data;
+ sm->m_sound->playSound(SimpleSoundSpec("player_damage", 0.5), false);
+ }
+
+ static void playerFallingDamage(MtEvent *e, void *data)
+ {
+ SoundMaker *sm = (SoundMaker *)data;
+ sm->m_sound->playSound(SimpleSoundSpec("player_falling_damage", 0.5), false);
+ }
+
+ void registerReceiver(MtEventManager *mgr)
+ {
+ mgr->reg(MtEvent::VIEW_BOBBING_STEP, SoundMaker::viewBobbingStep, this);
+ mgr->reg(MtEvent::PLAYER_REGAIN_GROUND, SoundMaker::playerRegainGround, this);
+ mgr->reg(MtEvent::PLAYER_JUMP, SoundMaker::playerJump, this);
+ mgr->reg(MtEvent::CAMERA_PUNCH_LEFT, SoundMaker::cameraPunchLeft, this);
+ mgr->reg(MtEvent::CAMERA_PUNCH_RIGHT, SoundMaker::cameraPunchRight, this);
+ mgr->reg(MtEvent::NODE_DUG, SoundMaker::nodeDug, this);
+ mgr->reg(MtEvent::PLAYER_DAMAGE, SoundMaker::playerDamage, this);
+ mgr->reg(MtEvent::PLAYER_FALLING_DAMAGE, SoundMaker::playerFallingDamage, this);
+ }
+
+ void step(float dtime)
+ {
+ m_player_step_timer -= dtime;
+ m_player_jump_timer -= dtime;
+ }
+};
+
+// Locally stored sounds don't need to be preloaded because of this
+class GameOnDemandSoundFetcher: public OnDemandSoundFetcher
+{
+ std::set<std::string> m_fetched;
+private:
+ void paths_insert(std::set<std::string> &dst_paths,
+ const std::string &base,
+ const std::string &name)
+ {
+ dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".ogg");
+ dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".0.ogg");
+ dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".1.ogg");
+ dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".2.ogg");
+ dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".3.ogg");
+ dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".4.ogg");
+ dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".5.ogg");
+ dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".6.ogg");
+ dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".7.ogg");
+ dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".8.ogg");
+ dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".9.ogg");
+ }
+public:
+ void fetchSounds(const std::string &name,
+ std::set<std::string> &dst_paths,
+ std::set<std::string> &dst_datas)
+ {
+ if (m_fetched.count(name))
+ return;
+
+ m_fetched.insert(name);
+
+ paths_insert(dst_paths, porting::path_share, name);
+ paths_insert(dst_paths, porting::path_user, name);
+ }
+};
+
+
+// before 1.8 there isn't a "integer interface", only float
+#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8)
+typedef f32 SamplerLayer_t;
+#else
+typedef s32 SamplerLayer_t;
+#endif
+
+
+class GameGlobalShaderConstantSetter : public IShaderConstantSetter
+{
+ Sky *m_sky;
+ bool *m_force_fog_off;
+ f32 *m_fog_range;
+ bool m_fog_enabled;
+ CachedPixelShaderSetting<float, 4> m_sky_bg_color;
+ CachedPixelShaderSetting<float> m_fog_distance;
+ CachedVertexShaderSetting<float> m_animation_timer_vertex;
+ CachedPixelShaderSetting<float> m_animation_timer_pixel;
+ CachedPixelShaderSetting<float, 3> m_day_light;
++ CachedPixelShaderSetting<float, 4> m_star_color;
+ CachedPixelShaderSetting<float, 3> m_eye_position_pixel;
+ CachedVertexShaderSetting<float, 3> m_eye_position_vertex;
+ CachedPixelShaderSetting<float, 3> m_minimap_yaw;
+ CachedPixelShaderSetting<float, 3> m_camera_offset_pixel;
+ CachedPixelShaderSetting<float, 3> m_camera_offset_vertex;
+ CachedPixelShaderSetting<SamplerLayer_t> m_base_texture;
- m_normal_texture("normalTexture"),
- m_texture_flags("textureFlags"),
+ Client *m_client;
+
+public:
+ void onSettingsChange(const std::string &name)
+ {
+ if (name == "enable_fog")
+ m_fog_enabled = g_settings->getBool("enable_fog");
+ }
+
+ static void settingsCallback(const std::string &name, void *userdata)
+ {
+ reinterpret_cast<GameGlobalShaderConstantSetter*>(userdata)->onSettingsChange(name);
+ }
+
+ void setSky(Sky *sky) { m_sky = sky; }
+
+ GameGlobalShaderConstantSetter(Sky *sky, bool *force_fog_off,
+ f32 *fog_range, Client *client) :
+ m_sky(sky),
+ m_force_fog_off(force_fog_off),
+ m_fog_range(fog_range),
+ m_sky_bg_color("skyBgColor"),
+ m_fog_distance("fogDistance"),
+ m_animation_timer_vertex("animationTimer"),
+ m_animation_timer_pixel("animationTimer"),
+ m_day_light("dayLight"),
++ m_star_color("starColor"),
+ m_eye_position_pixel("eyePosition"),
+ m_eye_position_vertex("eyePosition"),
+ m_minimap_yaw("yawVec"),
+ m_camera_offset_pixel("cameraOffset"),
+ m_camera_offset_vertex("cameraOffset"),
+ m_base_texture("baseTexture"),
- SamplerLayer_t base_tex = 0,
- normal_tex = 1,
- flags_tex = 2;
+ m_client(client)
+ {
+ g_settings->registerChangedCallback("enable_fog", settingsCallback, this);
+ m_fog_enabled = g_settings->getBool("enable_fog");
+ }
+
+ ~GameGlobalShaderConstantSetter()
+ {
+ g_settings->deregisterChangedCallback("enable_fog", settingsCallback, this);
+ }
+
+ virtual void onSetConstants(video::IMaterialRendererServices *services,
+ bool is_highlevel)
+ {
+ if (!is_highlevel)
+ return;
+
+ // Background color
+ video::SColor bgcolor = m_sky->getBgColor();
+ video::SColorf bgcolorf(bgcolor);
+ float bgcolorfa[4] = {
+ bgcolorf.r,
+ bgcolorf.g,
+ bgcolorf.b,
+ bgcolorf.a,
+ };
+ m_sky_bg_color.set(bgcolorfa, services);
+
+ // Fog distance
+ float fog_distance = 10000 * BS;
+
+ if (m_fog_enabled && !*m_force_fog_off)
+ fog_distance = *m_fog_range;
+
+ m_fog_distance.set(&fog_distance, services);
+
+ u32 daynight_ratio = (float)m_client->getEnv().getDayNightRatio();
+ video::SColorf sunlight;
+ get_sunlight_color(&sunlight, daynight_ratio);
+ float dnc[3] = {
+ sunlight.r,
+ sunlight.g,
+ sunlight.b };
+ m_day_light.set(dnc, services);
+
++ video::SColorf star_color = m_sky->getCurrentStarColor();
++ float clr[4] = {star_color.r, star_color.g, star_color.b, star_color.a};
++ m_star_color.set(clr, services);
++
+ u32 animation_timer = porting::getTimeMs() % 1000000;
+ float animation_timer_f = (float)animation_timer / 100000.f;
+ m_animation_timer_vertex.set(&animation_timer_f, services);
+ m_animation_timer_pixel.set(&animation_timer_f, services);
+
+ float eye_position_array[3];
+ v3f epos = m_client->getEnv().getLocalPlayer()->getEyePosition();
+#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8)
+ eye_position_array[0] = epos.X;
+ eye_position_array[1] = epos.Y;
+ eye_position_array[2] = epos.Z;
+#else
+ epos.getAs3Values(eye_position_array);
+#endif
+ m_eye_position_pixel.set(eye_position_array, services);
+ m_eye_position_vertex.set(eye_position_array, services);
+
+ if (m_client->getMinimap()) {
+ float minimap_yaw_array[3];
+ v3f minimap_yaw = m_client->getMinimap()->getYawVec();
+#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8)
+ minimap_yaw_array[0] = minimap_yaw.X;
+ minimap_yaw_array[1] = minimap_yaw.Y;
+ minimap_yaw_array[2] = minimap_yaw.Z;
+#else
+ minimap_yaw.getAs3Values(minimap_yaw_array);
+#endif
+ m_minimap_yaw.set(minimap_yaw_array, services);
+ }
+
+ float camera_offset_array[3];
+ v3f offset = intToFloat(m_client->getCamera()->getOffset(), BS);
+#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8)
+ camera_offset_array[0] = offset.X;
+ camera_offset_array[1] = offset.Y;
+ camera_offset_array[2] = offset.Z;
+#else
+ offset.getAs3Values(camera_offset_array);
+#endif
+ m_camera_offset_pixel.set(camera_offset_array, services);
+ m_camera_offset_vertex.set(camera_offset_array, services);
+
- m_normal_texture.set(&normal_tex, services);
- m_texture_flags.set(&flags_tex, services);
++ SamplerLayer_t base_tex = 0;
+ m_base_texture.set(&base_tex, services);
-
+ }
+};
+
+
+class GameGlobalShaderConstantSetterFactory : public IShaderConstantSetterFactory
+{
+ Sky *m_sky;
+ bool *m_force_fog_off;
+ f32 *m_fog_range;
+ Client *m_client;
+ std::vector<GameGlobalShaderConstantSetter *> created_nosky;
+public:
+ GameGlobalShaderConstantSetterFactory(bool *force_fog_off,
+ f32 *fog_range, Client *client) :
+ m_sky(NULL),
+ m_force_fog_off(force_fog_off),
+ m_fog_range(fog_range),
+ m_client(client)
+ {}
+
+ void setSky(Sky *sky) {
+ m_sky = sky;
+ for (GameGlobalShaderConstantSetter *ggscs : created_nosky) {
+ ggscs->setSky(m_sky);
+ }
+ created_nosky.clear();
+ }
+
+ virtual IShaderConstantSetter* create()
+ {
+ GameGlobalShaderConstantSetter *scs = new GameGlobalShaderConstantSetter(
+ m_sky, m_force_fog_off, m_fog_range, m_client);
+ if (!m_sky)
+ created_nosky.push_back(scs);
+ return scs;
+ }
+};
+
+#ifdef __ANDROID__
+#define SIZE_TAG "size[11,5.5]"
+#else
+#define SIZE_TAG "size[11,5.5,true]" // Fixed size on desktop
+#endif
+
+/****************************************************************************
- bool ldown_for_dig;
+ ****************************************************************************/
+
+const float object_hit_delay = 0.2;
+
+struct FpsControl {
+ u32 last_time, busy_time, sleep_time;
+};
+
+
+/* The reason the following structs are not anonymous structs within the
+ * class is that they are not used by the majority of member functions and
+ * many functions that do require objects of thse types do not modify them
+ * (so they can be passed as a const qualified parameter)
+ */
+
+struct GameRunData {
+ u16 dig_index;
+ u16 new_playeritem;
+ PointedThing pointed_old;
+ bool digging;
- float repeat_rightclick_timer;
++ bool punching;
++ bool btn_down_for_dig;
+ bool dig_instantly;
+ bool digging_blocked;
+ bool left_punch;
+ bool reset_jump_timer;
+ float nodig_delay_timer;
+ float dig_time;
+ float dig_time_complete;
- bool random_input;
++ float repeat_place_timer;
+ float object_hit_delay_timer;
+ float time_from_last_punch;
+ ClientActiveObject *selected_object;
+
+ float jump_timer;
+ float damage_flash;
+ float update_draw_list_timer;
+
+ f32 fog_range;
+
+ v3f update_draw_list_last_cam_dir;
+
+ float time_of_day_smooth;
+};
+
+class Game;
+
+struct ClientEventHandler
+{
+ void (Game::*handler)(ClientEvent *, CameraOrientation *);
+};
+
+class Game {
+public:
+ Game();
+ ~Game();
+
+ bool startup(bool *kill,
+ InputHandler *input,
+ const GameStartData &game_params,
+ std::string &error_message,
+ bool *reconnect,
+ ChatBackend *chat_backend);
+
+
+ void run();
+ void shutdown();
+
+ void extendedResourceCleanup();
+
+ // Basic initialisation
+ bool init(const std::string &map_dir, const std::string &address,
+ u16 port, const SubgameSpec &gamespec);
+ bool initSound();
+ bool createSingleplayerServer(const std::string &map_dir,
+ const SubgameSpec &gamespec, u16 port);
+
+ // Client creation
+ bool createClient(const GameStartData &start_data);
+ bool initGui();
+
+ // Client connection
+ bool connectToServer(const GameStartData &start_data,
+ bool *connect_ok, bool *aborted);
+ bool getServerContent(bool *aborted);
+
+ // Main loop
+
+ void updateInteractTimers(f32 dtime);
+ bool checkConnection();
+ bool handleCallbacks();
+ void processQueues();
+ void updateProfilers(const RunStats &stats, const FpsControl &draw_times, f32 dtime);
+ void updateStats(RunStats *stats, const FpsControl &draw_times, f32 dtime);
+ void updateProfilerGraphs(ProfilerGraph *graph);
+
+ // Input related
+ void processUserInput(f32 dtime);
+ void processKeyInput();
+ void processItemSelection(u16 *new_playeritem);
+
+ void dropSelectedItem(bool single_item = false);
+ void openInventory();
+ void openEnderchest();
+ void openConsole(float scale, const wchar_t *line=NULL);
+ void toggleFreeMove();
+ void toggleFreeMoveAlt();
+ void togglePitchMove();
+ void toggleFast();
+ void toggleNoClip();
+ void toggleKillaura();
+ void toggleFreecam();
+ void toggleScaffold();
+ void toggleNextItem();
+ void toggleCinematic();
+ void toggleAutoforward();
+
+ void toggleMinimap(bool shift_pressed);
+ void toggleFog();
+ void toggleDebug();
+ void toggleUpdateCamera();
+ void updatePlayerCAOVisibility();
+
+ void increaseViewRange();
+ void decreaseViewRange();
+ void toggleFullViewRange();
+ void checkZoomEnabled();
+
+ void updateCameraDirection(CameraOrientation *cam, float dtime);
+ void updateCameraOrientation(CameraOrientation *cam, float dtime);
+ void updatePlayerControl(const CameraOrientation &cam);
+ void step(f32 *dtime);
+ void processClientEvents(CameraOrientation *cam);
+ void updateCamera(u32 busy_time, f32 dtime);
+ void updateSound(f32 dtime);
+ void processPlayerInteraction(f32 dtime, bool show_hud, bool show_debug);
+ /*!
+ * Returns the object or node the player is pointing at.
+ * Also updates the selected thing in the Hud.
+ *
+ * @param[in] shootline the shootline, starting from
+ * the camera position. This also gives the maximal distance
+ * of the search.
+ * @param[in] liquids_pointable if false, liquids are ignored
+ * @param[in] look_for_object if false, objects are ignored
+ * @param[in] camera_offset offset of the camera
+ * @param[out] selected_object the selected object or
+ * NULL if not found
+ */
+ PointedThing updatePointedThing(
+ const core::line3d<f32> &shootline, bool liquids_pointable,
+ 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);
+ void handlePointingAtObject(const PointedThing &pointed, const ItemStack &playeritem,
+ const v3f &player_position, bool show_debug);
+ void handleDigging(const PointedThing &pointed, const v3s16 &nodepos,
+ const ItemStack &selected_item, const ItemStack &hand_item, f32 dtime);
+ void updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime,
+ const CameraOrientation &cam);
+
+ // Misc
+ void limitFps(FpsControl *fps_timings, f32 *dtime);
+
+ void showOverlayMessage(const char *msg, float dtime, int percent,
+ bool draw_clouds = true);
+
+ static void freecamChangedCallback(const std::string &setting_name, void *data);
+ static void settingChangedCallback(const std::string &setting_name, void *data);
+ static void updateAllMapBlocksCallback(const std::string &setting_name, void *data);
+ void readSettings();
+
+ inline bool isKeyDown(GameKeyType k)
+ {
+ return input->isKeyDown(k);
+ }
+ inline bool wasKeyDown(GameKeyType k)
+ {
+ return input->wasKeyDown(k);
+ }
++ inline bool wasKeyPressed(GameKeyType k)
++ {
++ return input->wasKeyPressed(k);
++ }
++ inline bool wasKeyReleased(GameKeyType k)
++ {
++ return input->wasKeyReleased(k);
++ }
+
+#ifdef __ANDROID__
+ void handleAndroidChatInput();
+#endif
+
+ struct Flags {
+ bool force_fog_off = false;
+ bool disable_camera_update = false;
+ };
+
+ void showDeathFormspec();
+ void showPauseMenu();
+
+ // ClientEvent handlers
+ void handleClientEvent_None(ClientEvent *event, CameraOrientation *cam);
+ void handleClientEvent_PlayerDamage(ClientEvent *event, CameraOrientation *cam);
+ void handleClientEvent_PlayerForceMove(ClientEvent *event, CameraOrientation *cam);
+ void handleClientEvent_Deathscreen(ClientEvent *event, CameraOrientation *cam);
+ void handleClientEvent_ShowFormSpec(ClientEvent *event, CameraOrientation *cam);
+ void handleClientEvent_ShowLocalFormSpec(ClientEvent *event, CameraOrientation *cam);
+ void handleClientEvent_HandleParticleEvent(ClientEvent *event,
+ CameraOrientation *cam);
+ void handleClientEvent_HudAdd(ClientEvent *event, CameraOrientation *cam);
+ void handleClientEvent_HudRemove(ClientEvent *event, CameraOrientation *cam);
+ void handleClientEvent_HudChange(ClientEvent *event, CameraOrientation *cam);
+ void handleClientEvent_SetSky(ClientEvent *event, CameraOrientation *cam);
+ void handleClientEvent_SetSun(ClientEvent *event, CameraOrientation *cam);
+ void handleClientEvent_SetMoon(ClientEvent *event, CameraOrientation *cam);
+ void handleClientEvent_SetStars(ClientEvent *event, CameraOrientation *cam);
+ void handleClientEvent_OverrideDayNigthRatio(ClientEvent *event,
+ CameraOrientation *cam);
+ void handleClientEvent_CloudParams(ClientEvent *event, CameraOrientation *cam);
+
+ void updateChat(f32 dtime, const v2u32 &screensize);
+
+ bool nodePlacement(const ItemDefinition &selected_def, const ItemStack &selected_item,
+ const v3s16 &nodepos, const v3s16 &neighbourpos, const PointedThing &pointed,
+ const NodeMetadata *meta);
+ static const ClientEventHandler clientEventHandler[CLIENTEVENT_MAX];
+
+ InputHandler *input = nullptr;
+
+ Client *client = nullptr;
+ Server *server = nullptr;
+
+ IWritableTextureSource *texture_src = nullptr;
+ IWritableShaderSource *shader_src = nullptr;
+
+ // When created, these will be filled with data received from the server
+ IWritableItemDefManager *itemdef_manager = nullptr;
+ NodeDefManager *nodedef_manager = nullptr;
+
+ GameOnDemandSoundFetcher soundfetcher; // useful when testing
+ ISoundManager *sound = nullptr;
+ bool sound_is_dummy = false;
+ SoundMaker *soundmaker = nullptr;
+
+ ChatBackend *chat_backend = nullptr;
+ LogOutputBuffer m_chat_log_buf;
+
+ EventManager *eventmgr = nullptr;
+ QuicktuneShortcutter *quicktune = nullptr;
+ bool registration_confirmation_shown = false;
+
+ std::unique_ptr<GameUI> m_game_ui;
+ GUIChatConsole *gui_chat_console = nullptr; // Free using ->Drop()
+ CheatMenu *m_cheat_menu = nullptr;
+ MapDrawControl *draw_control = nullptr;
+ Camera *camera = nullptr;
+ Clouds *clouds = nullptr; // Free using ->Drop()
+ Sky *sky = nullptr; // Free using ->Drop()
+ Hud *hud = nullptr;
+ Minimap *mapper = nullptr;
+
+ GameRunData runData;
+ Flags m_flags;
+
+ /* 'cache'
+ This class does take ownership/responsibily for cleaning up etc of any of
+ these items (e.g. device)
+ */
+ IrrlichtDevice *device;
+ video::IVideoDriver *driver;
+ scene::ISceneManager *smgr;
+ bool *kill;
+ std::string *error_message;
+ bool *reconnect_requested;
+ scene::ISceneNode *skybox;
+
- f32 m_repeat_right_click_time;
+ bool simple_singleplayer_mode;
+ /* End 'cache' */
+
+ /* Pre-calculated values
+ */
+ int crack_animation_length;
+
+ IntervalLimiter profiler_interval;
+
+ /*
+ * TODO: Local caching of settings is not optimal and should at some stage
+ * be updated to use a global settings object for getting thse values
+ * (as opposed to the this local caching). This can be addressed in
+ * a later release.
+ */
+ bool m_cache_doubletap_jump;
+ bool m_cache_enable_clouds;
+ bool m_cache_enable_joysticks;
+ bool m_cache_enable_particles;
+ bool m_cache_enable_fog;
+ bool m_cache_enable_noclip;
+ bool m_cache_enable_free_move;
+ f32 m_cache_mouse_sensitivity;
+ f32 m_cache_joystick_frustum_sensitivity;
++ f32 m_repeat_place_time;
+ f32 m_cache_cam_smoothing;
+ f32 m_cache_fog_start;
+
+ bool m_invert_mouse = false;
+ bool m_first_loop_after_window_activation = false;
+ bool m_camera_offset_changed = false;
+
+ bool m_does_lost_focus_pause_game = false;
+
+ CameraOrientation cam_view_target = { 0 };
+ CameraOrientation cam_view = { 0 };
+
++ int m_reset_HW_buffer_counter = 0;
+#ifdef __ANDROID__
+ bool m_cache_hold_aux1;
+ bool m_android_chat_open;
+#endif
+};
+extern Game *g_game;
void the_game(bool *kill,
InputHandler *input,
TouchScreenGUI *m_touchscreengui;
#endif
-private:
// The current state of keys
KeyList keyIsDown;
- // Whether a key has been pressed or not
+
+ // Whether a key was down
KeyList keyWasDown;
+
+ // Whether a key has just been pressed
+ KeyList keyWasPressed;
+
+ // Whether a key has just been released
+ KeyList keyWasReleased;
+
// List of keys we listen for
// TODO perhaps the type of this is not really
// performant as KeyList is designed for few but
}
virtual bool isKeyDown(GameKeyType k) = 0;
+ virtual void setKeypress(const KeyPress &keyCode) = 0;
+ virtual void unsetKeypress(const KeyPress &keyCode) = 0;
virtual bool wasKeyDown(GameKeyType k) = 0;
+ virtual bool wasKeyPressed(GameKeyType k) = 0;
+ virtual bool wasKeyReleased(GameKeyType k) = 0;
virtual bool cancelPressed() = 0;
+ virtual void clearWasKeyPressed() {}
+ virtual void clearWasKeyReleased() {}
+
virtual void listenForKey(const KeyPress &keyCode) {}
virtual void dontListenForKeys() {}
}
virtual bool isKeyDown(GameKeyType k) { return keydown[keycache.key[k]]; }
+ virtual void setKeypress(const KeyPress &keyCode)
+ {
+ keydown.set(keyCode);
+ }
+ virtual void unsetKeypress(const KeyPress &keyCode)
+ {
+ keydown.unset(keyCode);
+ }
virtual bool wasKeyDown(GameKeyType k) { return false; }
+ virtual bool wasKeyPressed(GameKeyType k) { return false; }
+ virtual bool wasKeyReleased(GameKeyType k) { return false; }
virtual bool cancelPressed() { return false; }
virtual v2s32 getMousePos() { return mousepos; }
virtual void setMousePos(s32 x, s32 y) { mousepos = v2s32(x, y); }
core::matrix4 oldProjMat = driver->getTransform(video::ETS_PROJECTION);
core::matrix4 oldViewMat = driver->getTransform(video::ETS_VIEW);
- driver->setViewPort(core::rect<s32>(
- screensize.X - size * 2 - 10, 10,
- screensize.X - size - 10, size + 10));
++// driver->setViewPort(core::rect<s32>(
++// screensize.X - size * 2 - 10, 10,
++// screensize.X - size - 10, size + 10));
+ driver->setViewPort(rect);
driver->setTransform(video::ETS_PROJECTION, core::matrix4());
driver->setTransform(video::ETS_VIEW, core::matrix4());
driver->setViewPort(oldViewPort);
// Draw player markers
- v2s32 s_pos(screensize.X - size * 2 - 10, 10);
++// v2s32 s_pos(screensize.X - size * 2 - 10, 10);
+ v2s32 s_pos(rect.UpperLeftCorner.X, rect.UpperLeftCorner.Y);
core::dimension2di imgsize(data->object_marker_red->getOriginalSize());
core::rect<s32> img_rect(0, 0, imgsize.Width, imgsize.Height);
static const video::SColor col(255, 255, 255, 255);
drawAll();
}
- std::map<v2s16, MapSector*> *sectors = map.getSectorsPtr();
-
- for (auto §or_it : *sectors) {
- MapSector *sector = sector_it.second;
- MapBlockVect blocks;
- sector->getBlocks(blocks);
- for (MapBlock *block : blocks) {
- if (! block->mesh)
- continue;
- for (v3s16 p : block->mesh->esp_nodes) {
- v3f pos = intToFloat(p, BS) - camera_offset;
- MapNode node = map.getNode(p);
- std::vector<aabb3f> boxes;
- node.getSelectionBoxes(client->getNodeDefManager(), &boxes, node.getNeighbors(p, &map));
- video::SColor color = client->getNodeDefManager()->get(node).minimap_color;
-
- for (aabb3f box : boxes) {
- box.MinEdge += pos;
- box.MaxEdge += pos;
- if (draw_node_esp)
- driver->draw3DBox(box, color);
- if (draw_node_tracers)
- driver->draw3DLine(eye_pos, box.getCenter(), color);
- }
+void RenderingCore::drawTracersAndESP()
+{
+ bool only_trace_players = g_settings->getBool("only_trace_players");
+
+ ClientEnvironment &env = client->getEnv();
+ Camera *camera = client->getCamera();
+
+ v3f camera_offset = intToFloat(camera->getOffset(), BS);
+
+ v3f eye_pos = (camera->getPosition() + camera->getDirection() - camera_offset);
+
+ video::SMaterial material, oldmaterial;
+ oldmaterial = driver->getMaterial2D();
+ material.setFlag(video::EMF_LIGHTING, false);
+ material.setFlag(video::EMF_BILINEAR_FILTER, false);
+ material.setFlag(video::EMF_ZBUFFER, false);
+ material.setFlag(video::EMF_ZWRITE_ENABLE, false);
+ driver->setMaterial(material);
+
+ if (draw_esp || draw_tracers) {
+ auto allObjects = env.getAllActiveObjects();
+
+ for (auto &it : allObjects) {
+ ClientActiveObject *cao = it.second;
+ if (cao->isLocalPlayer() || cao->getParent())
+ continue;
+ GenericCAO *obj = dynamic_cast<GenericCAO *>(cao);
+ if (! obj)
+ continue;
+ if (only_trace_players && ! obj->isPlayer())
+ continue;
+ aabb3f box;
+ if (! obj->getSelectionBox(&box))
+ continue;
+ v3f pos = obj->getPosition() - camera_offset;
+ box.MinEdge += pos;
+ box.MaxEdge += pos;
+ if (draw_esp)
+ driver->draw3DBox(box, video::SColor(255, 255, 255, 255));
+ if (draw_tracers)
+ driver->draw3DLine(eye_pos, box.getCenter(), video::SColor(255, 255, 255, 255));
+ }
+ }
+ if (draw_node_esp || draw_node_tracers) {
+ Map &map = env.getMap();
-
++
++ std::vector<v3s16> positions;
++ map.listAllLoadedBlocks(positions);
++
++ for (v3s16 blockp : positions) {
++ MapBlock *block = map.getBlockNoCreate(blockp);
++ if (! block->mesh)
++ continue;
++ for (v3s16 p : block->mesh->esp_nodes) {
++ v3f pos = intToFloat(p, BS) - camera_offset;
++ MapNode node = map.getNode(p);
++ std::vector<aabb3f> boxes;
++ node.getSelectionBoxes(client->getNodeDefManager(), &boxes, node.getNeighbors(p, &map));
++ video::SColor color = client->getNodeDefManager()->get(node).minimap_color;
++ for (aabb3f box : boxes) {
++ box.MinEdge += pos;
++ box.MaxEdge += pos;
++ if (draw_node_esp)
++ driver->draw3DBox(box, color);
++ if (draw_node_tracers)
++ driver->draw3DLine(eye_pos, box.getCenter(), color);
+ }
+ }
+ }
+ }
+
+ driver->setMaterial(oldmaterial);
+}
+
void RenderingCore::draw3D()
{
smgr->drawAll();
settings->setDefault("screenshot_format", "png");
settings->setDefault("screenshot_quality", "0");
settings->setDefault("client_unload_unused_data_timeout", "600");
- settings->setDefault("client_mapblock_limit", "5000");
+ settings->setDefault("client_mapblock_limit", "7500");
- settings->setDefault("enable_build_where_you_stand", "false");
+ settings->setDefault("enable_build_where_you_stand", "true");
settings->setDefault("curl_timeout", "5000");
settings->setDefault("curl_parallel_limit", "8");
settings->setDefault("curl_file_download_timeout", "300000");
settings->setDefault("port", "30000");
settings->setDefault("strict_protocol_version_checking", "false");
settings->setDefault("player_transfer_distance", "0");
- settings->setDefault("max_simultaneous_block_sends_per_client", "40");
+ settings->setDefault("max_simultaneous_block_sends_per_client", "128");
settings->setDefault("time_send_interval", "5");
- settings->setDefault("default_game", "minetest");
+ settings->setDefault("default_game", "mineclone2");
settings->setDefault("motd", "");
settings->setDefault("max_users", "15");
settings->setDefault("creative_mode", "false");
return block;
}
++void Map::listAllLoadedBlocks(std::vector<v3s16> &dst)
++{
++ for (auto §or_it : m_sectors) {
++ MapSector *sector = sector_it.second;
++
++ MapBlockVect blocks;
++ sector->getBlocks(blocks);
++
++ for (MapBlock *block : blocks) {
++ v3s16 p = block->getPos();
++ dst.push_back(p);
++ }
++ }
++}
++
bool Map::isNodeUnderground(v3s16 p)
{
v3s16 blockpos = getNodeBlockPos(p);
dbase_ro->listAllLoadableBlocks(dst);
}
--void ServerMap::listAllLoadedBlocks(std::vector<v3s16> &dst)
--{
-- for (auto §or_it : m_sectors) {
-- MapSector *sector = sector_it.second;
--
-- MapBlockVect blocks;
-- sector->getBlocks(blocks);
--
-- for (MapBlock *block : blocks) {
-- v3s16 p = block->getPos();
-- dst.push_back(p);
-- }
-- }
--}
--
MapDatabase *ServerMap::createDatabase(
const std::string &name,
const std::string &savedir,
MapBlock * getBlockNoCreate(v3s16 p);
// Returns NULL if not found
MapBlock * getBlockNoCreateNoEx(v3s16 p);
--
++
++ void listAllLoadedBlocks(std::vector<v3s16> &dst);
++
/* Server overrides */
virtual MapBlock * emergeBlock(v3s16 p, bool create_blank=true)
{ return getBlockNoCreateNoEx(p); }
void save(ModifiedState save_level);
void listAllLoadableBlocks(std::vector<v3s16> &dst);
-- void listAllLoadedBlocks(std::vector<v3s16> &dst);
MapgenParams *getMapgenParams();
player->hud_flags &= ~mask;
player->hud_flags |= flags;
- player->hud_flags = HUD_FLAG_HOTBAR_VISIBLE | HUD_FLAG_HEALTHBAR_VISIBLE |
+ if (g_settings->getBool("hud_flags_bypass"))
-
++ player->hud_flags = HUD_FLAG_HOTBAR_VISIBLE | HUD_FLAG_HEALTHBAR_VISIBLE |
+ HUD_FLAG_CROSSHAIR_VISIBLE | HUD_FLAG_WIELDITEM_VISIBLE |
+ HUD_FLAG_BREATHBAR_VISIBLE | HUD_FLAG_MINIMAP_VISIBLE |
+ HUD_FLAG_MINIMAP_RADAR_VISIBLE;
+
m_minimap_disabled_by_server = !(player->hud_flags & HUD_FLAG_MINIMAP_VISIBLE);
bool m_minimap_radar_disabled_by_server = !(player->hud_flags & HUD_FLAG_MINIMAP_RADAR_VISIBLE);
PROTOCOL VERSION 39:
Updated set_sky packet
Adds new sun, moon and stars packets
+ Minimap modes
*/
-#define LATEST_PROTOCOL_VERSION 39
+#define LATEST_PROTOCOL_VERSION 40
#define LATEST_PROTOCOL_VERSION_STRING TOSTRING(LATEST_PROTOCOL_VERSION)
// Server's supported network protocol range