diff --git a/client/source/hud/BlockCursor.cpp b/client/source/hud/BlockCursor.cpp index 520a70483..8e6603769 100644 --- a/client/source/hud/BlockCursor.cpp +++ b/client/source/hud/BlockCursor.cpp @@ -124,7 +124,15 @@ void BlockCursor::onEvent(const SDL_Event &event, const Hotbar &hotbar) { if (!boundingBox.intersects(playerBoundingBox)) { m_world.setBlock(x, y, z, hotbar.currentItem()); - m_client.sendPlayerPlaceBlock(x, y, z, hotbar.currentItem()); + u32 block = hotbar.currentItem(); + if (newBlock.isRotatable()) { + u16 data = m_player.getOppositeDirection() & 0x3; + m_world.setData(x, y, z, data); + + block |= data << 16; + } + + m_client.sendPlayerPlaceBlock(x, y, z, block); const ItemStack ¤tStack = m_player.inventory().getStack(hotbar.cursorPos(), 0); m_player.inventory().setStack(hotbar.cursorPos(), 0, currentStack.amount() > 1 ? currentStack.item().stringID() : "", currentStack.amount() - 1); diff --git a/client/source/hud/DebugOverlay.cpp b/client/source/hud/DebugOverlay.cpp index 19df495b7..bf14a86b0 100644 --- a/client/source/hud/DebugOverlay.cpp +++ b/client/source/hud/DebugOverlay.cpp @@ -64,7 +64,7 @@ void DebugOverlay::update() { stream << "cy: " << (py & -CHUNK_DEPTH) / CHUNK_DEPTH << " | "; stream << "cz: " << (pz & -CHUNK_HEIGHT) / CHUNK_HEIGHT; stream << '\n'; - stream << "dir: " << direction << " (" << m_player.viewAngleH() << ")"; + stream << "dir: " << direction << " (" << m_player.cameraYaw() << ")"; stream << '\n'; stream << "Loaded chunks: " << m_world.loadedChunkCount(); diff --git a/client/source/world/ChunkBuilder.cpp b/client/source/world/ChunkBuilder.cpp index 3f6df5424..396581d9f 100644 --- a/client/source/world/ChunkBuilder.cpp +++ b/client/source/world/ChunkBuilder.cpp @@ -29,9 +29,8 @@ #include "Registry.hpp" #include "TextureAtlas.hpp" +// Same order as enum BlockFace in TilesDef.hpp static const float cubeCoords[6 * 4 * 3] = { - // Same order as enum BlockFace in TilesDef.hpp - // West 0, 1, 0, 0, 0, 0, @@ -170,8 +169,25 @@ inline void ChunkBuilder::addFace(u8 x, u8 y, u8 z, u8 i, const ClientChunk &chu // Computing face normal (already normalized because vertexCoords are normalized) normal = glm::cross(v1, v2); + u8 faceID = i; + if (block->isRotatable()) { + u8 orientation = chunk.getData(x, y, z) & 0x3; + if (faceID < 4) { + u8 faceToAngle[4] = {0, 2, 1, 3}; + u8 angleToFace[4] = {BlockFace::West, BlockFace::South, BlockFace::East, BlockFace::North}; + + if (orientation == BlockFace::South) + faceID = angleToFace[(faceToAngle[faceID] + 1) % 4]; + else if (orientation == BlockFace::West) // FIXME: Find why East and West are inverted + faceID = angleToFace[(faceToAngle[faceID] + 2) % 4]; + else if (orientation == BlockFace::North) + faceID = angleToFace[(faceToAngle[faceID] + 3) % 4]; + } + } + const BlockData *blockData = chunk.getBlockData(x, y, z); - const gk::FloatRect &blockTexCoords = m_textureAtlas.getTexCoords(block->tiles().getTextureForFace(i, blockData ? blockData->useAltTiles : false)); + const std::string &texture = block->tiles().getTextureForFace(faceID, blockData ? blockData->useAltTiles : false); + const gk::FloatRect &blockTexCoords = m_textureAtlas.getTexCoords(texture); float faceTexCoords[2 * 4] = { blockTexCoords.x, blockTexCoords.y + blockTexCoords.sizeY, blockTexCoords.x + blockTexCoords.sizeX, blockTexCoords.y + blockTexCoords.sizeY, diff --git a/client/source/world/ClientPlayer.cpp b/client/source/world/ClientPlayer.cpp index b685b0ba2..6e23f120c 100644 --- a/client/source/world/ClientPlayer.cpp +++ b/client/source/world/ClientPlayer.cpp @@ -83,6 +83,11 @@ u8 ClientPlayer::getDirection() const { } } +u8 ClientPlayer::getOppositeDirection() const { + u8 direction = getDirection(); + return (direction % 2 == 0) ? direction + 1 : direction - 1; +} + void ClientPlayer::updateDir() { double ch = cos(m_viewAngleH * RADIANS_PER_DEGREES); double sh = sin(m_viewAngleH * RADIANS_PER_DEGREES); diff --git a/client/source/world/ClientPlayer.hpp b/client/source/world/ClientPlayer.hpp index d6bf90522..14d9dd0e1 100644 --- a/client/source/world/ClientPlayer.hpp +++ b/client/source/world/ClientPlayer.hpp @@ -53,8 +53,9 @@ class ClientPlayer : public Player { void turnViewV(double angle); // West, East, South, North + // Same order as enum BlockFace in TilesDef.hpp u8 getDirection() const; - double viewAngleH() const { return m_viewAngleH; } + u8 getOppositeDirection() const; void move(double direction); diff --git a/client/source/world/ClientWorld.cpp b/client/source/world/ClientWorld.cpp index fb87c0709..cdcce4499 100644 --- a/client/source/world/ClientWorld.cpp +++ b/client/source/world/ClientWorld.cpp @@ -107,13 +107,13 @@ void ClientWorld::receiveChunkData(sf::Packet &packet) { for (u16 z = 0 ; z < CHUNK_HEIGHT ; ++z) { for (u16 y = 0 ; y < CHUNK_DEPTH ; ++y) { for (u16 x = 0 ; x < CHUNK_WIDTH ; ++x) { - u16 block; + u32 block; u8 light; packet >> block >> light; chunk->setBlockRaw(x, y, z, block & 0xffff); - // chunk->setData(x, y, z, block >> 16); + chunk->setData(x, y, z, block >> 16); chunk->lightmap().setLightData(x, y, z, light); } } @@ -213,7 +213,7 @@ void ClientWorld::draw(gk::RenderTarget &target, gk::RenderStates states) const // an issue at larger coordinates, because the precision of floats // quickly degrades as the numbers grow, with a random wobbling being // very noticeable at e.g. coordinates >= 65536 or so, and the waving - // leaves effect being very jerky in conparison with the effect near the + // leaves effect being very jerky in comparison with the effect near the // origin. // // To gain rendering precision, we subtract the camera position from the diff --git a/common/source/core/TilesDef.cpp b/common/source/core/TilesDef.cpp index aa1c33421..8eb85c77c 100644 --- a/common/source/core/TilesDef.cpp +++ b/common/source/core/TilesDef.cpp @@ -40,12 +40,12 @@ const std::string &TilesDef::getTextureForFace(u8 face, bool useAltTiles) const static constexpr u8 faceToIndex[nSizes][nFaces] = { // Same order as enum BlockFace in TilesDef.hpp, // namely: West, East, South, North, Bottom, Top - { 0, 0, 0, 0, 0, 0, }, // for size = 1 - { 1, 1, 1, 1, 0, 0, }, // for size = 2 - { 2, 2, 2, 2, 1, 0, }, // for size = 3 - { 2, 3, 3, 3, 1, 0, }, // for size = 4 - { 2, 3, 4, 4, 1, 0, }, // for size = 5 - { 2, 3, 4, 5, 1, 0, }, // for size = 6 + {0, 0, 0, 0, 0, 0}, // for size = 1 + {1, 1, 1, 1, 0, 0}, // for size = 2 + {2, 2, 2, 2, 1, 0}, // for size = 3 + {2, 3, 3, 3, 1, 0}, // for size = 4 + {2, 3, 4, 4, 1, 0}, // for size = 5 + {2, 3, 4, 5, 1, 0}, // for size = 6 }; u8 index = faceToIndex[size <= nSizes ? size - 1 : nSizes - 1][face]; diff --git a/common/source/world/Block.cpp b/common/source/world/Block.cpp index 1cc63dd97..c65f4eb51 100644 --- a/common/source/world/Block.cpp +++ b/common/source/world/Block.cpp @@ -49,7 +49,8 @@ void Block::serialize(sf::Packet &packet) const { << m_boundingBox.x << m_boundingBox.y << m_boundingBox.z << m_boundingBox.sizeX << m_boundingBox.sizeY << m_boundingBox.sizeZ << m_isLightSource << m_canUpdate << m_canBeActivated - << m_colorMultiplier.r << m_colorMultiplier.g << m_colorMultiplier.b << m_colorMultiplier.a; + << m_colorMultiplier.r << m_colorMultiplier.g << m_colorMultiplier.b << m_colorMultiplier.a + << m_isRotatable; } void Block::deserialize(sf::Packet &packet) { @@ -61,7 +62,8 @@ void Block::deserialize(sf::Packet &packet) { >> m_boundingBox.x >> m_boundingBox.y >> m_boundingBox.z >> m_boundingBox.sizeX >> m_boundingBox.sizeY >> m_boundingBox.sizeZ >> m_isLightSource >> m_canUpdate >> m_canBeActivated - >> m_colorMultiplier.r >> m_colorMultiplier.g >> m_colorMultiplier.b >> m_colorMultiplier.a; + >> m_colorMultiplier.r >> m_colorMultiplier.g >> m_colorMultiplier.b >> m_colorMultiplier.a + >> m_isRotatable; m_id = id; m_drawType = BlockDrawType(drawType); diff --git a/common/source/world/Block.hpp b/common/source/world/Block.hpp index 1f2c7c6c4..8834eb3a3 100644 --- a/common/source/world/Block.hpp +++ b/common/source/world/Block.hpp @@ -101,6 +101,9 @@ class Block : public ISerializable { const gk::Color &colorMultiplier() const { return m_colorMultiplier; } void setColorMultiplier(const gk::Color &colorMultiplier) { m_colorMultiplier = colorMultiplier; } + bool isRotatable() const { return m_isRotatable; } + void setRotatable(bool isRotatable) { m_isRotatable = isRotatable; } + protected: glm::vec4 getTexCoordsFromID(int textureID) const; @@ -129,6 +132,8 @@ class Block : public ISerializable { bool m_isLightSource = false; gk::Color m_colorMultiplier = gk::Color::White; + + bool m_isRotatable = false; }; #endif // BLOCK_HPP_ diff --git a/mods/default/furnace.lua b/mods/default/furnace.lua index c6aee3c7a..ccadad3b6 100644 --- a/mods/default/furnace.lua +++ b/mods/default/furnace.lua @@ -30,6 +30,7 @@ mod:block { name = "Furnace", tiles = {"furnace_top.png", "furnace_top.png", "furnace_front.png", "furnace_side.png"}, alt_tiles = {"", "", "furnace_front_on.png", ""}, + is_rotatable = true, on_block_placed = function(pos, world) world:add_block_data(pos.x, pos.y, pos.z, 3, 1) diff --git a/server/source/lua/LuaMod.cpp b/server/source/lua/LuaMod.cpp index 09cd374a8..751d7e865 100644 --- a/server/source/lua/LuaMod.cpp +++ b/server/source/lua/LuaMod.cpp @@ -49,6 +49,7 @@ void LuaMod::registerBlock(const sol::table &table) { block.setOnBlockActivated(onBlockActivated); block.setOnTick(onTick); block.setOnBlockPlaced(table["on_block_placed"]); + block.setRotatable(table["is_rotatable"].get_or(false)); sol::optional boundingBox = table["bounding_box"]; if (boundingBox != sol::nullopt) { diff --git a/server/source/network/ServerCommandHandler.cpp b/server/source/network/ServerCommandHandler.cpp index 074b108a1..56c9e8dad 100644 --- a/server/source/network/ServerCommandHandler.cpp +++ b/server/source/network/ServerCommandHandler.cpp @@ -150,7 +150,8 @@ void ServerCommandHandler::setupCallbacks() { s32 x, y, z; u32 block; packet >> x >> y >> z >> block; - m_world.setBlock(x, y, z, block); + m_world.setBlock(x, y, z, block & 0xffff); + m_world.setData(x, y, z, block >> 16); sf::Packet answer; answer << Network::Command::BlockUpdate << x << y << z << block; diff --git a/server/source/world/ServerWorld.cpp b/server/source/world/ServerWorld.cpp index efb1bdb5f..6dcfb3815 100644 --- a/server/source/world/ServerWorld.cpp +++ b/server/source/world/ServerWorld.cpp @@ -105,7 +105,7 @@ void ServerWorld::sendChunkData(const Client &client, ServerChunk *chunk) { for (u16 z = 0 ; z < CHUNK_HEIGHT ; ++z) { for (u16 y = 0 ; y < CHUNK_DEPTH ; ++y) { for (u16 x = 0 ; x < CHUNK_WIDTH ; ++x) { - packet << u16(chunk->data()[z][y][x]); + packet << chunk->data()[z][y][x]; packet << chunk->lightmap().getLightData(x, y, z); BlockData *blockData = chunk->getBlockData(x, y, z);