Door block added.
This commit is contained in:
parent
c3eaa06653
commit
2ecef2ded9
@ -233,6 +233,13 @@ Parameters:
|
||||
- `screen_height` (`u16`): height of the screen
|
||||
- `gui_scale` (`u8`): current scaling setting
|
||||
|
||||
### `on_block_destroyed`
|
||||
|
||||
Parameters:
|
||||
|
||||
- `pos` (`ivec3`): position of the block
|
||||
- `world` (`World`): instance of `ServerWorld`
|
||||
|
||||
### `on_block_placed`
|
||||
|
||||
Parameters:
|
||||
|
@ -23,6 +23,8 @@
|
||||
- `void set_string(string attribute, string value)`
|
||||
- `int get_int(string attribute)`
|
||||
- `void set_int(string attribute, int value)`
|
||||
- `bool get_bool(string attribute)`
|
||||
- `void set_bool(string attribute, bool value)`
|
||||
|
||||
## Chunk
|
||||
|
||||
|
@ -132,9 +132,6 @@ mod:block {
|
||||
is_light_source = true
|
||||
}
|
||||
|
||||
dofile("mods/default/workbench.lua")
|
||||
dofile("mods/default/furnace.lua")
|
||||
|
||||
mod:block {
|
||||
id = "iron_ore",
|
||||
name = "Iron Ore",
|
||||
@ -315,3 +312,7 @@ mod:block {
|
||||
end
|
||||
}
|
||||
|
||||
dofile("mods/default/blocks/workbench.lua")
|
||||
dofile("mods/default/blocks/furnace.lua")
|
||||
dofile("mods/default/blocks/door.lua")
|
||||
|
||||
|
112
mods/default/blocks/door.lua
Normal file
112
mods/default/blocks/door.lua
Normal file
@ -0,0 +1,112 @@
|
||||
--
|
||||
-- =====================================================================================
|
||||
--
|
||||
-- OpenMiner
|
||||
--
|
||||
-- Copyright (C) 2018-2020 Unarelith, Quentin Bazin <openminer@unarelith.net>
|
||||
-- Copyright (C) 2019-2020 the OpenMiner contributors (see CONTRIBUTORS.md)
|
||||
--
|
||||
-- This file is part of OpenMiner.
|
||||
--
|
||||
-- OpenMiner is free software; you can redistribute it and/or
|
||||
-- modify it under the terms of the GNU Lesser General Public
|
||||
-- License as published by the Free Software Foundation; either
|
||||
-- version 2.1 of the License, or (at your option) any later version.
|
||||
--
|
||||
-- OpenMiner is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
-- Lesser General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU Lesser General Public License
|
||||
-- along with OpenMiner; if not, write to the Free Software Foundation, Inc.,
|
||||
-- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
--
|
||||
-- =====================================================================================
|
||||
--
|
||||
|
||||
function open_door(pos, world)
|
||||
local data = world:get_block_data(pos.x, pos.y, pos.z)
|
||||
if not data then return end
|
||||
|
||||
-- FIXME: Add a helper to get rotation from data
|
||||
local rotation = world:get_data(pos.x, pos.y, pos.z)
|
||||
|
||||
local is_opened = data.meta:get_bool("is_opened") or false
|
||||
if not is_opened then
|
||||
world:set_data(pos.x, pos.y, pos.z, (rotation - 1) % 4)
|
||||
else
|
||||
world:set_data(pos.x, pos.y, pos.z, (rotation + 1) % 4)
|
||||
end
|
||||
|
||||
data.meta:set_bool("is_opened", not is_opened)
|
||||
end
|
||||
|
||||
mod:block {
|
||||
id = "door_wood_upper",
|
||||
name = "Wooden Door",
|
||||
tiles = "door_wood_upper.png",
|
||||
inventory_image = "door_wood.png",
|
||||
groups = {ci_ignore = 1},
|
||||
|
||||
is_rotatable = true,
|
||||
is_opaque = false,
|
||||
|
||||
draw_type = "boundingbox",
|
||||
bounding_box = {13 / 16, 0, 0, 3 / 16, 1, 1},
|
||||
|
||||
on_block_placed = function(pos, world)
|
||||
world:add_block_data(pos.x, pos.y, pos.z, 0, 0)
|
||||
end,
|
||||
|
||||
on_block_destroyed = function(pos, world)
|
||||
local lower_block_id = openminer:registry():get_block_from_string("default:door_wood_lower"):id()
|
||||
if world:get_block(pos.x, pos.y, pos.z - 1) == lower_block_id then
|
||||
world:set_block(pos.x, pos.y, pos.z - 1, 0)
|
||||
end
|
||||
end,
|
||||
|
||||
on_block_activated = function(pos, player, world, client, server, screen_width, screen_height, gui_scale)
|
||||
open_door(pos, world)
|
||||
open_door({x = pos.x, y = pos.y, z = pos.z - 1}, world)
|
||||
end
|
||||
}
|
||||
|
||||
mod:block {
|
||||
id = "door_wood_lower",
|
||||
name = "Wooden Door",
|
||||
tiles = "door_wood_lower.png",
|
||||
inventory_image = "door_wood.png",
|
||||
|
||||
is_rotatable = true,
|
||||
is_opaque = false,
|
||||
|
||||
draw_type = "boundingbox",
|
||||
bounding_box = {13 / 16, 0, 0, 3 / 16, 1, 1},
|
||||
|
||||
on_block_placed = function(pos, world)
|
||||
world:add_block_data(pos.x, pos.y, pos.z, 0, 0)
|
||||
|
||||
if world:get_block(pos.x, pos.y, pos.z + 1) == 0 then
|
||||
local data = world:get_data(pos.x, pos.y, pos.z)
|
||||
world:set_data(pos.x, pos.y, pos.z + 1, data)
|
||||
|
||||
local upper_block_id = openminer:registry():get_block_from_string("default:door_wood_upper"):id()
|
||||
world:set_block(pos.x, pos.y, pos.z + 1, upper_block_id)
|
||||
end
|
||||
end,
|
||||
|
||||
on_block_destroyed = function(pos, world)
|
||||
local upper_block_id = openminer:registry():get_block_from_string("default:door_wood_upper"):id()
|
||||
if world:get_block(pos.x, pos.y, pos.z + 1) == upper_block_id then
|
||||
world:set_block(pos.x, pos.y, pos.z + 1, 0)
|
||||
end
|
||||
end,
|
||||
|
||||
on_block_activated = function(pos, player, world, client, server, screen_width, screen_height, gui_scale)
|
||||
open_door(pos, world)
|
||||
open_door({x = pos.x, y = pos.y, z = pos.z + 1}, world)
|
||||
end
|
||||
}
|
||||
|
||||
|
BIN
mods/default/textures/blocks/door_wood_lower.png
Normal file
BIN
mods/default/textures/blocks/door_wood_lower.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 686 B |
BIN
mods/default/textures/blocks/door_wood_upper.png
Normal file
BIN
mods/default/textures/blocks/door_wood_upper.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 691 B |
BIN
mods/default/textures/items/door_wood.png
Normal file
BIN
mods/default/textures/items/door_wood.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 391 B |
@ -42,7 +42,7 @@ ItemWidget::ItemWidget(Inventory &inventory, u16 x, u16 y, Widget *parent)
|
||||
void ItemWidget::update() {
|
||||
if (stack().item().isBlock()) {
|
||||
const Block &block = Registry::getInstance().getBlock(stack().item().id());
|
||||
if (block.drawType() != BlockDrawType::XShape) {
|
||||
if (block.drawType() != BlockDrawType::XShape && block.inventoryImage().empty()) {
|
||||
m_cube.updateVertexBuffer(block);
|
||||
m_isImage = false;
|
||||
}
|
||||
|
@ -91,8 +91,6 @@ void BlockCursor::onEvent(const SDL_Event &event, const Hotbar &hotbar) {
|
||||
gk::FloatBox boundingBox = newBlock.boundingBox() + gk::Vector3f(x - m_player.x(), y - m_player.y(), z - m_player.z());
|
||||
gk::FloatBox playerBoundingBox = m_player.hitbox();
|
||||
if (!boundingBox.intersects(playerBoundingBox)) {
|
||||
m_world.setBlock(x, y, z, hotbar.currentItem());
|
||||
|
||||
u32 block = hotbar.currentItem();
|
||||
if (newBlock.isRotatable()) {
|
||||
u16 data = m_player.getOppositeDirection() & 0x3;
|
||||
@ -101,6 +99,8 @@ void BlockCursor::onEvent(const SDL_Event &event, const Hotbar &hotbar) {
|
||||
block |= data << 16;
|
||||
}
|
||||
|
||||
m_world.setBlock(x, y, z, hotbar.currentItem());
|
||||
|
||||
m_client.sendPlayerPlaceBlock(x, y, z, block);
|
||||
|
||||
const ItemStack ¤tStack = m_player.inventory().getStack(hotbar.cursorPos(), 0);
|
||||
|
@ -36,6 +36,10 @@ void BlockMetadata::setInt(const std::string &name, int value) {
|
||||
m_data[name].set(value, BlockMetadataValue::Type::Int);
|
||||
}
|
||||
|
||||
void BlockMetadata::setBool(const std::string &name, bool value) {
|
||||
m_data[name].set(value, BlockMetadataValue::Type::Bool);
|
||||
}
|
||||
|
||||
void BlockMetadata::serialize(sf::Packet &packet) const {
|
||||
packet << u32(m_data.size());
|
||||
for (auto &it : m_data) {
|
||||
@ -46,6 +50,9 @@ void BlockMetadata::serialize(sf::Packet &packet) const {
|
||||
else if (it.second.type() == BlockMetadataValue::Type::Int) {
|
||||
packet << it.second.get<int>();
|
||||
}
|
||||
else if (it.second.type() == BlockMetadataValue::Type::Bool) {
|
||||
packet << it.second.get<bool>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,6 +75,11 @@ void BlockMetadata::deserialize(sf::Packet &packet) {
|
||||
packet >> value;
|
||||
m_data[name].set(value, type);
|
||||
}
|
||||
else if (type == BlockMetadataValue::Type::Bool) {
|
||||
bool value;
|
||||
packet >> value;
|
||||
m_data[name].set(value, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,8 @@ class BlockMetadataValue {
|
||||
enum class Type : u8 {
|
||||
Undefined,
|
||||
String,
|
||||
Int
|
||||
Int,
|
||||
Bool
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
@ -68,6 +69,7 @@ class BlockMetadata : public ISerializable {
|
||||
public:
|
||||
void setString(const std::string &name, const std::string &value);
|
||||
void setInt(const std::string &name, int value);
|
||||
void setBool(const std::string &name, bool value);
|
||||
|
||||
template<typename T>
|
||||
T &get(const std::string &name) {
|
||||
|
@ -68,7 +68,7 @@ void Chunk::setBlock(int x, int y, int z, u16 type) {
|
||||
if(z < 0) { if(m_surroundingChunks[4]) m_surroundingChunks[4]->setBlock(x, y, z + Chunk::height, type); return; }
|
||||
if(z >= Chunk::height) { if(m_surroundingChunks[5]) m_surroundingChunks[5]->setBlock(x, y, z - Chunk::height, type); return; }
|
||||
|
||||
if (m_data[z][y][x] == type) return;
|
||||
if ((m_data[z][y][x] & 0xffff) == type) return;
|
||||
|
||||
const Block &block = Registry::getInstance().getBlock(type);
|
||||
if (block.canUpdate()) {
|
||||
@ -89,6 +89,11 @@ void Chunk::setBlock(int x, int y, int z, u16 type) {
|
||||
|
||||
onBlockPlaced(x, y, z, block);
|
||||
|
||||
if (m_data[z][y][x] != 0) {
|
||||
const Block &oldBlock = Registry::getInstance().getBlock(m_data[z][y][x]);
|
||||
onBlockDestroyed(x, y, z, oldBlock);
|
||||
}
|
||||
|
||||
setBlockRaw(x, y, z, type);
|
||||
|
||||
if(x == 0 && m_surroundingChunks[West]) { m_surroundingChunks[West]->m_hasChanged = true; }
|
||||
@ -121,7 +126,7 @@ void Chunk::setBlockRaw(int x, int y, int z, u16 type) {
|
||||
if(z < 0) { if(m_surroundingChunks[4]) m_surroundingChunks[4]->setBlockRaw(x, y, z + Chunk::height, type); return; }
|
||||
if(z >= Chunk::height) { if(m_surroundingChunks[5]) m_surroundingChunks[5]->setBlockRaw(x, y, z - Chunk::height, type); return; }
|
||||
|
||||
if (m_data[z][y][x] == type) return;
|
||||
if ((m_data[z][y][x] & 0xffff) == type) return;
|
||||
|
||||
if (type == 0) {
|
||||
auto it = m_blockData.find(gk::Vector3i{x, y, z});
|
||||
@ -129,7 +134,8 @@ void Chunk::setBlockRaw(int x, int y, int z, u16 type) {
|
||||
m_blockData.erase(it);
|
||||
}
|
||||
|
||||
m_data[z][y][x] = type;
|
||||
m_data[z][y][x] &= 0xffff0000;
|
||||
m_data[z][y][x] |= type;
|
||||
|
||||
m_hasChanged = true;
|
||||
}
|
||||
|
@ -66,6 +66,7 @@ class Chunk : public gk::NonCopyable {
|
||||
void setBlockRaw(int x, int y, int z, u16 block);
|
||||
|
||||
virtual void onBlockPlaced(int, int, int, const Block &) const {}
|
||||
virtual void onBlockDestroyed(int, int, int, const Block &) const {}
|
||||
|
||||
BlockData *getBlockData(int x, int y, int z) const;
|
||||
BlockData *addBlockData(int x, int y, int z, int inventoryWidth = 0, int inventoryHeight = 0);
|
||||
|
@ -168,7 +168,10 @@ void ScriptEngine::initUsertypes() {
|
||||
"set_string", &BlockMetadata::setString,
|
||||
|
||||
"get_int", &BlockMetadata::getLuaObject<int>,
|
||||
"set_int", &BlockMetadata::setInt
|
||||
"set_int", &BlockMetadata::setInt,
|
||||
|
||||
"get_bool", &BlockMetadata::getLuaObject<bool>,
|
||||
"set_bool", &BlockMetadata::setBool
|
||||
);
|
||||
|
||||
m_lua.new_usertype<ClientInfo>("ClientInfo",
|
||||
|
@ -67,6 +67,7 @@ inline void LuaBlockLoader::loadProperties(ServerBlock &block, const sol::table
|
||||
block.setOnBlockActivated(table["on_block_activated"]);
|
||||
block.setOnTick(table["on_tick"]);
|
||||
block.setOnBlockPlaced(table["on_block_placed"]);
|
||||
block.setOnBlockDestroyed(table["on_block_destroyed"]);
|
||||
block.setRotatable(table["is_rotatable"].get_or(false));
|
||||
block.setInventoryImage(table["inventory_image"].get_or<std::string>(""));
|
||||
}
|
||||
|
@ -162,8 +162,8 @@ void ServerCommandHandler::setupCallbacks() {
|
||||
packet >> x >> y >> z >> block;
|
||||
|
||||
ServerWorld &world = getWorldForClient(client.id);
|
||||
world.setBlock(x, y, z, block & 0xffff);
|
||||
world.setData(x, y, z, block >> 16);
|
||||
world.setBlock(x, y, z, block & 0xffff);
|
||||
|
||||
m_scriptEngine.luaCore().onEvent(LuaEventType::OnBlockPlaced, glm::ivec3{x, y, z}, m_players.at(client.id), world, client, *this);
|
||||
|
||||
|
@ -80,3 +80,14 @@ void ServerBlock::onBlockPlaced(const glm::ivec3 &pos, World &world) const {
|
||||
}
|
||||
}
|
||||
|
||||
void ServerBlock::onBlockDestroyed(const glm::ivec3 &pos, World &world) const {
|
||||
try {
|
||||
if (m_onBlockDestroyed) {
|
||||
m_onBlockDestroyed(pos, world);
|
||||
}
|
||||
}
|
||||
catch (const sol::error &e) {
|
||||
std::cerr << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,17 +41,21 @@ class ServerBlock : public Block {
|
||||
void onTick(const glm::ivec3 &, Chunk &, World &, ServerCommandHandler &) const;
|
||||
bool onBlockActivated(const glm::ivec3 &pos, Player &player, World &world, ClientInfo &client, ServerCommandHandler &server, u16 screenWidth, u16 screenHeight, u8 guiScale) const;
|
||||
void onBlockPlaced(const glm::ivec3 &pos, World &world) const;
|
||||
void onBlockDestroyed(const glm::ivec3 &pos, World &world) const;
|
||||
|
||||
bool canUpdate() const { return m_onTick.valid(); }
|
||||
|
||||
void setOnBlockActivated(const sol::function &function) { m_onBlockActivated = function; m_canBeActivated = m_onBlockActivated.valid(); }
|
||||
void setOnTick(const sol::function &function) { m_onTick = function; m_canUpdate = m_onTick.valid(); }
|
||||
void setOnBlockPlaced(const sol::function &function) { m_onBlockPlaced = function; }
|
||||
void setOnBlockActivated(const sol::protected_function &function) { m_onBlockActivated = function; m_canBeActivated = m_onBlockActivated.valid(); }
|
||||
void setOnTick(const sol::protected_function &function) { m_onTick = function; m_canUpdate = m_onTick.valid(); }
|
||||
void setOnBlockPlaced(const sol::protected_function &function) { m_onBlockPlaced = function; }
|
||||
void setOnBlockDestroyed(const sol::protected_function &function) { m_onBlockDestroyed = function; }
|
||||
|
||||
private:
|
||||
sol::unsafe_function m_onBlockActivated;
|
||||
sol::unsafe_function m_onTick;
|
||||
sol::unsafe_function m_onBlockPlaced;
|
||||
sol::protected_function m_onBlockActivated;
|
||||
sol::protected_function m_onTick;
|
||||
sol::protected_function m_onBlockPlaced;
|
||||
sol::protected_function m_onBlockDestroyed;
|
||||
|
||||
mutable bool m_onTickEnabled = true;
|
||||
};
|
||||
|
||||
|
@ -42,6 +42,11 @@ void ServerChunk::onBlockPlaced(int x, int y, int z, const Block &block) const {
|
||||
serverBlock.onBlockPlaced(glm::ivec3{x + m_x * CHUNK_WIDTH, y + m_y * CHUNK_DEPTH, z + m_z * CHUNK_HEIGHT}, m_world);
|
||||
}
|
||||
|
||||
void ServerChunk::onBlockDestroyed(int x, int y, int z, const Block &block) const {
|
||||
const ServerBlock &serverBlock = (ServerBlock &)block;
|
||||
serverBlock.onBlockDestroyed(glm::ivec3{x + m_x * CHUNK_WIDTH, y + m_y * CHUNK_DEPTH, z + m_z * CHUNK_HEIGHT}, m_world);
|
||||
}
|
||||
|
||||
void ServerChunk::tick(World &world, ServerCommandHandler &server) {
|
||||
if (!m_tickingBlocks.empty()) {
|
||||
for (auto &it : m_tickingBlocks) {
|
||||
|
@ -43,6 +43,8 @@ class ServerChunk : public Chunk {
|
||||
void updateLights();
|
||||
|
||||
void onBlockPlaced(int x, int y, int z, const Block &block) const;
|
||||
void onBlockDestroyed(int x, int y, int z, const Block &block) const;
|
||||
|
||||
void tick(World &world, ServerCommandHandler &server);
|
||||
|
||||
bool isSent() const { return m_isSent; }
|
||||
|
BIN
texturepacks/minecraft/blocks/door_wood_lower.png
Normal file
BIN
texturepacks/minecraft/blocks/door_wood_lower.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 398 B |
BIN
texturepacks/minecraft/blocks/door_wood_upper.png
Normal file
BIN
texturepacks/minecraft/blocks/door_wood_upper.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 401 B |
BIN
texturepacks/minecraft/items/door_wood.png
Normal file
BIN
texturepacks/minecraft/items/door_wood.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 146 B |
Loading…
x
Reference in New Issue
Block a user