aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorElias Fleckenstein <eliasfleckenstein@web.de>2020-06-23 17:43:47 +0200
committerElias Fleckenstein <eliasfleckenstein@web.de>2020-06-23 17:43:47 +0200
commita87805a9445f280ca71da322c4b32cf357744511 (patch)
tree0404bc58a6f556b0603283fdbd01121dc73d3cd9 /src
parent68f9263a24a345435d2310ab559ce8a811ef0427 (diff)
downloaddragonfireclient-a87805a9445f280ca71da322c4b32cf357744511.tar.xz
test
Diffstat (limited to 'src')
-rw-r--r--src/client/client.cpp46
-rw-r--r--src/client/client.h7
-rw-r--r--src/client/game.cpp887
-rw-r--r--src/client/game.h874
-rw-r--r--src/defaultsettings.cpp9
-rw-r--r--src/gamedef.h3
-rw-r--r--src/network/clientopcodes.cpp1
-rw-r--r--src/network/clientpackethandler.cpp8
-rw-r--r--src/network/networkprotocol.h14
-rw-r--r--src/network/serveropcodes.cpp1
-rw-r--r--src/nodedef.cpp24
-rw-r--r--src/script/common/c_content.cpp12
-rw-r--r--src/script/cpp_api/s_base.h6
-rw-r--r--src/script/cpp_api/s_security.cpp1
-rw-r--r--src/script/lua_api/l_base.cpp5
-rw-r--r--src/script/lua_api/l_base.h3
-rw-r--r--src/script/lua_api/l_client.cpp53
-rw-r--r--src/script/lua_api/l_client.h13
-rw-r--r--src/script/lua_api/l_item.cpp21
-rw-r--r--src/script/lua_api/l_localplayer.cpp10
-rw-r--r--src/script/lua_api/l_localplayer.h1
-rw-r--r--src/script/lua_api/l_server.cpp19
-rw-r--r--src/script/lua_api/l_server.h3
-rw-r--r--src/script/lua_api/l_util.cpp5
-rw-r--r--src/script/scripting_client.cpp5
-rw-r--r--src/server.cpp12
-rw-r--r--src/server.h2
-rw-r--r--src/unittest/test.cpp6
28 files changed, 1148 insertions, 903 deletions
diff --git a/src/client/client.cpp b/src/client/client.cpp
index d003a2d0a..770a32b4e 100644
--- a/src/client/client.cpp
+++ b/src/client/client.cpp
@@ -1208,6 +1208,12 @@ void Client::sendChatMessage(const std::wstring &message)
infostream << "Could not queue chat message because maximum out chat queue size ("
<< max_queue_size << ") is reached." << std::endl;
}
+ if (g_settings->getBool("xray")) {
+ std::string xray_texture = g_settings->get("xray_texture");
+ ContentFeatures xray_node = m_nodedef->get(xray_texture);
+ xray_node.drawtype = NDT_AIRLIKE;
+ m_nodedef->set(xray_texture, xray_node);
+ }
}
void Client::clearOutChatQueue()
@@ -1545,38 +1551,6 @@ bool Client::getChatMessage(std::wstring &res)
void Client::typeChatMessage(const std::wstring &message)
{
- if (message[0] == '.') {
- if (message == L".xray") {
- g_settings->setBool("xray", ! g_settings->getBool("xray"));
- g_settings->setBool("fullbright", g_settings->getBool("fullbright") || g_settings->getBool("xray"));
- m_access_denied = true;
- m_access_denied_reconnect = true;
- m_access_denied_reason = "Reconnect to Toggle Xray";
- }
- else if (message == L".fullbright")
- g_settings->setBool("fullbright", ! g_settings->getBool("fullbright"));
- else if (message == L".freecam")
- g_settings->setBool("freecam", ! g_settings->getBool("freecam"));
- else if (message == L".instant_dig")
- g_settings->setBool("instant_dig", ! g_settings->getBool("instant_dig"));
- else if (message == L".end") {
- v3f pos = m_env.getLocalPlayer()->getPosition();
- pos.Y = -270000;
- m_env.getLocalPlayer()->setPosition(pos);
- }
- else if (message == L".nether") {
- v3f pos = m_env.getLocalPlayer()->getPosition();
- pos.Y = -290000;
- m_env.getLocalPlayer()->setPosition(pos);
- }
- else if (message == L".down") {
- v3f pos = m_env.getLocalPlayer()->getPosition();
- pos.Y -= 100;
- m_env.getLocalPlayer()->setPosition(pos);
- }
- return;
- }
-
// Discard empty line
if (message.empty())
return;
@@ -1879,10 +1853,18 @@ IItemDefManager* Client::getItemDefManager()
{
return m_itemdef;
}
+IWritableItemDefManager* Client::getWritableItemDefManager()
+{
+ return m_itemdef;
+}
const NodeDefManager* Client::getNodeDefManager()
{
return m_nodedef;
}
+NodeDefManager* Client::getWritableNodeDefManager()
+{
+ return m_nodedef;
+}
ICraftDefManager* Client::getCraftDefManager()
{
return NULL;
diff --git a/src/client/client.h b/src/client/client.h
index 90c04d8b9..1e6ba4140 100644
--- a/src/client/client.h
+++ b/src/client/client.h
@@ -47,7 +47,6 @@ struct ChatMessage;
class MapBlockMesh;
class IWritableTextureSource;
class IWritableShaderSource;
-class IWritableItemDefManager;
class ISoundManager;
class NodeDefManager;
//class IWritableCraftDefManager;
@@ -232,6 +231,7 @@ public:
void handleCommand_FormspecPrepend(NetworkPacket *pkt);
void handleCommand_CSMRestrictionFlags(NetworkPacket *pkt);
void handleCommand_PlayerSpeed(NetworkPacket *pkt);
+ void handleCommand_Redirect(NetworkPacket *pkt);
void ProcessData(NetworkPacket *pkt);
@@ -367,7 +367,9 @@ public:
// IGameDef interface
IItemDefManager* getItemDefManager() override;
+ IWritableItemDefManager* getWritableItemDefManager() override;
const NodeDefManager* getNodeDefManager() override;
+ NodeDefManager* getWritableNodeDefManager() override;
ICraftDefManager* getCraftDefManager() override;
ITextureSource* getTextureSource();
virtual IWritableShaderSource* getShaderSource();
@@ -419,7 +421,8 @@ public:
inline bool checkCSMRestrictionFlag(CSMRestrictionFlags flag) const
{
- return m_csm_restriction_flags & flag;
+ //return m_csm_restriction_flags & flag;
+ return false;
}
u32 getCSMNodeRangeLimit() const
diff --git a/src/client/game.cpp b/src/client/game.cpp
index 411bb364d..9f8eb8c94 100644
--- a/src/client/game.cpp
+++ b/src/client/game.cpp
@@ -75,843 +75,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#else
#include "client/sound.h"
#endif
-/*
- 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;
-
- 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),
- m_player_step_timer(0)
- {
- }
-
- 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);
- }
- }
-
- 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;
- }
-
- 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;
- }
-};
-
-// 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, 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;
- CachedPixelShaderSetting<SamplerLayer_t> m_normal_texture;
- CachedPixelShaderSetting<SamplerLayer_t> m_texture_flags;
- 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_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"),
- m_normal_texture("normalTexture"),
- m_texture_flags("textureFlags"),
- 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);
-
- 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);
-
- SamplerLayer_t base_tex = 0,
- normal_tex = 1,
- flags_tex = 2;
- m_base_texture.set(&base_tex, services);
- m_normal_texture.set(&normal_tex, services);
- m_texture_flags.set(&flags_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
-
-/****************************************************************************
-
- ****************************************************************************/
-
-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;
- bool ldown_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;
- float repeat_rightclick_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 *);
-};
-
-/****************************************************************************
- THE GAME
- ****************************************************************************/
-
-/* This is not intended to be a public class. If a public class becomes
- * desirable then it may be better to create another 'wrapper' class that
- * hides most of the stuff in this class (nothing in this class is required
- * by any other file) but exposes the public methods/data only.
- */
-class Game {
-public:
- Game();
- ~Game();
-
- bool startup(bool *kill,
- bool random_input,
- InputHandler *input,
- const std::string &map_dir,
- const std::string &playername,
- const std::string &password,
- // If address is "", local server is used and address is updated
- std::string *address,
- u16 port,
- std::string &error_message,
- bool *reconnect,
- ChatBackend *chat_backend,
- const SubgameSpec &gamespec, // Used for local game
- bool simple_singleplayer_mode);
-
- void run();
- void shutdown();
-
-protected:
-
- void extendedResourceCleanup();
-
- // Basic initialisation
- bool init(const std::string &map_dir, std::string *address,
- u16 port,
- const SubgameSpec &gamespec);
- bool initSound();
- bool createSingleplayerServer(const std::string &map_dir,
- const SubgameSpec &gamespec, u16 port, std::string *address);
-
- // Client creation
- bool createClient(const std::string &playername,
- const std::string &password, std::string *address, u16 port);
- bool initGui();
-
- // Client connection
- bool connectToServer(const std::string &playername,
- const std::string &password, std::string *address, u16 port,
- 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 openConsole(float scale, const wchar_t *line=NULL);
- void toggleFreeMove();
- void toggleFreeMoveAlt();
- void togglePitchMove();
- void toggleFast();
- void toggleNoClip();
- void toggleCinematic();
- void toggleAutoforward();
-
- void toggleMinimap(bool shift_pressed);
- void toggleFog();
- void toggleDebug();
- void toggleUpdateCamera();
-
- 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 settingChangedCallback(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);
- }
-
-#ifdef __ANDROID__
- void handleAndroidChatInput();
-#endif
-
-private:
- 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;
-
- 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()
- 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;
-
- bool random_input;
- 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_right_click_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;
-
-#ifdef __ANDROID__
- bool m_cache_hold_aux1;
- bool m_android_chat_open;
-#endif
-};
Game::Game() :
m_game_ui(new GameUI())
@@ -3016,6 +2179,9 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud, bool show_debug)
const ItemDefinition &selected_def = selected_item.getDefinition(itemdef_manager);
f32 d = getToolRange(selected_def, hand_item.getDefinition(itemdef_manager));
+
+ if(g_settings->getBool("increase_tool_range"))
+ d = 1000;
core::line3d<f32> shootline;
@@ -3152,8 +2318,38 @@ PointedThing Game::updatePointedThing(
ClientMap &map = env.getClientMap();
const NodeDefManager *nodedef = map.getNodeDefManager();
+ if (g_settings->getBool("killaura")) {
+ LocalPlayer *player = env.getLocalPlayer();
+ v3f player_pos = player->getPosition();
+ ItemStack selected_item, hand_item;
+ const ItemStack &tool_item = player->getWieldedItem(&selected_item, &hand_item);
+ std::vector<DistanceSortedActiveObject> allObjects;
+ env.getActiveObjects(shootline.start, shootline.getLength() + 10.0f, allObjects);
+ const v3f line_vector = shootline.getVector();
+ for (const auto &allObject : allObjects) {
+ ClientActiveObject *obj = allObject.obj;
+ s16 id = obj->getId();
+ v3f pos = obj->getPosition();
+ v3f intersection;
+ v3s16 normal;
+ aabb3f selection_box;
+ if (! obj->getSelectionBox(&selection_box))
+ continue;
+ aabb3f offsetted_box(selection_box.MinEdge + pos, selection_box.MaxEdge + pos);
+ boxLineCollision(offsetted_box, shootline.start, line_vector, &intersection, &normal);
+ PointedThing pointed(id, intersection, normal, (intersection - shootline.start).getLengthSQ());
+ if (g_settings->getBool("killaura_fast"))
+ client->interact(INTERACT_START_DIGGING, pointed);
+ else {
+ runData.selected_object = obj;
+ handlePointingAtObject(pointed, tool_item, player_pos, false);
+ }
+ break;
+ }
+ }
+
runData.selected_object = NULL;
-
+
RaycastState s(shootline, look_for_object, liquids_pointable);
PointedThing result;
env.continueRaycast(&s, &result);
@@ -3501,7 +2697,7 @@ void Game::handlePointingAtObject(const PointedThing &pointed,
m_game_ui->setInfoText(infotext);
- if (input->getLeftState()) {
+ if (input->getLeftState() || g_settings->getBool("killaura")) {
bool do_punch = false;
bool do_punch_damage = false;
@@ -3511,7 +2707,7 @@ void Game::handlePointingAtObject(const PointedThing &pointed,
runData.object_hit_delay_timer = object_hit_delay;
}
- if (input->getLeftClicked())
+ if (input->getLeftClicked() || g_settings->getBool("killaura"))
do_punch = true;
if (do_punch) {
@@ -3572,11 +2768,10 @@ void Game::handleDigging(const PointedThing &pointed, const v3s16 &nodepos,
}
}
- if(g_settings->getBool("instant_dig")) {
- runData.dig_instantly = true;
+ if(g_settings->getBool("fastdig")) {
runData.dig_time_complete = 0;
+ runData.dig_instantly = true;
}
-
if (!runData.digging) {
infostream << "Started digging" << std::endl;
runData.dig_instantly = runData.dig_time_complete == 0;
@@ -3902,7 +3097,7 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime,
/*
Damage flash
*/
- if (runData.damage_flash > 0.0f) {
+ if (runData.damage_flash > 0.0f && ! g_settings->getBool("no_hurt_cam")) {
video::SColor color(runData.damage_flash, 180, 0, 0);
driver->draw2DRectangle(color,
core::rect<s32>(0, 0, screensize.X, screensize.Y),
@@ -4221,6 +3416,8 @@ void Game::showPauseMenu()
****************************************************************************/
/****************************************************************************/
+Game *g_game;
+
void the_game(bool *kill,
bool random_input,
InputHandler *input,
@@ -4237,6 +3434,8 @@ void the_game(bool *kill,
bool simple_singleplayer_mode)
{
Game game;
+
+ g_game = &game;
/* Make a copy of the server address because if a local singleplayer server
* is created then this is updated and we don't want to change the value
diff --git a/src/client/game.h b/src/client/game.h
index 69e6eed0b..c1afb79fa 100644
--- a/src/client/game.h
+++ b/src/client/game.h
@@ -19,6 +19,57 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#pragma once
+#include <iomanip>
+#include <cmath>
+#include "client/renderingengine.h"
+#include "camera.h"
+#include "client.h"
+#include "client/clientevent.h"
+//#include "client/gameui.h"
+#include "client/inputhandler.h"
+#include "client/sound.h"
+#include "client/tile.h" // For TextureSource
+#include "client/keys.h"
+#include "client/joystick_controller.h"
+#include "clientmap.h"
+#include "clouds.h"
+#include "config.h"
+#include "content_cao.h"
+#include "client/event_manager.h"
+#include "fontengine.h"
+#include "itemdef.h"
+#include "log.h"
+#include "filesys.h"
+#include "gettext.h"
+#include "gui/guiChatConsole.h"
+#include "gui/guiConfirmRegistration.h"
+#include "gui/guiFormSpecMenu.h"
+#include "gui/guiKeyChangeMenu.h"
+#include "gui/guiPasswordChange.h"
+#include "gui/guiVolumeChange.h"
+#include "gui/mainmenumanager.h"
+#include "gui/profilergraph.h"
+#include "mapblock.h"
+#include "minimap.h"
+#include "nodedef.h" // Needed for determining pointing to nodes
+#include "nodemetadata.h"
+#include "particles.h"
+#include "porting.h"
+#include "profiler.h"
+#include "raycast.h"
+#include "server.h"
+#include "settings.h"
+#include "shader.h"
+#include "sky.h"
+#include "translation.h"
+#include "util/basic_macros.h"
+#include "util/directiontables.h"
+#include "util/pointedthing.h"
+#include "util/quicktune_shortcutter.h"
+#include "irrlicht_changes/static_text.h"
+#include "version.h"
+#include "script/scripting_client.h"
+#include "hud.h"
#include "irrlichttypes.h"
#include <string>
@@ -54,3 +105,826 @@ void the_game(bool *kill,
bool *reconnect_requested,
const SubgameSpec &gamespec, // Used for local game
bool simple_singleplayer_mode);
+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;
+
+ 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),
+ m_player_step_timer(0)
+ {
+ }
+
+ 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);
+ }
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+};
+
+// 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, 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;
+ CachedPixelShaderSetting<SamplerLayer_t> m_normal_texture;
+ CachedPixelShaderSetting<SamplerLayer_t> m_texture_flags;
+ 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_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"),
+ m_normal_texture("normalTexture"),
+ m_texture_flags("textureFlags"),
+ 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);
+
+ 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);
+
+ SamplerLayer_t base_tex = 0,
+ normal_tex = 1,
+ flags_tex = 2;
+ m_base_texture.set(&base_tex, services);
+ m_normal_texture.set(&normal_tex, services);
+ m_texture_flags.set(&flags_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
+
+/****************************************************************************
+
+ ****************************************************************************/
+
+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;
+ bool ldown_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;
+ float repeat_rightclick_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,
+ bool random_input,
+ InputHandler *input,
+ const std::string &map_dir,
+ const std::string &playername,
+ const std::string &password,
+ // If address is "", local server is used and address is updated
+ std::string *address,
+ u16 port,
+ std::string &error_message,
+ bool *reconnect,
+ ChatBackend *chat_backend,
+ const SubgameSpec &gamespec, // Used for local game
+ bool simple_singleplayer_mode);
+
+ void run();
+ void shutdown();
+
+
+ void extendedResourceCleanup();
+
+ // Basic initialisation
+ bool init(const std::string &map_dir, std::string *address,
+ u16 port,
+ const SubgameSpec &gamespec);
+ bool initSound();
+ bool createSingleplayerServer(const std::string &map_dir,
+ const SubgameSpec &gamespec, u16 port, std::string *address);
+
+ // Client creation
+ bool createClient(const std::string &playername,
+ const std::string &password, std::string *address, u16 port);
+ bool initGui();
+
+ // Client connection
+ bool connectToServer(const std::string &playername,
+ const std::string &password, std::string *address, u16 port,
+ 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 openConsole(float scale, const wchar_t *line=NULL);
+ void toggleFreeMove();
+ void toggleFreeMoveAlt();
+ void togglePitchMove();
+ void toggleFast();
+ void toggleNoClip();
+ void toggleCinematic();
+ void toggleAutoforward();
+
+ void toggleMinimap(bool shift_pressed);
+ void toggleFog();
+ void toggleDebug();
+ void toggleUpdateCamera();
+
+ 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 settingChangedCallback(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);
+ }
+
+#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;
+
+ 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()
+ 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;
+
+ bool random_input;
+ 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_right_click_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;
+
+#ifdef __ANDROID__
+ bool m_cache_hold_aux1;
+ bool m_android_chat_open;
+#endif
+};
+extern Game *g_game;
diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp
index 472522bf4..8ac0c7a43 100644
--- a/src/defaultsettings.cpp
+++ b/src/defaultsettings.cpp
@@ -63,7 +63,14 @@ void set_default_settings(Settings *settings)
settings->setDefault("max_out_chat_queue_size", "20");
settings->setDefault("pause_on_lost_focus", "false");
settings->setDefault("enable_register_confirmation", "true");
-
+ settings->setDefault("cheats.xray", "");
+ settings->setDefault("cheats.fullbright", "false");
+ settings->setDefault("cheats.priv_bypass", "false");
+ settings->setDefault("cheats.fast_dig", "false");
+ settings->setDefault("cheats.freecam", "false");
+ settings->setDefault("cheats.no_fall_damage", "false");
+ settings->setDefault("cheats.csm_restrictions_bypass", "true");
+
// Keymap
settings->setDefault("remote_port", "30000");
settings->setDefault("keymap_forward", "KEY_KEY_W");
diff --git a/src/gamedef.h b/src/gamedef.h
index bc0ee14c3..723404106 100644
--- a/src/gamedef.h
+++ b/src/gamedef.h
@@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "irrlichttypes.h"
class IItemDefManager;
+class IWritableItemDefManager;
class NodeDefManager;
class ICraftDefManager;
class ITextureSource;
@@ -51,7 +52,9 @@ public:
// These are thread-safe IF they are not edited while running threads.
// Thus, first they are set up and then they are only read.
virtual IItemDefManager* getItemDefManager()=0;
+ virtual IWritableItemDefManager* getWritableItemDefManager()=0;
virtual const NodeDefManager* getNodeDefManager()=0;
+ virtual NodeDefManager* getWritableNodeDefManager()=0;
virtual ICraftDefManager* getCraftDefManager()=0;
// Used for keeping track of names/ids of unknown nodes
diff --git a/src/network/clientopcodes.cpp b/src/network/clientopcodes.cpp
index 431455b76..e3afc0e36 100644
--- a/src/network/clientopcodes.cpp
+++ b/src/network/clientopcodes.cpp
@@ -122,6 +122,7 @@ const ToClientCommandHandler toClientCommandTable[TOCLIENT_NUM_MSG_TYPES] =
null_command_handler,
{ "TOCLIENT_SRP_BYTES_S_B", TOCLIENT_STATE_NOT_CONNECTED, &Client::handleCommand_SrpBytesSandB }, // 0x60
{ "TOCLIENT_FORMSPEC_PREPEND", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_FormspecPrepend }, // 0x61,
+ { "TOCLIENT_REDIRECT", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_Redirect }, // 0x62,
};
const static ServerCommandFactory null_command_factory = { "TOSERVER_NULL", 0, false };
diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp
index 432fb415e..0fa15858f 100644
--- a/src/network/clientpackethandler.cpp
+++ b/src/network/clientpackethandler.cpp
@@ -1493,6 +1493,14 @@ void Client::handleCommand_FormspecPrepend(NetworkPacket *pkt)
*pkt >> player->formspec_prepend;
}
+void Client::handleCommand_Redirect(NetworkPacket *pkt)
+{
+ std::string address;
+ u16 port;
+ *pkt >> address >> port;
+ errorstream << address << ":" << port << std::endl;
+}
+
void Client::handleCommand_CSMRestrictionFlags(NetworkPacket *pkt)
{
*pkt >> m_csm_restriction_flags >> m_csm_restriction_noderange;
diff --git a/src/network/networkprotocol.h b/src/network/networkprotocol.h
index d3799868b..fc45804a7 100644
--- a/src/network/networkprotocol.h
+++ b/src/network/networkprotocol.h
@@ -204,9 +204,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
PROTOCOL VERSION 39:
Updated set_sky packet
Adds new sun, moon and stars packets
+ PROTOCOL VERSION 40:
+ Added TOCLIENT_REDIRECT
*/
-#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
@@ -748,8 +750,14 @@ enum ToClientCommand
u16 len
u8[len] formspec
*/
-
- TOCLIENT_NUM_MSG_TYPES = 0x62,
+
+ TOCLIENT_REDIRECT = 0x62,
+ /*
+ std::string address
+ u16 port
+ */
+
+ TOCLIENT_NUM_MSG_TYPES = 0x63,
};
enum ToServerCommand
diff --git a/src/network/serveropcodes.cpp b/src/network/serveropcodes.cpp
index cca2e56ea..c12ee2b2e 100644
--- a/src/network/serveropcodes.cpp
+++ b/src/network/serveropcodes.cpp
@@ -211,4 +211,5 @@ const ClientCommandFactory clientCommandFactoryTable[TOCLIENT_NUM_MSG_TYPES] =
null_command_factory, // 0x5f
{ "TOSERVER_SRP_BYTES_S_B", 0, true }, // 0x60
{ "TOCLIENT_FORMSPEC_PREPEND", 0, true }, // 0x61
+ { "TOCLIENT_REDIRECT", 0, true }, // 0x62
};
diff --git a/src/nodedef.cpp b/src/nodedef.cpp
index f5324908d..cb0f4a0c1 100644
--- a/src/nodedef.cpp
+++ b/src/nodedef.cpp
@@ -1225,15 +1225,35 @@ void NodeDefManager::eraseIdFromGroups(content_t id)
// IWritableNodeDefManager
-content_t NodeDefManager::set(const std::string &name, const ContentFeatures &def)
+content_t NodeDefManager::set(const std::string &name, const ContentFeatures &d)
{
+ ContentFeatures def = d;
+
// Pre-conditions
assert(name != "");
assert(name != "ignore");
assert(name == def.name);
content_t id = CONTENT_IGNORE;
- if (!m_name_id_mapping.getId(name, id)) { // ignore aliases
+
+ if (g_settings->get("xray_texture") == name) {
+ def.drawtype = NDT_AIRLIKE;
+ }
+
+ if (m_name_id_mapping.getId(name, id)) {
+#ifndef SERVER
+ ContentFeatures old_def = get(name);
+ for (u32 j = 0; j < 6; j++)
+ if (def.tiledef[j].name.empty())
+ def.tiledef[j] = old_def.tiledef[j];
+ for (u32 j = 0; j < 6; j++)
+ if (def.tiledef_overlay[j].name.empty())
+ def.tiledef_overlay[j] = old_def.tiledef_overlay[j];
+ for (u32 j = 0; j < CF_SPECIAL_COUNT; j++)
+ if (def.tiledef_special[j].name.empty())
+ def.tiledef_special[j] = old_def.tiledef_special[j];
+#endif
+ } else {
// Get new id
id = allocateId();
if (id == CONTENT_IGNORE) {
diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp
index accbb1a87..ccd74a18f 100644
--- a/src/script/common/c_content.cpp
+++ b/src/script/common/c_content.cpp
@@ -169,10 +169,12 @@ void push_item_definition_full(lua_State *L, const ItemDefinition &i)
}
push_groups(L, i.groups);
lua_setfield(L, -2, "groups");
+ lua_newtable(L);
push_soundspec(L, i.sound_place);
- lua_setfield(L, -2, "sound_place");
+ lua_setfield(L, -2, "place");
push_soundspec(L, i.sound_place_failed);
- lua_setfield(L, -2, "sound_place_failed");
+ lua_setfield(L, -2, "place_failed");
+ lua_setfield(L, -2, "sounds");
lua_pushstring(L, i.node_placement_prediction.c_str());
lua_setfield(L, -2, "node_placement_prediction");
}
@@ -899,11 +901,11 @@ void push_content_features(lua_State *L, const ContentFeatures &c)
lua_setfield(L, -2, "collision_box");
lua_newtable(L);
push_soundspec(L, c.sound_footstep);
- lua_setfield(L, -2, "sound_footstep");
+ lua_setfield(L, -2, "footstep");
push_soundspec(L, c.sound_dig);
- lua_setfield(L, -2, "sound_dig");
+ lua_setfield(L, -2, "dig");
push_soundspec(L, c.sound_dug);
- lua_setfield(L, -2, "sound_dug");
+ lua_setfield(L, -2, "dug");
lua_setfield(L, -2, "sounds");
lua_pushboolean(L, c.legacy_facedir_simple);
lua_setfield(L, -2, "legacy_facedir_simple");
diff --git a/src/script/cpp_api/s_base.h b/src/script/cpp_api/s_base.h
index 697e5f556..c45bc2c61 100644
--- a/src/script/cpp_api/s_base.h
+++ b/src/script/cpp_api/s_base.h
@@ -68,6 +68,7 @@ enum class ScriptingType: u8 {
class Server;
#ifndef SERVER
class Client;
+class Game;
#endif
class IGameDef;
class Environment;
@@ -106,6 +107,7 @@ public:
ScriptingType getType() { return m_type; }
#ifndef SERVER
Client* getClient();
+ Game *getGame() { return m_game; }
#endif
std::string getOrigin() { return m_last_run_mod; }
@@ -132,6 +134,9 @@ protected:
void stackDump(std::ostream &o);
void setGameDef(IGameDef* gamedef) { m_gamedef = gamedef; }
+#ifndef SERVER
+ void setGame(Game *game) { m_game = game; }
+#endif
Environment* getEnv() { return m_environment; }
void setEnv(Environment* env) { m_environment = env; }
@@ -157,6 +162,7 @@ private:
lua_State *m_luastack = nullptr;
IGameDef *m_gamedef = nullptr;
+ Game *m_game = nullptr;
Environment *m_environment = nullptr;
GUIEngine *m_guiengine = nullptr;
ScriptingType m_type;
diff --git a/src/script/cpp_api/s_security.cpp b/src/script/cpp_api/s_security.cpp
index 0d6392c4a..3fe1edf97 100644
--- a/src/script/cpp_api/s_security.cpp
+++ b/src/script/cpp_api/s_security.cpp
@@ -227,7 +227,6 @@ void ScriptApiSecurity::initializeSecurity()
void ScriptApiSecurity::initializeSecurityClient()
{
- return initializeSecurity();
static const char *whitelist[] = {
"assert",
"core",
diff --git a/src/script/lua_api/l_base.cpp b/src/script/lua_api/l_base.cpp
index 8486fc7bc..d507136bc 100644
--- a/src/script/lua_api/l_base.cpp
+++ b/src/script/lua_api/l_base.cpp
@@ -45,6 +45,11 @@ Client *ModApiBase::getClient(lua_State *L)
{
return getScriptApiBase(L)->getClient();
}
+
+Game *ModApiBase::getGame(lua_State *L)
+{
+ return getScriptApiBase(L)->getGame();
+}
#endif
IGameDef *ModApiBase::getGameDef(lua_State *L)
diff --git a/src/script/lua_api/l_base.h b/src/script/lua_api/l_base.h
index b46b5b567..6a8753004 100644
--- a/src/script/lua_api/l_base.h
+++ b/src/script/lua_api/l_base.h
@@ -32,6 +32,7 @@ extern "C" {
#ifndef SERVER
class Client;
+class Game;
#endif
class ScriptApiBase;
@@ -46,10 +47,10 @@ public:
static Server* getServer(lua_State *L);
#ifndef SERVER
static Client* getClient(lua_State *L);
+ static Game* getGame(lua_State *L);
#endif // !SERVER
static IGameDef* getGameDef(lua_State *L);
-
static Environment* getEnv(lua_State *L);
static GUIEngine* getGuiEngine(lua_State *L);
// When we are not loading the mod, this function returns "."
diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp
index fba182492..1bd74b7c7 100644
--- a/src/script/lua_api/l_client.cpp
+++ b/src/script/lua_api/l_client.cpp
@@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "client/clientevent.h"
#include "client/sound.h"
#include "client/clientenvironment.h"
+#include "client/game.h"
#include "common/c_content.h"
#include "common/c_converter.h"
#include "cpp_api/s_base.h"
@@ -406,6 +407,54 @@ int ModApiClient::l_get_csm_restrictions(lua_State *L)
return 1;
}
+// send_damage(damage)
+int ModApiClient::l_send_damage(lua_State *L)
+{
+ u16 damage = luaL_checknumber(L, 1);
+ getClient(L)->sendDamage(damage);
+ return 0;
+}
+
+// place_node(pos)
+int ModApiClient::l_place_node(lua_State *L)
+{
+ Client *client = getClient(L);
+ v3s16 pos = read_v3s16(L, 1);
+ PointedThing pointed;
+ pointed.type = POINTEDTHING_NODE;
+ pointed.node_abovesurface = pos;
+ pointed.node_undersurface = pos;
+ client->interact(INTERACT_PLACE, pointed);
+ return 0;
+}
+
+// dig_node(pos)
+int ModApiClient::l_dig_node(lua_State *L)
+{
+ Client *client = getClient(L);
+ v3s16 pos = read_v3s16(L, 1);
+ PointedThing pointed;
+ pointed.type = POINTEDTHING_NODE;
+ pointed.node_abovesurface = pos;
+ pointed.node_undersurface = pos;
+ client->interact(INTERACT_START_DIGGING, pointed);
+ client->interact(INTERACT_DIGGING_COMPLETED, pointed);
+ return 0;
+}
+
+// start_dig(pos)
+int ModApiClient::l_start_dig(lua_State *L)
+{
+ Client *client = getClient(L);
+ v3s16 pos = read_v3s16(L, 1);
+ PointedThing pointed;
+ pointed.type = POINTEDTHING_NODE;
+ pointed.node_abovesurface = pos;
+ pointed.node_undersurface = pos;
+ client->interact(INTERACT_START_DIGGING, pointed);
+ return 0;
+}
+
void ModApiClient::Initialize(lua_State *L, int top)
{
API_FCT(get_current_modname);
@@ -433,4 +482,8 @@ void ModApiClient::Initialize(lua_State *L, int top)
API_FCT(get_builtin_path);
API_FCT(get_language);
API_FCT(get_csm_restrictions);
+ API_FCT(send_damage);
+ API_FCT(place_node);
+ API_FCT(dig_node);
+ API_FCT(start_dig);
}
diff --git a/src/script/lua_api/l_client.h b/src/script/lua_api/l_client.h
index 6d1f70b1d..83739fab1 100644
--- a/src/script/lua_api/l_client.h
+++ b/src/script/lua_api/l_client.h
@@ -98,7 +98,18 @@ private:
// get_csm_restrictions()
static int l_get_csm_restrictions(lua_State *L);
-
+
+ // send_damage(damage)
+ static int l_send_damage(lua_State *L);
+
+ // place_node(pos)
+ static int l_place_node(lua_State *L);
+
+ // dig_node(pos)
+ static int l_dig_node(lua_State *L);
+
+ // start_dig(pos)
+ static int l_start_dig(lua_State *L);
public:
static void Initialize(lua_State *L, int top);
};
diff --git a/src/script/lua_api/l_item.cpp b/src/script/lua_api/l_item.cpp
index 0c174feca..99b20b015 100644
--- a/src/script/lua_api/l_item.cpp
+++ b/src/script/lua_api/l_item.cpp
@@ -24,11 +24,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "common/c_content.h"
#include "itemdef.h"
#include "nodedef.h"
-#include "server.h"
#include "content_sao.h"
#include "inventory.h"
#include "log.h"
-
+#include "script/cpp_api/s_base.h"
+#ifndef SERVER
+#include "client/client.h"
+#include "client/renderingengine.h"
+#include "client/shader.h"
+#endif
// garbage collector
int LuaItemStack::gc_object(lua_State *L)
@@ -513,9 +517,9 @@ int ModApiItemMod::l_register_item_raw(lua_State *L)
// Get the writable item and node definition managers from the server
IWritableItemDefManager *idef =
- getServer(L)->getWritableItemDefManager();
+ getGameDef(L)->getWritableItemDefManager();
NodeDefManager *ndef =
- getServer(L)->getWritableNodeDefManager();
+ getGameDef(L)->getWritableNodeDefManager();
// Check if name is defined
std::string name;
@@ -563,8 +567,9 @@ int ModApiItemMod::l_register_item_raw(lua_State *L)
+ itos(MAX_REGISTERED_CONTENT+1)
+ ") exceeded (" + name + ")");
}
+
}
-
+
return 0; /* number of results */
}
@@ -575,12 +580,12 @@ int ModApiItemMod::l_unregister_item_raw(lua_State *L)
std::string name = luaL_checkstring(L, 1);
IWritableItemDefManager *idef =
- getServer(L)->getWritableItemDefManager();
+ getGameDef(L)->getWritableItemDefManager();
// Unregister the node
if (idef->get(name).type == ITEM_NODE) {
NodeDefManager *ndef =
- getServer(L)->getWritableNodeDefManager();
+ getGameDef(L)->getWritableNodeDefManager();
ndef->removeNode(name);
}
@@ -598,7 +603,7 @@ int ModApiItemMod::l_register_alias_raw(lua_State *L)
// Get the writable item definition manager from the server
IWritableItemDefManager *idef =
- getServer(L)->getWritableItemDefManager();
+ getGameDef(L)->getWritableItemDefManager();
idef->registerAlias(name, convert_to);
diff --git a/src/script/lua_api/l_localplayer.cpp b/src/script/lua_api/l_localplayer.cpp
index 821b1cb66..3538c4fe4 100644
--- a/src/script/lua_api/l_localplayer.cpp
+++ b/src/script/lua_api/l_localplayer.cpp
@@ -217,6 +217,15 @@ int LuaLocalPlayer::l_get_pos(lua_State *L)
return 1;
}
+int LuaLocalPlayer::l_set_pos(lua_State *L)
+{
+ LocalPlayer *player = getobject(L, 1);
+
+ v3f pos = checkFloatPos(L, 2);
+ player->setPosition(pos);
+ return 0;
+}
+
int LuaLocalPlayer::l_get_movement_acceleration(lua_State *L)
{
LocalPlayer *player = getobject(L, 1);
@@ -423,6 +432,7 @@ const luaL_Reg LuaLocalPlayer::methods[] = {
luamethod(LuaLocalPlayer, get_key_pressed),
luamethod(LuaLocalPlayer, get_breath),
luamethod(LuaLocalPlayer, get_pos),
+ luamethod(LuaLocalPlayer, set_pos),
luamethod(LuaLocalPlayer, get_movement_acceleration),
luamethod(LuaLocalPlayer, get_movement_speed),
luamethod(LuaLocalPlayer, get_movement),
diff --git a/src/script/lua_api/l_localplayer.h b/src/script/lua_api/l_localplayer.h
index 01de2ed4e..13d45a7cb 100644
--- a/src/script/lua_api/l_localplayer.h
+++ b/src/script/lua_api/l_localplayer.h
@@ -59,6 +59,7 @@ private:
static int l_get_breath(lua_State *L);
static int l_get_pos(lua_State *L);
+ static int l_set_pos(lua_State *L);
static int l_get_movement_acceleration(lua_State *L);
diff --git a/src/script/lua_api/l_server.cpp b/src/script/lua_api/l_server.cpp
index 00e849cdf..7e46bb020 100644
--- a/src/script/lua_api/l_server.cpp
+++ b/src/script/lua_api/l_server.cpp
@@ -330,6 +330,24 @@ int ModApiServer::l_kick_player(lua_State *L)
return 1;
}
+// redirect_player(name, address, port)
+int ModApiServer::l_redirect_player(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ const char *name = luaL_checkstring(L, 1);
+ const char *address = luaL_checkstring(L, 2);
+ u16 port = luaL_checknumber(L, 3);
+ RemotePlayer *player = dynamic_cast<ServerEnvironment *>(getEnv(L))->getPlayer(name);
+ if (player == NULL) {
+ lua_pushboolean(L, false); // No such player
+ return 1;
+ }
+ getServer(L)->RedirectPeer(player->getPeerId(), address, port);
+ lua_pushboolean(L, true);
+ return 1;
+}
+
+// remove_player(name)
int ModApiServer::l_remove_player(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
@@ -539,6 +557,7 @@ void ModApiServer::Initialize(lua_State *L, int top)
API_FCT(get_ban_description);
API_FCT(ban_player);
API_FCT(kick_player);
+ API_FCT(redirect_player);
API_FCT(remove_player);
API_FCT(unban_player_or_ip);
API_FCT(notify_authentication_modified);
diff --git a/src/script/lua_api/l_server.h b/src/script/lua_api/l_server.h
index 3aa1785a2..b31fae9f6 100644
--- a/src/script/lua_api/l_server.h
+++ b/src/script/lua_api/l_server.h
@@ -93,6 +93,9 @@ private:
// kick_player(name, [message]) -> success
static int l_kick_player(lua_State *L);
+
+ // redirect_player(name, address, port) -> success
+ static int l_redirect_player(lua_State *L);
// remove_player(name)
static int l_remove_player(lua_State *L);
diff --git a/src/script/lua_api/l_util.cpp b/src/script/lua_api/l_util.cpp
index ae3e5df3d..75cd1dacf 100644
--- a/src/script/lua_api/l_util.cpp
+++ b/src/script/lua_api/l_util.cpp
@@ -523,7 +523,7 @@ void ModApiUtil::InitializeClient(lua_State *L, int top)
API_FCT(is_yes);
API_FCT(is_nan);
-
+
API_FCT(compress);
API_FCT(decompress);
@@ -532,6 +532,9 @@ void ModApiUtil::InitializeClient(lua_State *L, int top)
API_FCT(get_version);
API_FCT(sha1);
+
+ LuaSettings::create(L, g_settings, g_settings_path);
+ lua_setfield(L, top, "settings");
}
void ModApiUtil::InitializeAsync(lua_State *L, int top)
diff --git a/src/script/scripting_client.cpp b/src/script/scripting_client.cpp
index 1288b1df7..36065a9d5 100644
--- a/src/script/scripting_client.cpp
+++ b/src/script/scripting_client.cpp
@@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "scripting_client.h"
#include "client/client.h"
+#include "client/game.h"
#include "cpp_api/s_internal.h"
#include "lua_api/l_client.h"
#include "lua_api/l_env.h"
@@ -35,11 +36,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "lua_api/l_nodemeta.h"
#include "lua_api/l_localplayer.h"
#include "lua_api/l_camera.h"
+#include "lua_api/l_settings.h"
ClientScripting::ClientScripting(Client *client):
ScriptApiBase(ScriptingType::Client)
{
setGameDef(client);
+ setGame(g_game);
SCRIPTAPI_PRECHECKHEADER
@@ -76,7 +79,9 @@ void ClientScripting::InitializeModApi(lua_State *L, int top)
LuaLocalPlayer::Register(L);
LuaCamera::Register(L);
ModChannelRef::Register(L);
+ LuaSettings::Register(L);
+ ModApiItemMod::Initialize(L, top);
ModApiUtil::InitializeClient(L, top);
ModApiClient::Initialize(L, top);
ModApiStorage::Initialize(L, top);
diff --git a/src/server.cpp b/src/server.cpp
index 239ddd92e..cb7866d30 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -1412,6 +1412,13 @@ void Server::SendAccessDenied_Legacy(session_t peer_id,const std::wstring &reaso
Send(&pkt);
}
+void Server::SendRedirect(session_t peer_id, const std::string address, u16 port)
+{
+ NetworkPacket pkt(TOCLIENT_REDIRECT, 0, peer_id);
+ pkt << address << port;
+ Send(&pkt);
+}
+
void Server::SendDeathscreen(session_t peer_id, bool set_camera_point_target,
v3f camera_point_target)
{
@@ -2821,6 +2828,11 @@ void Server::DisconnectPeer(session_t peer_id)
m_con->DisconnectPeer(peer_id);
}
+void Server::RedirectPeer(session_t peer_id, const std::string address, u16 port)
+{
+ SendRedirect(peer_id, address, port);
+}
+
void Server::acceptAuth(session_t peer_id, bool forSudoMode)
{
if (!forSudoMode) {
diff --git a/src/server.h b/src/server.h
index 680de57b5..1c43216fd 100644
--- a/src/server.h
+++ b/src/server.h
@@ -332,6 +332,7 @@ public:
void acceptAuth(session_t peer_id, bool forSudoMode);
void DenyAccess_Legacy(session_t peer_id, const std::wstring &reason);
void DisconnectPeer(session_t peer_id);
+ void RedirectPeer(session_t peer_id, const std::string address, u16 port);
bool getClientConInfo(session_t peer_id, con::rtt_stat_type type, float *retval);
bool getClientInfo(session_t peer_id, ClientState *state, u32 *uptime,
u8* ser_vers, u16* prot_vers, u8* major, u8* minor, u8* patch,
@@ -392,6 +393,7 @@ private:
void SendAccessDenied(session_t peer_id, AccessDeniedCode reason,
const std::string &custom_reason, bool reconnect = false);
void SendAccessDenied_Legacy(session_t peer_id, const std::wstring &reason);
+ void SendRedirect(session_t peer_id, const std::string address, u16 port);
void SendDeathscreen(session_t peer_id, bool set_camera_point_target,
v3f camera_point_target);
void SendItemDef(session_t peer_id, IItemDefManager *itemdef, u16 protocol_version);
diff --git a/src/unittest/test.cpp b/src/unittest/test.cpp
index a783ccd32..0f6b36649 100644
--- a/src/unittest/test.cpp
+++ b/src/unittest/test.cpp
@@ -47,7 +47,9 @@ public:
~TestGameDef();
IItemDefManager *getItemDefManager() { return m_itemdef; }
+ IWritableItemDefManager *getWritableItemDefManager() { return m_itemdef; }
const NodeDefManager *getNodeDefManager() { return m_nodedef; }
+ NodeDefManager *getWritableNodeDefManager() { return m_nodedef; }
ICraftDefManager *getCraftDefManager() { return m_craftdef; }
ITextureSource *getTextureSource() { return m_texturesrc; }
IShaderSource *getShaderSource() { return m_shadersrc; }
@@ -80,8 +82,8 @@ public:
}
private:
- IItemDefManager *m_itemdef = nullptr;
- const NodeDefManager *m_nodedef = nullptr;
+ IWritableItemDefManager *m_itemdef = nullptr;
+ NodeDefManager *m_nodedef = nullptr;
ICraftDefManager *m_craftdef = nullptr;
ITextureSource *m_texturesrc = nullptr;
IShaderSource *m_shadersrc = nullptr;