From 4a6bbbe5ea1b463e7926e01d08ebbda0c68a37b3 Mon Sep 17 00:00:00 2001 From: Quentin Bazin Date: Fri, 22 May 2020 18:49:13 +0200 Subject: [PATCH] [Dimension] 'gravity' field added to change gravity per-dimension. --- docs/lua-api-dimension.md | 11 +++++++++++ mods/default/dimensions.lua | 2 ++ source/client/network/ClientCommandHandler.cpp | 2 +- source/client/states/ServerLoadingState.cpp | 2 +- source/client/world/ClientChunk.hpp | 9 +++++++-- source/client/world/ClientPlayer.cpp | 2 +- source/client/world/ClientPlayer.hpp | 1 - source/client/world/ClientWorld.cpp | 13 +++++++------ source/client/world/ClientWorld.hpp | 4 +++- source/common/world/Chunk.hpp | 2 ++ source/common/world/Dimension.cpp | 4 ++-- source/common/world/Dimension.hpp | 5 +++++ source/server/lua/loader/LuaDimensionLoader.cpp | 1 + 13 files changed, 43 insertions(+), 15 deletions(-) diff --git a/docs/lua-api-dimension.md b/docs/lua-api-dimension.md index f2b452ce3..8b2daef19 100644 --- a/docs/lua-api-dimension.md +++ b/docs/lua-api-dimension.md @@ -24,6 +24,17 @@ Example: biomes = {"default:grassland", "default:desert"} ``` +### `gravity` + +Gravity of the dimension. + +Example: +```lua +gravity = 0.5 +``` + +Default value is `1`. + ### `id` ID of the dimension. **Mandatory field.** diff --git a/mods/default/dimensions.lua b/mods/default/dimensions.lua index de403c13c..7567ecadd 100644 --- a/mods/default/dimensions.lua +++ b/mods/default/dimensions.lua @@ -41,5 +41,7 @@ mod:dimension { biomes = {"default:netherland"}, sky = "default:sky_nether", + + gravity = 1.4, } diff --git a/source/client/network/ClientCommandHandler.cpp b/source/client/network/ClientCommandHandler.cpp index b3457fcb0..3c106ba69 100644 --- a/source/client/network/ClientCommandHandler.cpp +++ b/source/client/network/ClientCommandHandler.cpp @@ -208,7 +208,7 @@ void ClientCommandHandler::setupCallbacks() { m_player.setDimension(dimension); m_player.setPosition(x, y, z); m_world.clear(); - m_world.updateSky(dimension); + m_world.changeDimension(dimension); m_entityMap.clear(); } }); diff --git a/source/client/states/ServerLoadingState.cpp b/source/client/states/ServerLoadingState.cpp index 2e89602fa..51b117e1f 100644 --- a/source/client/states/ServerLoadingState.cpp +++ b/source/client/states/ServerLoadingState.cpp @@ -95,7 +95,7 @@ void ServerLoadingState::update() { if (m_showLoadingState) std::this_thread::sleep_for(std::chrono::milliseconds(500)); - m_game.world().updateSky(0); + m_game.world().changeDimension(0); m_stateStack->pop(); diff --git a/source/client/world/ClientChunk.hpp b/source/client/world/ClientChunk.hpp index b9708a5e2..cf70f45e1 100644 --- a/source/client/world/ClientChunk.hpp +++ b/source/client/world/ClientChunk.hpp @@ -32,18 +32,21 @@ #include "Chunk.hpp" #include "ChunkBuilder.hpp" #include "Config.hpp" +#include "Dimension.hpp" class TextureAtlas; class ClientChunk : public Chunk { public: - ClientChunk(s32 x, s32 y, s32 z, World &world, TextureAtlas &textureAtlas) - : Chunk(x, y, z, world), m_textureAtlas(textureAtlas), m_builder{textureAtlas} {} + ClientChunk(s32 x, s32 y, s32 z, const Dimension &dimension, World &world, TextureAtlas &textureAtlas) + : Chunk(x, y, z, world), m_dimension(dimension), m_textureAtlas(textureAtlas), m_builder{textureAtlas} {} void update(); void drawLayer(gk::RenderTarget &target, gk::RenderStates states, u8 layer) const; + const Dimension &dimension() const { return m_dimension; } + bool hasBeenRequested() const { return m_hasBeenRequested; } void setHasBeenRequested(bool hasBeenRequested) { m_hasBeenRequested = hasBeenRequested; } @@ -53,6 +56,8 @@ class ClientChunk : public Chunk { bool areAllNeighboursTooFar() const; private: + const Dimension &m_dimension; + TextureAtlas &m_textureAtlas; ChunkBuilder m_builder; diff --git a/source/client/world/ClientPlayer.cpp b/source/client/world/ClientPlayer.cpp index d31a335de..a91111419 100644 --- a/source/client/world/ClientPlayer.cpp +++ b/source/client/world/ClientPlayer.cpp @@ -127,7 +127,7 @@ void ClientPlayer::updatePosition(const ClientWorld &world) { ClientChunk *chunk = (ClientChunk *)world.getChunkAtBlockPos(m_x, m_y, m_z); if (chunk && chunk->isInitialized()) { if (!Config::isFlyModeEnabled) { - m_velocity.z -= m_gravity; // Gravity + m_velocity.z -= chunk->dimension().gravity() * 0.001f; m_isJumping = true; diff --git a/source/client/world/ClientPlayer.hpp b/source/client/world/ClientPlayer.hpp index 139b42914..36fc5ccf2 100644 --- a/source/client/world/ClientPlayer.hpp +++ b/source/client/world/ClientPlayer.hpp @@ -99,7 +99,6 @@ class ClientPlayer : public Player { glm::vec3 m_velocity{0.f}; bool m_isJumping = false; - const float m_gravity = 0.001f; const float m_jumpSpeed = 0.06f; }; diff --git a/source/client/world/ClientWorld.cpp b/source/client/world/ClientWorld.cpp index ed5bf3f86..673c40a20 100644 --- a/source/client/world/ClientWorld.cpp +++ b/source/client/world/ClientWorld.cpp @@ -95,7 +95,7 @@ void ClientWorld::checkPlayerChunk(double playerX, double playerY, double player ClientChunk *chunk = (ClientChunk *)getChunk(pcx, pcy, pcz); if (!chunk) { - m_chunks.emplace(gk::Vector3i{pcx, pcy, pcz}, new ClientChunk(pcx, pcy, pcz, *this, m_textureAtlas)); + m_chunks.emplace(gk::Vector3i{pcx, pcy, pcz}, new ClientChunk(pcx, pcy, pcz, *m_dimension, *this, m_textureAtlas)); } } @@ -104,10 +104,11 @@ void ClientWorld::clear() { m_scene.registry().clear(); } -void ClientWorld::updateSky(u16 dimensionID) { +void ClientWorld::changeDimension(u16 dimensionID) { const Dimension &dimension = Registry::getInstance().getDimension(dimensionID); - const Sky &sky = Registry::getInstance().getSkyFromStringID(dimension.sky()); + m_dimension = &dimension; + const Sky &sky = Registry::getInstance().getSkyFromStringID(dimension.sky()); m_sky = &sky; } @@ -118,7 +119,7 @@ void ClientWorld::receiveChunkData(Network::Packet &packet) { // Get the chunk from the map or create it if it doesn't exist ClientChunk *chunk = (ClientChunk *)getChunk(cx, cy, cz); if (!chunk) { - auto it = m_chunks.emplace(gk::Vector3i{cx, cy, cz}, new ClientChunk(cx, cy, cz, *this, m_textureAtlas)); + auto it = m_chunks.emplace(gk::Vector3i{cx, cy, cz}, new ClientChunk(cx, cy, cz, *m_dimension, *this, m_textureAtlas)); chunk = it.first->second.get(); } @@ -204,7 +205,7 @@ void ClientWorld::createChunkNeighbours(ClientChunk *chunk) { ClientChunk *neighbour = (ClientChunk *)getChunk(scx, scy, scz); if (!neighbour) { - auto it = m_chunks.emplace(gk::Vector3i{scx, scy, scz}, new ClientChunk(scx, scy, scz, *this, m_textureAtlas)); + auto it = m_chunks.emplace(gk::Vector3i{scx, scy, scz}, new ClientChunk(scx, scy, scz, *m_dimension, *this, m_textureAtlas)); neighbour = it.first->second.get(); } @@ -214,7 +215,7 @@ void ClientWorld::createChunkNeighbours(ClientChunk *chunk) { } void ClientWorld::draw(gk::RenderTarget &target, gk::RenderStates states) const { - // glClearColor used to be called in updateSky(), but when "toggling fullscreen mode" + // glClearColor used to be called in changeDimension(), but when "toggling fullscreen mode" // with SFML, you actually recreate a window. Thus, all the glEnable/glDisable/glClearColor // states are cleared when fullscreen mode is enabled/disabled. if (m_sky) diff --git a/source/client/world/ClientWorld.hpp b/source/client/world/ClientWorld.hpp index ca3472731..b51aa7115 100644 --- a/source/client/world/ClientWorld.hpp +++ b/source/client/world/ClientWorld.hpp @@ -53,7 +53,7 @@ class ClientWorld : public World, public gk::Drawable { void clear(); - void updateSky(u16 dimensionID); + void changeDimension(u16 dimensionID); void receiveChunkData(Network::Packet &packet); void removeChunk(ChunkMap::iterator &it); @@ -73,6 +73,8 @@ class ClientWorld : public World, public gk::Drawable { void draw(gk::RenderTarget &target, gk::RenderStates states) const override; + const Dimension *m_dimension = nullptr; + ClientScene m_scene; ChunkMap m_chunks; diff --git a/source/common/world/Chunk.hpp b/source/common/world/Chunk.hpp index fcf5a3152..e30205d86 100644 --- a/source/common/world/Chunk.hpp +++ b/source/common/world/Chunk.hpp @@ -74,6 +74,8 @@ class Chunk : public gk::NonCopyable { s32 y() const { return m_y; } s32 z() const { return m_z; } + World &world() { return m_world; } + Chunk *getSurroundingChunk(u8 i) { return (i > 5) ? nullptr : m_surroundingChunks[i]; } const Chunk *getSurroundingChunk(u8 i) const { return (i > 5) ? nullptr : m_surroundingChunks[i]; } void setSurroundingChunk(u8 i, Chunk *chunk) { if (i < 6) m_surroundingChunks[i] = chunk; } diff --git a/source/common/world/Dimension.cpp b/source/common/world/Dimension.cpp index 11e791be2..a4826b973 100644 --- a/source/common/world/Dimension.cpp +++ b/source/common/world/Dimension.cpp @@ -28,11 +28,11 @@ #include "NetworkUtils.hpp" void Dimension::serialize(sf::Packet &packet) const { - packet << m_id << m_stringID << m_name << m_biomes << m_sky; + packet << m_id << m_stringID << m_name << m_biomes << m_sky << m_gravity; } void Dimension::deserialize(sf::Packet &packet) { - packet >> m_id >> m_stringID >> m_name >> m_biomes >> m_sky; + packet >> m_id >> m_stringID >> m_name >> m_biomes >> m_sky >> m_gravity; } // Please update 'docs/lua-api-cpp.md' if you change this diff --git a/source/common/world/Dimension.hpp b/source/common/world/Dimension.hpp index 0d66bdf13..88a130ef1 100644 --- a/source/common/world/Dimension.hpp +++ b/source/common/world/Dimension.hpp @@ -54,6 +54,9 @@ class Dimension : public ISerializable { const std::string &sky() const { return m_sky; } void setSky(const std::string &sky) { m_sky = sky; } + float gravity() const { return m_gravity; } + void setGravity(float gravity) { m_gravity = gravity; } + static void initUsertype(sol::state &lua); private: @@ -65,6 +68,8 @@ class Dimension : public ISerializable { std::vector m_biomes; std::string m_sky; + + float m_gravity = 1.f; }; #endif // DIMENSION_HPP_ diff --git a/source/server/lua/loader/LuaDimensionLoader.cpp b/source/server/lua/loader/LuaDimensionLoader.cpp index cda2e8ab3..9412f6755 100644 --- a/source/server/lua/loader/LuaDimensionLoader.cpp +++ b/source/server/lua/loader/LuaDimensionLoader.cpp @@ -38,6 +38,7 @@ void LuaDimensionLoader::loadDimension(const sol::table &table) const { if (biomesObject.valid() && biomesObject.get_type() == sol::type::table) { Dimension &dimension = Registry::getInstance().registerDimension(id, name); dimension.setSky(table["sky"].get()); + dimension.setGravity(table["gravity"].get_or(1.f)); sol::table biomesTable = biomesObject.as(); for (auto &it : biomesTable) {