diff --git a/dev/VoxelEngine.png b/dev/VoxelEngine.png index 0d69ae74..80c21b05 100644 Binary files a/dev/VoxelEngine.png and b/dev/VoxelEngine.png differ diff --git a/src/frontend/WorldRenderer.cpp b/src/frontend/WorldRenderer.cpp index 9463dc6a..a322c10b 100644 --- a/src/frontend/WorldRenderer.cpp +++ b/src/frontend/WorldRenderer.cpp @@ -126,7 +126,7 @@ void WorldRenderer::drawChunks(Chunks* chunks, } -void WorldRenderer::draw(const GfxContext& pctx, Camera* camera){ +void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool hudVisible){ EngineSettings& settings = engine->getSettings(); skybox->refresh(level->world->daytime, 1.0f+fog*2.0f, 4); @@ -187,7 +187,7 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera){ drawChunks(level->chunks, camera, shader); // Selected block - if (PlayerController::selectedBlockId != -1){ + if (PlayerController::selectedBlockId != -1 && hudVisible){ blockid_t id = PlayerController::selectedBlockId; Block* block = contentIds->getBlockDef(id); assert(block != nullptr); diff --git a/src/frontend/WorldRenderer.h b/src/frontend/WorldRenderer.h index a1ecf2c5..bb500c3b 100644 --- a/src/frontend/WorldRenderer.h +++ b/src/frontend/WorldRenderer.h @@ -37,7 +37,7 @@ public: WorldRenderer(Engine* engine, LevelFrontend* frontend); ~WorldRenderer(); - void draw(const GfxContext& context, Camera* camera); + void draw(const GfxContext& context, Camera* camera, bool hudVisible); void drawDebug(const GfxContext& context, Camera* camera); void drawBorders(int sx, int sy, int sz, int ex, int ey, int ez); diff --git a/src/frontend/screens.cpp b/src/frontend/screens.cpp index 97dda8f5..4fc782d8 100644 --- a/src/frontend/screens.cpp +++ b/src/frontend/screens.cpp @@ -149,7 +149,7 @@ void LevelScreen::draw(float delta) { Viewport viewport(Window::width, Window::height); GfxContext ctx(nullptr, viewport, batch.get()); - worldRenderer->draw(ctx, camera.get()); + worldRenderer->draw(ctx, camera.get(), hudVisible); if (hudVisible) { hud->draw(ctx); diff --git a/src/items/ItemDef.h b/src/items/ItemDef.h index 1c5d8885..37b3d1f3 100644 --- a/src/items/ItemDef.h +++ b/src/items/ItemDef.h @@ -8,6 +8,8 @@ struct item_funcs_set { bool init: 1; + bool on_use_on_block: 1; + bool on_block_break_by: 1; }; enum class item_icon_type { diff --git a/src/logic/LevelController.cpp b/src/logic/LevelController.cpp index 5e01d26d..7327f593 100644 --- a/src/logic/LevelController.cpp +++ b/src/logic/LevelController.cpp @@ -13,7 +13,7 @@ LevelController::LevelController(EngineSettings& settings, Level* level) chunks = std::make_unique(level, settings.chunks.padding); player = std::make_unique(level, settings, blocks.get()); - scripting::on_world_load(level); + scripting::on_world_load(level, blocks.get()); } LevelController::~LevelController() { diff --git a/src/logic/PlayerController.cpp b/src/logic/PlayerController.cpp index 939783cd..8c410042 100644 --- a/src/logic/PlayerController.cpp +++ b/src/logic/PlayerController.cpp @@ -259,10 +259,23 @@ void PlayerController::updateInteraction(){ } } + if (lclick) { + if (!input.shift && item->rt.funcsset.on_use_on_block) { + if (scripting::on_item_break_block(player, item, x, y, z)) + return; + } + } + Block* target = contentIds->getBlockDef(vox->id); if (lclick && target->breakable){ blocksController->breakBlock(player, target, x, y, z); } + if (rclick) { + if (!input.shift && item->rt.funcsset.on_use_on_block) { + if (scripting::on_item_use_on_block(player, item, x, y, z)) + return; + } + } if (def && rclick){ if (!input.shift && target->rt.funcsset.oninteract) { scripting::on_block_interact(player, target, x, y, z); diff --git a/src/logic/scripting/api_lua.cpp b/src/logic/scripting/api_lua.cpp index da16ed88..97237455 100644 --- a/src/logic/scripting/api_lua.cpp +++ b/src/logic/scripting/api_lua.cpp @@ -6,19 +6,49 @@ #include "../../physics/Hitbox.h" #include "../../objects/Player.h" #include "../../world/Level.h" +#include "../../world/World.h" #include "../../content/Content.h" #include "../../voxels/Block.h" #include "../../voxels/Chunks.h" #include "../../voxels/voxel.h" #include "../../lighting/Lighting.h" +#include "../../logic/BlocksController.h" -int l_block_name(lua_State* L) { +static int l_world_get_day_time(lua_State* L) { + lua_pushnumber(L, scripting::level->world->daytime); + return 1; +} + +static int l_world_set_day_time(lua_State* L) { + double value = scripting::level->world->daytime; + scripting::level->world->daytime = fmod(value, 1.0); + return 0; +} + +static int l_world_get_seed(lua_State* L) { + lua_pushinteger(L, scripting::level->world->seed); + return 1; +} + +static const luaL_Reg worldlib [] = { + {"get_day_time", l_world_get_day_time}, + {"set_day_time", l_world_set_day_time}, + {"get_seed", l_world_get_seed}, + {NULL, NULL} +}; + +int luaopen_world(lua_State* L) { + luaL_openlib(L, "world", worldlib, 0); + return 1; +} + +static int l_block_name(lua_State* L) { int id = lua_tointeger(L, 1); lua_pushstring(L, scripting::content->indices->getBlockDef(id)->name.c_str()); return 1; } -int l_is_solid_at(lua_State* L) { +static int l_is_solid_at(lua_State* L) { int x = lua_tointeger(L, 1); int y = lua_tointeger(L, 2); int z = lua_tointeger(L, 3); @@ -27,29 +57,32 @@ int l_is_solid_at(lua_State* L) { return 1; } -int l_blocks_count(lua_State* L) { +static int l_blocks_count(lua_State* L) { lua_pushinteger(L, scripting::content->indices->countBlockDefs()); return 1; } -int l_block_index(lua_State* L) { +static int l_block_index(lua_State* L) { auto name = lua_tostring(L, 1); lua_pushinteger(L, scripting::content->requireBlock(name)->rt.id); return 1; } -int l_set_block(lua_State* L) { +static int l_set_block(lua_State* L) { int x = lua_tointeger(L, 1); int y = lua_tointeger(L, 2); int z = lua_tointeger(L, 3); int id = lua_tointeger(L, 4); int states = lua_tointeger(L, 5); + bool noupdate = lua_toboolean(L, 6); scripting::level->chunks->set(x, y, z, id, states); scripting::level->lighting->onBlockSet(x,y,z, id); + if (!noupdate) + scripting::blocks->updateSides(x, y, z); return 0; } -int l_get_block(lua_State* L) { +static int l_get_block(lua_State* L) { int x = lua_tointeger(L, 1); int y = lua_tointeger(L, 2); int z = lua_tointeger(L, 3); @@ -66,7 +99,7 @@ inline int lua_pushivec3(lua_State* L, int x, int y, int z) { return 3; } -int l_get_block_x(lua_State* L) { +static int l_get_block_x(lua_State* L) { int x = lua_tointeger(L, 1); int y = lua_tointeger(L, 2); int z = lua_tointeger(L, 3); @@ -83,7 +116,7 @@ int l_get_block_x(lua_State* L) { } } -int l_get_block_y(lua_State* L) { +static int l_get_block_y(lua_State* L) { int x = lua_tointeger(L, 1); int y = lua_tointeger(L, 2); int z = lua_tointeger(L, 3); @@ -100,7 +133,7 @@ int l_get_block_y(lua_State* L) { } } -int l_get_block_z(lua_State* L) { +static int l_get_block_z(lua_State* L) { int x = lua_tointeger(L, 1); int y = lua_tointeger(L, 2); int z = lua_tointeger(L, 3); @@ -117,7 +150,7 @@ int l_get_block_z(lua_State* L) { } } -int l_get_player_pos(lua_State* L) { +static int l_get_player_pos(lua_State* L) { glm::vec3 pos = scripting::level->player->hitbox->position; lua_pushnumber(L, pos.x); lua_pushnumber(L, pos.y); @@ -125,14 +158,14 @@ int l_get_player_pos(lua_State* L) { return 3; } -int l_get_player_rot(lua_State* L) { +static int l_get_player_rot(lua_State* L) { glm::vec2 rot = scripting::level->player->cam; lua_pushnumber(L, rot.x); lua_pushnumber(L, rot.y); return 2; } -int l_set_player_rot(lua_State* L) { +static int l_set_player_rot(lua_State* L) { double x = lua_tonumber(L, 1); double y = lua_tonumber(L, 2); glm::vec2& cam = scripting::level->player->cam; @@ -141,7 +174,7 @@ int l_set_player_rot(lua_State* L) { return 0; } -int l_set_player_pos(lua_State* L) { +static int l_set_player_pos(lua_State* L) { double x = lua_tonumber(L, 1); double y = lua_tonumber(L, 2); double z = lua_tonumber(L, 3); @@ -149,7 +182,7 @@ int l_set_player_pos(lua_State* L) { return 0; } -int l_get_block_states(lua_State* L) { +static int l_get_block_states(lua_State* L) { int x = lua_tointeger(L, 1); int y = lua_tointeger(L, 2); int z = lua_tointeger(L, 3); @@ -159,7 +192,7 @@ int l_get_block_states(lua_State* L) { return 1; } -int l_get_block_user_bits(lua_State* L) { +static int l_get_block_user_bits(lua_State* L) { int x = lua_tointeger(L, 1); int y = lua_tointeger(L, 2); int z = lua_tointeger(L, 3); @@ -177,7 +210,7 @@ int l_get_block_user_bits(lua_State* L) { return 1; } -int l_set_block_user_bits(lua_State* L) { +static int l_set_block_user_bits(lua_State* L) { int x = lua_tointeger(L, 1); int y = lua_tointeger(L, 2); int z = lua_tointeger(L, 3); @@ -195,7 +228,7 @@ int l_set_block_user_bits(lua_State* L) { return 0; } -int l_is_replaceable_at(lua_State* L) { +static int l_is_replaceable_at(lua_State* L) { int x = lua_tointeger(L, 1); int y = lua_tointeger(L, 2); int z = lua_tointeger(L, 3); @@ -208,6 +241,8 @@ int l_is_replaceable_at(lua_State* L) { lua_setglobal(L, NAME)) void apilua::create_funcs(lua_State* L) { + luaopen_world(L); + lua_addfunc(L, l_block_index, "block_index"); lua_addfunc(L, l_block_name, "block_name"); lua_addfunc(L, l_blocks_count, "blocks_count"); diff --git a/src/logic/scripting/scripting.cpp b/src/logic/scripting/scripting.cpp index 17bbd863..922d75db 100644 --- a/src/logic/scripting/scripting.cpp +++ b/src/logic/scripting/scripting.cpp @@ -10,6 +10,7 @@ #include "../../world/Level.h" #include "../../voxels/Block.h" #include "../../items/ItemDef.h" +#include "../../logic/BlocksController.h" #include "api_lua.h" using namespace scripting; @@ -23,6 +24,14 @@ lua_State* scripting::L = nullptr; Level* scripting::level = nullptr; const Content* scripting::content = nullptr; EnginePaths* scripting::paths = nullptr; +BlocksController* scripting::blocks = nullptr; + +inline int lua_pushivec3(lua_State* L, int x, int y, int z) { + lua_pushinteger(L, x); + lua_pushinteger(L, y); + lua_pushinteger(L, z); + return 3; +} void delete_global(lua_State* L, const char* name) { lua_pushnil(L); @@ -40,11 +49,15 @@ bool rename_global(lua_State* L, const char* src, const char* dst) { return true; } -void call_func(lua_State* L, int argc, const std::string& name) { +int call_func(lua_State* L, int argc, const std::string& name) { if (lua_pcall(L, argc, LUA_MULTRET, 0)) { std::cerr << "Lua error in " << name << ": "; std::cerr << lua_tostring(L,-1) << std::endl; + return 0; } + int res_count = lua_tointeger(L, -1); + lua_pop(L, -1); + return res_count; } void scripting::initialize(EnginePaths* paths) { @@ -72,9 +85,10 @@ void scripting::initialize(EnginePaths* paths) { apilua::create_funcs(L); } -void scripting::on_world_load(Level* level) { +void scripting::on_world_load(Level* level, BlocksController* blocks) { scripting::level = level; scripting::content = level->content; + scripting::blocks = blocks; fs::path file = paths->getResources()/fs::path("scripts/world.lua"); std::string src = files::read_string(file); @@ -90,46 +104,61 @@ void scripting::on_world_quit() { void scripting::update_block(const Block* block, int x, int y, int z) { std::string name = block->name+".update"; lua_getglobal(L, name.c_str()); - lua_pushinteger(L, x); - lua_pushinteger(L, y); - lua_pushinteger(L, z); + lua_pushivec3(L, x, y, z); call_func(L, 3, name); } void scripting::random_update_block(const Block* block, int x, int y, int z) { std::string name = block->name+".randupdate"; lua_getglobal(L, name.c_str()); - lua_pushinteger(L, x); - lua_pushinteger(L, y); - lua_pushinteger(L, z); + lua_pushivec3(L, x, y, z); call_func(L, 3, name); } void scripting::on_block_placed(Player* player, const Block* block, int x, int y, int z) { std::string name = block->name+".placed"; lua_getglobal(L, name.c_str()); - lua_pushinteger(L, x); - lua_pushinteger(L, y); - lua_pushinteger(L, z); - call_func(L, 3, name); + lua_pushivec3(L, x, y, z); + lua_pushinteger(L, 1); + call_func(L, 4, name); } void scripting::on_block_broken(Player* player, const Block* block, int x, int y, int z) { std::string name = block->name+".broken"; lua_getglobal(L, name.c_str()); - lua_pushinteger(L, x); - lua_pushinteger(L, y); - lua_pushinteger(L, z); - call_func(L, 3, name); + lua_pushivec3(L, x, y, z); + lua_pushinteger(L, 1); + call_func(L, 4, name); } void scripting::on_block_interact(Player* player, const Block* block, int x, int y, int z) { std::string name = block->name+".oninteract"; lua_getglobal(L, name.c_str()); - lua_pushinteger(L, x); - lua_pushinteger(L, y); - lua_pushinteger(L, z); - call_func(L, 3, name); + lua_pushivec3(L, x, y, z); + lua_pushinteger(L, 1); + call_func(L, 4, name); +} + +bool scripting::on_item_use_on_block(Player* player, const ItemDef* item, int x, int y, int z) { + std::string name = item->name+".useon"; + lua_getglobal(L, name.c_str()); + lua_pushivec3(L, x, y, z); + lua_pushinteger(L, 1); + if (call_func(L, 4, name)) { + return lua_toboolean(L, -1); + } + return false; +} + +bool scripting::on_item_break_block(Player* player, const ItemDef* item, int x, int y, int z) { + std::string name = item->name+".blockbreakby"; + lua_getglobal(L, name.c_str()); + lua_pushivec3(L, x, y, z); + lua_pushinteger(L, 1); + if (call_func(L, 4, name)) { + return lua_toboolean(L, -1); + } + return false; } // todo: refactor @@ -159,6 +188,8 @@ void scripting::load_item_script(std::string prefix, fs::path file, item_funcs_s } call_func(L, 0, "