Add clouds API
authorBen Deutsch <ben@bendeutsch.de>
Fri, 17 Mar 2017 09:39:47 +0000 (10:39 +0100)
committerparamat <mat.gregory@virginmedia.com>
Sat, 29 Apr 2017 23:06:13 +0000 (00:06 +0100)
17 files changed:
doc/lua_api.txt
src/client.h
src/cloudparams.h [new file with mode: 0644]
src/clouds.cpp
src/clouds.h
src/game.cpp
src/network/clientopcodes.cpp
src/network/clientpackethandler.cpp
src/network/networkprotocol.h
src/network/serveropcodes.cpp
src/remoteplayer.cpp
src/remoteplayer.h
src/script/lua_api/l_object.cpp
src/script/lua_api/l_object.h
src/server.cpp
src/server.h
src/sky.cpp

index eba8a5fef475d0592477aa36e5f2dcbb201d3454..479e38a2eef0cf081db76f7736564ab3ef47eee3 100644 (file)
@@ -3077,6 +3077,15 @@ This is basically a reference to a C++ `ServerActiveObject`
         * `"skybox"`: Uses 6 textures, `bgcolor` used
         * `"plain"`: Uses 0 textures, `bgcolor` used
 * `get_sky()`: returns bgcolor, type and a table with the textures
+* `set_clouds(parameters)`: set cloud parameters
+       * `parameters` is a table with the following optional fields:
+               * `density`: from `0` (no clouds) to `1` (full clouds) (default `0.4`)
+               * `color`: basic cloud color, with alpha channel (default `#fff0f0e5`)
+               * `ambient`: cloud color lower bound, use for a "glow at night" effect (default `#000000`)
+               * `height`: cloud height, i.e. y of cloud base (default per conf, usually `120`)
+               * `thickness`: cloud thickness in nodes (default `16`)
+               * `speed`: 2D cloud speed + direction in nodes per second (default `{x=0, y=-2}`)
+* `get_clouds()`: returns a table with the current cloud parameters as in `set_clouds`
 * `override_day_night_ratio(ratio or nil)`
     * `0`...`1`: Overrides day-night ratio, controlling sunlight to a specific amount
     * `nil`: Disables override, defaulting to sunlight based on day-night cycle
index f5b03f19df2a0689e2e45b56ac7ae8e64896083e..7cbfadd50fd36f98d636388c12b8b572c0c9868b 100644 (file)
@@ -77,6 +77,7 @@ enum ClientEventType
        CE_HUDCHANGE,
        CE_SET_SKY,
        CE_OVERRIDE_DAY_NIGHT_RATIO,
+       CE_CLOUD_PARAMS,
 };
 
 struct ClientEvent
@@ -178,6 +179,15 @@ struct ClientEvent
                        bool do_override;
                        float ratio_f;
                } override_day_night_ratio;
+               struct {
+                       f32 density;
+                       u32 color_bright;
+                       u32 color_ambient;
+                       f32 height;
+                       f32 thickness;
+                       f32 speed_x;
+                       f32 speed_y;
+               } cloud_params;
        };
 };
 
@@ -331,6 +341,7 @@ public:
        void handleCommand_HudSetFlags(NetworkPacket* pkt);
        void handleCommand_HudSetParam(NetworkPacket* pkt);
        void handleCommand_HudSetSky(NetworkPacket* pkt);
+       void handleCommand_CloudParams(NetworkPacket* pkt);
        void handleCommand_OverrideDayNightRatio(NetworkPacket* pkt);
        void handleCommand_LocalPlayerAnimations(NetworkPacket* pkt);
        void handleCommand_EyeOffset(NetworkPacket* pkt);
diff --git a/src/cloudparams.h b/src/cloudparams.h
new file mode 100644 (file)
index 0000000..dafec4b
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+Minetest
+Copyright (C) 2017 bendeutsch, Ben Deutsch <ben@bendeutsch.de>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef CLOUDPARAMS_HEADER
+#define CLOUDPARAMS_HEADER
+
+struct CloudParams
+{
+       float density;
+       video::SColor color_bright;
+       video::SColor color_ambient;
+       float thickness;
+       float height;
+       v2f speed;
+};
+
+#endif
index 82b63b6b35006d64609a8e9609d40697de32a004..627fac47a2742157c4b72266907e0e06f0518a97 100644 (file)
@@ -32,6 +32,7 @@ irr::scene::ISceneManager *g_menucloudsmgr = NULL;
 
 static void cloud_3d_setting_changed(const std::string &settingname, void *data)
 {
+       // TODO: only re-read cloud settings, not height or radius
        ((Clouds *)data)->readSettings();
 }
 
@@ -44,9 +45,10 @@ Clouds::Clouds(
 ):
        scene::ISceneNode(parent, mgr, id),
        m_seed(seed),
-       m_camera_pos(0,0),
-       m_time(0),
-       m_camera_offset(0,0,0)
+       m_camera_pos(0.0f, 0.0f),
+       m_origin(0.0f, 0.0f),
+       m_camera_offset(0.0f, 0.0f, 0.0f),
+       m_color(1.0f, 1.0f, 1.0f, 1.0f)
 {
        m_material.setFlag(video::EMF_LIGHTING, false);
        //m_material.setFlag(video::EMF_BACK_FACE_CULLING, false);
@@ -57,14 +59,18 @@ Clouds::Clouds(
        //m_material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
        m_material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
 
+       m_params.density       = 0.4f;
+       m_params.thickness     = 16.0f;
+       m_params.color_bright  = video::SColor(229, 255, 240, 240);
+       m_params.color_ambient = video::SColor(255, 0, 0, 0);
+       m_params.speed         = v2f(0.0f, -2.0f);
+
        m_passed_cloud_y = cloudheight;
        readSettings();
        g_settings->registerChangedCallback("enable_3d_clouds",
                &cloud_3d_setting_changed, this);
 
-       m_box = aabb3f(-BS*1000000,m_cloud_y-BS,-BS*1000000,
-                       BS*1000000,m_cloud_y+BS,BS*1000000);
-
+       updateBox();
 }
 
 Clouds::~Clouds()
@@ -88,6 +94,10 @@ void Clouds::OnRegisterSceneNode()
 
 void Clouds::render()
 {
+
+       if (m_params.density <= 0.0f)
+               return; // no need to do anything
+
        video::IVideoDriver* driver = SceneManager->getVideoDriver();
 
        if(SceneManager->getSceneNodeRenderPass() != scene::ESNRP_TRANSPARENT)
@@ -107,15 +117,12 @@ void Clouds::render()
                Clouds move from Z+ towards Z-
        */
 
-       const float cloud_size = BS * 64;
-       const v2f cloud_speed(0, -BS * 2);
+       static const float cloud_size = BS * 64.0f;
        
        const float cloud_full_radius = cloud_size * m_cloud_radius_i;
        
-       // Position of cloud noise origin in world coordinates
-       v2f world_cloud_origin_pos_f = m_time * cloud_speed;
        // Position of cloud noise origin from the camera
-       v2f cloud_origin_from_camera_f = world_cloud_origin_pos_f - m_camera_pos;
+       v2f cloud_origin_from_camera_f = m_origin - m_camera_pos;
        // The center point of drawing in the noise
        v2f center_of_drawing_in_noise_f = -cloud_origin_from_camera_f;
        // The integer center point of drawing in the noise
@@ -127,7 +134,7 @@ void Clouds::render()
        v2f world_center_of_drawing_in_noise_f = v2f(
                center_of_drawing_in_noise_i.X * cloud_size,
                center_of_drawing_in_noise_i.Y * cloud_size
-       ) + world_cloud_origin_pos_f;
+       ) + m_origin;
 
        /*video::SColor c_top(128,b*240,b*240,b*255);
        video::SColor c_side_1(128,b*230,b*230,b*255);
@@ -146,10 +153,6 @@ void Clouds::render()
        c_bottom_f.r *= 0.80;
        c_bottom_f.g *= 0.80;
        c_bottom_f.b *= 0.80;
-       c_top_f.a = 0.9;
-       c_side_1_f.a = 0.9;
-       c_side_2_f.a = 0.9;
-       c_bottom_f.a = 0.9;
        video::SColor c_top = c_top_f.toSColor();
        video::SColor c_side_1 = c_side_1_f.toSColor();
        video::SColor c_side_2 = c_side_2_f.toSColor();
@@ -187,11 +190,14 @@ void Clouds::render()
                                zi + center_of_drawing_in_noise_i.Y
                        );
 
-                       double noise = noise2d_perlin(
+                       float noise = noise2d_perlin(
                                        (float)p_in_noise_i.X * cloud_size_noise,
                                        (float)p_in_noise_i.Y * cloud_size_noise,
                                        m_seed, 3, 0.5);
-                       grid[i] = (noise >= 0.4);
+                       // normalize to 0..1 (given 3 octaves)
+                       static const float noise_bound = 1.0f + 0.5f + 0.25f;
+                       float density = noise / noise_bound * 0.5f + 0.5f;
+                       grid[i] = (density < m_params.density);
                }
        }
 
@@ -236,8 +242,9 @@ void Clouds::render()
                        v[3].Color.setBlue(255);
                }*/
 
-               f32 rx = cloud_size/2;
-               f32 ry = 8 * BS;
+               f32 rx = cloud_size / 2.0f;
+               // if clouds are flat, the top layer should be at the given height
+               f32 ry = m_enable_3d ? m_params.thickness * BS : 0.0f;
                f32 rz = cloud_size / 2;
 
                for(int i=0; i<num_faces_to_draw; i++)
@@ -265,8 +272,8 @@ void Clouds::render()
                                }
                                v[0].Pos.set(-rx, ry,-rz);
                                v[1].Pos.set( rx, ry,-rz);
-                               v[2].Pos.set( rx,-ry,-rz);
-                               v[3].Pos.set(-rx,-ry,-rz);
+                               v[2].Pos.set( rx,  0,-rz);
+                               v[3].Pos.set(-rx,  0,-rz);
                                break;
                        case 2: //right
                                if (INAREA(xi + 1, zi, m_cloud_radius_i)) {
@@ -280,8 +287,8 @@ void Clouds::render()
                                }
                                v[0].Pos.set( rx, ry,-rz);
                                v[1].Pos.set( rx, ry, rz);
-                               v[2].Pos.set( rx,-ry, rz);
-                               v[3].Pos.set( rx,-ry,-rz);
+                               v[2].Pos.set( rx,  0, rz);
+                               v[3].Pos.set( rx,  0,-rz);
                                break;
                        case 3: // front
                                if (INAREA(xi, zi + 1, m_cloud_radius_i)) {
@@ -295,8 +302,8 @@ void Clouds::render()
                                }
                                v[0].Pos.set( rx, ry, rz);
                                v[1].Pos.set(-rx, ry, rz);
-                               v[2].Pos.set(-rx,-ry, rz);
-                               v[3].Pos.set( rx,-ry, rz);
+                               v[2].Pos.set(-rx,  0, rz);
+                               v[3].Pos.set( rx,  0, rz);
                                break;
                        case 4: // left
                                if (INAREA(xi-1, zi, m_cloud_radius_i)) {
@@ -310,22 +317,22 @@ void Clouds::render()
                                }
                                v[0].Pos.set(-rx, ry, rz);
                                v[1].Pos.set(-rx, ry,-rz);
-                               v[2].Pos.set(-rx,-ry,-rz);
-                               v[3].Pos.set(-rx,-ry, rz);
+                               v[2].Pos.set(-rx,  0,-rz);
+                               v[3].Pos.set(-rx,  0, rz);
                                break;
                        case 5: // bottom
                                for(int j=0;j<4;j++){
                                        v[j].Color = c_bottom;
                                        v[j].Normal.set(0,-1,0);
                                }
-                               v[0].Pos.set( rx,-ry, rz);
-                               v[1].Pos.set(-rx,-ry, rz);
-                               v[2].Pos.set(-rx,-ry,-rz);
-                               v[3].Pos.set( rx,-ry,-rz);
+                               v[0].Pos.set( rx,  0, rz);
+                               v[1].Pos.set(-rx,  0, rz);
+                               v[2].Pos.set(-rx,  0,-rz);
+                               v[3].Pos.set( rx,  0,-rz);
                                break;
                        }
 
-                       v3f pos(p0.X, m_cloud_y, p0.Y);
+                       v3f pos(p0.X, m_params.height * BS, p0.Y);
                        pos -= intToFloat(m_camera_offset, BS);
 
                        for(u16 i=0; i<4; i++)
@@ -345,22 +352,25 @@ void Clouds::render()
 
 void Clouds::step(float dtime)
 {
-       m_time += dtime;
+       m_origin = m_origin + dtime * BS * m_params.speed;
 }
 
-void Clouds::update(v2f camera_p, video::SColorf color)
+void Clouds::update(v2f camera_p, video::SColorf color_diffuse)
 {
        m_camera_pos = camera_p;
-       m_color = color;
-       //m_brightness = brightness;
-       //dstream<<"m_brightness="<<m_brightness<<std::endl;
+       m_color.r = MYMIN(MYMAX(color_diffuse.r * m_params.color_bright.getRed(),
+                       m_params.color_ambient.getRed()), 255) / 255.0f;
+       m_color.g = MYMIN(MYMAX(color_diffuse.r * m_params.color_bright.getGreen(),
+                       m_params.color_ambient.getGreen()), 255) / 255.0f;
+       m_color.b = MYMIN(MYMAX(color_diffuse.b * m_params.color_bright.getBlue(),
+                       m_params.color_ambient.getBlue()), 255) / 255.0f;
+       m_color.a = m_params.color_bright.getAlpha() / 255.0f;
 }
 
 void Clouds::readSettings()
 {
-       m_cloud_y = BS * (m_passed_cloud_y ? m_passed_cloud_y :
+       m_params.height = (m_passed_cloud_y ? m_passed_cloud_y :
                g_settings->getS16("cloud_height"));
        m_cloud_radius_i = g_settings->getU16("cloud_radius");
        m_enable_3d = g_settings->getBool("enable_3d_clouds");
 }
-
index 9c6b417866cafd8546164f194f5f1a6b271e80dc..a0bda28df901677355b00a521e64da7b2226bf9c 100644 (file)
@@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "irrlichttypes_extrabloated.h"
 #include <iostream>
 #include "constants.h"
+#include "cloudparams.h"
 
 // Menu clouds
 class Clouds;
@@ -79,27 +80,68 @@ public:
        void updateCameraOffset(v3s16 camera_offset)
        {
                m_camera_offset = camera_offset;
-               m_box = aabb3f(-BS * 1000000, m_cloud_y - BS - BS * camera_offset.Y, -BS * 1000000,
-                       BS * 1000000, m_cloud_y + BS - BS * camera_offset.Y, BS * 1000000);
+               updateBox();
        }
 
        void readSettings();
 
+       void setDensity(float density)
+       {
+               m_params.density = density;
+               // currently does not need bounding
+       }
+
+       void setColorBright(const video::SColor &color_bright)
+       {
+               m_params.color_bright = color_bright;
+       }
+
+       void setColorAmbient(const video::SColor &color_ambient)
+       {
+               m_params.color_ambient = color_ambient;
+       }
+
+       void setHeight(float height)
+       {
+               m_params.height = height; // add bounding when necessary
+               updateBox();
+       }
+
+       void setSpeed(v2f speed)
+       {
+               m_params.speed = speed;
+       }
+
+       void setThickness(float thickness)
+       {
+               m_params.thickness = thickness;
+               updateBox();
+       }
+
 private:
+       void updateBox()
+       {
+               float height_bs    = m_params.height    * BS;
+               float thickness_bs = m_params.thickness * BS;
+               m_box = aabb3f(-BS * 1000000.0f, height_bs - BS * m_camera_offset.Y, -BS * 1000000.0f,
+                               BS * 1000000.0f, height_bs + thickness_bs - BS * m_camera_offset.Y, BS * 1000000.0f);
+       }
+
        video::SMaterial m_material;
        aabb3f m_box;
        s16 m_passed_cloud_y;
-       float m_cloud_y;
        u16 m_cloud_radius_i;
        bool m_enable_3d;
-       video::SColorf m_color;
        u32 m_seed;
        v2f m_camera_pos;
-       float m_time;
+       v2f m_origin;
+       v2f m_speed;
        v3s16 m_camera_offset;
+       video::SColorf m_color;
+       CloudParams m_params;
+
 };
 
 
 
 #endif
-
index a1cc1ab15e82abe18d02527c84b3270e38c2e49f..ba6530d8037eb214112c705ed4125ca2ea18f19d 100644 (file)
@@ -3295,6 +3295,19 @@ void Game::processClientEvents(CameraOrientation *cam)
                                        event.override_day_night_ratio.ratio_f * 1000);
                        break;
 
+               case CE_CLOUD_PARAMS:
+                       if (clouds) {
+                               clouds->setDensity(event.cloud_params.density);
+                               clouds->setColorBright(video::SColor(event.cloud_params.color_bright));
+                               clouds->setColorAmbient(video::SColor(event.cloud_params.color_ambient));
+                               clouds->setHeight(event.cloud_params.height);
+                               clouds->setThickness(event.cloud_params.thickness);
+                               clouds->setSpeed(v2f(
+                                               event.cloud_params.speed_x,
+                                               event.cloud_params.speed_y));
+                       }
+                       break;
+
                default:
                        // unknown or unhandled type
                        break;
index 563baf77b8af8070e15525110485961a3118ff0b..1be6e5522fb3caa99ab759d08365d47ab45df4d8 100644 (file)
@@ -108,7 +108,7 @@ const ToClientCommandHandler toClientCommandTable[TOCLIENT_NUM_MSG_TYPES] =
        { "TOCLIENT_LOCAL_PLAYER_ANIMATIONS",  TOCLIENT_STATE_CONNECTED, &Client::handleCommand_LocalPlayerAnimations }, // 0x51
        { "TOCLIENT_EYE_OFFSET",               TOCLIENT_STATE_CONNECTED, &Client::handleCommand_EyeOffset }, // 0x52
        { "TOCLIENT_DELETE_PARTICLESPAWNER",   TOCLIENT_STATE_CONNECTED, &Client::handleCommand_DeleteParticleSpawner }, // 0x53
-       null_command_handler,
+       { "TOCLIENT_CLOUD_PARAMS",             TOCLIENT_STATE_CONNECTED, &Client::handleCommand_CloudParams }, // 0x54
        null_command_handler,
        null_command_handler,
        null_command_handler,
index 772ffe905a2c183542d2ba80830d76093899c74c..defc83f31027bfe6503e2747b19dca991bef9228 100644 (file)
@@ -1168,6 +1168,34 @@ void Client::handleCommand_HudSetSky(NetworkPacket* pkt)
        m_client_event_queue.push(event);
 }
 
+void Client::handleCommand_CloudParams(NetworkPacket* pkt)
+{
+       f32 density;
+       video::SColor color_bright;
+       video::SColor color_ambient;
+       f32 height;
+       f32 thickness;
+       v2f speed;
+
+       *pkt >> density >> color_bright >> color_ambient
+                       >> height >> thickness >> speed;
+
+       ClientEvent event;
+       event.type                       = CE_CLOUD_PARAMS;
+       event.cloud_params.density       = density;
+       // use the underlying u32 representation, because we can't
+       // use struct members with constructors here, and this way
+       // we avoid using new() and delete() for no good reason
+       event.cloud_params.color_bright  = color_bright.color;
+       event.cloud_params.color_ambient = color_ambient.color;
+       event.cloud_params.height        = height;
+       event.cloud_params.thickness     = thickness;
+       // same here: deconstruct to skip constructor
+       event.cloud_params.speed_x       = speed.X;
+       event.cloud_params.speed_y       = speed.Y;
+       m_client_event_queue.push(event);
+}
+
 void Client::handleCommand_OverrideDayNightRatio(NetworkPacket* pkt)
 {
        bool do_override;
index e7a3469b73a8f048192653ada38c23fe6459dc66..a1a4f5bfadf207d49eccae2296e101e0d0c510f4 100644 (file)
@@ -610,6 +610,16 @@ enum ToClientCommand
                u32 id
        */
 
+       TOCLIENT_CLOUD_PARAMS = 0x54,
+       /*
+               f1000 density
+               u8[4] color_diffuse (ARGB)
+               u8[4] color_ambient (ARGB)
+               f1000 height
+               f1000 thickness
+               v2f1000 speed
+       */
+
        TOCLIENT_SRP_BYTES_S_B = 0x60,
        /*
                Belonging to AUTH_MECHANISM_LEGACY_PASSWORD and AUTH_MECHANISM_SRP.
index 31b571ff04d5debda29d2e6c5246dd75cf1b25ab..450730ca2001ec85fb1a640856fd0ee812c16441 100644 (file)
@@ -197,7 +197,7 @@ const ClientCommandFactory clientCommandFactoryTable[TOCLIENT_NUM_MSG_TYPES] =
        { "TOCLIENT_LOCAL_PLAYER_ANIMATIONS",  0, true }, // 0x51
        { "TOCLIENT_EYE_OFFSET",               0, true }, // 0x52
        { "TOCLIENT_DELETE_PARTICLESPAWNER",   0, true }, // 0x53
-       null_command_factory,
+       { "TOCLIENT_CLOUD_PARAMS",             0, true }, // 0x54
        null_command_factory,
        null_command_factory,
        null_command_factory,
index 2dbfe9d9d964021c493459a730e3a2432f90b082..2b4db62f5fc3bdd58ab6ef209cad03ec7bd366dc 100644 (file)
@@ -65,6 +65,14 @@ RemotePlayer::RemotePlayer(const char *name, IItemDefManager *idef):
        movement_liquid_fluidity_smooth = g_settings->getFloat("movement_liquid_fluidity_smooth") * BS;
        movement_liquid_sink            = g_settings->getFloat("movement_liquid_sink")            * BS;
        movement_gravity                = g_settings->getFloat("movement_gravity")                * BS;
+
+       // copy defaults
+       m_cloud_params.density = 0.4f;
+       m_cloud_params.color_bright = video::SColor(255, 255, 240, 240);
+       m_cloud_params.color_ambient = video::SColor(255, 0, 0, 0);
+       m_cloud_params.height = 120.0f;
+       m_cloud_params.thickness = 16.0f;
+       m_cloud_params.speed = v2f(0.0f, -2.0f);
 }
 
 void RemotePlayer::serializeExtraAttributes(std::string &output)
index 4b96835fcf8df09906da277a152a2da8dfba96b3..b9d9c74f540b0ac168ec5517e22d3863a2007e21 100644 (file)
@@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define REMOTEPLAYER_HEADER
 
 #include "player.h"
+#include "cloudparams.h"
 
 class PlayerSAO;
 
@@ -99,6 +100,16 @@ public:
                *params = m_sky_params;
        }
 
+       void setCloudParams(const CloudParams &cloud_params)
+       {
+               m_cloud_params = cloud_params;
+       }
+
+       const CloudParams &getCloudParams() const
+       {
+               return m_cloud_params;
+       }
+
        bool checkModified() const { return m_dirty || inventory.checkModified(); }
 
        void setModified(const bool x)
@@ -154,6 +165,7 @@ private:
        std::string m_sky_type;
        video::SColor m_sky_bgcolor;
        std::vector<std::string> m_sky_params;
+       CloudParams m_cloud_params;
 };
 
 #endif
index a5b6e3941f58e68df011dd0c4b7e2df9051ee1bf..6cd852299c2cbe470f906f180e653204b4a76cf1 100644 (file)
@@ -1729,6 +1729,85 @@ int ObjectRef::l_get_sky(lua_State *L)
        return 3;
 }
 
+// set_clouds(self, {density=, color=, ambient=, height=, thickness=, speed=})
+int ObjectRef::l_set_clouds(lua_State *L)
+{
+       NO_MAP_LOCK_REQUIRED;
+       ObjectRef *ref = checkobject(L, 1);
+       RemotePlayer *player = getplayer(ref);
+       if (!player)
+               return 0;
+       if (!lua_istable(L, 2))
+               return 0;
+
+       CloudParams cloud_params = player->getCloudParams();
+
+       cloud_params.density = getfloatfield_default(L, 2, "density", cloud_params.density);
+
+       lua_getfield(L, 2, "color");
+       if (!lua_isnil(L, -1))
+               read_color(L, -1, &cloud_params.color_bright);
+       lua_pop(L, 1);
+       lua_getfield(L, 2, "ambient");
+       if (!lua_isnil(L, -1))
+               read_color(L, -1, &cloud_params.color_ambient);
+       lua_pop(L, 1);
+
+       cloud_params.height    = getfloatfield_default(L, 2, "height",    cloud_params.height   );
+       cloud_params.thickness = getfloatfield_default(L, 2, "thickness", cloud_params.thickness);
+
+       lua_getfield(L, 2, "speed");
+       if (lua_istable(L, -1)) {
+               v2f new_speed;
+               new_speed.X = getfloatfield_default(L, -1, "x", 0);
+               new_speed.Y = getfloatfield_default(L, -1, "y", 0);
+               cloud_params.speed = new_speed;
+       }
+       lua_pop(L, 1);
+
+       if (!getServer(L)->setClouds(player, cloud_params.density,
+                       cloud_params.color_bright, cloud_params.color_ambient,
+                       cloud_params.height, cloud_params.thickness,
+                       cloud_params.speed))
+               return 0;
+
+       player->setCloudParams(cloud_params);
+
+       lua_pushboolean(L, true);
+       return 1;
+}
+
+int ObjectRef::l_get_clouds(lua_State *L)
+{
+       NO_MAP_LOCK_REQUIRED;
+       ObjectRef *ref = checkobject(L, 1);
+       RemotePlayer *player = getplayer(ref);
+       if (!player)
+               return 0;
+       const CloudParams &cloud_params = player->getCloudParams();
+
+       lua_newtable(L);
+       lua_pushnumber(L, cloud_params.density);
+       lua_setfield(L, -2, "density");
+       push_ARGB8(L, cloud_params.color_bright);
+       lua_setfield(L, -2, "color");
+       push_ARGB8(L, cloud_params.color_ambient);
+       lua_setfield(L, -2, "ambient");
+       lua_pushnumber(L, cloud_params.height);
+       lua_setfield(L, -2, "height");
+       lua_pushnumber(L, cloud_params.thickness);
+       lua_setfield(L, -2, "thickness");
+       lua_newtable(L);
+       lua_pushnumber(L, cloud_params.speed.X);
+       lua_setfield(L, -2, "x");
+       lua_pushnumber(L, cloud_params.speed.Y);
+       lua_setfield(L, -2, "y");
+       lua_setfield(L, -2, "speed");
+
+       return 1;
+}
+
+
 // override_day_night_ratio(self, brightness=0...1)
 int ObjectRef::l_override_day_night_ratio(lua_State *L)
 {
@@ -1911,6 +1990,8 @@ const luaL_Reg ObjectRef::methods[] = {
        luamethod(ObjectRef, hud_get_hotbar_selected_image),
        luamethod(ObjectRef, set_sky),
        luamethod(ObjectRef, get_sky),
+       luamethod(ObjectRef, set_clouds),
+       luamethod(ObjectRef, get_clouds),
        luamethod(ObjectRef, override_day_night_ratio),
        luamethod(ObjectRef, get_day_night_ratio),
        luamethod(ObjectRef, set_local_animation),
index 98f5c2b112f4d951dcaab0b85b519c7765dee10f..0912a1c49d0b67feed8887292b1eb55a16ccc9a4 100644 (file)
@@ -289,6 +289,12 @@ private:
        // get_sky(self, type, list)
        static int l_get_sky(lua_State *L);
 
+       // set_clouds(self, {density=, color=, ambient=, height=, thickness=, speed=})
+       static int l_set_clouds(lua_State *L);
+
+       // get_clouds(self)
+       static int l_get_clouds(lua_State *L);
+
        // override_day_night_ratio(self, type)
        static int l_override_day_night_ratio(lua_State *L);
 
index 2edf83947ddc054e197a387e05928c8dfd23fd73..9ef69cb373ec991198dbffae39164a624d178723 100644 (file)
@@ -1882,6 +1882,20 @@ void Server::SendSetSky(u16 peer_id, const video::SColor &bgcolor,
        Send(&pkt);
 }
 
+void Server::SendCloudParams(u16 peer_id, float density,
+               const video::SColor &color_bright,
+               const video::SColor &color_ambient,
+               float height,
+               float thickness,
+               const v2f &speed)
+{
+       NetworkPacket pkt(TOCLIENT_CLOUD_PARAMS, 0, peer_id);
+       pkt << density << color_bright << color_ambient
+                       << height << thickness << speed;
+
+       Send(&pkt);
+}
+
 void Server::SendOverrideDayNightRatio(u16 peer_id, bool do_override,
                float ratio)
 {
@@ -3196,6 +3210,22 @@ bool Server::setSky(RemotePlayer *player, const video::SColor &bgcolor,
        return true;
 }
 
+bool Server::setClouds(RemotePlayer *player, float density,
+       const video::SColor &color_bright,
+       const video::SColor &color_ambient,
+       float height,
+       float thickness,
+       const v2f &speed)
+{
+       if (!player)
+               return false;
+
+       SendCloudParams(player->peer_id, density,
+                       color_bright, color_ambient, height,
+                       thickness, speed);
+       return true;
+}
+
 bool Server::overrideDayNightRatio(RemotePlayer *player, bool do_override,
        float ratio)
 {
index 948fb8fc270825d6464c5dd7e63fc25001a4383b..3a082b9a487c321f09df25dcd4a2c4da29907c36 100644 (file)
@@ -332,6 +332,12 @@ public:
 
        bool setSky(RemotePlayer *player, const video::SColor &bgcolor,
                        const std::string &type, const std::vector<std::string> &params);
+       bool setClouds(RemotePlayer *player, float density,
+                       const video::SColor &color_bright,
+                       const video::SColor &color_ambient,
+                       float height,
+                       float thickness,
+                       const v2f &speed);
 
        bool overrideDayNightRatio(RemotePlayer *player, bool do_override, float brightness);
 
@@ -401,6 +407,12 @@ private:
        void SendHUDSetParam(u16 peer_id, u16 param, const std::string &value);
        void SendSetSky(u16 peer_id, const video::SColor &bgcolor,
                        const std::string &type, const std::vector<std::string> &params);
+       void SendCloudParams(u16 peer_id, float density,
+                       const video::SColor &color_bright,
+                       const video::SColor &color_ambient,
+                       float height,
+                       float thickness,
+                       const v2f &speed);
        void SendOverrideDayNightRatio(u16 peer_id, bool do_override, float ratio);
 
        /*
index 211a2dcdcd9f78656fd1095ab8335c9ead281a37..7f999feb0ec371ea25748c3656fa3a4be2756bfa 100644 (file)
@@ -534,8 +534,10 @@ void Sky::update(float time_of_day, float time_brightness,
        video::SColorf skycolor_bright_dawn_f = video::SColor(255, 180, 186, 250);
        video::SColorf skycolor_bright_night_f = video::SColor(255, 0, 107, 255);
        
-       video::SColorf cloudcolor_bright_normal_f = video::SColor(255, 240, 240, 255);
-       video::SColorf cloudcolor_bright_dawn_f = video::SColor(255, 255, 223, 191);
+       // pure white: becomes "diffuse light component" for clouds
+       video::SColorf cloudcolor_bright_normal_f = video::SColor(255, 255, 255, 255);
+       // dawn-factoring version of pure white (note: R is above 1.0)
+       video::SColorf cloudcolor_bright_dawn_f(255.0f/240.0f, 223.0f/240.0f, 191.0f/255.0f);
 
        float cloud_color_change_fraction = 0.95;
        if (sunlight_seen) {