Add player:set_sky() with simple skybox support
authorPerttu Ahola <celeron55@gmail.com>
Thu, 2 May 2013 20:52:50 +0000 (23:52 +0300)
committersapier <Sapier at GMX dot net>
Sat, 1 Feb 2014 17:34:26 +0000 (18:34 +0100)
doc/lua_api.txt
src/client.cpp
src/client.h
src/clientserver.h
src/game.cpp
src/script/lua_api/l_object.cpp
src/script/lua_api/l_object.h
src/server.cpp
src/server.h
src/sky.cpp
src/sky.h

index 9d97dd6fadd9dafba897babd57b2fa60c816dbbe..beec5408522e9a46e386221ce6ddb8340f6cec87 100644 (file)
@@ -1812,6 +1812,14 @@ Player-only: (no-op for other objects)
   ^ sets background image for hotbar
 - hud_set_hotbar_selected_image(texturename)
   ^ sets image for selected item of hotbar
+- set_sky(bgcolor, type, {texture names})
+  ^ bgcolor: {r=0...255, g=0...255, b=0...255} or nil, defaults to white
+  ^ Available types:
+    - "regular": Uses 0 textures, bgcolor ignored
+    - "skybox": Uses 6 textures, bgcolor used
+    - "plain": Uses 0 textures, bgcolor used
+  ^ Note: currently does not work directly in on_joinplayer; use
+          minetest.after(0) in there.
 
 InvRef: Reference to an inventory
 methods:
index cc1ec2a9891faf598a2c95a81a14ffe5259fee1a..48b00377f36138077191cf76399ce92a2ef7c8a3 100644 (file)
@@ -2026,6 +2026,25 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
                        ((LocalPlayer *) player)->hotbar_selected_image = value;
                }
        }
+       else if(command == TOCLIENT_SET_SKY)
+       {
+               std::string datastring((char *)&data[2], datasize - 2);
+               std::istringstream is(datastring, std::ios_base::binary);
+
+               video::SColor *bgcolor = new video::SColor(readARGB8(is));
+               std::string *type = new std::string(deSerializeString(is));
+               u16 count = readU16(is);
+               std::vector<std::string> *params = new std::vector<std::string>;
+               for(size_t i=0; i<count; i++)
+                       params->push_back(deSerializeString(is));
+
+               ClientEvent event;
+               event.type = CE_SET_SKY;
+               event.set_sky.bgcolor = bgcolor;
+               event.set_sky.type = type;
+               event.set_sky.params = params;
+               m_client_event_queue.push_back(event);
+       }
        else
        {
                infostream<<"Client: Ignoring unknown command "
index 9a788dfca5d70fcedec70d535ead46808c413ff5..33d806f9f6ffb8eedcd13fd92f63c122d05bcb9c 100644 (file)
@@ -133,7 +133,8 @@ enum ClientEventType
        CE_DELETE_PARTICLESPAWNER,
        CE_HUDADD,
        CE_HUDRM,
-       CE_HUDCHANGE
+       CE_HUDCHANGE,
+       CE_SET_SKY,
 };
 
 struct ClientEvent
@@ -217,6 +218,11 @@ struct ClientEvent
                        u32 data;
                        v3f *v3fdata;
                } hudchange;
+               struct{
+                       video::SColor *bgcolor;
+                       std::string *type;
+                       std::vector<std::string> *params;
+               } set_sky;
        };
 };
 
index 0d66e1b50121fd2ea1456c5402c0169df395e15e..ecdc644dcb31675f087a5bce5fc41ced40d887db 100644 (file)
@@ -507,6 +507,18 @@ enum ToClientCommand
                u16 command
                u16 breath
        */
+
+       TOCLIENT_SET_SKY = 0x4f,
+       /*
+               u16 command
+               u8[4] color (ARGB)
+               u8 len
+               u8[len] type
+               u16 count
+               foreach count:
+                       u8 len
+                       u8[len] param
+       */
 };
 
 enum ToServerCommand
index 407672ac29c857b2103dcadaa692f088392b4cbb..ef694b6afebfaf9e0a4988f42ec5f121f36f7499 100644 (file)
@@ -1337,6 +1337,8 @@ void the_game(
 
        Sky *sky = NULL;
        sky = new Sky(smgr->getRootSceneNode(), smgr, -1, client.getEnv().getLocalPlayer());
+
+       scene::ISceneNode* skybox = NULL;
        
        /*
                A copy of the local inventory
@@ -2462,6 +2464,40 @@ void the_game(
                                        delete event.hudchange.v2fdata;
                                        delete event.hudchange.sdata;
                                }
+                               else if (event.type == CE_SET_SKY)
+                               {
+                                       sky->setVisible(false);
+                                       if(skybox){
+                                               skybox->drop();
+                                               skybox = NULL;
+                                       }
+                                       // Handle according to type
+                                       if(*event.set_sky.type == "regular"){
+                                               sky->setVisible(true);
+                                       }
+                                       else if(*event.set_sky.type == "skybox" &&
+                                                       event.set_sky.params->size() == 6){
+                                               sky->setFallbackBgColor(*event.set_sky.bgcolor);
+                                               skybox = smgr->addSkyBoxSceneNode(
+                                                               tsrc->getTexture((*event.set_sky.params)[0]),
+                                                               tsrc->getTexture((*event.set_sky.params)[1]),
+                                                               tsrc->getTexture((*event.set_sky.params)[2]),
+                                                               tsrc->getTexture((*event.set_sky.params)[3]),
+                                                               tsrc->getTexture((*event.set_sky.params)[4]),
+                                                               tsrc->getTexture((*event.set_sky.params)[5]));
+                                       }
+                                       // Handle everything else as plain color
+                                       else {
+                                               if(*event.set_sky.type != "plain")
+                                                       infostream<<"Unknown sky type: "
+                                                                       <<(*event.set_sky.type)<<std::endl;
+                                               sky->setFallbackBgColor(*event.set_sky.bgcolor);
+                                       }
+
+                                       delete event.set_sky.bgcolor;
+                                       delete event.set_sky.type;
+                                       delete event.set_sky.params;
+                               }
                        }
                }
                
index 6c6415a09800eab0088e25c37e8f71a47e47c628..86e5a71cd4a8c10c3765c51ff028dddccccaf531 100644 (file)
@@ -1090,6 +1090,45 @@ int ObjectRef::l_hud_set_hotbar_selected_image(lua_State *L)
        return 1;
 }
 
+// set_sky(self, bgcolor, type, list)
+int ObjectRef::l_set_sky(lua_State *L)
+{
+       ObjectRef *ref = checkobject(L, 1);
+       Player *player = getplayer(ref);
+       if (player == NULL)
+               return 0;
+
+       video::SColor bgcolor(255,255,255,255);
+       if (!lua_isnil(L, 2))
+               bgcolor = readARGB8(L, 2);
+
+       std::string type = luaL_checkstring(L, 3);
+
+       std::vector<std::string> params;
+       if (lua_istable(L, 4)) {
+               int table = lua_gettop(L);
+               lua_pushnil(L);
+               while (lua_next(L, table) != 0) {
+                       // key at index -2 and value at index -1
+                       if (lua_isstring(L, -1))
+                               params.push_back(lua_tostring(L, -1));
+                       else
+                               params.push_back("");
+                       // removes value, keeps key for next iteration
+                       lua_pop(L, 1);
+               }
+       }
+
+       if (type == "skybox" && params.size() != 6)
+               throw LuaError(L, "skybox expects 6 textures");
+
+       if (!getServer(L)->setSky(player, bgcolor, type, params))
+               return 0;
+
+       lua_pushboolean(L, true);
+       return 1;
+}
+
 ObjectRef::ObjectRef(ServerActiveObject *object):
        m_object(object)
 {
@@ -1207,5 +1246,6 @@ const luaL_reg ObjectRef::methods[] = {
        luamethod(ObjectRef, hud_set_hotbar_itemcount),
        luamethod(ObjectRef, hud_set_hotbar_image),
        luamethod(ObjectRef, hud_set_hotbar_selected_image),
+       luamethod(ObjectRef, set_sky),
        {0,0}
 };
index c8c67f2c52ae5c6d97e30675ba4af721c4761adf..b41938ca7c6d151fe0d4cad6e450421c302f9e34 100644 (file)
@@ -225,6 +225,9 @@ private:
        // hud_set_hotbar_selected_image(self, name)
        static int l_hud_set_hotbar_selected_image(lua_State *L);
 
+       // set_sky(self, type, list)
+       static int l_set_sky(lua_State *L);
+
 public:
        ObjectRef(ServerActiveObject *object);
 
index ce0b44110134475b41a3faa6e01f46a626730f04..644aec1f5cd242b5e134338dcc129353082a92b4 100644 (file)
@@ -3271,6 +3271,26 @@ void Server::SendHUDSetParam(u16 peer_id, u16 param, const std::string &value)
        m_clients.send(peer_id, 0, data, true);
 }
 
+void Server::SendSetSky(u16 peer_id, const video::SColor &bgcolor,
+               const std::string &type, const std::vector<std::string> &params)
+{
+       std::ostringstream os(std::ios_base::binary);
+
+       // Write command
+       writeU16(os, TOCLIENT_SET_SKY);
+       writeARGB8(os, bgcolor);
+       os<<serializeString(type);
+       writeU16(os, params.size());
+       for(size_t i=0; i<params.size(); i++)
+               os<<serializeString(params[i]);
+
+       // Make data buffer
+       std::string s = os.str();
+       SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
+       // Send as reliable
+       m_clients.send(peer_id, 0, data, true);
+}
+
 void Server::SendTimeOfDay(u16 peer_id, u16 time, f32 time_speed)
 {
        DSTACK(__FUNCTION_NAME);
@@ -4435,6 +4455,16 @@ void Server::hudSetHotbarSelectedImage(Player *player, std::string name) {
        SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
 }
 
+bool Server::setSky(Player *player, const video::SColor &bgcolor,
+               const std::string &type, const std::vector<std::string> &params)
+{
+       if (!player)
+               return false;
+
+       SendSetSky(player->peer_id, bgcolor, type, params);
+       return true;
+}
+
 void Server::notifyPlayers(const std::wstring msg)
 {
        SendChatMessage(PEER_ID_INEXISTENT,msg);
index 94b0b6a2deb5cd1afe5455a8b7b56b35d3bdd87c..e493c5ea985eeedc73047102709f480b491bac77 100644 (file)
@@ -319,6 +319,9 @@ public:
 
        inline Address getPeerAddress(u16 peer_id)
                        { return m_con.GetPeerAddress(peer_id); }
+                       
+       bool setSky(Player *player, const video::SColor &bgcolor,
+                       const std::string &type, const std::vector<std::string> &params);
 
        /* con::PeerHandler implementation. */
        void peerAdded(con::Peer *peer);
@@ -355,7 +358,9 @@ private:
        void SendHUDChange(u16 peer_id, u32 id, HudElementStat stat, void *value);
        void SendHUDSetFlags(u16 peer_id, u32 flags, u32 mask);
        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);
+       
        /*
                Send a node removal/addition event to all clients except ignore_id.
                Additionally, if far_players!=NULL, players further away than
index e8fd3a1d8564658ffd4df39f8f8815742be02504..3ba9a44c0b9b9a15532c8f38980e299804da5f7f 100644 (file)
@@ -14,6 +14,8 @@
 //! constructor
 Sky::Sky(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id, LocalPlayer* player):
                scene::ISceneNode(parent, mgr, id),
+               m_visible(true),
+               m_fallback_bg_color(255,255,255,255),
                m_first_update(true),
                m_brightness(0.5),
                m_cloud_brightness(0.5),
@@ -77,6 +79,9 @@ const core::aabbox3d<f32>& Sky::getBoundingBox() const
 //! renders the node.
 void Sky::render()
 {
+       if(!m_visible)
+               return;
+
        video::IVideoDriver* driver = SceneManager->getVideoDriver();
        scene::ICameraSceneNode* camera = SceneManager->getActiveCamera();
 
index 9de9d9947075fbed21b618627ecbd55545ffc594..06a99310371f8b37de242806dd850d8f66091a6c 100644 (file)
--- a/src/sky.h
+++ b/src/sky.h
@@ -53,12 +53,22 @@ public:
                        float direct_brightness, bool sunlight_seen);
        
        float getBrightness(){ return m_brightness; }
-       video::SColor getBgColor(){ return m_bgcolor; }
-       video::SColor getSkyColor(){ return m_skycolor; }
+
+       video::SColor getBgColor(){
+               return m_visible ? m_bgcolor : m_fallback_bg_color;
+       }
+       video::SColor getSkyColor(){
+               return m_visible ? m_skycolor : m_fallback_bg_color;
+       }
        
-       bool getCloudsVisible(){ return m_clouds_visible; }
+       bool getCloudsVisible(){ return m_clouds_visible && m_visible; }
        video::SColorf getCloudColor(){ return m_cloudcolor_f; }
 
+       void setVisible(bool visible){ m_visible = visible; }
+       void setFallbackBgColor(const video::SColor &fallback_bg_color){
+               m_fallback_bg_color = fallback_bg_color;
+       }
+
 private:
        core::aabbox3d<f32> Box;
        video::SMaterial m_materials[SKY_MATERIAL_COUNT];
@@ -98,6 +108,8 @@ private:
                return result;
        }
 
+       bool m_visible;
+       video::SColor m_fallback_bg_color; // Used when m_visible=false
        bool m_first_update;
        float m_time_of_day;
        float m_time_brightness;