From 86a6cca3cf641fc2c88184ad26d2be3d7e7460f7 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Thu, 2 May 2013 23:52:50 +0300 Subject: [PATCH] Add player:set_sky() with simple skybox support --- doc/lua_api.txt | 8 +++++++ src/client.cpp | 19 ++++++++++++++++ src/client.h | 8 ++++++- src/clientserver.h | 12 ++++++++++ src/game.cpp | 36 +++++++++++++++++++++++++++++ src/script/lua_api/l_object.cpp | 40 +++++++++++++++++++++++++++++++++ src/script/lua_api/l_object.h | 3 +++ src/server.cpp | 30 +++++++++++++++++++++++++ src/server.h | 7 +++++- src/sky.cpp | 5 +++++ src/sky.h | 18 ++++++++++++--- 11 files changed, 181 insertions(+), 5 deletions(-) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 9d97dd6fa..beec54085 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -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: diff --git a/src/client.cpp b/src/client.cpp index cc1ec2a98..48b00377f 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -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 *params = new std::vector; + for(size_t i=0; ipush_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 " diff --git a/src/client.h b/src/client.h index 9a788dfca..33d806f9f 100644 --- a/src/client.h +++ b/src/client.h @@ -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 *params; + } set_sky; }; }; diff --git a/src/clientserver.h b/src/clientserver.h index 0d66e1b50..ecdc644dc 100644 --- a/src/clientserver.h +++ b/src/clientserver.h @@ -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 diff --git a/src/game.cpp b/src/game.cpp index 407672ac2..ef694b6af 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -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)<setFallbackBgColor(*event.set_sky.bgcolor); + } + + delete event.set_sky.bgcolor; + delete event.set_sky.type; + delete event.set_sky.params; + } } } diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 6c6415a09..86e5a71cd 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -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 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} }; diff --git a/src/script/lua_api/l_object.h b/src/script/lua_api/l_object.h index c8c67f2c5..b41938ca7 100644 --- a/src/script/lua_api/l_object.h +++ b/src/script/lua_api/l_object.h @@ -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); diff --git a/src/server.cpp b/src/server.cpp index ce0b44110..644aec1f5 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -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 ¶ms) +{ + std::ostringstream os(std::ios_base::binary); + + // Write command + writeU16(os, TOCLIENT_SET_SKY); + writeARGB8(os, bgcolor); + os< 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 ¶ms) +{ + 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); diff --git a/src/server.h b/src/server.h index 94b0b6a2d..e493c5ea9 100644 --- a/src/server.h +++ b/src/server.h @@ -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 ¶ms); /* 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 ¶ms); + /* Send a node removal/addition event to all clients except ignore_id. Additionally, if far_players!=NULL, players further away than diff --git a/src/sky.cpp b/src/sky.cpp index e8fd3a1d8..3ba9a44c0 100644 --- a/src/sky.cpp +++ b/src/sky.cpp @@ -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& Sky::getBoundingBox() const //! renders the node. void Sky::render() { + if(!m_visible) + return; + video::IVideoDriver* driver = SceneManager->getVideoDriver(); scene::ICameraSceneNode* camera = SceneManager->getActiveCamera(); diff --git a/src/sky.h b/src/sky.h index 9de9d9947..06a993103 100644 --- 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 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;