Synchronize block interaction callbacks, wieldlists, etc. Breaking broke

master
Nicole Collings 2020-07-28 14:11:11 -07:00
parent ad029752ef
commit 38b75c212b
39 changed files with 563 additions and 274 deletions

View File

@ -1,4 +1,5 @@
runfile(_PATH .. "models/init")
runfile(_PATH .. "player_interact")
runfile(_PATH .. "inventory")
runfile(_PATH .. "tools")

View File

@ -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

View File

@ -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})
lua/usertype/Target.cpp lua/usertype/Target.h lua/usertype/BaseUsertype.h lua/usertype/SubgameUsertype.h world/Target.cpp)

View File

@ -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<EntityVertex> &vertices, std::vector<unsigned int> &indices, std::vector<MeshPart> &meshParts) {
for (const MeshPart& mp : meshParts) {
glm::vec4 uv;
@ -81,4 +87,4 @@ void BlockCrackEntity::addFaces(unsigned int &indOffset, std::vector<EntityVerte
indOffset += mp.vertices.size();
}
}
}

View File

@ -18,6 +18,7 @@ public:
void update();
void addDamage(double damage);
void setDamage(double damage);
int maxHealth = 0;
double damage = 0;

View File

@ -138,21 +138,19 @@ void DebugGui::update(Player& player, LocalWorld& world, LocalSubgame& game, dou
str << "Texture Slots: " << game.textures.textureSlotsUsed << " / " << game.textures.maxTextureSlots
<< " (" << round(game.textures.textureSlotsUsed / static_cast<float>(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<GuiText>("crosshairText")->setText(crossText.str());
}

View File

@ -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();

View File

@ -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<LocalLuaPlayer>("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<LuaItemStack>, sol::optional<glm::vec3>> res = game.lua->safe_function(
game.lua->core["block_place"], LocalLuaPlayer(*player), Api::Usertype::Target(target));
auto stack = std::get<sol::optional<LuaItemStack>>(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<LuaItemStack>, sol::optional<glm::vec3>> res = game.lua->safe_function(
game.lua->core["block_interact_or_place"], LocalLuaPlayer(*player), Api::Usertype::Target(target));
auto stack = std::get<sol::optional<LuaItemStack>>(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();
}

View File

@ -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<PacketView> p);
void commitChunk(std::shared_ptr<Chunk> 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<Chunk> 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<BlockCrackEntity*> crackedBlocks;
std::unordered_map<glm::ivec3, BlockCrackEntity*, Vec::ivec3> crackEntities;
std::vector<ParticleEntity*> particles;
Player* player = nullptr;

View File

@ -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<unsigned short>(index));
if (assert) net.assertPlayerField(NetPlayerField::WIELD_INDEX, static_cast<unsigned short>(index));
}
/*
@ -386,13 +373,6 @@ void Player::updateWieldAndHandItems() {
handItemModel.setModel(model);
}
template <typename T>
void Player::assertField(NetPlayerField field, T data) {
std::cout << "attempt to assert field" << std::endl;
// Serializer().append(static_cast<unsigned int>(field)).append<T>(data)
// .packet(PacketType::THIS_PLAYER_INFO).sendTo(peer, PacketChannel::PLAYER);
}
void Player::handleAssertion(Deserializer &d) {
while (!d.atEnd()) {
switch (static_cast<NetPlayerField>(d.read<unsigned int>())) {

View File

@ -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<LuaGuiElement> hud);
std::shared_ptr<LuaGuiElement> 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 <typename T> 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;
};

View File

@ -2,4 +2,30 @@
// Created by aurailus on 2020-01-09.
//
#include "World.h"
#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<double>(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++;
}
}

View File

@ -4,14 +4,37 @@
#pragma once
#include <map>
#include <memory>
#include <glm/vec3.hpp>
#include <unordered_map>
#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<std::string, std::shared_ptr<Dimension>> dimensions;
struct Damage { double curr, max; };
std::unordered_map<glm::ivec3, Damage, Vec::ivec3> blockDamages;
Subgame& game;
};

View File

@ -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);

View File

@ -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::Module::Time>(Api::State::CLIENT, lua, core));
modules.emplace_back(std::make_unique<Api::Module::Time>(Api::State::SERVER, lua, core));
modules.emplace_back(std::make_unique<Api::Module::Block>(Api::State::SERVER, core, game, world));
modules.emplace_back(std::make_unique<Api::Module::Entity>(Api::State::SERVER, core, game, world));
modules.emplace_back(std::make_unique<Api::Module::Register>(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();

View File

@ -26,15 +26,16 @@ public:
void playerConnected(std::shared_ptr<ServerClient> client);
void playerDisconnected(std::shared_ptr<ServerClient> client);
template<typename... Args> void safe_function(sol::protected_function f, Args... args) {
template<typename... Args> 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;

View File

@ -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) {}

View File

@ -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:

View File

@ -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);
}

View File

@ -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);
};
}

View File

@ -0,0 +1,19 @@
//
// Created by aurailus on 2020-07-27.
//
#pragma once
#include <sol/forward.hpp>
#include "../modules/BaseModule.h"
namespace Api {
namespace Usertype {
class BaseUsertype {
public:
BaseUsertype() = default;
static void bind(State state, sol::state& lua, sol::table& core) {};
};
}
}

View File

@ -89,9 +89,9 @@ sol::object LocalLuaPlayer::get_wield_list(sol::this_state s) {
}
void LocalLuaPlayer::set_wield_list(sol::optional<sol::object> list) {
if (!list) player.setWieldList("");
else if (list->is<std::string>()) player.setWieldList(list->as<std::string>());
else if (list->is<LocalLuaInventoryList>()) player.setWieldList(list->as<LocalLuaInventoryList>().get_name());
if (!list) player.setWieldList("", true);
else if (list->is<std::string>()) player.setWieldList(list->as<std::string>(), true);
else if (list->is<LocalLuaInventoryList>()) player.setWieldList(list->as<LocalLuaInventoryList>().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() {

View File

@ -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<std::string>()) player.setHandList((*player.getInventory())[list.as<std::string>()], true);
else if (list.is<ServerLuaInventoryList>()) player.setHandList((*player.getInventory())[list.as<ServerLuaInventoryList>().get_name()], true);
else if (list.is<std::string>()) player.setHandList(list.as<std::string>(), true);
else if (list.is<ServerLuaInventoryList>()) player.setHandList(list.as<ServerLuaInventoryList>().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<std::string>()) player.setWieldList((*player.getInventory())[list.as<std::string>()], true);
else if (list.is<ServerLuaInventoryList>()) player.setWieldList((*player.getInventory())[list.as<ServerLuaInventoryList>().get_name()], true);
if (!list) player.setWieldList(nullptr, true);
else if (list.is<std::string>()) player.setWieldList(list.as<std::string>(), true);
else if (list.is<ServerLuaInventoryList>()) player.setWieldList(list.as<ServerLuaInventoryList>().get_name(), true);
else throw "Attempted to set wield list to nil.";
}

View File

@ -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) {};
};
}
}

View File

@ -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>("Target",
"type", sol::property(&Target::getType),
"pos", sol::readonly(&Target::pos),
"pos_above", sol::readonly(&Target::pos_above)
);
}

26
src/lua/usertype/Target.h Normal file
View File

@ -0,0 +1,26 @@
//
// Created by aurailus on 2020-07-27.
//
#pragma once
#include <glm/vec3.hpp>
#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);
};
}

View File

@ -28,8 +28,11 @@ enum class PacketType {
MAPBLOCK,
// Block
BLOCK_SET,
BLOCK_PLACE,
BLOCK_INTERACT,
BLOCK_PLACE_OR_INTERACT,
BLOCK_SET,
// Entity
ENTITY_INFO,

View File

@ -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<PacketView> 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<glm::ivec3>(target.pos).append(static_cast<unsigned short>(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<glm::ivec3>(target.pos).append(static_cast<unsigned short>(target.face))
.packet(PacketType::BLOCK_INTERACT).sendTo(connection.getPeer(), PacketChannel::INTERACT);
}
void ClientNetworkInterpreter::blockPlaceOrInteract(Target &target) {
Serializer().append<glm::ivec3>(target.pos).append(static_cast<unsigned short>(target.face))
.packet(PacketType::BLOCK_PLACE_OR_INTERACT).sendTo(connection.getPeer(), PacketChannel::INTERACT);
}
void ClientNetworkInterpreter::invWatch(const std::string& inv, const std::string& list) {

View File

@ -8,12 +8,16 @@
#include <functional>
#include <glm/vec3.hpp>
#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<void(std::unique_ptr<PacketView>)> 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 <typename T> void assertPlayerField(NetPlayerField field, T data) {
Serializer().append(static_cast<unsigned int>(field)).append<T>(data)
.packet(PacketType::THIS_PLAYER_INFO).sendTo(connection.getPeer(), PacketChannel::INTERACT);
}
int recvPackets = 0;
int serverSideChunkGens = 0;
private:

View File

@ -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<int>(p.type) << ") recieved." << Log::endl;
break;
}
break; }
case PacketType::PLAYER_INFO: {
client.setPos(p.d.read<glm::vec3>());
client.setPitch(p.d.read<float>());
client.setYaw(p.d.read<float>());
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<glm::ivec3>();
unsigned int block = p.d.read<unsigned int>();
@ -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<glm::ivec3>();
auto face = static_cast<EVec>(p.d.read<unsigned short>());
world.blockPlace(Target(pos, face), client);
break; }
case PacketType::BLOCK_INTERACT: {
glm::ivec3 pos = p.d.read<glm::ivec3>();
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<EVec>(p.d.read<unsigned short>());
world.blockInteract(Target(pos, face), client);
break; }
case PacketType::BLOCK_PLACE_OR_INTERACT: {
glm::ivec3 pos = p.d.read<glm::ivec3>();
auto face = static_cast<EVec>(p.d.read<unsigned short>());
world.blockPlaceOrInteract(Target(pos, face), client);
break; }
case PacketType::INV_WATCH: {
std::string source = p.d.read<std::string>();
std::string list = p.d.read<std::string>();
@ -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>();
std::string list = p.d.read<std::string>();
@ -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<unsigned short>();
std::string source = p.d.read<std::string>();
@ -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; }
}
}

View File

@ -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<Inventory> ServerClient::getInventory() {
}
std::shared_ptr<InventoryList> ServerClient::getHandList() {
return handList;
return (*inventory)[handList];
}
void ServerClient::setHandList(std::shared_ptr<InventoryList> 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<InventoryList> ServerClient::getWieldList() {
return wieldList;
return (*inventory)[wieldList];
}
void ServerClient::setWieldList(std::shared_ptr<InventoryList> 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<unsigned short>(wieldIndex));
}
void ServerClient::handleAssertion(Deserializer &d) {
while (!d.atEnd()) {
switch (static_cast<NetPlayerField>(d.read<unsigned int>())) {
case NetPlayerField::POSITION: setPos(d.read<glm::vec3>()); break;
case NetPlayerField::VELOCITY: setVel(d.read<glm::vec3>()); break;
case NetPlayerField::PITCH: setPitch(d.read<float>()); break;
case NetPlayerField::YAW: setYaw(d.read<float>()); break;
case NetPlayerField::FLYING: setFlying(d.read<bool>()); break;
case NetPlayerField::HAND_INV: setHandList(d.read<std::string>()); break;
case NetPlayerField::WIELD_INV: setWieldList(d.read<std::string>()); break;
case NetPlayerField::WIELD_INDEX: setWieldIndex(d.read<unsigned short>()); break;
}
}
}
//void ServerClient::setMapBlockIntegrity(glm::ivec3 pos, unsigned long long integrity) {
// mapBlockIntegrity[pos] = integrity;
//}
@ -116,4 +140,4 @@ template <typename T>
void ServerClient::assertField(NetPlayerField field, T data) {
Serializer().append(static_cast<unsigned int>(field)).append<T>(data)
.packet(PacketType::THIS_PLAYER_INFO).sendTo(peer, PacketChannel::INTERACT);
}
}

View File

@ -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<Inventory> getInventory();
std::shared_ptr<InventoryList> getHandList();
void setHandList(std::shared_ptr<InventoryList> list, bool assert = false);
void setHandList(const std::string& list, bool assert = false);
std::shared_ptr<InventoryList> getWieldList();
void setWieldList(std::shared_ptr<InventoryList> 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> inventory;
unsigned int wieldIndex = 0;
std::shared_ptr<InventoryList> handList = nullptr;
std::shared_ptr<InventoryList> wieldList = nullptr;
std::string handList = "";
std::string wieldList = "";
unsigned int handItem = DefinitionAtlas::AIR;
unsigned int wieldItem = DefinitionAtlas::AIR;

View File

@ -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<glm::ivec3, Vec::ivec3> 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<LuaItemStack>, sol::optional<glm::vec3>> res = game.lua->safe_function(
game.lua->core["block_place"], ServerLuaPlayer(client), Api::Usertype::Target(target));
auto stack = std::get<sol::optional<LuaItemStack>>(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<LuaItemStack>, sol::optional<glm::vec3>> res = game.lua->safe_function(
game.lua->core["block_interact_or_place"], ServerLuaPlayer(client), Api::Usertype::Target(target));
auto stack = std::get<sol::optional<LuaItemStack>>(res);
if (stack) client.getWieldList()->setStack(client.getWieldIndex(), ItemStack(*stack, game.getDefs()));
}
bool ServerWorld::isInBounds(glm::ivec3 cPos, std::pair<glm::ivec3, glm::ivec3> &bounds) {
return (cPos.x >= bounds.first.x && cPos.x <= bounds.second.x
&& cPos.y >= bounds.first.y && cPos.y <= bounds.second.y

View File

@ -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);

View File

@ -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};
};

13
src/world/Target.cpp Normal file
View File

@ -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);
}

24
src/world/Target.h Normal file
View File

@ -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;
};

View File

@ -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})

View File

@ -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})
add_library(Zepha_Test
Main.cpp
tests/TestSpace.cpp
tests/TestBlockChunk.cpp
tests/TestSerializer.cpp
tests/TestBlockChunkSerialization.cpp
)