refactor players

This commit is contained in:
MihailRis 2024-11-22 16:17:13 +03:00
parent 7f41f95013
commit bd2acd5766
13 changed files with 101 additions and 151 deletions

View File

@ -1,23 +0,0 @@
#pragma once
#include <stdint.h>
#include <stdlib.h>
#include <iostream>
class Level;
class Object {
private:
public:
uint64_t objectUID;
bool shouldUpdate = true;
public:
~Object() { destroyed(); }
public:
virtual void spawned() { }
virtual void update(float delta) { }
virtual void destroyed() { }
};

View File

@ -5,7 +5,6 @@
#include "debug/Logger.hpp"
#include "engine.hpp"
#include "files/WorldFiles.hpp"
#include "interfaces/Object.hpp"
#include "objects/Entities.hpp"
#include "physics/Hitbox.hpp"
#include "settings.hpp"
@ -26,7 +25,7 @@ LevelController::LevelController(Engine* engine, std::unique_ptr<Level> levelPtr
*level, settings.chunks.padding.get()
)),
player(std::make_unique<PlayerController>(
settings, this->level.get(), blocks.get()
settings, level.get(), blocks.get()
)) {
scripting::on_world_load(this);
}
@ -45,11 +44,6 @@ void LevelController::update(float delta, bool input, bool pause) {
if (!pause) {
// update all objects that needed
for (const auto& obj : level->objects) {
if (obj && obj->shouldUpdate) {
obj->update(delta);
}
}
blocks->update(delta);
player->update(delta, input, pause);
level->entities->updatePhysics(delta);
@ -57,17 +51,6 @@ void LevelController::update(float delta, bool input, bool pause) {
}
level->entities->clean();
player->postUpdate(delta, input, pause);
// erease null pointers
auto& objects = level->objects;
objects.erase(
std::remove_if(
objects.begin(),
objects.end(),
[](auto obj) { return obj == nullptr; }
),
objects.end()
);
}
void LevelController::saveWorld() {

View File

@ -40,7 +40,7 @@ const float C_ZOOM = 0.1f;
const float CROUCH_SHIFT_Y = -0.2f;
CameraControl::CameraControl(
const std::shared_ptr<Player>& player, const CameraSettings& settings
Player* player, const CameraSettings& settings
)
: player(player),
camera(player->fpCamera),
@ -193,7 +193,7 @@ PlayerController::PlayerController(
BlocksController* blocksController
)
: settings(settings), level(level),
player(level->getObject<Player>(0)),
player(level->getPlayer(0)),
camControl(player, settings.camera),
blocksController(blocksController),
playerTickClock(20, 3) {
@ -215,7 +215,7 @@ void PlayerController::onFootstep(const Hitbox& hitbox) {
continue;
}
blocksController->onBlockInteraction(
player.get(),
player,
glm::ivec3(x, y, z),
def,
BlockInteraction::step
@ -254,7 +254,7 @@ void PlayerController::update(float delta, bool input, bool pause) {
if (playerTickClock.update(delta)) {
if (player->getId() % playerTickClock.getParts() ==
playerTickClock.getPart()) {
scripting::on_player_tick(player.get(), playerTickClock.getTickRate());
scripting::on_player_tick(player, playerTickClock.getTickRate());
}
}
}
@ -390,12 +390,12 @@ voxel* PlayerController::updateSelection(float maxDistance) {
if (selection.entity != prevEntity) {
if (prevEntity != ENTITY_NONE) {
if (auto pentity = level->entities->get(prevEntity)) {
scripting::on_aim_off(*pentity, player.get());
scripting::on_aim_off(*pentity, player);
}
}
if (selection.entity != ENTITY_NONE) {
if (auto pentity = level->entities->get(selection.entity)) {
scripting::on_aim_on(*pentity, player.get());
scripting::on_aim_on(*pentity, player);
}
}
}
@ -432,8 +432,8 @@ void PlayerController::processRightClick(const Block& def, const Block& target)
if (!input.shift && target.rt.funcsset.oninteract) {
if (scripting::on_block_interact(
player.get(), target, selection.actualPosition
)) {
player, target, selection.actualPosition
)) {
return;
}
}
@ -474,7 +474,7 @@ void PlayerController::processRightClick(const Block& def, const Block& target)
slot.setCount(slot.getCount()-1);
}
blocksController->placeBlock(
player.get(), def, state, coord.x, coord.y, coord.z
player, def, state, coord.x, coord.y, coord.z
);
}
}
@ -488,10 +488,10 @@ void PlayerController::updateEntityInteraction(
}
auto entity = *entityOpt;
if (lclick) {
scripting::on_attacked(entity, player.get(), player->getEntity());
scripting::on_attacked(entity, player, player->getEntity());
}
if (rclick) {
scripting::on_entity_used(entity, player.get());
scripting::on_entity_used(entity, player);
}
}
@ -523,7 +523,7 @@ void PlayerController::updateInteraction(float delta) {
auto vox = updateSelection(maxDistance);
if (vox == nullptr) {
if (rclick && item.rt.funcsset.on_use) {
scripting::on_item_use(player.get(), item);
scripting::on_item_use(player, item);
}
if (selection.entity) {
updateEntityInteraction(selection.entity, lattack, rclick);
@ -534,7 +534,7 @@ void PlayerController::updateInteraction(float delta) {
auto iend = selection.position;
if (lclick && !input.shift && item.rt.funcsset.on_block_break_by) {
if (scripting::on_item_break_block(
player.get(), item, iend.x, iend.y, iend.z
player, item, iend.x, iend.y, iend.z
)) {
return;
}
@ -543,7 +543,7 @@ void PlayerController::updateInteraction(float delta) {
if (lclick) {
if (player->isInstantDestruction() && target.breakable) {
blocksController->breakBlock(
player.get(), target, iend.x, iend.y, iend.z
player, target, iend.x, iend.y, iend.z
);
}
}
@ -551,10 +551,10 @@ void PlayerController::updateInteraction(float delta) {
bool preventDefault = false;
if (item.rt.funcsset.on_use_on_block) {
preventDefault = scripting::on_item_use_on_block(
player.get(), item, iend, selection.normal
player, item, iend, selection.normal
);
} else if (item.rt.funcsset.on_use) {
preventDefault = scripting::on_item_use(player.get(), item);
preventDefault = scripting::on_item_use(player, item);
}
if (preventDefault) {
return;
@ -566,10 +566,10 @@ void PlayerController::updateInteraction(float delta) {
}
if (Events::jactive(BIND_PLAYER_PICK)) {
auto coord = selection.actualPosition;
pick_block(indices, chunks, player.get(), coord.x, coord.y, coord.z);
pick_block(indices, chunks, player, coord.x, coord.y, coord.z);
}
}
Player* PlayerController::getPlayer() {
return player.get();
return player;
}

View File

@ -18,7 +18,7 @@ struct CameraSettings;
struct EngineSettings;
class CameraControl {
std::shared_ptr<Player> player;
Player* player;
std::shared_ptr<Camera> camera;
const CameraSettings& settings;
glm::vec3 offset;
@ -40,7 +40,7 @@ class CameraControl {
void switchCamera();
public:
CameraControl(
const std::shared_ptr<Player>& player, const CameraSettings& settings
Player* player, const CameraSettings& settings
);
void updateMouse(PlayerInput& input);
void update(PlayerInput input, float delta, Chunks* chunks);
@ -50,7 +50,7 @@ public:
class PlayerController {
const EngineSettings& settings;
Level* level;
std::shared_ptr<Player> player;
Player* player;
PlayerInput input {};
CameraControl camControl;
BlocksController* blocksController;

View File

@ -350,9 +350,9 @@ static int l_place(lua::State* L) {
"there is no block with index " + std::to_string(id)
);
}
auto player = level->getObject<Player>(playerid);
auto player = level->getPlayer(playerid);
controller->getBlocksController()->placeBlock(
player ? player.get() : nullptr, *def, int2blockstate(state), x, y, z
player, *def, int2blockstate(state), x, y, z
);
return 0;
}
@ -367,10 +367,8 @@ static int l_destruct(lua::State* L) {
return 0;
}
auto& def = level->content->getIndices()->blocks.require(voxel->id);
auto player = level->getObject<Player>(playerid);
controller->getBlocksController()->breakBlock(
player ? player.get() : nullptr, def, x, y, z
);
auto player = level->getPlayer(playerid);
controller->getBlocksController()->breakBlock(player, def, x, y, z);
return 0;
}

View File

@ -11,8 +11,8 @@
using namespace scripting;
inline std::shared_ptr<Player> get_player(lua::State* L, int idx) {
return level->getObject<Player>(lua::tointeger(L, idx));
inline Player* get_player(lua::State* L, int idx) {
return level->getPlayer(lua::tointeger(L, idx));
}
static int l_get_pos(lua::State* L) {

View File

@ -29,12 +29,14 @@ constexpr int SPAWN_ATTEMPTS_PER_UPDATE = 64;
Player::Player(
Level* level,
int64_t id,
glm::vec3 position,
float speed,
std::shared_ptr<Inventory> inv,
entityid_t eid
)
: level(level),
id(id),
speed(speed),
chosenSlot(0),
position(position),
@ -49,8 +51,7 @@ Player::Player(
tpCamera->setFov(glm::radians(90.0f));
}
Player::~Player() {
}
Player::~Player() = default;
void Player::updateEntity() {
if (eid == 0) {
@ -283,6 +284,8 @@ glm::vec3 Player::getSpawnPoint() const {
dv::value Player::serialize() const {
auto root = dv::object();
root["id"] = id;
root["position"] = dv::to_value(position);
root["rotation"] = dv::to_value(cam);
root["spawnpoint"] = dv::to_value(spawnpoint);
@ -304,6 +307,8 @@ dv::value Player::serialize() const {
}
void Player::deserialize(const dv::value& src) {
src.at("id").get(id);
const auto& posarr = src["position"];
dv::get_vec(posarr, position);

View File

@ -4,7 +4,6 @@
#include <memory>
#include <optional>
#include "interfaces/Object.hpp"
#include "interfaces/Serializable.hpp"
#include "settings.hpp"
#include "voxels/voxel.hpp"
@ -40,8 +39,9 @@ struct CursorSelection {
entityid_t entity = ENTITY_NONE;
};
class Player : public Object, public Serializable {
class Player : public Serializable {
Level* level;
int64_t id;
float speed;
int chosenSlot;
glm::vec3 position;
@ -52,7 +52,7 @@ class Player : public Object, public Serializable {
bool infiniteItems = true;
bool instantDestruction = true;
entityid_t eid;
entityid_t selectedEid;
entityid_t selectedEid = 0;
public:
std::shared_ptr<Camera> fpCamera, spCamera, tpCamera;
std::shared_ptr<Camera> currentCamera;
@ -62,6 +62,7 @@ public:
Player(
Level* level,
int64_t id,
glm::vec3 position,
float speed,
std::shared_ptr<Inventory> inv,
@ -115,7 +116,7 @@ public:
static void convert(dv::value& data, const ContentReport* report);
inline int getId() const {
return objectUID;
inline u64id_t getId() const {
return id;
}
};

View File

@ -62,9 +62,9 @@ bool Events::jclicked(int button) {
void Events::toggleCursor() {
cursor_drag = false;
_cursor_locked = !_cursor_locked;
Window::setCursorMode(
/*Window::setCursorMode(
_cursor_locked ? GLFW_CURSOR_DISABLED : GLFW_CURSOR_NORMAL
);
);*/
}
void Events::pollEvents() {

View File

@ -29,7 +29,7 @@ Level::Level(
events(std::make_unique<LevelEvents>()),
entities(std::make_unique<Entities>(this)),
settings(settings) {
auto& worldInfo = world->getInfo();
const auto& worldInfo = world->getInfo();
auto& cameraIndices = content->getIndices(ResourceType::CAMERA);
for (size_t i = 0; i < cameraIndices.size(); i++) {
auto camera = std::make_shared<Camera>();
@ -54,9 +54,11 @@ Level::Level(
auto inv = std::make_shared<Inventory>(
world->getNextInventoryId(), DEF_PLAYER_INVENTORY_SIZE
);
auto player = spawnObject<Player>(
this, glm::vec3(0, DEF_PLAYER_Y, 0), DEF_PLAYER_SPEED, inv, 0
auto playerPtr = std::make_unique<Player>(
this, 0, glm::vec3(0, DEF_PLAYER_Y, 0), DEF_PLAYER_SPEED, inv, 0
);
auto player = playerPtr.get();
addPlayer(std::move(playerPtr));
uint matrixSize =
(settings.chunks.loadDistance.get() + settings.chunks.padding.get()) *
@ -75,9 +77,18 @@ Level::Level(
}
Level::~Level() {
for (auto obj : objects) {
obj.reset();
}
void Level::addPlayer(std::unique_ptr<Player> player) {
players[player->getId()] = std::move(player);
}
Player* Level::getPlayer(int64_t id) const {
const auto& found = players.find(id);
if (found == players.end()) {
return nullptr;
}
return found->second.get();
}
void Level::loadMatrix(int32_t x, int32_t z, uint32_t radius) {

View File

@ -2,8 +2,9 @@
#include <memory>
#include <vector>
#include <unordered_map>
#include "interfaces/Object.hpp"
#include "typedefs.hpp"
inline constexpr float DEF_PLAYER_Y = 100.0f;
inline constexpr float DEF_PLAYER_SPEED = 4.0f;
@ -19,6 +20,7 @@ class Lighting;
class PhysicsSolver;
class ChunksStorage;
class Camera;
class Player;
struct EngineSettings;
/// @brief A level, contains chunks and objects
@ -26,7 +28,7 @@ class Level {
std::unique_ptr<World> world;
public:
const Content* const content;
std::vector<std::shared_ptr<Object>> objects;
std::unordered_map<int64_t, std::unique_ptr<Player>> players;
std::unique_ptr<Chunks> chunks;
std::unique_ptr<ChunksStorage> chunksStorage;
std::unique_ptr<Inventories> inventories;
@ -52,35 +54,9 @@ public:
const World* getWorld() const;
/// Spawns object of class T and returns pointer to it.
/// @param T class that derives the Object class
/// @param args pass arguments needed for T class constructor
template <class T, typename... Args>
std::shared_ptr<T> spawnObject(Args&&... args) {
static_assert(
std::is_base_of<Object, T>::value,
"T must be a derived of Object class"
);
std::shared_ptr<T> tObj = std::make_shared<T>(args...);
void addPlayer(std::unique_ptr<Player> player);
std::shared_ptr<Object> obj =
std::dynamic_pointer_cast<Object, T>(tObj);
obj->objectUID = objects.size();
objects.push_back(obj);
obj->spawned();
return tObj;
}
template <class T>
std::shared_ptr<T> getObject(uint64_t id) const {
static_assert(
std::is_base_of<Object, T>::value,
"T must be a derived of Object class"
);
if (id >= objects.size()) return nullptr;
std::shared_ptr<T> object = std::dynamic_pointer_cast<T>(objects[id]);
return object;
}
Player* getPlayer(int64_t id) const;
void onSave();

View File

@ -71,10 +71,8 @@ void World::write(Level* level) {
auto playerFile = dv::object();
auto& players = playerFile.list("players");
for (const auto& object : level->objects) {
if (auto player = std::dynamic_pointer_cast<Player>(object)) {
players.add(player->serialize());
}
for (const auto& [id, player] : level->players) {
players.add(player->serialize());
}
files::write_json(wfile->getPlayerFile(), playerFile);
@ -94,6 +92,7 @@ std::unique_ptr<Level> World::create(
info.name = name;
info.generator = generator;
info.seed = seed;
info.nextPlayerId = 1;
auto world = std::make_unique<World>(
info,
std::make_unique<WorldFiles>(directory, settings.debug),
@ -121,45 +120,42 @@ std::unique_ptr<Level> World::load(
<< " generator: " << info->generator;
auto world = std::make_unique<World>(
info.value(),
std::move(worldFilesPtr),
content,
packs
info.value(), std::move(worldFilesPtr), content, packs
);
auto& wfile = world->wfile;
wfile->readResourcesData(content);
auto level = std::make_unique<Level>(std::move(world), content, settings);
{
fs::path file = wfile->getPlayerFile();
if (!fs::is_regular_file(file)) {
logger.warning() << "player.json does not exists";
} else {
auto playerRoot = files::read_json(file);
if (playerRoot.has("players")) {
level->objects.clear();
const auto& players = playerRoot["players"];
for (auto& playerMap : players) {
auto player = level->spawnObject<Player>(
level.get(),
glm::vec3(0, DEF_PLAYER_Y, 0),
DEF_PLAYER_SPEED,
level->inventories->create(DEF_PLAYER_INVENTORY_SIZE),
0
);
player->deserialize(playerMap);
auto& inventory = player->getInventory();
// invalid inventory id pre 0.25
if (inventory->getId() == 0) {
inventory->setId(level->getWorld()->getNextInventoryId());
}
level->inventories->store(player->getInventory());
}
} else {
auto player = level->getObject<Player>(0);
player->deserialize(playerRoot);
level->inventories->store(player->getInventory());
fs::path file = wfile->getPlayerFile();
if (!fs::is_regular_file(file)) {
logger.warning() << "player.json does not exists";
} else {
level->players.clear();
auto playerRoot = files::read_json(file);
const auto& players = playerRoot["players"];
if (!players[0].has("id")) {
world->getInfo().nextPlayerId++;
}
for (auto& playerMap : players) {
auto playerPtr = std::make_unique<Player>(
level.get(),
0,
glm::vec3(0, DEF_PLAYER_Y, 0),
DEF_PLAYER_SPEED,
level->inventories->create(DEF_PLAYER_INVENTORY_SIZE),
0
);
auto player = playerPtr.get();
player->deserialize(playerMap);
level->addPlayer(std::move(playerPtr));
auto& inventory = player->getInventory();
// invalid inventory id pre 0.25
if (inventory->getId() == 0) {
inventory->setId(level->getWorld()->getNextInventoryId());
}
level->inventories->store(player->getInventory());
}
}
return level;
@ -231,6 +227,7 @@ void WorldInfo::deserialize(const dv::value& root) {
}
nextInventoryId = root["next-inventory-id"].asInteger(2);
nextEntityId = root["next-entity-id"].asInteger(1);
root.at("next-player-id").get(nextPlayerId);
}
dv::value WorldInfo::serialize() const {
@ -254,5 +251,6 @@ dv::value WorldInfo::serialize() const {
root["next-inventory-id"] = nextInventoryId;
root["next-entity-id"] = nextEntityId;
root["next-player-id"] = nextPlayerId;
return root;
}

View File

@ -28,6 +28,7 @@ struct WorldInfo : public Serializable {
std::string generator;
uint64_t seed;
int64_t nextInventoryId = 1;
int64_t nextPlayerId = 0;
/// @brief Day/night loop timer in range 0..1 where
/// 0.0 - is midnight and