From 38b75c212b140f23cff8b5f4ff2ad73e3315a922 Mon Sep 17 00:00:00 2001 From: Nicole Collings <100Toby1@gmail.com> Date: Tue, 28 Jul 2020 14:11:11 -0700 Subject: [PATCH] Synchronize block interaction callbacks, wieldlists, etc. Breaking broke --- assets/base/script/game/init.lua | 1 + assets/base/script/game/player_interact.lua | 63 +++++++++ src/CMakeLists.txt | 11 +- src/game/entity/engine/BlockCrackEntity.cpp | 8 +- src/game/entity/engine/BlockCrackEntity.h | 1 + src/game/hud/DebugGui.cpp | 32 +++-- src/game/scene/GameScene.cpp | 4 +- src/game/scene/world/LocalWorld.cpp | 123 ++++++++---------- src/game/scene/world/LocalWorld.h | 28 ++-- src/game/scene/world/Player.cpp | 68 ++++------ src/game/scene/world/Player.h | 14 +- src/game/scene/world/World.cpp | 28 +++- src/game/scene/world/World.h | 25 +++- src/lua/LocalLuaParser.cpp | 5 +- src/lua/ServerLuaParser.cpp | 7 +- src/lua/ServerLuaParser.h | 5 +- src/lua/modules/BaseModule.cpp | 8 -- src/lua/modules/BaseModule.h | 4 +- src/lua/modules/Block.cpp | 16 +++ src/lua/modules/Block.h | 4 + src/lua/usertype/BaseUsertype.h | 19 +++ src/lua/usertype/LocalLuaPlayer.cpp | 10 +- src/lua/usertype/ServerLuaPlayer.cpp | 10 +- src/lua/usertype/SubgameUsertype.h | 19 +++ src/lua/usertype/Target.cpp | 27 ++++ src/lua/usertype/Target.h | 26 ++++ src/net/PacketType.h | 5 +- src/net/client/ClientNetworkInterpreter.cpp | 18 ++- src/net/client/ClientNetworkInterpreter.h | 18 ++- src/net/server/Server.cpp | 53 +++++--- src/net/server/conn/ServerClient.cpp | 42 ++++-- src/net/server/conn/ServerClient.h | 12 +- src/net/server/world/ServerWorld.cpp | 28 +++- src/net/server/world/ServerWorld.h | 8 +- src/world/PointedThing.h | 38 ------ src/world/Target.cpp | 13 ++ src/world/Target.h | 24 ++++ .../mods/aurailus_crazyblocks/script/init.lua | 1 + test/CMakeLists.txt | 11 +- 39 files changed, 563 insertions(+), 274 deletions(-) create mode 100644 assets/base/script/game/player_interact.lua delete mode 100644 src/lua/modules/BaseModule.cpp create mode 100644 src/lua/usertype/BaseUsertype.h create mode 100644 src/lua/usertype/SubgameUsertype.h create mode 100644 src/lua/usertype/Target.cpp create mode 100644 src/lua/usertype/Target.h delete mode 100644 src/world/PointedThing.h create mode 100644 src/world/Target.cpp create mode 100644 src/world/Target.h diff --git a/assets/base/script/game/init.lua b/assets/base/script/game/init.lua index e8b8b0eb..ce0355ed 100644 --- a/assets/base/script/game/init.lua +++ b/assets/base/script/game/init.lua @@ -1,4 +1,5 @@ runfile(_PATH .. "models/init") +runfile(_PATH .. "player_interact") runfile(_PATH .. "inventory") runfile(_PATH .. "tools") diff --git a/assets/base/script/game/player_interact.lua b/assets/base/script/game/player_interact.lua new file mode 100644 index 00000000..5ff26168 --- /dev/null +++ b/assets/base/script/game/player_interact.lua @@ -0,0 +1,63 @@ +-- zepha.block_interact_or_place(player: Player , target: Target [, stack: ItemStack]): ItemStack, Vector | nil +-- Calls zepha.block_interact if the targeted block can be interacted with, returns the passed in stack or wield stack and nil. +-- Otherwise, calls zepha.block_place and returned the function's returned values. +function zepha.block_interact_or_place(player, target, stack) + local stack = stack or player:get_wield_stack() + local target_block = zepha.get_block(target.pos) + local target_def = zepha.registered_blocks[target_block] + local stack_def = zepha.registered_blocks[stack and stack.name or nil] + + if target_def and (target_def.on_interact or target_def.on_interact_client) then + -- Trigger an interaction if the targeted block has one. + zepha.block_interact(player, target) + return stack, nil + end + + -- Return if stack isn't a block. + if stack == nil or stack_def == nil then return stack, nil end + + -- Place a block using the passed in stack. + return zepha.block_place(player, target, stack) +end + +-- zepha.block_interact(player: Player, target: Target): nil +-- Interacts with the targeted block. Returns true if the block has an on_interact or +-- on_interact_client callback, returns false otherwise. +function zepha.block_interact(player, target) + local block = zepha.get_block(target.pos) + local def = zepha.registered_blocks[block] + + local cb = zepha.server and "on_interact" or "on_interact_client" + if type(def[cb]) == "function" then def[cb](target.pos, player) end + zepha.trigger(cb, target.pos, player) + + return def.on_interact or def.on_interact_client +end + +-- zepha.block_place(player: Player, target: Target [, stack: ItemStack]): ItemStack, Vector | nil +-- Attempts to place `stack` or the wield stack in the world, on success returning the +-- wield stack with one count removed, and the placed position, or on failure returning the +-- original stack and nil. +function zepha.block_place(player, target, stack) + local stack = stack or player:get_wield_stack() + local stack_def = zepha.registered_blocks[stack and stack.name or nil] + if stack == nil or stack_def == nil then return stack, nil end + + zepha.set_block(target.pos_above, stack.name) + + stack.count = stack.count - 1 + return stack, target.pos_above +end + +function zepha.block_hit(player, target) + local block = zepha.get_block(target.pos) + local def = zepha.registered_blocks[block] + + -- Don't do anything, return a small timeout to avoid spamming the function. + if not def then return 0, 0.1 end + + local damage, timeout = zepha.get_hit_impact(player, block) + zepha.block_damage_add(target.pos, damage) + + return damage, timeout +end \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f550dd14..20874a4f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,4 @@ -set(ZEPHA_SRC +add_library(Zepha_Core def/DefinitionAtlas.cpp def/DefinitionAtlas.h def/gen/BiomeAtlas.cpp @@ -200,8 +200,7 @@ set(ZEPHA_SRC lua/LuaMod.h lua/LuaParser.cpp lua/LuaParser.h - lua/modules/BaseModule.cpp - lua/modules/BaseModule.h + lua/modules/BaseModule.h lua/modules/Block.cpp lua/modules/Block.h lua/modules/create_structure.h @@ -321,9 +320,7 @@ set(ZEPHA_SRC world/fs/FileManipulator.h world/LocalDimension.cpp world/LocalDimension.h - world/PointedThing.h + world/Target.h world/ServerDimension.cpp world/ServerDimension.h -) - -add_library (Zepha_Core ${ZEPHA_SRC}) \ No newline at end of file + lua/usertype/Target.cpp lua/usertype/Target.h lua/usertype/BaseUsertype.h lua/usertype/SubgameUsertype.h world/Target.cpp) \ No newline at end of file diff --git a/src/game/entity/engine/BlockCrackEntity.cpp b/src/game/entity/engine/BlockCrackEntity.cpp index 2a0649d5..5506921c 100644 --- a/src/game/entity/engine/BlockCrackEntity.cpp +++ b/src/game/entity/engine/BlockCrackEntity.cpp @@ -58,6 +58,12 @@ void BlockCrackEntity::addDamage(double damage) { update(); } +void BlockCrackEntity::setDamage(double damage) { + double diff = damage - (this->damage + damagePending); + std::cout << diff << ", " << this->damage << ", " << damagePending << std::endl; + addDamage(diff); +} + void BlockCrackEntity::addFaces(unsigned int &indOffset, std::vector &vertices, std::vector &indices, std::vector &meshParts) { for (const MeshPart& mp : meshParts) { glm::vec4 uv; @@ -81,4 +87,4 @@ void BlockCrackEntity::addFaces(unsigned int &indOffset, std::vector(game.textures.maxTextureSlots) * 100) << "%)" << std::endl << std::endl; - PointedThing thing = player.getPointedThing(); - if (thing.thing == PointedThing::Thing::BLOCK) { - EVec faceDir = thing.target.block.face; - + Target thing = player.getPointedThing(); + if (thing.type == Target::Type::BLOCK) { std::string face = - faceDir == EVec::TOP ? "TOP" : - faceDir == EVec::BOTTOM ? "BOTTOM" : - faceDir == EVec::LEFT ? "LEFT" : - faceDir == EVec::RIGHT ? "RIGHT" : - faceDir == EVec::FRONT ? "FRONT" : - faceDir == EVec::BACK ? "BACK" : - "NONE" ; + thing.face == EVec::TOP ? "TOP" : + thing.face == EVec::BOTTOM ? "BOTTOM" : + thing.face == EVec::LEFT ? "LEFT" : + thing.face == EVec::RIGHT ? "RIGHT" : + thing.face == EVec::FRONT ? "FRONT" : + thing.face == EVec::BACK ? "BACK" : + "NONE" ; - str << "Pointing At: " << game.defs->blockFromId(thing.target.block.blockId).identifier << std::endl; - str << "Pointed Position: " << vecToString(thing.target.block.pos) << std::endl; + str << "Pointing At: " << game.defs->blockFromId(world.getBlock(thing.pos)).identifier << std::endl; + str << "Pointed Position: " << vecToString(thing.pos) << std::endl; str << "Pointed Face: " << face << std::endl; } else { @@ -163,12 +161,12 @@ void DebugGui::update(Player& player, LocalWorld& world, LocalSubgame& game, dou } { //Crosshair Text - PointedThing thing = player.getPointedThing(); + Target target = player.getPointedThing(); std::ostringstream crossText; - if (thing.thing == PointedThing::Thing::BLOCK) { - crossText << game.defs->blockFromId(thing.target.block.blockId).name - << " (" << game.defs->blockFromId(thing.target.block.blockId).identifier << ")" << std::endl; + if (target.type == Target::Type::BLOCK) { + crossText << game.defs->blockFromId(world.getBlock(target.pos)).name + << " (" << game.defs->blockFromId(world.getBlock(target.pos)).identifier << ")" << std::endl; } get("crosshairText")->setText(crossText.str()); } diff --git a/src/game/scene/GameScene.cpp b/src/game/scene/GameScene.cpp index 5d7dcfb5..00af0fe0 100644 --- a/src/game/scene/GameScene.cpp +++ b/src/game/scene/GameScene.cpp @@ -14,7 +14,7 @@ GameScene::GameScene(ClientState& state) : Scene(state), game(state.defs), world(game, &net), net(state.connection, game, player), - player(world, game, state.renderer, refs), + player(game, world, state.renderer, refs, net), debugGui(state.renderer.window.getSize(), game) { namespace ph = std::placeholders; @@ -23,7 +23,7 @@ GameScene::GameScene(ClientState& state) : Scene(state), r.sendTo(state.connection.getPeer(), PacketChannel::CONNECT); world.init(&player); - net .init(&world, std::bind(&LocalInventoryRefs::packetReceived, refs, ph::_1)); + net .init(&world, Util::bind_this(&refs, &LocalInventoryRefs::packetReceived)); game .init(world, player, state); refs .init(); diff --git a/src/game/scene/world/LocalWorld.cpp b/src/game/scene/world/LocalWorld.cpp index 99ccf563..fb7e5e16 100644 --- a/src/game/scene/world/LocalWorld.cpp +++ b/src/game/scene/world/LocalWorld.cpp @@ -9,23 +9,24 @@ #include "WorldInterpolationStream.h" #include "../../../world/chunk/Chunk.h" #include "../../../def/item/BlockDef.h" -#include "../../../def/gen/LocalBiomeAtlas.h" -#include "../../../def/LocalDefinitionAtlas.h" -#include "../../../lua/LocalLuaParser.h" +#include "../../../lua/usertype/Target.h" +#include "../../../lua/usertype/LuaItemStack.h" +#include "../../inventory/LocalInventoryList.h" #include "../../entity/engine/ParticleEntity.h" #include "../../entity/engine/BlockCrackEntity.h" #include "../../../lua/usertype/LocalLuaPlayer.h" #include "../../../net/client/ClientNetworkInterpreter.h" LocalWorld::LocalWorld(LocalSubgame& defs, ClientNetworkInterpreter* server) : - defs(defs), - net(server), - dimension(defs) {} + World(defs), + game(defs), + net(server), + dimension(defs) {} void LocalWorld::init(Player* player) { this->player = player; delete worldGenStream; - worldGenStream = new WorldInterpolationStream(55, defs); + worldGenStream = new WorldInterpolationStream(55, game); } void LocalWorld::update(double delta) { @@ -61,61 +62,49 @@ void LocalWorld::setBlock(glm::ivec3 pos, unsigned int block) { dimension.setBlock(pos, block); } -void LocalWorld::blockPlace(glm::vec3 pos, unsigned int block) { - if (block == LocalDefinitionAtlas::AIR) { - auto& def = defs.defs->blockFromId(getBlock(pos)); - if (def.callbacks.count(Callback::BREAK_CLIENT)) - defs.lua->safe_function(def.callbacks[Callback::BREAK_CLIENT], pos); - } - else { - auto& def = defs.defs->blockFromId(block); - if (def.callbacks.count(Callback::PLACE_CLIENT)) - defs.lua->safe_function(def.callbacks[Callback::PLACE_CLIENT], pos); - } - - net->blockPlace(pos, block); - dimension.setBlock(pos, block); -} - -void LocalWorld::blockBreak(glm::vec3 pos) { - blockPlace(pos, DefinitionAtlas::AIR); -} - -void LocalWorld::blockInteract(PointedThing &thing) { - auto& def = defs.defs->blockFromId(getBlock(thing.target.block.pos)); - - if (def.callbacks.count(Callback::INTERACT_CLIENT)) - defs.lua->safe_function(def.callbacks[Callback::INTERACT_CLIENT], thing.target.block.pos); - - net->blockInteract(thing.target.block.pos); -} - -double LocalWorld::blockHit(PointedThing& thing) { - glm::ivec3 pos = thing.target.block.pos; - - auto& blockDef = defs.defs->blockFromId(getBlock(thing.target.block.pos)); - - double damage = 0, timeout = 0; - sol::tie(damage, timeout) = defs.lua->safe_function(defs.lua->core["get_hit_impact"], - defs.lua->core.get("player"), blockDef.identifier); - - if (damage == 0) return timeout; +double LocalWorld::setBlockDamage(glm::ivec3 pos, double damage) { + double totalDamage = World::setBlockDamage(pos, damage); BlockCrackEntity* block = nullptr; - for (auto test : crackedBlocks) if (glm::ivec3(test->getPos()) == pos) { block = test; break; } - if (block == nullptr) { - block = new BlockCrackEntity(blockDef, defs.textures, pos); - crackedBlocks.push_back(block); - } - - block->addDamage(damage); + if (crackEntities.count(pos)) block = crackEntities[pos]; + else block = new BlockCrackEntity(game.defs->blockFromId(getBlock(pos)), game.textures, pos); + block->setDamage(damage); block->time = 0; -// auto def = defs.defs.blockFromId(getBlock(pos)); -// for (int i = 0; i < 40 * damage; i++) { -// auto p = new ParticleEntity(pos, def); -// particles.push_back(p); -// } + return totalDamage; +} + +void LocalWorld::blockPlace(Target& target) { + std::tuple, sol::optional> res = game.lua->safe_function( + game.lua->core["block_place"], LocalLuaPlayer(*player), Api::Usertype::Target(target)); + + auto stack = std::get>(res); + if (stack) player->getWieldList()->setStack(player->getWieldIndex(), ItemStack(*stack, game.getDefs())); + net->blockPlace(target); +} + +void LocalWorld::blockInteract(Target &target) { + game.lua->safe_function(game.lua->core["block_interact"], + LocalLuaPlayer(*player), Api::Usertype::Target(target)); + + net->blockInteract(target); +} + +void LocalWorld::blockPlaceOrInteract(Target &target) { + std::tuple, sol::optional> res = game.lua->safe_function( + game.lua->core["block_interact_or_place"], LocalLuaPlayer(*player), Api::Usertype::Target(target)); + + auto stack = std::get>(res); + if (stack) player->getWieldList()->setStack(player->getWieldIndex(), ItemStack(*stack, game.getDefs())); + net->blockPlaceOrInteract(target); +} + +double LocalWorld::blockHit(Target& target) { + double timeout = 0, damage = 0; + sol::tie(damage, timeout) = game.lua->safe_function(game.lua->core["block_hit"], + LocalLuaPlayer(*player), Api::Usertype::Target(target)); + +// net->blockHit(target); return timeout; } @@ -143,24 +132,26 @@ int LocalWorld::renderChunks(Renderer &renderer) { } void LocalWorld::renderEntities(Renderer &renderer) { - for (auto block : crackedBlocks) block->draw(renderer); - for (auto &p : particles) p->draw(renderer); + for (auto& block : crackEntities) block.second->draw(renderer); + for (auto& particle : particles) particle->draw(renderer); dimension.renderEntities(renderer); } void LocalWorld::updateBlockDamages(double delta) { - auto it = crackedBlocks.cbegin(); - while (it != crackedBlocks.cend()) { + auto it = crackEntities.cbegin(); + while (it != crackEntities.cend()) { bool deleteMe = false; auto curr = it++; - auto block = *curr; + auto block = curr->second; block->time += delta; if (block->damage >= block->maxHealth) { - blockBreak(block->getPos()); + //Todo: Lua callback~ + setBlock(block->getPos(), DefinitionAtlas::AIR); + setBlockDamage(block->getPos(), 0); deleteMe = true; } @@ -175,8 +166,8 @@ void LocalWorld::updateBlockDamages(double delta) { } if (deleteMe) { - delete *curr; - it = crackedBlocks.erase(curr); + delete block; + it = crackEntities.erase(curr); } else block->update(); } diff --git a/src/game/scene/world/LocalWorld.h b/src/game/scene/world/LocalWorld.h index a4354002..e7dc1b1b 100644 --- a/src/game/scene/world/LocalWorld.h +++ b/src/game/scene/world/LocalWorld.h @@ -8,14 +8,15 @@ #include "../../../world/LocalDimension.h" +class Target; +class Player; +class Renderer; +class ItemStack; +class LocalSubgame; +class ParticleEntity; +class BlockCrackEntity; class ClientNetworkInterpreter; class WorldInterpolationStream; -class BlockCrackEntity; -class ParticleEntity; -class PointedThing; -class LocalSubgame; -class Renderer; -class Player; class LocalWorld : public World { public: @@ -24,17 +25,20 @@ public: void init(Player* player); void update(double delta) override; + void createDimension(std::string identifier); + void loadWorldPacket(std::unique_ptr p); void commitChunk(std::shared_ptr chunk); unsigned int getBlock(glm::ivec3 pos) override; void setBlock(glm::ivec3 pos, unsigned int block) override; - void blockPlace(glm::vec3 pos, unsigned int block); - void blockBreak(glm::vec3 pos); + double setBlockDamage(glm::ivec3 pos, double damage) override; - void blockInteract(PointedThing& thing); - double blockHit(PointedThing& thing); + void blockPlace(Target& target); + void blockPlaceOrInteract(Target& target); + void blockInteract(Target& target); + double blockHit(Target& target); unsigned short getBiome(glm::vec3 pos); std::shared_ptr getChunk(glm::ivec3 pos); @@ -43,7 +47,7 @@ public: int renderChunks(Renderer &render); void renderEntities(Renderer &renderer); - LocalSubgame& defs; + LocalSubgame& game; LocalDimension dimension; int mapBlocksInterpolated = 0; @@ -52,7 +56,7 @@ private: void finishChunks(); void updateBlockDamages(double delta); - std::vector crackedBlocks; + std::unordered_map crackEntities; std::vector particles; Player* player = nullptr; diff --git a/src/game/scene/world/Player.cpp b/src/game/scene/world/Player.cpp index bcc7da22..06e71372 100644 --- a/src/game/scene/world/Player.cpp +++ b/src/game/scene/world/Player.cpp @@ -8,23 +8,23 @@ #include "../../../util/Ray.h" #include "../../graph/Renderer.h" #include "../../../def/ItemDef.h" -#include "../../../net/Serializer.h" #include "../../../net/Deserializer.h" #include "../../../def/item/BlockDef.h" #include "../../../world/chunk/Chunk.h" #include "../../inventory/LocalInventory.h" -#include "../../../def/LocalDefinitionAtlas.h" #include "../../inventory/LocalInventoryList.h" #include "../../../net/client/NetPlayerField.h" +#include "../../../net/client/ClientNetworkInterpreter.h" -Player::Player(LocalWorld& world, LocalSubgame& defs, Renderer& renderer, LocalInventoryRefs& refs) : - Collidable(world, defs, {{-0.3, 0, -0.3}, {0.3, 1.8, 0.3}}), +Player::Player(LocalSubgame &game, LocalWorld &world, Renderer &renderer, LocalInventoryRefs &refs, ClientNetworkInterpreter& net) : + Collidable(world, game, {{-0.3, 0, -0.3}, {0.3, 1.8, 0.3}}), + net(net), refs(refs), - game(defs), + game(game), renderer(renderer), wireframe({}, 0.01, {1, 1, 1}), - gameGui(refs, renderer.window.getSize(), defs, renderer) { + gameGui(refs, renderer.window.getSize(), game, renderer) { handItemModel.parent = &handModel; renderer.window.addResizeCallback("player", [&](glm::ivec2 win) { @@ -186,27 +186,25 @@ void Player::findPointedThing(Input &input) { auto face = sBox.intersects(rayEnd, roundedPos); if (face != EVec::NONE) { - pointedThing.thing = PointedThing::Thing::BLOCK; - pointedThing.target.block = { blockID, roundedPos, face }; + target = Target(roundedPos, face); return; } } } - pointedThing.thing = PointedThing::Thing::NOTHING; - pointedThing.target.nothing = 0; + target = Target {}; } void Player::updateWireframe() { if (!gameGui.isVisible()) { wireframe.setVisible(false); } - else if (pointedThing.thing == PointedThing::Thing::BLOCK) { - auto& boxes = game.defs->blockFromId(pointedThing.target.block.blockId).sBoxes; - float distance = glm::distance(pos, glm::vec3(pointedThing.target.block.pos) + glm::vec3(0.5)); + else if (target.type == Target::Type::BLOCK) { + auto& boxes = game.defs->blockFromId(world.getBlock(target.pos)).sBoxes; + float distance = glm::distance(pos, target.pos + glm::vec3(0.5)); wireframe.updateMesh(boxes, 0.002f + distance * 0.0014f); - wireframe.setPos(pointedThing.target.block.pos); + wireframe.setPos(target.pos); wireframe.setVisible(true); } else { @@ -215,23 +213,12 @@ void Player::updateWireframe() { } void Player::interact(Input& input, double delta) { - if (pointedThing.thing == PointedThing::Thing::BLOCK) { + if (target.type == Target::Type::BLOCK) { if (input.mouseDown(GLFW_MOUSE_BUTTON_LEFT) && breakTime == 0) { - breakInterval = world.blockHit(pointedThing); + breakInterval = world.blockHit(target); breakTime += delta; } - else if (input.mousePressed(GLFW_MOUSE_BUTTON_RIGHT)) { - auto& target = game.defs->blockFromId(world.getBlock(pointedThing.target.block.pos)); - - if (target.hasInteraction()) world.blockInteract(pointedThing); - else if (wieldItem > DefinitionAtlas::AIR && game.defs->fromId(wieldItem).type == ItemDef::Type::BLOCK) { - world.blockPlace(pointedThing.target.block.pos + SelectionBox::faceToOffset(pointedThing.target.block.face), wieldItem); - } - else { - //TODO: Item interactions. -// world.itemUse(pointedThing, activeItem); - } - } + else if (input.mousePressed(GLFW_MOUSE_BUTTON_RIGHT)) world.blockPlaceOrInteract(target); } if (breakTime > 0) breakTime += delta; @@ -249,7 +236,7 @@ glm::vec3 Player::getPos() { void Player::setPos(glm::vec3 pos, bool assert) { this->pos = pos; this->renderer.camera.setPos({pos.x, pos.y + EYE_HEIGHT, pos.z}); - if (assert) assertField(NetPlayerField::POSITION, pos); + if (assert) net.assertPlayerField(NetPlayerField::POSITION, pos); } glm::vec3 Player::getVel() { @@ -258,7 +245,7 @@ glm::vec3 Player::getVel() { void Player::setVel(glm::vec3 vel, bool assert) { this->vel = vel; - if (assert) assertField(NetPlayerField::VELOCITY, vel); + if (assert) net.assertPlayerField(NetPlayerField::VELOCITY, vel); } float Player::getYaw() { @@ -267,7 +254,7 @@ float Player::getYaw() { void Player::setYaw(float yaw, bool assert) { this->yaw = yaw; - if (assert) assertField(NetPlayerField::YAW, yaw); + if (assert) net.assertPlayerField(NetPlayerField::YAW, yaw); } float Player::getPitch() { @@ -276,7 +263,7 @@ float Player::getPitch() { void Player::setPitch(float pitch, bool assert) { this->pitch = pitch; - if (assert) assertField(NetPlayerField::PITCH, pitch); + if (assert) net.assertPlayerField(NetPlayerField::PITCH, pitch); } bool Player::isFlying() { @@ -285,11 +272,11 @@ bool Player::isFlying() { void Player::setFlying(bool flying, bool assert) { this->flying = flying; - if (assert) assertField(NetPlayerField::FLYING, flying); + if (assert) net.assertPlayerField(NetPlayerField::FLYING, flying); } -PointedThing& Player::getPointedThing() { - return pointedThing; +Target& Player::getPointedThing() { + return target; } LocalInventory& Player::getInventory() { @@ -313,7 +300,7 @@ void Player::setWieldList(const std::string& list, bool assert) { refs.setWieldList(list); setWieldIndex(wieldIndex); updateWieldAndHandItems(); - if (assert) assertField(NetPlayerField::WIELD_INV, list); + if (assert) net.assertPlayerField(NetPlayerField::WIELD_INV, list); } unsigned short Player::getWieldIndex() { @@ -324,7 +311,7 @@ void Player::setWieldIndex(unsigned short index, bool assert) { auto wieldList = refs.getWieldList(); wieldIndex = index % std::max((wieldList ? wieldList->getLength() : 1), 1); updateWieldAndHandItems(); - if (assert) assertField(NetPlayerField::WIELD_INV, static_cast(index)); + if (assert) net.assertPlayerField(NetPlayerField::WIELD_INDEX, static_cast(index)); } /* @@ -386,13 +373,6 @@ void Player::updateWieldAndHandItems() { handItemModel.setModel(model); } -template -void Player::assertField(NetPlayerField field, T data) { - std::cout << "attempt to assert field" << std::endl; -// Serializer().append(static_cast(field)).append(data) -// .packet(PacketType::THIS_PLAYER_INFO).sendTo(peer, PacketChannel::PLAYER); -} - void Player::handleAssertion(Deserializer &d) { while (!d.atEnd()) { switch (static_cast(d.read())) { diff --git a/src/game/scene/world/Player.h b/src/game/scene/world/Player.h index c5217bce..12093296 100644 --- a/src/game/scene/world/Player.h +++ b/src/game/scene/world/Player.h @@ -8,7 +8,7 @@ #include "../../graph/drawable/Drawable.h" #include "../../hud/GameGui.h" -#include "../../../world/PointedThing.h" +#include "../../../world/Target.h" #include "../../entity/engine/WireframeEntity.h" class Input; @@ -22,8 +22,8 @@ class Player : Collidable, public Drawable { public: enum class PlayerControl { FORWARD, LEFT, BACKWARD, RIGHT, - JUMP, MOD1, MOD2 - }; + JUMP, MOD1, MOD2 }; + static constexpr float MOUSE_SENSITIVITY = 0.1f; static constexpr float LOOK_DISTANCE = 6.5f; static constexpr float LOOK_PRECISION = 0.01f; @@ -31,7 +31,7 @@ public: static constexpr float BASE_MOVE_SPEED = 4.3f; static constexpr float JUMP_VEL = 0.14f; - Player(LocalWorld& world, LocalSubgame& defs, Renderer& renderer, LocalInventoryRefs& refs); + Player(LocalSubgame &game, LocalWorld &world, Renderer &renderer, LocalInventoryRefs &refs, ClientNetworkInterpreter& net); void update(Input &input, double delta, glm::vec2 mouseDelta); ~Player(); @@ -68,7 +68,7 @@ public: void setHud(std::shared_ptr hud); std::shared_ptr getHud(); - PointedThing& getPointedThing(); + Target& getPointedThing(); void setHudVisible(bool hudVisible); void draw(Renderer& renderer) override; @@ -90,9 +90,9 @@ private: void interact(Input& input, double delta); void updateWieldAndHandItems(); - template void assertField(NetPlayerField field, T data); LocalSubgame& game; + ClientNetworkInterpreter& net; Renderer& renderer; GameGui gameGui; @@ -112,6 +112,6 @@ private: double breakTime = 0; double breakInterval = 0; - PointedThing pointedThing; + Target target; }; diff --git a/src/game/scene/world/World.cpp b/src/game/scene/world/World.cpp index d59878ce..8bd35e53 100644 --- a/src/game/scene/world/World.cpp +++ b/src/game/scene/world/World.cpp @@ -2,4 +2,30 @@ // Created by aurailus on 2020-01-09. // -#include "World.h" \ No newline at end of file +#include "World.h" + +#include "../../../def/Subgame.h" +#include "../../../def/item/BlockDef.h" +#include "../../../def/DefinitionAtlas.h" + +World::World(Subgame &game) : game(game) {} + +double World::getBlockDamage(glm::ivec3 pos) const { + return blockDamages.count(pos) ? blockDamages.at(pos).curr : 0; +} + +double World::setBlockDamage(glm::ivec3 pos, double damage) { + if (blockDamages.count(pos)) blockDamages[pos].curr = damage; + else blockDamages.insert({pos, Damage { damage, static_cast(game.getDefs().blockFromId(getBlock(pos)).health)}}); + return getBlockDamage(pos); +} + +void World::updateBlockDamages() { + for (auto it = blockDamages.begin(); it != blockDamages.end(); ) { + if (it->second.curr > it->second.max) { + setBlock(it->first, DefinitionAtlas::AIR); + it = blockDamages.erase(it); + } + else it++; + } +} diff --git a/src/game/scene/world/World.h b/src/game/scene/world/World.h index a0d23302..ee5fda62 100644 --- a/src/game/scene/world/World.h +++ b/src/game/scene/world/World.h @@ -4,14 +4,37 @@ #pragma once +#include +#include #include +#include + +#include "../../../util/Vec.h" + +class Subgame; +class Dimension; class World { public: - explicit World() = default; + explicit World(Subgame& game); virtual void update(double delta) = 0; +// virtual Dimension& getDimension() = 0; + virtual unsigned int getBlock(glm::ivec3 pos) = 0; virtual void setBlock(glm::ivec3 pos, unsigned int block) = 0; + + virtual double getBlockDamage(glm::ivec3 pos) const; + virtual double setBlockDamage(glm::ivec3 pos, double damage); + +protected: + void updateBlockDamages(); + + std::map> dimensions; + + struct Damage { double curr, max; }; + std::unordered_map blockDamages; + + Subgame& game; }; diff --git a/src/lua/LocalLuaParser.cpp b/src/lua/LocalLuaParser.cpp index ed489582..81f1c6ec 100644 --- a/src/lua/LocalLuaParser.cpp +++ b/src/lua/LocalLuaParser.cpp @@ -19,15 +19,14 @@ #include "usertype/cLuaEntity.h" #include "usertype/cInventoryRef.h" #include "usertype/cAnimationManager.h" +#include "usertype/Target.h" // Modules #include "modules/Time.h" #include "modules/Block.h" #include "modules/Entity.h" #include "modules/Register.h" - #include "modules/create_structure.h" -#include "LuaMod.h" LocalLuaParser::LocalLuaParser(LocalSubgame& game): LuaParser(game), game(game), keybinds(this) {} @@ -68,6 +67,8 @@ void LocalLuaParser::loadApi(LocalSubgame &defs, LocalWorld &world, Player& play ClientApi::item_stack (lua); ClientApi::gui_element (lua); + Api::Usertype::Target::bind(Api::State::CLIENT, lua, core); + core["client"] = true; core["player"] = LocalLuaPlayer(player); diff --git a/src/lua/ServerLuaParser.cpp b/src/lua/ServerLuaParser.cpp index 660a74b4..05ffa484 100644 --- a/src/lua/ServerLuaParser.cpp +++ b/src/lua/ServerLuaParser.cpp @@ -19,6 +19,7 @@ #include "usertype/sLuaEntity.h" #include "usertype/sInventoryRef.h" #include "usertype/cItemStack.h" +#include "usertype/Target.h" // Modules #include "modules/Time.h" @@ -98,11 +99,13 @@ void ServerLuaParser::loadApi(ServerSubgame &defs, ServerWorld &world) { ServerApi::inventory (lua); ClientApi::item_stack (lua); + Api::Usertype::Target::bind(Api::State::SERVER, lua, core); + core["server"] = true; core["players"] = lua.create_table(); // Modules - modules.emplace_back(std::make_unique(Api::State::CLIENT, lua, core)); + modules.emplace_back(std::make_unique(Api::State::SERVER, lua, core)); modules.emplace_back(std::make_unique(Api::State::SERVER, core, game, world)); modules.emplace_back(std::make_unique(Api::State::SERVER, core, game, world)); modules.emplace_back(std::make_unique(Api::State::SERVER, core, game, world)); @@ -122,7 +125,7 @@ void ServerLuaParser::registerDefs(ServerSubgame &defs) { RegisterBiomes::server(core, defs); } -sol::protected_function_result ServerLuaParser::errorCallback(sol::protected_function_result errPfr) { +sol::protected_function_result ServerLuaParser::errorCallback(sol::protected_function_result errPfr) const { sol::error err = errPfr; std::string errString = err.what(); diff --git a/src/lua/ServerLuaParser.h b/src/lua/ServerLuaParser.h index c43b61d1..de1679fa 100644 --- a/src/lua/ServerLuaParser.h +++ b/src/lua/ServerLuaParser.h @@ -26,15 +26,16 @@ public: void playerConnected(std::shared_ptr client); void playerDisconnected(std::shared_ptr client); - template void safe_function(sol::protected_function f, Args... args) { + template sol::safe_function_result safe_function(sol::protected_function f, Args... args) const { auto res = f(args...); if (!res.valid()) errorCallback(res); + return res; } private: void loadApi(ServerSubgame& defs, ServerWorld& world); void registerDefs(ServerSubgame &defs); - sol::protected_function_result errorCallback(sol::protected_function_result errPfr); + sol::protected_function_result errorCallback(sol::protected_function_result errPfr) const; sol::protected_function_result runFileSandboxed(const std::string& file); ServerSubgame& game; diff --git a/src/lua/modules/BaseModule.cpp b/src/lua/modules/BaseModule.cpp deleted file mode 100644 index 03879f4d..00000000 --- a/src/lua/modules/BaseModule.cpp +++ /dev/null @@ -1,8 +0,0 @@ -// -// Created by aurailus on 2020-07-26. -// - -#include "BaseModule.h" - -Api::Module::BaseModule::BaseModule(Api::State state, sol::state& lua, sol::table& core) : - state(state), lua(lua), core(core) {} diff --git a/src/lua/modules/BaseModule.h b/src/lua/modules/BaseModule.h index 54b88bab..42c62904 100644 --- a/src/lua/modules/BaseModule.h +++ b/src/lua/modules/BaseModule.h @@ -12,7 +12,9 @@ namespace Api { namespace Module { class BaseModule { public: - BaseModule(State state, sol::state& lua, sol::table& core); + BaseModule(State state, sol::state& lua, sol::table& core) : + state(state), lua(lua), core(core) {} + virtual void bind() = 0; protected: diff --git a/src/lua/modules/Block.cpp b/src/lua/modules/Block.cpp index 0ff8de76..73c1c646 100644 --- a/src/lua/modules/Block.cpp +++ b/src/lua/modules/Block.cpp @@ -14,6 +14,10 @@ void Api::Module::Block::bind() { core.set_function("get_block", Util::bind_this(this, &Block::getBlock)); core.set_function("set_block", Util::bind_this(this, &Block::setBlock)); core.set_function("remove_block", [&](glm::ivec3 pos) { setBlock(pos, "air"); }); + + core.set_function("block_damage_get", Util::bind_this(this, &Block::damageGet)); + core.set_function("block_damage_set", Util::bind_this(this, &Block::damageSet)); + core.set_function("block_damage_add", Util::bind_this(this, &Block::damageAdd)); } std::string Api::Module::Block::getBlock(glm::ivec3 pos) { @@ -23,3 +27,15 @@ std::string Api::Module::Block::getBlock(glm::ivec3 pos) { void Api::Module::Block::setBlock(glm::ivec3 pos, const std::string &identifier) { world.setBlock(pos, game.getDefs().fromStr(identifier).index); } + +double Api::Module::Block::damageGet(glm::ivec3 pos) { + return world.getBlockDamage(pos); +} + +double Api::Module::Block::damageSet(glm::ivec3 pos, double damage) { + return world.setBlockDamage(pos, damage); +} + +double Api::Module::Block::damageAdd(glm::ivec3 pos, double damage) { + return world.setBlockDamage(pos, world.getBlockDamage(pos) + damage); +} diff --git a/src/lua/modules/Block.h b/src/lua/modules/Block.h index 9830120c..a5deb822 100644 --- a/src/lua/modules/Block.h +++ b/src/lua/modules/Block.h @@ -17,5 +17,9 @@ namespace Api::Module { protected: std::string getBlock(glm::ivec3 pos); void setBlock(glm::ivec3 pos, const std::string& identifier); + + double damageGet(glm::ivec3 pos); + double damageSet(glm::ivec3 pos, double damage); + double damageAdd(glm::ivec3 pos, double damage); }; } \ No newline at end of file diff --git a/src/lua/usertype/BaseUsertype.h b/src/lua/usertype/BaseUsertype.h new file mode 100644 index 00000000..0c98a812 --- /dev/null +++ b/src/lua/usertype/BaseUsertype.h @@ -0,0 +1,19 @@ +// +// Created by aurailus on 2020-07-27. +// + +#pragma once + +#include + +#include "../modules/BaseModule.h" + +namespace Api { + namespace Usertype { + class BaseUsertype { + public: + BaseUsertype() = default; + static void bind(State state, sol::state& lua, sol::table& core) {}; + }; + } +} \ No newline at end of file diff --git a/src/lua/usertype/LocalLuaPlayer.cpp b/src/lua/usertype/LocalLuaPlayer.cpp index 209af2e7..2c621e28 100644 --- a/src/lua/usertype/LocalLuaPlayer.cpp +++ b/src/lua/usertype/LocalLuaPlayer.cpp @@ -89,9 +89,9 @@ sol::object LocalLuaPlayer::get_wield_list(sol::this_state s) { } void LocalLuaPlayer::set_wield_list(sol::optional list) { - if (!list) player.setWieldList(""); - else if (list->is()) player.setWieldList(list->as()); - else if (list->is()) player.setWieldList(list->as().get_name()); + if (!list) player.setWieldList("", true); + else if (list->is()) player.setWieldList(list->as(), true); + else if (list->is()) player.setWieldList(list->as().get_name(), true); else throw "Attempted to set wield list to nil."; } @@ -100,7 +100,7 @@ unsigned int LocalLuaPlayer::get_wield_index() { } void LocalLuaPlayer::set_wield_index(unsigned int index) { - player.setWieldIndex(index - 1); + player.setWieldIndex(index - 1, true); } sol::object LocalLuaPlayer::get_wield_stack(sol::this_state s) { @@ -110,7 +110,7 @@ sol::object LocalLuaPlayer::get_wield_stack(sol::this_state s) { } void LocalLuaPlayer::set_flying(bool shouldFly) { - player.setFlying(shouldFly); + player.setFlying(shouldFly, true); } bool LocalLuaPlayer::get_flying() { diff --git a/src/lua/usertype/ServerLuaPlayer.cpp b/src/lua/usertype/ServerLuaPlayer.cpp index 62ca6176..442752f8 100644 --- a/src/lua/usertype/ServerLuaPlayer.cpp +++ b/src/lua/usertype/ServerLuaPlayer.cpp @@ -74,8 +74,8 @@ sol::object ServerLuaPlayer::get_hand_list(sol::this_state s) { void ServerLuaPlayer::set_hand_list(sol::object list) { if (!list) player.setHandList(nullptr); - else if (list.is()) player.setHandList((*player.getInventory())[list.as()], true); - else if (list.is()) player.setHandList((*player.getInventory())[list.as().get_name()], true); + else if (list.is()) player.setHandList(list.as(), true); + else if (list.is()) player.setHandList(list.as().get_name(), true); else throw "Attempted to set hand list to nil."; } @@ -92,9 +92,9 @@ sol::object ServerLuaPlayer::get_wield_list(sol::this_state s) { } void ServerLuaPlayer::set_wield_list(sol::object list) { - if (!list) player.setWieldList(nullptr); - else if (list.is()) player.setWieldList((*player.getInventory())[list.as()], true); - else if (list.is()) player.setWieldList((*player.getInventory())[list.as().get_name()], true); + if (!list) player.setWieldList(nullptr, true); + else if (list.is()) player.setWieldList(list.as(), true); + else if (list.is()) player.setWieldList(list.as().get_name(), true); else throw "Attempted to set wield list to nil."; } diff --git a/src/lua/usertype/SubgameUsertype.h b/src/lua/usertype/SubgameUsertype.h new file mode 100644 index 00000000..e96cf3d3 --- /dev/null +++ b/src/lua/usertype/SubgameUsertype.h @@ -0,0 +1,19 @@ +// +// Created by aurailus on 2020-07-27. +// + +#pragma once + +#include "BaseUsertype.h" + +class State; + +namespace Api { + namespace Usertype { + class SubgameUsertype : public BaseUsertype { + public: + SubgameUsertype() = default; + static void bind(State state, sol::state& lua, sol::table& core) {}; + }; + } +} \ No newline at end of file diff --git a/src/lua/usertype/Target.cpp b/src/lua/usertype/Target.cpp new file mode 100644 index 00000000..b113a020 --- /dev/null +++ b/src/lua/usertype/Target.cpp @@ -0,0 +1,27 @@ +// +// Created by aurailus on 2020-07-27. +// + +#include "Target.h" + +#include "../Lua.h" + +Api::Usertype::Target::Target(const ::Target &target) : + pos(target.pos), + type(target.type), + pos_above(target.getAbovePos()) {} + +std::string Api::Usertype::Target::getType() { + return type == ::Target::Type::BLOCK ? "block" : + type == ::Target::Type::ENTITY ? "entity" : + "nothing"; +} + +void Api::Usertype::Target::bind(State, sol::state &lua, sol::table &core) { + lua.new_usertype("Target", + "type", sol::property(&Target::getType), + + "pos", sol::readonly(&Target::pos), + "pos_above", sol::readonly(&Target::pos_above) + ); +} \ No newline at end of file diff --git a/src/lua/usertype/Target.h b/src/lua/usertype/Target.h new file mode 100644 index 00000000..2f49e64a --- /dev/null +++ b/src/lua/usertype/Target.h @@ -0,0 +1,26 @@ +// +// Created by aurailus on 2020-07-27. +// + +#pragma once + +#include + +#include "SubgameUsertype.h" +#include "../../world/Target.h" + +namespace Api::Usertype { + class Target : public SubgameUsertype { + public: + Target(const ::Target& target); + + std::string getType(); + + ::Target::Type type; + + glm::ivec3 pos; + glm::ivec3 pos_above; + + static void bind(State state, sol::state& lua, sol::table& core); + }; +} diff --git a/src/net/PacketType.h b/src/net/PacketType.h index 9881a9d5..a6ef3f46 100644 --- a/src/net/PacketType.h +++ b/src/net/PacketType.h @@ -28,8 +28,11 @@ enum class PacketType { MAPBLOCK, // Block - BLOCK_SET, + BLOCK_PLACE, BLOCK_INTERACT, + BLOCK_PLACE_OR_INTERACT, + + BLOCK_SET, // Entity ENTITY_INFO, diff --git a/src/net/client/ClientNetworkInterpreter.cpp b/src/net/client/ClientNetworkInterpreter.cpp index b63511bd..a686257d 100644 --- a/src/net/client/ClientNetworkInterpreter.cpp +++ b/src/net/client/ClientNetworkInterpreter.cpp @@ -11,7 +11,6 @@ #include "../NetHandler.h" #include "../../util/Log.h" #include "NetPlayerField.h" -#include "ServerConnection.h" #include "../../game/entity/Model.h" #include "../../game/scene/world/Player.h" #include "../../game/scene/world/LocalWorld.h" @@ -128,14 +127,19 @@ void ClientNetworkInterpreter::receivedPacket(std::unique_ptr p) { } } -void ClientNetworkInterpreter::blockPlace(glm::ivec3 pos, unsigned int block) { - Serializer().append(pos).append(block).packet(PacketType::BLOCK_SET) - .sendTo(connection.getPeer(), PacketChannel::INTERACT); +void ClientNetworkInterpreter::blockPlace(Target &target) { + Serializer().append(target.pos).append(static_cast(target.face)) + .packet(PacketType::BLOCK_PLACE).sendTo(connection.getPeer(), PacketChannel::INTERACT); } -void ClientNetworkInterpreter::blockInteract(glm::ivec3 pos) { - Serializer().append(pos).packet(PacketType::BLOCK_INTERACT) - .sendTo(connection.getPeer(), PacketChannel::INTERACT); +void ClientNetworkInterpreter::blockInteract(Target &target) { + Serializer().append(target.pos).append(static_cast(target.face)) + .packet(PacketType::BLOCK_INTERACT).sendTo(connection.getPeer(), PacketChannel::INTERACT); +} + +void ClientNetworkInterpreter::blockPlaceOrInteract(Target &target) { + Serializer().append(target.pos).append(static_cast(target.face)) + .packet(PacketType::BLOCK_PLACE_OR_INTERACT).sendTo(connection.getPeer(), PacketChannel::INTERACT); } void ClientNetworkInterpreter::invWatch(const std::string& inv, const std::string& list) { diff --git a/src/net/client/ClientNetworkInterpreter.h b/src/net/client/ClientNetworkInterpreter.h index 6b8a0c6d..d7c10a88 100644 --- a/src/net/client/ClientNetworkInterpreter.h +++ b/src/net/client/ClientNetworkInterpreter.h @@ -8,12 +8,16 @@ #include #include +#include "../Serializer.h" +#include "ServerConnection.h" + class Model; class Player; +class Target; class LocalWorld; -class LocalSubgame; class PacketView; -class ServerConnection; +class LocalSubgame; +enum class NetPlayerField; class ClientNetworkInterpreter { public: @@ -23,14 +27,20 @@ public: void init(LocalWorld* world, std::function)> invCallback); void update(); - void blockPlace(glm::ivec3 pos, unsigned int block); - void blockInteract(glm::ivec3 pos); + void blockPlace(Target& target); + void blockInteract(Target& target); + void blockPlaceOrInteract(Target& target); void invWatch(const std::string& inv, const std::string& list); void invUnwatch(const std::string& inv, const std::string& list); void invInteractPrimary(const std::string& inv, const std::string& list, unsigned short ind); void invInteractSecondary(const std::string& inv, const std::string& list, unsigned short ind); + template void assertPlayerField(NetPlayerField field, T data) { + Serializer().append(static_cast(field)).append(data) + .packet(PacketType::THIS_PLAYER_INFO).sendTo(connection.getPeer(), PacketChannel::INTERACT); + } + int recvPackets = 0; int serverSideChunkGens = 0; private: diff --git a/src/net/server/Server.cpp b/src/net/server/Server.cpp index 01378bd1..ff123651 100644 --- a/src/net/server/Server.cpp +++ b/src/net/server/Server.cpp @@ -8,13 +8,10 @@ #include "Server.h" #include "../Serializer.h" -#include "../PacketView.h" -#include "../../util/Log.h" #include "../../util/Timer.h" #include "../PacketChannel.h" +#include "../../world/Target.h" #include "../../def/item/BlockDef.h" -#include "../../def/ServerDefinitionAtlas.h" -#include "../../lua/ServerLuaParser.h" #include "../../lua/usertype/ServerLuaPlayer.h" Server::Server(unsigned short port, const std::string& subgame) : @@ -114,16 +111,20 @@ void Server::handlePlayerPacket(ServerClient& client, PacketView& p) { switch (p.type) { default: { std::cout << Log::err << "Invalid packet type (" << static_cast(p.type) << ") recieved." << Log::endl; - break; - } + break; } + case PacketType::PLAYER_INFO: { client.setPos(p.d.read()); client.setPitch(p.d.read()); client.setYaw(p.d.read()); playersUpdated.emplace(client.cid); - break; - } + break; } + + case PacketType::THIS_PLAYER_INFO: { + client.handleAssertion(p.d); + break; } + case PacketType::BLOCK_SET: { glm::ivec3 pos = p.d.read(); unsigned int block = p.d.read(); @@ -155,14 +156,26 @@ void Server::handlePlayerPacket(ServerClient& client, PacketView& p) { defs.lua->safe_function(def.callbacks[Callback::AFTER_PLACE], pos, ServerLuaPlayer(client)); defs.lua->safe_function(defs.lua->core["trigger"], "after_place", pos, ServerLuaPlayer(client)); } - break; - } + break; } + + case PacketType::BLOCK_PLACE: { + glm::ivec3 pos = p.d.read(); + auto face = static_cast(p.d.read()); + world.blockPlace(Target(pos, face), client); + break; } + case PacketType::BLOCK_INTERACT: { glm::ivec3 pos = p.d.read(); - auto& def = defs.defs->blockFromId(world.getBlock(pos)); - if (def.callbacks.count(Callback::INTERACT)) defs.lua->safe_function(def.callbacks[Callback::INTERACT], pos, ServerLuaPlayer(client)); - break; - } + auto face = static_cast(p.d.read()); + world.blockInteract(Target(pos, face), client); + break; } + + case PacketType::BLOCK_PLACE_OR_INTERACT: { + glm::ivec3 pos = p.d.read(); + auto face = static_cast(p.d.read()); + world.blockPlaceOrInteract(Target(pos, face), client); + break; } + case PacketType::INV_WATCH: { std::string source = p.d.read(); std::string list = p.d.read(); @@ -173,8 +186,8 @@ void Server::handlePlayerPacket(ServerClient& client, PacketView& p) { bool exists = refs.addWatcher(source, list, client.cid); if (!exists) Serializer().append(source).append(list) .packet(PacketType::INV_INVALID).sendTo(client.peer, PacketChannel::INVENTORY); - break; - } + break; } + case PacketType::INV_UNWATCH: { std::string source = p.d.read(); std::string list = p.d.read(); @@ -189,10 +202,9 @@ void Server::handlePlayerPacket(ServerClient& client, PacketView& p) { break; } - break; - } - case PacketType::INV_INTERACT: { + break; } + case PacketType::INV_INTERACT: { unsigned short type = p.d.read(); std::string source = p.d.read(); @@ -205,8 +217,7 @@ void Server::handlePlayerPacket(ServerClient& client, PacketView& p) { if (type == 0) refs.primaryInteract(source, list, ind, client.cid); else refs.secondaryInteract(source, list, ind, client.cid); - break; - } + break; } } } diff --git a/src/net/server/conn/ServerClient.cpp b/src/net/server/conn/ServerClient.cpp index 9aa16e1a..dc493ca2 100644 --- a/src/net/server/conn/ServerClient.cpp +++ b/src/net/server/conn/ServerClient.cpp @@ -8,6 +8,7 @@ #include "../../Packet.h" #include "../../Serializer.h" +#include "../../Deserializer.h" #include "../../client/NetPlayerField.h" #include "../../../game/inventory/InventoryRefs.h" @@ -77,21 +78,26 @@ std::shared_ptr ServerClient::getInventory() { } std::shared_ptr ServerClient::getHandList() { - return handList; + return (*inventory)[handList]; } -void ServerClient::setHandList(std::shared_ptr list, bool assert) { - handList = list; - if (assert) assertField(NetPlayerField::HAND_INV, handList ? handList->getName() : ""); +void ServerClient::setHandList(const std::string& list, bool assert) { + if (list.empty() || !(*inventory)[list]) this->handList = ""; + else this->handList = list; + + if (assert) assertField(NetPlayerField::HAND_INV, this->handList); } std::shared_ptr ServerClient::getWieldList() { - return wieldList; + return (*inventory)[wieldList]; } -void ServerClient::setWieldList(std::shared_ptr list, bool assert) { - wieldList = list; - if (assert) assertField(NetPlayerField::WIELD_INV, wieldList ? wieldList->getName() : ""); +void ServerClient::setWieldList(const std::string& list, bool assert) { + if (list.empty() || !(*inventory)[list]) this->wieldList = ""; + else this->wieldList = list; + + if (assert) assertField(NetPlayerField::WIELD_INV, this->wieldList); + setWieldIndex(wieldIndex, assert); } unsigned short ServerClient::getWieldIndex() { @@ -99,10 +105,28 @@ unsigned short ServerClient::getWieldIndex() { } void ServerClient::setWieldIndex(unsigned short index, bool assert) { + auto wieldList = (*inventory)[this->wieldList]; wieldIndex = index % (wieldList ? wieldList->getLength() : 1); if (assert) assertField(NetPlayerField::WIELD_INDEX, static_cast(wieldIndex)); } +void ServerClient::handleAssertion(Deserializer &d) { + while (!d.atEnd()) { + switch (static_cast(d.read())) { + case NetPlayerField::POSITION: setPos(d.read()); break; + case NetPlayerField::VELOCITY: setVel(d.read()); break; + case NetPlayerField::PITCH: setPitch(d.read()); break; + case NetPlayerField::YAW: setYaw(d.read()); break; + + case NetPlayerField::FLYING: setFlying(d.read()); break; + + case NetPlayerField::HAND_INV: setHandList(d.read()); break; + case NetPlayerField::WIELD_INV: setWieldList(d.read()); break; + case NetPlayerField::WIELD_INDEX: setWieldIndex(d.read()); break; + } + } +} + //void ServerClient::setMapBlockIntegrity(glm::ivec3 pos, unsigned long long integrity) { // mapBlockIntegrity[pos] = integrity; //} @@ -116,4 +140,4 @@ template void ServerClient::assertField(NetPlayerField field, T data) { Serializer().append(static_cast(field)).append(data) .packet(PacketType::THIS_PLAYER_INFO).sendTo(peer, PacketChannel::INTERACT); -} +} \ No newline at end of file diff --git a/src/net/server/conn/ServerClient.h b/src/net/server/conn/ServerClient.h index f8fd5286..ac51c29c 100644 --- a/src/net/server/conn/ServerClient.h +++ b/src/net/server/conn/ServerClient.h @@ -14,6 +14,7 @@ #include "../../../game/inventory/ServerInventoryList.h" enum class NetPlayerField; +class Deserializer; class InventoryRefs; class ServerClient { @@ -42,14 +43,16 @@ public: std::shared_ptr getInventory(); std::shared_ptr getHandList(); - void setHandList(std::shared_ptr list, bool assert = false); + void setHandList(const std::string& list, bool assert = false); std::shared_ptr getWieldList(); - void setWieldList(std::shared_ptr list, bool assert = false); + void setWieldList(const std::string& list, bool assert = false); unsigned short getWieldIndex(); void setWieldIndex(unsigned short index, bool assert = false); + void handleAssertion(Deserializer& d); + // void setMapBlockIntegrity(glm::ivec3 pos, unsigned long long integrity); // unsigned long long getMapBlockIntegrity(glm::ivec3 pos); @@ -76,8 +79,9 @@ private: std::shared_ptr inventory; unsigned int wieldIndex = 0; - std::shared_ptr handList = nullptr; - std::shared_ptr wieldList = nullptr; + + std::string handList = ""; + std::string wieldList = ""; unsigned int handItem = DefinitionAtlas::AIR; unsigned int wieldItem = DefinitionAtlas::AIR; diff --git a/src/net/server/world/ServerWorld.cpp b/src/net/server/world/ServerWorld.cpp index 34960ede..6d5fc4c0 100644 --- a/src/net/server/world/ServerWorld.cpp +++ b/src/net/server/world/ServerWorld.cpp @@ -17,12 +17,15 @@ #include "../../../def/ServerSubgame.h" #include "../../../def/item/BlockDef.h" #include "../../../world/chunk/Chunk.h" +#include "../../../lua/usertype/Target.h" #include "../../../world/chunk/MapBlock.h" #include "../../../world/fs/FileManipulator.h" -#include "../../../def/ServerDefinitionAtlas.h" +#include "../../../lua/usertype/LuaItemStack.h" #include "../../../lua/usertype/ServerLuaEntity.h" +#include "../../../lua/usertype/ServerLuaPlayer.h" ServerWorld::ServerWorld(unsigned int seed, ServerSubgame& game, ClientList& clients) : + World(game), clientList(clients), dimension(game), seed(seed), @@ -68,7 +71,7 @@ void ServerWorld::init(const std::string& worldDir) { generateMapBlock({0, 0, 0}); } -void ServerWorld::update(double delta) { +void ServerWorld::update(double) { dimension.update(clientList.clients, mapBlockGenRange); std::unordered_set updatedChunks {}; @@ -253,6 +256,27 @@ void ServerWorld::setBlock(glm::ivec3 pos, unsigned int block) { } } +void ServerWorld::blockPlace(const Target &target, ServerClient &client) { + std::tuple, sol::optional> res = game.lua->safe_function( + game.lua->core["block_place"], ServerLuaPlayer(client), Api::Usertype::Target(target)); + + auto stack = std::get>(res); + if (stack) client.getWieldList()->setStack(client.getWieldIndex(), ItemStack(*stack, game.getDefs())); +} + +void ServerWorld::blockInteract(const Target &target, ServerClient &client) { + game.lua->safe_function(game.lua->core["block_interact"], + ServerLuaPlayer(client), Api::Usertype::Target(target)); +} + +void ServerWorld::blockPlaceOrInteract(const Target &target, ServerClient &client) { + std::tuple, sol::optional> res = game.lua->safe_function( + game.lua->core["block_interact_or_place"], ServerLuaPlayer(client), Api::Usertype::Target(target)); + + auto stack = std::get>(res); + if (stack) client.getWieldList()->setStack(client.getWieldIndex(), ItemStack(*stack, game.getDefs())); +} + bool ServerWorld::isInBounds(glm::ivec3 cPos, std::pair &bounds) { return (cPos.x >= bounds.first.x && cPos.x <= bounds.second.x && cPos.y >= bounds.first.y && cPos.y <= bounds.second.y diff --git a/src/net/server/world/ServerWorld.h b/src/net/server/world/ServerWorld.h index f45b9518..4688a71d 100644 --- a/src/net/server/world/ServerWorld.h +++ b/src/net/server/world/ServerWorld.h @@ -10,9 +10,11 @@ #include "../../../world/ServerDimension.h" -class ServerSubgame; +class Target; +class ItemStack; class ClientList; class ServerClient; +class ServerSubgame; class FileManipulator; class ServerGenStream; class ServerPacketStream; @@ -27,6 +29,10 @@ public: unsigned int getBlock(glm::ivec3 pos) override; void setBlock(glm::ivec3 pos, unsigned int block) override; + void blockPlace(const Target& target, ServerClient& client); + void blockPlaceOrInteract(const Target& target, ServerClient& client); + void blockInteract(const Target& target, ServerClient& client); + ServerDimension dimension; private: void changedMapBlocks(ServerClient& client); diff --git a/src/world/PointedThing.h b/src/world/PointedThing.h deleted file mode 100644 index 183472eb..00000000 --- a/src/world/PointedThing.h +++ /dev/null @@ -1,38 +0,0 @@ -// -// Created by aurailus on 13/05/19. -// - -#pragma once - -#include "../util/Vec.h" - -class PointedThing { -public: - enum class Thing { - ENTITY, - BLOCK, - NOTHING - }; - - struct PointedBlock { - unsigned int blockId; - glm::ivec3 pos; - EVec face; - }; - - struct PointedEntity { - //TODO; - }; - - typedef union { - PointedBlock block; - PointedEntity entity; - unsigned short nothing; - } PointedThingTarget; - - PointedThing() = default; - PointedThing(const PointedThing &o) = default; - - Thing thing = PointedThing::Thing::NOTHING; - PointedThingTarget target = PointedThingTarget{0}; -}; diff --git a/src/world/Target.cpp b/src/world/Target.cpp new file mode 100644 index 00000000..0ebec11f --- /dev/null +++ b/src/world/Target.cpp @@ -0,0 +1,13 @@ +// +// Created by aurailus on 2020-07-27. +// + +#include "Target.h" + +#include "../def/item/SelectionBox.h" + +Target::Target(glm::ivec3 pos, EVec face) : type(Type::BLOCK), pos(pos), face(face) {} + +glm::ivec3 Target::getAbovePos() const { + return glm::ivec3(pos) + SelectionBox::faceToOffset(face); +} diff --git a/src/world/Target.h b/src/world/Target.h new file mode 100644 index 00000000..9e684e73 --- /dev/null +++ b/src/world/Target.h @@ -0,0 +1,24 @@ +// +// Created by aurailus on 13/05/19. +// + +#pragma once + +#include "../util/Vec.h" + +class Target { +public: + enum class Type { ENTITY, BLOCK, NOTHING }; + + Target() = default; + Target(const Target &o) = default; + Target(glm::ivec3 pos, EVec face); + + glm::ivec3 getAbovePos() const; + +public: + Type type = Target::Type::NOTHING; + + glm::vec3 pos {}; + EVec face = EVec::NONE; +}; diff --git a/subgames/zeus/mods/aurailus_crazyblocks/script/init.lua b/subgames/zeus/mods/aurailus_crazyblocks/script/init.lua index 31985c46..8c983a3a 100644 --- a/subgames/zeus/mods/aurailus_crazyblocks/script/init.lua +++ b/subgames/zeus/mods/aurailus_crazyblocks/script/init.lua @@ -27,6 +27,7 @@ zepha.register_block("@aurailus:crazyblocks:inventory", { if zepha.server then zepha.bind("new_player", function(player) + player:get_inventory():get_list("hot_wheel_1"):add_stack({"zeus:default:dirt", 32}) player:get_inventory():get_list("hot_wheel_1"):add_stack({"@aurailus:crazyblocks:stacker", 1}) player:get_inventory():get_list("hot_wheel_1"):add_stack({"@aurailus:crazyblocks:inventory", 1}) player:get_inventory():get_list("hot_wheel_1"):add_stack({"@aurailus:crazyblocks:box", 1}) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 323256ce..9487940a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,4 +1,7 @@ -set(ZEPHA_TEST - Main.cpp tests/TestSpace.cpp tests/TestBlockChunk.cpp tests/TestSerializer.cpp tests/TestBlockChunkSerialization.cpp) - -add_library (Zepha_Test ${ZEPHA_TEST}) \ No newline at end of file +add_library(Zepha_Test + Main.cpp + tests/TestSpace.cpp + tests/TestBlockChunk.cpp + tests/TestSerializer.cpp + tests/TestBlockChunkSerialization.cpp +) \ No newline at end of file