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);
playerController = std::make_unique<PlayerController>(
settings,
level,
player,
controller->getBlocksController()
*level,
*player,
*controller->getBlocksController()
);
frontend = std::make_unique<LevelFrontend>(

View File

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

View File

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