diff --git a/docs/lua-api-sky.md b/docs/lua-api-sky.md index 6ed6cc01f..44a489f69 100644 --- a/docs/lua-api-sky.md +++ b/docs/lua-api-sky.md @@ -13,6 +13,27 @@ mod:sky { fog_color = { day = {50, 153, 204}, }, + + objects = { + sun = { + texture = "texture-sun", + size = 256, + }, + + moon = { + texture = "texture-moon_phases", + size = 256, + phases = { + count = 8, + size = 32 + } + }, + + stars = { + count = 1000, + size = 4, + } + } } ``` @@ -59,3 +80,57 @@ id = "sky_nether" IDs are usually of the form `mod:sky` but the `mod:` prefix is prepended automatically so it's not needed. +### `objects` + +#### `moon` + +Moon attributes table. Example: +```lua +moon = { + texture = "texture-moon_phases" + size = 256, + phases = { + count = 8, + size = 32 + } +}, +``` + +Attributes: + +- `texture`: texture to use (without texture, the moon will use this color: (240, 240, 240)) +- `size`: size of the moon (default: `256`) +- `phases` + - `count`: amount of phases (default: `1`) + - `size`: size of the phase texture (default: `32`) + +#### `sun` + +Sun attribute table. Example: +```lua +sun = { + texture = "texture-sun", + size = 256, +}, +``` + +Attributes: + +- `texture`: texture to use (without texture, the sun will use this color: (255, 255, 0)) +- `size`: size of the sun (default: `256`) + +#### `stars` + +Stars attribute table. Example: +```lua +stars = { + count = 1000, + size = 4, +} +``` + +Attributes: + +- `count`: size of the sun (default: `1000`) +- `size`: size of the sun (default: `4`) + diff --git a/mods/default/sky.lua b/mods/default/sky.lua index f7726df8f..bce188ca8 100644 --- a/mods/default/sky.lua +++ b/mods/default/sky.lua @@ -35,6 +35,27 @@ mod:sky { fog_color = { day = {50, 153, 204}, }, + + objects = { + sun = { + texture = "texture-sun", -- FIXME: Use a path instead like block attribute 'tiles' + size = 256, + }, + + moon = { + texture = "texture-moon_phases", -- FIXME: ^ + size = 256, + phases = { + count = 8, + size = 32 + } + }, + + stars = { + count = 1000, + size = 4, + } + } } mod:sky { diff --git a/source/client/graphics/CelestialObject.cpp b/source/client/graphics/CelestialObject.cpp index dc5d8e865..858199dec 100644 --- a/source/client/graphics/CelestialObject.cpp +++ b/source/client/graphics/CelestialObject.cpp @@ -37,6 +37,8 @@ CelestialObject::CelestialObject() { } void CelestialObject::setTexture(const std::string &textureName) { + if (textureName.empty()) return; + m_texture = &gk::ResourceHandler::getInstance().get(textureName); m_isUpdateNeeded = true; diff --git a/source/client/graphics/Skybox.cpp b/source/client/graphics/Skybox.cpp index 590d57690..96277f246 100644 --- a/source/client/graphics/Skybox.cpp +++ b/source/client/graphics/Skybox.cpp @@ -34,21 +34,44 @@ Skybox::Skybox(gk::Camera &camera, ClientWorld &world) : m_camera(camera), m_wor m_shader.addShader(GL_VERTEX_SHADER, "resources/shaders/skybox.v.glsl"); m_shader.addShader(GL_FRAGMENT_SHADER, "resources/shaders/skybox.f.glsl"); m_shader.linkProgram(); +} - m_sun.setSize(256, 256); +void Skybox::loadSky(const Sky &sky) { + const Sky::SunDefinition &sun = sky.sunDefinition(); + m_sun = CelestialObject{}; + m_sun.setSize(sun.size, sun.size); m_sun.setPosition(500, -m_sun.width() / 2, -m_sun.height() / 2); - m_sun.setTexture("texture-sun"); - m_moon.setSize(256, 256); + try { + m_sun.setTexture(sun.texture); + } + catch (...) { + m_sun.setColor(gk::Color::Yellow); + gkWarning() << "Failed to load sun texture" << sun.texture; + } + + const Sky::MoonDefinition &moon = sky.moonDefinition(); + m_moon = CelestialObject{}; + m_moon.setSize(moon.size, moon.size); m_moon.setPosition(-500, -m_moon.width() / 2, -m_moon.height() / 2); - m_moon.setTexture("texture-moon_phases"); - m_moon.setPhaseCount(8, 32); + m_moon.setPhaseCount(moon.phaseCount, moon.phaseSize); m_moon.setCurrentPhase(0); - for (int i = 0 ; i < 1000 ; ++i) { + try { + m_moon.setTexture(moon.texture); + } + catch (...) { + m_moon.setColor(gk::Color{240, 240, 240}); + gkWarning() << "Failed to load moon texture" << sun.texture; + } + + const Sky::StarsDefinition &stars = sky.starsDefinition(); + m_stars.clear(); + m_stars.reserve(stars.count); + for (int i = 0 ; i < stars.count ; ++i) { auto &star = m_stars.emplace_back(); star.setColor(gk::Color{0, 0, 0, 0}); - star.setSize(4, 4); + star.setSize(stars.size, stars.size); star.setPosition(650 * ((rand() % 2) * 2 - 1), (rand() % 500) * 2 - 500, (rand() % 500) * 2 - 500); star.setRotationOffset(rand() % GameTime::dayLength); star.setRotationAxis({rand() % 100 / 100.f, rand() % 100 / 100.f, rand() % 100 / 100.f}); @@ -74,8 +97,11 @@ void Skybox::draw(gk::RenderTarget &target, gk::RenderStates states) const { const gk::Vector3d &cameraPosition = m_camera.getDPosition(); states.transform.translate(cameraPosition.x, cameraPosition.y, cameraPosition.z - 50); - target.draw(m_sun, states); - target.draw(m_moon, states); + if (m_sun.width() && m_sun.height()) + target.draw(m_sun, states); + + if (m_moon.width() && m_moon.height()) + target.draw(m_moon, states); if (Config::isStarRenderingEnabled && skyColor != starColor) { glDisable(GL_CULL_FACE); diff --git a/source/client/graphics/Skybox.hpp b/source/client/graphics/Skybox.hpp index 07faf28c0..f54a9f7dc 100644 --- a/source/client/graphics/Skybox.hpp +++ b/source/client/graphics/Skybox.hpp @@ -33,11 +33,14 @@ #include "CelestialObject.hpp" class ClientWorld; +class Sky; class Skybox : public gk::Drawable, public gk::Transformable { public: Skybox(gk::Camera &camera, ClientWorld &world); + void loadSky(const Sky &sky); + private: void draw(gk::RenderTarget &target, gk::RenderStates states) const override; diff --git a/source/client/states/GameState.cpp b/source/client/states/GameState.cpp index b5fcf1569..a7f4e95ca 100644 --- a/source/client/states/GameState.cpp +++ b/source/client/states/GameState.cpp @@ -184,6 +184,12 @@ void GameState::update() { } m_client.update(); + + static const Sky *sky = nullptr; + if (sky != m_world.sky() && m_world.sky()) { + sky = m_world.sky(); + m_skybox.loadSky(*sky); + } } void GameState::initShaders() { diff --git a/source/common/world/Sky.cpp b/source/common/world/Sky.cpp index 0f69ac814..9195aa9cc 100644 --- a/source/common/world/Sky.cpp +++ b/source/common/world/Sky.cpp @@ -33,10 +33,18 @@ Sky::Sky(u16 id, const std::string &stringID) { } void Sky::serialize(sf::Packet &packet) const { - packet << m_id << m_stringID << m_color << m_fogColor; + packet << m_id << m_stringID << m_color << m_fogColor + << m_sunDefinition.texture << m_sunDefinition.size + << m_moonDefinition.texture << m_moonDefinition.size + << m_moonDefinition.phaseCount << m_moonDefinition.phaseSize + << m_starsDefinition.count << m_starsDefinition.size; } void Sky::deserialize(sf::Packet &packet) { - packet >> m_id >> m_stringID >> m_color >> m_fogColor; + packet >> m_id >> m_stringID >> m_color >> m_fogColor + >> m_sunDefinition.texture >> m_sunDefinition.size + >> m_moonDefinition.texture >> m_moonDefinition.size + >> m_moonDefinition.phaseCount >> m_moonDefinition.phaseSize + >> m_starsDefinition.count >> m_starsDefinition.size; } diff --git a/source/common/world/Sky.hpp b/source/common/world/Sky.hpp index 57b1ad35e..8e73dd953 100644 --- a/source/common/world/Sky.hpp +++ b/source/common/world/Sky.hpp @@ -49,12 +49,41 @@ class Sky : public gk::ISerializable { void setColor(const gk::Color &color) { m_color = color; } void setFogColor(const gk::Color &fogColor) { m_fogColor = fogColor; } + struct SunDefinition { + std::string texture; + float size; + }; + + struct MoonDefinition { + std::string texture; + float size; + u16 phaseCount; + u16 phaseSize; + }; + + struct StarsDefinition { + u16 count; + float size; + }; + + const SunDefinition &sunDefinition() const { return m_sunDefinition; } + const MoonDefinition &moonDefinition() const { return m_moonDefinition; } + const StarsDefinition &starsDefinition() const { return m_starsDefinition; } + + void setSunDefinition(const SunDefinition &sunDefinition) { m_sunDefinition = sunDefinition; } + void setMoonDefinition(const MoonDefinition &moonDefinition) { m_moonDefinition = moonDefinition; } + void setStarsDefinition(const StarsDefinition &starsDefinition) { m_starsDefinition = starsDefinition; } + private: u16 m_id; std::string m_stringID; gk::Color m_color; gk::Color m_fogColor; + + SunDefinition m_sunDefinition; + MoonDefinition m_moonDefinition; + StarsDefinition m_starsDefinition; }; #endif // SKY_HPP_ diff --git a/source/server/lua/loader/LuaSkyLoader.cpp b/source/server/lua/loader/LuaSkyLoader.cpp index 84fae4bb0..50e49fcf5 100644 --- a/source/server/lua/loader/LuaSkyLoader.cpp +++ b/source/server/lua/loader/LuaSkyLoader.cpp @@ -50,5 +50,49 @@ void LuaSkyLoader::loadSky(const sol::table &table) const { u8 a = fogColor["day"][4].get_or(255); sky.setFogColor(gk::Color{r, g, b, a}); } + + loadObjects(sky, table); +} + +void LuaSkyLoader::loadObjects(Sky &sky, const sol::table &table) const { + if (sol::object obj = table["objects"] ; obj.valid()) { + sol::table objectsTable = obj.as(); + + if (sol::object obj = objectsTable["sun"] ; obj.valid()) { + sol::table sunTable = obj.as(); + + Sky::SunDefinition sunDefinition; + sunDefinition.texture = sunTable["texture"].get_or(""); + sunDefinition.size = sunTable["size"].get_or(256); + + sky.setSunDefinition(sunDefinition); + } + + if (sol::object obj = objectsTable["moon"] ; obj.valid()) { + sol::table moonTable = obj.as(); + + Sky::MoonDefinition moonDefinition; + moonDefinition.texture = moonTable["texture"].get_or(""); + moonDefinition.size = moonTable["size"].get_or(256); + + if (sol::object obj = moonTable["phases"] ; obj.valid()) { + sol::table phasesTable = obj.as(); + moonDefinition.phaseCount = phasesTable["count"].get_or(1); + moonDefinition.phaseSize = phasesTable["size"].get_or(32); + } + + sky.setMoonDefinition(moonDefinition); + } + + if (sol::object obj = objectsTable["stars"] ; obj.valid()) { + sol::table starsTable = obj.as(); + + Sky::StarsDefinition starsDefinition; + starsDefinition.count = starsTable["count"].get_or(1000); + starsDefinition.size = starsTable["size"].get_or(4); + + sky.setStarsDefinition(starsDefinition); + } + } } diff --git a/source/server/lua/loader/LuaSkyLoader.hpp b/source/server/lua/loader/LuaSkyLoader.hpp index 9799b2201..599eea80d 100644 --- a/source/server/lua/loader/LuaSkyLoader.hpp +++ b/source/server/lua/loader/LuaSkyLoader.hpp @@ -30,6 +30,7 @@ #include class LuaMod; +class Sky; class LuaSkyLoader { public: @@ -38,6 +39,8 @@ class LuaSkyLoader { void loadSky(const sol::table &table) const; private: + void loadObjects(Sky &sky, const sol::table &table) const; + LuaMod &m_mod; };