commit
cd4c92790f
@ -77,6 +77,13 @@ player.get_spawnpoint(playerid: int) -> number, number, number
|
||||
|
||||
Spawn point setter and getter
|
||||
|
||||
```lua
|
||||
player.set_name(playerid: int, name: str)
|
||||
player.get_name(playerid: int) -> str
|
||||
```
|
||||
|
||||
Player name setter and getter
|
||||
|
||||
```lua
|
||||
player.get_selected_block(playerid: int) -> x,y,z
|
||||
```
|
||||
|
||||
@ -77,6 +77,13 @@ player.get_spawnpoint(playerid: int) -> number, number, number
|
||||
|
||||
Сеттер и геттер точки спавна игрока
|
||||
|
||||
```lua
|
||||
player.set_name(playerid: int, name: str)
|
||||
player.get_name(playerid: int) -> str
|
||||
```
|
||||
|
||||
Сеттер и геттер имени игрока
|
||||
|
||||
```lua
|
||||
player.get_selected_block(playerid: int) -> x,y,z
|
||||
```
|
||||
|
||||
3
res/presets/text3d/player_name.toml
Normal file
3
res/presets/text3d/player_name.toml
Normal file
@ -0,0 +1,3 @@
|
||||
display = "projected"
|
||||
xray_opacity = 0.3
|
||||
render_distance = 128
|
||||
@ -18,7 +18,6 @@
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
|
||||
class Level;
|
||||
class Screen;
|
||||
class EnginePaths;
|
||||
class ResPaths;
|
||||
|
||||
@ -50,7 +50,7 @@ LevelScreen::LevelScreen(Engine* engine, std::unique_ptr<Level> levelPtr)
|
||||
hud = std::make_unique<Hud>(engine, *frontend, controller->getPlayer());
|
||||
|
||||
decorator = std::make_unique<Decorator>(
|
||||
*controller, *worldRenderer->particles, assets
|
||||
*engine, *controller, *worldRenderer, assets
|
||||
);
|
||||
|
||||
keepAlive(settings.graphics.backlight.observe([=](bool) {
|
||||
|
||||
@ -1,13 +1,22 @@
|
||||
#include "Decorator.hpp"
|
||||
|
||||
#include "ParticlesRenderer.hpp"
|
||||
#include "WorldRenderer.hpp"
|
||||
#include "TextsRenderer.hpp"
|
||||
#include "TextNote.hpp"
|
||||
#include "assets/assets_util.hpp"
|
||||
#include "content/Content.hpp"
|
||||
#include "voxels/Chunks.hpp"
|
||||
#include "voxels/Block.hpp"
|
||||
#include "world/Level.hpp"
|
||||
#include "window/Camera.hpp"
|
||||
#include "objects/Players.hpp"
|
||||
#include "logic/LevelController.hpp"
|
||||
#include "util/stringutil.hpp"
|
||||
#include "engine.hpp"
|
||||
#include "files/files.hpp"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
/// @brief Not greather than 64 for this BIG_PRIME value
|
||||
inline constexpr int UPDATE_AREA_DIAMETER = 32;
|
||||
@ -20,15 +29,32 @@ inline constexpr int ITERATIONS = 512;
|
||||
inline constexpr int BIG_PRIME = 666667;
|
||||
|
||||
Decorator::Decorator(
|
||||
LevelController& controller, ParticlesRenderer& particles, const Assets& assets
|
||||
Engine& engine, LevelController& controller, WorldRenderer& renderer, const Assets& assets
|
||||
)
|
||||
: level(*controller.getLevel()), particles(particles), assets(assets) {
|
||||
: engine(engine),
|
||||
level(*controller.getLevel()),
|
||||
renderer(renderer),
|
||||
assets(assets),
|
||||
player(*controller.getPlayer()) {
|
||||
controller.getBlocksController()->listenBlockInteraction(
|
||||
[this](auto player, const auto& pos, const auto& def, BlockInteraction type) {
|
||||
if (type == BlockInteraction::placing && def.particles) {
|
||||
addParticles(def, pos);
|
||||
}
|
||||
});
|
||||
for (const auto& [id, player] : *level.players) {
|
||||
if (id == controller.getPlayer()->getId()) {
|
||||
continue;
|
||||
}
|
||||
playerTexts[id] = renderer.texts->add(std::make_unique<TextNote>(
|
||||
util::str2wstr_utf8(player->getName()),
|
||||
playerNamePreset,
|
||||
player->getPosition()
|
||||
));
|
||||
}
|
||||
playerNamePreset.deserialize(engine.getResPaths()->readCombinedObject(
|
||||
"presets/text3d/player_name.toml"
|
||||
));
|
||||
}
|
||||
|
||||
void Decorator::addParticles(const Block& def, const glm::ivec3& pos) {
|
||||
@ -37,7 +63,7 @@ void Decorator::addParticles(const Block& def, const glm::ivec3& pos) {
|
||||
auto treg = util::get_texture_region(
|
||||
assets, def.particles->texture, ""
|
||||
);
|
||||
blockEmitters[pos] = particles.add(std::make_unique<Emitter>(
|
||||
blockEmitters[pos] = renderer.particles->add(std::make_unique<Emitter>(
|
||||
level,
|
||||
glm::vec3{pos.x + 0.5, pos.y + 0.5, pos.z + 0.5},
|
||||
*def.particles,
|
||||
@ -81,7 +107,7 @@ void Decorator::update(float delta, const Camera& camera) {
|
||||
const auto& indices = *level.content->getIndices();
|
||||
auto iter = blockEmitters.begin();
|
||||
while (iter != blockEmitters.end()) {
|
||||
auto emitter = particles.getEmitter(iter->second);
|
||||
auto emitter = renderer.particles->getEmitter(iter->second);
|
||||
if (emitter == nullptr) {
|
||||
iter = blockEmitters.erase(iter);
|
||||
continue;
|
||||
@ -108,4 +134,28 @@ void Decorator::update(float delta, const Camera& camera) {
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
|
||||
for (const auto& [id, player] : *level.players) {
|
||||
if (id == this->player.getId() ||
|
||||
playerTexts.find(id) != playerTexts.end()) {
|
||||
continue;
|
||||
}
|
||||
playerTexts[id] = renderer.texts->add(std::make_unique<TextNote>(
|
||||
util::str2wstr_utf8(player->getName()),
|
||||
playerNamePreset,
|
||||
player->getPosition()
|
||||
));
|
||||
}
|
||||
|
||||
auto textsIter = playerTexts.begin();
|
||||
while (textsIter != playerTexts.end()) {
|
||||
auto note = renderer.texts->get(textsIter->second);
|
||||
auto player = level.players->get(textsIter->first);
|
||||
if (player == nullptr) {
|
||||
textsIter = playerTexts.erase(textsIter);
|
||||
} else {
|
||||
note->setPosition(player->getPosition() + glm::vec3(0, 1, 0));
|
||||
++textsIter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,20 +6,29 @@
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include "typedefs.hpp"
|
||||
#include "presets/NotePreset.hpp"
|
||||
|
||||
class Level;
|
||||
class Chunks;
|
||||
class Camera;
|
||||
class Assets;
|
||||
class Player;
|
||||
struct Block;
|
||||
class Engine;
|
||||
class LevelController;
|
||||
class ParticlesRenderer;
|
||||
class WorldRenderer;
|
||||
|
||||
class Decorator {
|
||||
Engine& engine;
|
||||
const Level& level;
|
||||
const Assets& assets;
|
||||
ParticlesRenderer& particles;
|
||||
Player& player;
|
||||
WorldRenderer& renderer;
|
||||
std::unordered_map<glm::ivec3, uint64_t> blockEmitters;
|
||||
std::unordered_map<int64_t, u64id_t> playerTexts;
|
||||
int currentIndex = 0;
|
||||
NotePreset playerNamePreset {};
|
||||
|
||||
void update(
|
||||
float delta, const glm::ivec3& areaStart, const glm::ivec3& areaCenter
|
||||
@ -27,7 +36,10 @@ class Decorator {
|
||||
void addParticles(const Block& def, const glm::ivec3& pos);
|
||||
public:
|
||||
Decorator(
|
||||
LevelController& level, ParticlesRenderer& particles, const Assets& assets
|
||||
Engine& engine,
|
||||
LevelController& level,
|
||||
WorldRenderer& renderer,
|
||||
const Assets& assets
|
||||
);
|
||||
|
||||
void update(float delta, const Camera& camera);
|
||||
|
||||
@ -61,6 +61,10 @@ void TextsRenderer::renderNote(
|
||||
if (preset.displayMode == NoteDisplayMode::XY_FREE_BILLBOARD) {
|
||||
yvec = camera.up;
|
||||
}
|
||||
float scale =
|
||||
(1.0f - preset.perspective) * glm::pow(glm::distance(camera.position, pos), 1.0f-preset.perspective);
|
||||
xvec *= 1.0f + scale;
|
||||
yvec *= 1.0f + scale;
|
||||
}
|
||||
if (preset.displayMode != NoteDisplayMode::PROJECTED) {
|
||||
if (!frustum.isBoxVisible(pos - xvec * (width * 0.5f),
|
||||
|
||||
@ -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() { }
|
||||
};
|
||||
@ -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() {
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
#include "lighting/Lighting.hpp"
|
||||
#include "objects/Entities.hpp"
|
||||
#include "objects/Player.hpp"
|
||||
#include "objects/Players.hpp"
|
||||
#include "physics/Hitbox.hpp"
|
||||
#include "physics/PhysicsSolver.hpp"
|
||||
#include "settings.hpp"
|
||||
@ -40,7 +41,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 +194,7 @@ PlayerController::PlayerController(
|
||||
BlocksController* blocksController
|
||||
)
|
||||
: settings(settings), level(level),
|
||||
player(level->getObject<Player>(0)),
|
||||
player(level->players->get(0)),
|
||||
camControl(player, settings.camera),
|
||||
blocksController(blocksController),
|
||||
playerTickClock(20, 3) {
|
||||
@ -215,7 +216,7 @@ void PlayerController::onFootstep(const Hitbox& hitbox) {
|
||||
continue;
|
||||
}
|
||||
blocksController->onBlockInteraction(
|
||||
player.get(),
|
||||
player,
|
||||
glm::ivec3(x, y, z),
|
||||
def,
|
||||
BlockInteraction::step
|
||||
@ -254,7 +255,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 +391,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 +433,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 +475,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 +489,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 +524,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 +535,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 +544,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 +552,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 +567,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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
#include "lighting/Lighting.hpp"
|
||||
#include "logic/BlocksController.hpp"
|
||||
#include "logic/LevelController.hpp"
|
||||
#include "objects/Players.hpp"
|
||||
#include "voxels/Block.hpp"
|
||||
#include "voxels/Chunk.hpp"
|
||||
#include "voxels/Chunks.hpp"
|
||||
@ -350,9 +351,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->players->get(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 +368,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->players->get(playerid);
|
||||
controller->getBlocksController()->breakBlock(player, def, x, y, z);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
#include "items/Inventory.hpp"
|
||||
#include "objects/Entities.hpp"
|
||||
#include "objects/Player.hpp"
|
||||
#include "objects/Players.hpp"
|
||||
#include "physics/Hitbox.hpp"
|
||||
#include "window/Camera.hpp"
|
||||
#include "world/Level.hpp"
|
||||
@ -11,8 +12,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->players->get(lua::tointeger(L, idx));
|
||||
}
|
||||
|
||||
static int l_get_pos(lua::State* L) {
|
||||
@ -235,6 +236,20 @@ static int l_set_camera(lua::State* L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_get_name(lua::State* L) {
|
||||
if (auto player = get_player(L, 1)) {
|
||||
return lua::pushstring(L, player->getName());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_set_name(lua::State* L) {
|
||||
if (auto player = get_player(L, 1)) {
|
||||
player->setName(lua::require_string(L, 2));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const luaL_Reg playerlib[] = {
|
||||
{"get_pos", lua::wrap<l_get_pos>},
|
||||
{"set_pos", lua::wrap<l_set_pos>},
|
||||
@ -260,5 +275,7 @@ const luaL_Reg playerlib[] = {
|
||||
{"set_entity", lua::wrap<l_set_entity>},
|
||||
{"get_camera", lua::wrap<l_get_camera>},
|
||||
{"set_camera", lua::wrap<l_set_camera>},
|
||||
{"get_name", lua::wrap<l_get_name>},
|
||||
{"set_name", lua::wrap<l_set_name>},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
@ -29,12 +29,16 @@ constexpr int SPAWN_ATTEMPTS_PER_UPDATE = 64;
|
||||
|
||||
Player::Player(
|
||||
Level* level,
|
||||
int64_t id,
|
||||
const std::string& name,
|
||||
glm::vec3 position,
|
||||
float speed,
|
||||
std::shared_ptr<Inventory> inv,
|
||||
entityid_t eid
|
||||
)
|
||||
: level(level),
|
||||
id(id),
|
||||
name(name),
|
||||
speed(speed),
|
||||
chosenSlot(0),
|
||||
position(position),
|
||||
@ -49,8 +53,7 @@ Player::Player(
|
||||
tpCamera->setFov(glm::radians(90.0f));
|
||||
}
|
||||
|
||||
Player::~Player() {
|
||||
}
|
||||
Player::~Player() = default;
|
||||
|
||||
void Player::updateEntity() {
|
||||
if (eid == 0) {
|
||||
@ -268,6 +271,14 @@ entityid_t Player::getSelectedEntity() const {
|
||||
return selectedEid;
|
||||
}
|
||||
|
||||
void Player::setName(const std::string& name) {
|
||||
this->name = name;
|
||||
}
|
||||
|
||||
const std::string& Player::getName() const {
|
||||
return name;
|
||||
}
|
||||
|
||||
const std::shared_ptr<Inventory>& Player::getInventory() const {
|
||||
return inventory;
|
||||
}
|
||||
@ -283,6 +294,9 @@ glm::vec3 Player::getSpawnPoint() const {
|
||||
dv::value Player::serialize() const {
|
||||
auto root = dv::object();
|
||||
|
||||
root["id"] = id;
|
||||
root["name"] = name;
|
||||
|
||||
root["position"] = dv::to_value(position);
|
||||
root["rotation"] = dv::to_value(cam);
|
||||
root["spawnpoint"] = dv::to_value(spawnpoint);
|
||||
@ -304,6 +318,9 @@ dv::value Player::serialize() const {
|
||||
}
|
||||
|
||||
void Player::deserialize(const dv::value& src) {
|
||||
src.at("id").get(id);
|
||||
src.at("name").get(name);
|
||||
|
||||
const auto& posarr = src["position"];
|
||||
|
||||
dv::get_vec(posarr, position);
|
||||
|
||||
@ -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,10 @@ struct CursorSelection {
|
||||
entityid_t entity = ENTITY_NONE;
|
||||
};
|
||||
|
||||
class Player : public Object, public Serializable {
|
||||
class Player : public Serializable {
|
||||
Level* level;
|
||||
int64_t id;
|
||||
std::string name;
|
||||
float speed;
|
||||
int chosenSlot;
|
||||
glm::vec3 position;
|
||||
@ -52,7 +53,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 +63,8 @@ public:
|
||||
|
||||
Player(
|
||||
Level* level,
|
||||
int64_t id,
|
||||
const std::string& name,
|
||||
glm::vec3 position,
|
||||
float speed,
|
||||
std::shared_ptr<Inventory> inv,
|
||||
@ -99,9 +102,12 @@ public:
|
||||
|
||||
entityid_t getSelectedEntity() const;
|
||||
|
||||
void setName(const std::string& name);
|
||||
const std::string& getName() const;
|
||||
|
||||
const std::shared_ptr<Inventory>& getInventory() const;
|
||||
|
||||
glm::vec3 getPosition() const {
|
||||
const glm::vec3& getPosition() const {
|
||||
return position;
|
||||
}
|
||||
|
||||
@ -115,7 +121,7 @@ public:
|
||||
|
||||
static void convert(dv::value& data, const ContentReport* report);
|
||||
|
||||
inline int getId() const {
|
||||
return objectUID;
|
||||
inline u64id_t getId() const {
|
||||
return id;
|
||||
}
|
||||
};
|
||||
|
||||
73
src/objects/Players.cpp
Normal file
73
src/objects/Players.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
#include "Players.hpp"
|
||||
|
||||
#include "Player.hpp"
|
||||
#include "items/Inventories.hpp"
|
||||
#include "world/Level.hpp"
|
||||
#include "world/World.hpp"
|
||||
|
||||
Players::Players(Level* level) : level(level) {}
|
||||
|
||||
void Players::addPlayer(std::unique_ptr<Player> player) {
|
||||
players[player->getId()] = std::move(player);
|
||||
}
|
||||
|
||||
Player* Players::get(int64_t id) const {
|
||||
const auto& found = players.find(id);
|
||||
if (found == players.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return found->second.get();
|
||||
}
|
||||
|
||||
Player* Players::create() {
|
||||
auto playerPtr = std::make_unique<Player>(
|
||||
level,
|
||||
level->getWorld()->getInfo().nextPlayerId++,
|
||||
"",
|
||||
glm::vec3(0, DEF_PLAYER_Y, 0),
|
||||
DEF_PLAYER_SPEED,
|
||||
level->inventories->create(DEF_PLAYER_INVENTORY_SIZE),
|
||||
0
|
||||
);
|
||||
auto player = playerPtr.get();
|
||||
addPlayer(std::move(playerPtr));
|
||||
|
||||
level->inventories->store(player->getInventory());
|
||||
return player;
|
||||
}
|
||||
|
||||
dv::value Players::serialize() const {
|
||||
auto root = dv::object();
|
||||
auto& list = root.list("players");
|
||||
|
||||
for (const auto& [id, player] : players) {
|
||||
list.add(player->serialize());
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
void Players::deserialize(const dv::value& src) {
|
||||
players.clear();
|
||||
|
||||
const auto& players = src["players"];
|
||||
for (auto& playerMap : players) {
|
||||
auto playerPtr = std::make_unique<Player>(
|
||||
level,
|
||||
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);
|
||||
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());
|
||||
}
|
||||
}
|
||||
39
src/objects/Players.hpp
Normal file
39
src/objects/Players.hpp
Normal file
@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "typedefs.hpp"
|
||||
#include "interfaces/Serializable.hpp"
|
||||
|
||||
inline constexpr float DEF_PLAYER_Y = 100.0f;
|
||||
inline constexpr float DEF_PLAYER_SPEED = 4.0f;
|
||||
inline constexpr int DEF_PLAYER_INVENTORY_SIZE = 40;
|
||||
|
||||
class Level;
|
||||
class Player;
|
||||
|
||||
class Players : public Serializable {
|
||||
Level* level;
|
||||
std::unordered_map<int64_t, std::unique_ptr<Player>> players;
|
||||
|
||||
void addPlayer(std::unique_ptr<Player> player);
|
||||
public:
|
||||
Players(Level* level);
|
||||
|
||||
Player* get(int64_t id) const;
|
||||
|
||||
Player* create();
|
||||
|
||||
dv::value serialize() const override;
|
||||
|
||||
void deserialize(const dv::value& src) override;
|
||||
|
||||
auto begin() const {
|
||||
return players.begin();
|
||||
}
|
||||
|
||||
auto end() const {
|
||||
return players.end();
|
||||
}
|
||||
};
|
||||
@ -7,6 +7,7 @@
|
||||
#include "lighting/Lighting.hpp"
|
||||
#include "objects/Entities.hpp"
|
||||
#include "objects/Player.hpp"
|
||||
#include "objects/Players.hpp"
|
||||
#include "physics/Hitbox.hpp"
|
||||
#include "physics/PhysicsSolver.hpp"
|
||||
#include "settings.hpp"
|
||||
@ -28,8 +29,9 @@ Level::Level(
|
||||
physics(std::make_unique<PhysicsSolver>(glm::vec3(0, -22.6f, 0))),
|
||||
events(std::make_unique<LevelEvents>()),
|
||||
entities(std::make_unique<Entities>(this)),
|
||||
players(std::make_unique<Players>(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>();
|
||||
@ -51,12 +53,6 @@ Level::Level(
|
||||
if (worldInfo.nextEntityId) {
|
||||
entities->setNextID(worldInfo.nextEntityId);
|
||||
}
|
||||
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
|
||||
);
|
||||
|
||||
uint matrixSize =
|
||||
(settings.chunks.loadDistance.get() + settings.chunks.padding.get()) *
|
||||
@ -71,14 +67,9 @@ Level::Level(
|
||||
});
|
||||
|
||||
inventories = std::make_unique<Inventories>(*this);
|
||||
inventories->store(player->getInventory());
|
||||
}
|
||||
|
||||
Level::~Level() {
|
||||
for (auto obj : objects) {
|
||||
obj.reset();
|
||||
}
|
||||
}
|
||||
Level::~Level() = default;
|
||||
|
||||
void Level::loadMatrix(int32_t x, int32_t z, uint32_t radius) {
|
||||
chunks->setCenter(x, z);
|
||||
|
||||
@ -2,12 +2,10 @@
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "interfaces/Object.hpp"
|
||||
|
||||
inline constexpr float DEF_PLAYER_Y = 100.0f;
|
||||
inline constexpr float DEF_PLAYER_SPEED = 4.0f;
|
||||
inline constexpr int DEF_PLAYER_INVENTORY_SIZE = 40;
|
||||
#include "typedefs.hpp"
|
||||
|
||||
class Content;
|
||||
class World;
|
||||
@ -19,6 +17,7 @@ class Lighting;
|
||||
class PhysicsSolver;
|
||||
class ChunksStorage;
|
||||
class Camera;
|
||||
class Players;
|
||||
struct EngineSettings;
|
||||
|
||||
/// @brief A level, contains chunks and objects
|
||||
@ -26,7 +25,7 @@ class Level {
|
||||
std::unique_ptr<World> world;
|
||||
public:
|
||||
const Content* const content;
|
||||
std::vector<std::shared_ptr<Object>> objects;
|
||||
|
||||
std::unique_ptr<Chunks> chunks;
|
||||
std::unique_ptr<ChunksStorage> chunksStorage;
|
||||
std::unique_ptr<Inventories> inventories;
|
||||
@ -35,6 +34,7 @@ public:
|
||||
std::unique_ptr<Lighting> lighting;
|
||||
std::unique_ptr<LevelEvents> events;
|
||||
std::unique_ptr<Entities> entities;
|
||||
std::unique_ptr<Players> players;
|
||||
std::vector<std::shared_ptr<Camera>> cameras; // move somewhere?
|
||||
|
||||
const EngineSettings& settings;
|
||||
@ -52,36 +52,6 @@ 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...);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void onSave();
|
||||
|
||||
std::shared_ptr<Camera> getCamera(const std::string& name);
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
#include "items/Inventories.hpp"
|
||||
#include "objects/Entities.hpp"
|
||||
#include "objects/Player.hpp"
|
||||
#include "objects/Players.hpp"
|
||||
#include "settings.hpp"
|
||||
#include "voxels/Chunk.hpp"
|
||||
#include "voxels/Chunks.hpp"
|
||||
@ -69,13 +70,7 @@ void World::write(Level* level) {
|
||||
info.nextEntityId = level->entities->peekNextID();
|
||||
wfile->write(this, content);
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
auto playerFile = level->players->serialize();
|
||||
files::write_json(wfile->getPlayerFile(), playerFile);
|
||||
|
||||
writeResources(content);
|
||||
@ -100,7 +95,9 @@ std::unique_ptr<Level> World::create(
|
||||
content,
|
||||
packs
|
||||
);
|
||||
return std::make_unique<Level>(std::move(world), content, settings);
|
||||
auto level = std::make_unique<Level>(std::move(world), content, settings);
|
||||
level->players->create();
|
||||
return level;
|
||||
}
|
||||
|
||||
std::unique_ptr<Level> World::load(
|
||||
@ -121,45 +118,23 @@ 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";
|
||||
level->players->create();
|
||||
} else {
|
||||
auto playerRoot = files::read_json(file);
|
||||
level->players->deserialize(playerRoot);
|
||||
|
||||
if (!playerRoot["players"][0].has("id")) {
|
||||
level->getWorld()->getInfo().nextPlayerId++;
|
||||
}
|
||||
}
|
||||
return level;
|
||||
@ -231,6 +206,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 +230,6 @@ dv::value WorldInfo::serialize() const {
|
||||
|
||||
root["next-inventory-id"] = nextInventoryId;
|
||||
root["next-entity-id"] = nextEntityId;
|
||||
root["next-player-id"] = nextPlayerId;
|
||||
return root;
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user