refactor PlayerController

This commit is contained in:
MihailRis 2024-12-19 00:38:41 +03:00
parent 8eda26f171
commit 8a4f1e16f3
3 changed files with 91 additions and 88 deletions

View File

@ -49,9 +49,9 @@ LevelScreen::LevelScreen(Engine& engine, std::unique_ptr<Level> levelPtr)
std::make_unique<LevelController>(&engine, std::move(levelPtr), player); std::make_unique<LevelController>(&engine, std::move(levelPtr), player);
playerController = std::make_unique<PlayerController>( playerController = std::make_unique<PlayerController>(
settings, settings,
level, *level,
player, *player,
controller->getBlocksController() *controller->getBlocksController()
); );
frontend = std::make_unique<LevelFrontend>( frontend = std::make_unique<LevelFrontend>(

View File

@ -41,20 +41,20 @@ const float C_ZOOM = 0.1f;
const float CROUCH_SHIFT_Y = -0.2f; const float CROUCH_SHIFT_Y = -0.2f;
CameraControl::CameraControl( CameraControl::CameraControl(
Player* player, const CameraSettings& settings Player& player, const CameraSettings& settings
) )
: player(player), : player(player),
camera(player->fpCamera), camera(player.fpCamera),
settings(settings), settings(settings),
offset(0.0f, 0.7f, 0.0f) { offset(0.0f, 0.7f, 0.0f) {
} }
void CameraControl::refresh() { void CameraControl::refresh() {
camera->position = player->getPosition() + offset; camera->position = player.getPosition() + offset;
} }
void CameraControl::updateMouse(PlayerInput& input) { void CameraControl::updateMouse(PlayerInput& input) {
glm::vec3& cam = player->cam; glm::vec3& cam = player.cam;
float sensitivity = float sensitivity =
(input.zoom ? settings.sensitivity.get() / 4.f (input.zoom ? settings.sensitivity.get() / 4.f
@ -131,28 +131,29 @@ void CameraControl::updateFovEffects(
// more extensible but uglier // more extensible but uglier
void CameraControl::switchCamera() { void CameraControl::switchCamera() {
const std::vector<std::shared_ptr<Camera>> playerCameras { const std::vector<std::shared_ptr<Camera>> playerCameras {
camera, player->tpCamera, player->spCamera}; camera, player.tpCamera, player.spCamera
};
auto index = std::distance( auto index = std::distance(
playerCameras.begin(), playerCameras.begin(),
std::find_if( std::find_if(
playerCameras.begin(), playerCameras.begin(),
playerCameras.end(), playerCameras.end(),
[=](auto ptr) { return ptr.get() == player->currentCamera.get(); } [this](auto& ptr) { return ptr.get() == player.currentCamera.get(); }
) )
); );
if (static_cast<size_t>(index) != playerCameras.size()) { if (static_cast<size_t>(index) != playerCameras.size()) {
index = (index + 1) % playerCameras.size(); index = (index + 1) % playerCameras.size();
player->currentCamera = playerCameras.at(index); player.currentCamera = playerCameras.at(index);
} else { } else {
player->currentCamera = camera; player.currentCamera = camera;
} }
} }
void CameraControl::update(PlayerInput input, float delta, Chunks* chunks) { void CameraControl::update(PlayerInput input, float delta, Chunks& chunks) {
offset = glm::vec3(0.0f, 0.0f, 0.0f); offset = glm::vec3(0.0f, 0.0f, 0.0f);
if (auto hitbox = player->getHitbox()) { if (auto hitbox = player.getHitbox()) {
offset.y += hitbox->halfsize.y * (0.7f / 0.9f); offset.y += hitbox->halfsize.y * (0.7f / 0.9f);
if (settings.shaking.get() && !input.cheat) { if (settings.shaking.get() && !input.cheat) {
offset += updateCameraShaking(*hitbox, delta); offset += updateCameraShaking(*hitbox, delta);
@ -165,38 +166,38 @@ void CameraControl::update(PlayerInput input, float delta, Chunks* chunks) {
switchCamera(); switchCamera();
} }
auto spCamera = player->spCamera; auto& spCamera = player.spCamera;
auto tpCamera = player->tpCamera; auto& tpCamera = player.tpCamera;
refresh(); refresh();
camera->updateVectors(); camera->updateVectors();
if (player->currentCamera == spCamera) { if (player.currentCamera == spCamera) {
spCamera->position = spCamera->position =
chunks->rayCastToObstacle(camera->position, camera->front, 3.0f) - chunks.rayCastToObstacle(camera->position, camera->front, 3.0f) -
0.4f * camera->front; 0.4f * camera->front;
spCamera->dir = -camera->dir; spCamera->dir = -camera->dir;
spCamera->front = -camera->front; spCamera->front = -camera->front;
spCamera->right = -camera->right; spCamera->right = -camera->right;
} else if (player->currentCamera == tpCamera) { } else if (player.currentCamera == tpCamera) {
tpCamera->position = tpCamera->position =
chunks->rayCastToObstacle(camera->position, -camera->front, 3.0f) + chunks.rayCastToObstacle(camera->position, -camera->front, 3.0f) +
0.4f * camera->front; 0.4f * camera->front;
tpCamera->dir = camera->dir; tpCamera->dir = camera->dir;
tpCamera->front = camera->front; tpCamera->front = camera->front;
tpCamera->right = camera->right; tpCamera->right = camera->right;
} }
if (player->currentCamera == spCamera || if (player.currentCamera == spCamera ||
player->currentCamera == tpCamera || player->currentCamera == camera) { player.currentCamera == tpCamera || player.currentCamera == camera) {
player->currentCamera->setFov(glm::radians(settings.fov.get())); player.currentCamera->setFov(glm::radians(settings.fov.get()));
} }
} }
PlayerController::PlayerController( PlayerController::PlayerController(
const EngineSettings& settings, const EngineSettings& settings,
Level* level, Level& level,
Player* player, Player& player,
BlocksController* blocksController BlocksController& blocksController
) )
: settings(settings), : settings(settings),
level(level), level(level),
@ -214,14 +215,14 @@ void PlayerController::onFootstep(const Hitbox& hitbox) {
int x = std::floor(pos.x + half.x * offsetX); int x = std::floor(pos.x + half.x * offsetX);
int y = std::floor(pos.y - half.y * 1.1f); int y = std::floor(pos.y - half.y * 1.1f);
int z = std::floor(pos.z + half.z * offsetZ); int z = std::floor(pos.z + half.z * offsetZ);
auto vox = player->chunks->get(x, y, z); auto vox = player.chunks->get(x, y, z);
if (vox) { if (vox) {
auto& def = level->content->getIndices()->blocks.require(vox->id); auto& def = level.content->getIndices()->blocks.require(vox->id);
if (!def.obstacle) { if (!def.obstacle) {
continue; continue;
} }
blocksController->onBlockInteraction( blocksController.onBlockInteraction(
player, &player,
glm::ivec3(x, y, z), glm::ivec3(x, y, z),
def, def,
BlockInteraction::step BlockInteraction::step
@ -233,7 +234,7 @@ void PlayerController::onFootstep(const Hitbox& hitbox) {
} }
void PlayerController::updateFootsteps(float delta) { void PlayerController::updateFootsteps(float delta) {
auto hitbox = player->getHitbox(); auto hitbox = player.getHitbox();
if (hitbox && hitbox->grounded) { if (hitbox && hitbox->grounded) {
const glm::vec3& vel = hitbox->velocity; const glm::vec3& vel = hitbox->velocity;
float f = glm::length(glm::vec2(vel.x, vel.z)); float f = glm::length(glm::vec2(vel.x, vel.z));
@ -250,7 +251,7 @@ void PlayerController::updateFootsteps(float delta) {
void PlayerController::update(float delta, bool input) { void PlayerController::update(float delta, bool input) {
if (input) { if (input) {
updateKeyboard(); updateKeyboard();
player->updateSelectedEntity(); player.updateSelectedEntity();
} else { } else {
resetKeyboard(); resetKeyboard();
} }
@ -265,12 +266,12 @@ void PlayerController::postUpdate(float delta, bool input, bool pause) {
if (!pause && input) { if (!pause && input) {
camControl.updateMouse(this->input); camControl.updateMouse(this->input);
} }
player->postUpdate(); player.postUpdate();
camControl.update(this->input, pause ? 0.0f : delta, player->chunks.get()); camControl.update(this->input, pause ? 0.0f : delta, *player.chunks);
if (input) { if (input) {
updateInteraction(delta); updateInteraction(delta);
} else { } else {
player->selection = {}; player.selection = {};
} }
} }
@ -302,8 +303,8 @@ void PlayerController::resetKeyboard() {
} }
void PlayerController::updatePlayer(float delta) { void PlayerController::updatePlayer(float delta) {
player->updateEntity(); player.updateEntity();
player->updateInput(input, delta); player.updateInput(input, delta);
} }
static int determine_rotation( static int determine_rotation(
@ -339,16 +340,20 @@ static int determine_rotation(
} }
static void pick_block( static void pick_block(
ContentIndices* indices, Chunks* chunks, Player* player, int x, int y, int z ContentIndices* indices,
const Block& block,
Player& player,
int x,
int y,
int z
) { ) {
auto& block = indices->blocks.require(chunks->get(x, y, z)->id);
itemid_t id = block.rt.pickingItem; itemid_t id = block.rt.pickingItem;
auto inventory = player->getInventory(); auto inventory = player.getInventory();
size_t slotid = inventory->findSlotByItem(id, 0, 10); size_t slotid = inventory->findSlotByItem(id, 0, 10);
if (slotid == Inventory::npos) { if (slotid == Inventory::npos) {
slotid = player->getChosenSlot(); slotid = player.getChosenSlot();
} else { } else {
player->setChosenSlot(slotid); player.setChosenSlot(slotid);
} }
ItemStack& stack = inventory->getSlot(slotid); ItemStack& stack = inventory->getSlot(slotid);
if (stack.getItemId() != id) { if (stack.getItemId() != id) {
@ -357,10 +362,10 @@ static void pick_block(
} }
voxel* PlayerController::updateSelection(float maxDistance) { voxel* PlayerController::updateSelection(float maxDistance) {
auto indices = level->content->getIndices(); auto indices = level.content->getIndices();
auto& chunks = *player->chunks; auto& chunks = *player.chunks;
auto camera = player->fpCamera.get(); auto camera = player.fpCamera.get();
auto& selection = player->selection; auto& selection = player.selection;
glm::vec3 end; glm::vec3 end;
glm::ivec3 iend; glm::ivec3 iend;
@ -374,8 +379,8 @@ voxel* PlayerController::updateSelection(float maxDistance) {
auto prevEntity = selection.entity; auto prevEntity = selection.entity;
selection.entity = ENTITY_NONE; selection.entity = ENTITY_NONE;
selection.actualPosition = iend; selection.actualPosition = iend;
if (auto result = level->entities->rayCast( if (auto result = level.entities->rayCast(
camera->position, camera->front, maxDistance, player->getEntity() camera->position, camera->front, maxDistance, player.getEntity()
)) { )) {
selection.entity = result->entity; selection.entity = result->entity;
selection.hitPosition = selection.hitPosition =
@ -386,13 +391,13 @@ voxel* PlayerController::updateSelection(float maxDistance) {
} }
if (selection.entity != prevEntity) { if (selection.entity != prevEntity) {
if (prevEntity != ENTITY_NONE) { if (prevEntity != ENTITY_NONE) {
if (auto pentity = level->entities->get(prevEntity)) { if (auto pentity = level.entities->get(prevEntity)) {
scripting::on_aim_off(*pentity, player); scripting::on_aim_off(*pentity, &player);
} }
} }
if (selection.entity != ENTITY_NONE) { if (selection.entity != ENTITY_NONE) {
if (auto pentity = level->entities->get(selection.entity)) { if (auto pentity = level.entities->get(selection.entity)) {
scripting::on_aim_on(*pentity, player); scripting::on_aim_on(*pentity, &player);
} }
} }
} }
@ -420,16 +425,16 @@ voxel* PlayerController::updateSelection(float maxDistance) {
} }
void PlayerController::processRightClick(const Block& def, const Block& target) { void PlayerController::processRightClick(const Block& def, const Block& target) {
const auto& selection = player->selection; const auto& selection = player.selection;
auto& chunks = *player->chunks; auto& chunks = *player.chunks;
auto camera = player->fpCamera.get(); auto camera = player.fpCamera.get();
blockstate state {}; blockstate state {};
state.rotation = determine_rotation(&def, selection.normal, camera->dir); state.rotation = determine_rotation(&def, selection.normal, camera->dir);
if (!input.shift && target.rt.funcsset.oninteract) { if (!input.shift && target.rt.funcsset.oninteract) {
if (scripting::on_block_interact( if (scripting::on_block_interact(
player, target, selection.actualPosition &player, target, selection.actualPosition
)) { )) {
return; return;
} }
@ -445,7 +450,7 @@ void PlayerController::processRightClick(const Block& def, const Block& target)
if (def.obstacle) { if (def.obstacle) {
const auto& hitboxes = def.rt.hitboxes[state.rotation]; const auto& hitboxes = def.rt.hitboxes[state.rotation];
for (const AABB& blockAABB : hitboxes) { for (const AABB& blockAABB : hitboxes) {
if (level->entities->hasBlockingInside(blockAABB.translated(coord))) { if (level.entities->hasBlockingInside(blockAABB.translated(coord))) {
return; return;
} }
} }
@ -466,12 +471,12 @@ void PlayerController::processRightClick(const Block& def, const Block& target)
} }
} }
if (chosenBlock != vox->id && chosenBlock) { if (chosenBlock != vox->id && chosenBlock) {
if (!player->isInfiniteItems()) { if (!player.isInfiniteItems()) {
auto& slot = player->getInventory()->getSlot(player->getChosenSlot()); auto& slot = player.getInventory()->getSlot(player.getChosenSlot());
slot.setCount(slot.getCount()-1); slot.setCount(slot.getCount()-1);
} }
blocksController->placeBlock( blocksController.placeBlock(
player, def, state, coord.x, coord.y, coord.z &player, def, state, coord.x, coord.y, coord.z
); );
} }
} }
@ -479,23 +484,23 @@ void PlayerController::processRightClick(const Block& def, const Block& target)
void PlayerController::updateEntityInteraction( void PlayerController::updateEntityInteraction(
entityid_t eid, bool lclick, bool rclick entityid_t eid, bool lclick, bool rclick
) { ) {
auto entityOpt = level->entities->get(eid); auto entityOpt = level.entities->get(eid);
if (!entityOpt.has_value()) { if (!entityOpt.has_value()) {
return; return;
} }
auto entity = *entityOpt; auto entity = *entityOpt;
if (lclick) { if (lclick) {
scripting::on_attacked(entity, player, player->getEntity()); scripting::on_attacked(entity, &player, player.getEntity());
} }
if (rclick) { if (rclick) {
scripting::on_entity_used(entity, player); scripting::on_entity_used(entity, &player);
} }
} }
void PlayerController::updateInteraction(float delta) { void PlayerController::updateInteraction(float delta) {
auto indices = level->content->getIndices(); auto indices = level.content->getIndices();
auto chunks = player->chunks.get(); auto chunks = player.chunks.get();
const auto& selection = player->selection; const auto& selection = player.selection;
if (interactionTimer > 0.0f) { if (interactionTimer > 0.0f) {
interactionTimer -= delta; interactionTimer -= delta;
@ -512,14 +517,14 @@ void PlayerController::updateInteraction(float delta) {
interactionTimer = INTERACTION_RELOAD; interactionTimer = INTERACTION_RELOAD;
} }
auto inventory = player->getInventory(); auto inventory = player.getInventory();
const ItemStack& stack = inventory->getSlot(player->getChosenSlot()); const ItemStack& stack = inventory->getSlot(player.getChosenSlot());
auto& item = indices->items.require(stack.getItemId()); auto& item = indices->items.require(stack.getItemId());
auto vox = updateSelection(maxDistance); auto vox = updateSelection(maxDistance);
if (vox == nullptr) { if (vox == nullptr) {
if (rclick && item.rt.funcsset.on_use) { if (rclick && item.rt.funcsset.on_use) {
scripting::on_item_use(player, item); scripting::on_item_use(&player, item);
} }
if (selection.entity) { if (selection.entity) {
updateEntityInteraction(selection.entity, lattack, rclick); updateEntityInteraction(selection.entity, lattack, rclick);
@ -530,16 +535,16 @@ void PlayerController::updateInteraction(float delta) {
auto iend = selection.position; auto iend = selection.position;
if (lclick && !input.shift && item.rt.funcsset.on_block_break_by) { if (lclick && !input.shift && item.rt.funcsset.on_block_break_by) {
if (scripting::on_item_break_block( if (scripting::on_item_break_block(
player, item, iend.x, iend.y, iend.z &player, item, iend.x, iend.y, iend.z
)) { )) {
return; return;
} }
} }
auto& target = indices->blocks.require(vox->id); auto& target = indices->blocks.require(vox->id);
if (lclick) { if (lclick) {
if (player->isInstantDestruction() && target.breakable) { if (player.isInstantDestruction() && target.breakable) {
blocksController->breakBlock( blocksController.breakBlock(
player, target, iend.x, iend.y, iend.z &player, target, iend.x, iend.y, iend.z
); );
} }
} }
@ -547,10 +552,10 @@ void PlayerController::updateInteraction(float delta) {
bool preventDefault = false; bool preventDefault = false;
if (item.rt.funcsset.on_use_on_block) { if (item.rt.funcsset.on_use_on_block) {
preventDefault = scripting::on_item_use_on_block( preventDefault = scripting::on_item_use_on_block(
player, item, iend, selection.normal &player, item, iend, selection.normal
); );
} else if (item.rt.funcsset.on_use) { } else if (item.rt.funcsset.on_use) {
preventDefault = scripting::on_item_use(player, item); preventDefault = scripting::on_item_use(&player, item);
} }
if (preventDefault) { if (preventDefault) {
return; return;
@ -562,10 +567,10 @@ void PlayerController::updateInteraction(float delta) {
} }
if (Events::jactive(BIND_PLAYER_PICK)) { if (Events::jactive(BIND_PLAYER_PICK)) {
auto coord = selection.actualPosition; auto coord = selection.actualPosition;
pick_block(indices, chunks, player, coord.x, coord.y, coord.z); pick_block(indices, target, player, coord.x, coord.y, coord.z);
} }
} }
Player* PlayerController::getPlayer() { Player* PlayerController::getPlayer() {
return player; return &player;
} }

View File

@ -18,7 +18,7 @@ struct CameraSettings;
struct EngineSettings; struct EngineSettings;
class CameraControl { class CameraControl {
Player* player; Player& player;
std::shared_ptr<Camera> camera; std::shared_ptr<Camera> camera;
const CameraSettings& settings; const CameraSettings& settings;
glm::vec3 offset; glm::vec3 offset;
@ -39,21 +39,19 @@ class CameraControl {
/// @brief Switch active player camera /// @brief Switch active player camera
void switchCamera(); void switchCamera();
public: public:
CameraControl( CameraControl(Player& player, const CameraSettings& settings);
Player* player, const CameraSettings& settings
);
void updateMouse(PlayerInput& input); void updateMouse(PlayerInput& input);
void update(PlayerInput input, float delta, Chunks* chunks); void update(PlayerInput input, float delta, Chunks& chunks);
void refresh(); void refresh();
}; };
class PlayerController { class PlayerController {
const EngineSettings& settings; const EngineSettings& settings;
Level* level; Level& level;
Player* player; Player& player;
PlayerInput input {}; PlayerInput input {};
CameraControl camControl; CameraControl camControl;
BlocksController* blocksController; BlocksController& blocksController;
float interactionTimer = 0.0f; float interactionTimer = 0.0f;
void updateKeyboard(); void updateKeyboard();
@ -71,9 +69,9 @@ class PlayerController {
public: public:
PlayerController( PlayerController(
const EngineSettings& settings, const EngineSettings& settings,
Level* level, Level& level,
Player* player, Player& player,
BlocksController* blocksController BlocksController& blocksController
); );
/// @brief Called after blocks update if not paused /// @brief Called after blocks update if not paused