feat: solid entity material support & minor refactor

This commit is contained in:
MihailRis 2026-03-05 20:52:45 +03:00
parent 01d46b2690
commit dbc7cd56bd
6 changed files with 91 additions and 63 deletions

View file

@ -10,17 +10,19 @@
#include "logic/LevelController.hpp" #include "logic/LevelController.hpp"
#include "logic/PlayerController.hpp" #include "logic/PlayerController.hpp"
#include "objects/Player.hpp" #include "objects/Player.hpp"
#include "physics/Hitbox.hpp"
#include "voxels/Block.hpp" #include "voxels/Block.hpp"
#include "voxels/Chunks.hpp"
#include "world/Level.hpp" #include "world/Level.hpp"
#include "engine/Engine.hpp" #include "engine/Engine.hpp"
LevelFrontend::LevelFrontend( LevelFrontend::LevelFrontend(
Engine& engine, Engine& engine,
Player* currentPlayer, PlayerController& playerController,
LevelController* controller, LevelController& controller,
const EngineSettings& settings const EngineSettings& settings
) )
: level(*controller->getLevel()), : level(*controller.getLevel()),
controller(controller), controller(controller),
assets(*engine.getAssets()), assets(*engine.getAssets()),
contentCache(std::make_unique<ContentGfxCache>( contentCache(std::make_unique<ContentGfxCache>(
@ -36,45 +38,79 @@ LevelFrontend::LevelFrontend(
"block-previews" "block-previews"
); );
auto& rassets = assets; auto& currentPlayer = playerController.getPlayer();
controller->getBlocksController()->listenBlockInteraction( auto& assets = this->assets;
[currentPlayer, controller, &rassets](auto player, const auto& pos, const auto& def, BlockInteraction type) { auto& level = this->level;
const auto& level = *controller->getLevel();
playerController.setFootstepCallback(
[&level, &currentPlayer, &assets](const Hitbox& hitbox) {
const BlockMaterial* material = nullptr;
if (hitbox.groundMaterial.empty()) {
const auto& pos = hitbox.position;
const auto& half = hitbox.getHalfSize();
auto& blockIndices = level.content.getIndices()->blocks;
for (int offsetZ = -1; offsetZ <= 1; offsetZ++) {
for (int offsetX = -1; offsetX <= 1; offsetX++) {
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 = currentPlayer.chunks->get(x, y, z);
if (vox) {
auto& def = blockIndices.require(vox->id);
if (!def.obstacle) {
continue;
}
material = level.content.findBlockMaterial(def.material);
break;
}
}
}
} else {
material = level.content.findBlockMaterial(hitbox.groundMaterial);
}
if (material == nullptr) {
return;
}
auto sound = assets.get<audio::Sound>(material->stepsSound);
glm::vec3 pos {};
auto soundsCamera = currentPlayer.currentCamera.get();
if (currentPlayer.isCurrentCameraBuiltin()) {
soundsCamera = currentPlayer.fpCamera.get();
}
bool relative = soundsCamera == currentPlayer.fpCamera.get();
if (!relative) {
pos = currentPlayer.getPosition();
}
audio::play(
sound,
pos,
relative,
0.333f,
1.0f + (rand() % 6 - 3) * 0.05f,
false,
audio::PRIORITY_LOW,
audio::get_channel_index("regular")
);
});
controller.getBlocksController()->listenBlockInteraction(
[&level, &assets]
(auto player, const auto& pos, const auto& def, BlockInteraction type) {
auto material = level.content.findBlockMaterial(def.material); auto material = level.content.findBlockMaterial(def.material);
if (material == nullptr) { if (material == nullptr) {
return; return;
} }
if (type == BlockInteraction::step) { if (type != BlockInteraction::step) {
auto sound = rassets.get<audio::Sound>(material->stepsSound);
glm::vec3 pos {};
auto soundsCamera = currentPlayer->currentCamera.get();
if (currentPlayer->isCurrentCameraBuiltin()) {
soundsCamera = currentPlayer->fpCamera.get();
}
bool relative = player == currentPlayer &&
soundsCamera == currentPlayer->fpCamera.get();
if (!relative) {
pos = player->getPosition();
}
audio::play(
sound,
pos,
relative,
0.333f,
1.0f + (rand() % 6 - 3) * 0.05f,
false,
audio::PRIORITY_LOW,
audio::get_channel_index("regular")
);
} else {
audio::Sound* sound = nullptr; audio::Sound* sound = nullptr;
switch (type) { switch (type) {
case BlockInteraction::placing: case BlockInteraction::placing:
sound = rassets.get<audio::Sound>(material->placeSound); sound = assets.get<audio::Sound>(material->placeSound);
break; break;
case BlockInteraction::destruction: case BlockInteraction::destruction:
sound = rassets.get<audio::Sound>(material->breakSound); sound = assets.get<audio::Sound>(material->breakSound);
break; break;
default: default:
break; break;
@ -108,6 +144,6 @@ const ContentGfxCache& LevelFrontend::getContentGfxCache() const {
return *contentCache; return *contentCache;
} }
LevelController* LevelFrontend::getController() const { LevelController& LevelFrontend::getController() const {
return controller; return controller;
} }

View file

@ -2,24 +2,24 @@
#include <memory> #include <memory>
class Level;
class Assets; class Assets;
class Player;
class Engine;
class ContentGfxCache; class ContentGfxCache;
class Engine;
class Level;
class LevelController; class LevelController;
class PlayerController;
struct EngineSettings; struct EngineSettings;
class LevelFrontend { class LevelFrontend {
Level& level; Level& level;
LevelController* controller; LevelController& controller;
Assets& assets; Assets& assets;
std::unique_ptr<ContentGfxCache> contentCache; std::unique_ptr<ContentGfxCache> contentCache;
public: public:
LevelFrontend( LevelFrontend(
Engine& engine, Engine& engine,
Player* currentPlayer, PlayerController& currentPlayer,
LevelController* controller, LevelController& controller,
const EngineSettings& settings const EngineSettings& settings
); );
~LevelFrontend(); ~LevelFrontend();
@ -27,5 +27,5 @@ public:
Level& getLevel(); Level& getLevel();
const ContentGfxCache& getContentGfxCache() const; const ContentGfxCache& getContentGfxCache() const;
ContentGfxCache& getContentGfxCache(); ContentGfxCache& getContentGfxCache();
LevelController* getController() const; LevelController& getController() const;
}; };

View file

@ -272,7 +272,7 @@ void Hud::updateWorldGenDebug() {
const auto& chunks = *player.chunks; const auto& chunks = *player.chunks;
uint padding = engine.getSettings().chunks.padding.get(); uint padding = engine.getSettings().chunks.padding.get();
auto generator = auto generator =
frontend.getController()->getChunksController()->getGenerator(); frontend.getController().getChunksController()->getGenerator();
auto debugInfo = generator->createDebugInfo(); auto debugInfo = generator->createDebugInfo();
int width = debugImgWorldGen->getWidth(); int width = debugImgWorldGen->getWidth();
@ -294,7 +294,7 @@ void Hud::updateWorldGenDebug() {
bool isInLoadingZone = bool isInLoadingZone =
frontend.getController() frontend.getController()
->getChunksController() .getChunksController()
->isInLoadingZone(player, padding, ax + ox, az + oz); ->isInLoadingZone(player, padding, ax + ox, az + oz);
data[(flippedZ * width + x) * 4 + 1] = data[(flippedZ * width + x) * 4 + 1] =

View file

@ -68,7 +68,7 @@ LevelScreen::LevelScreen(
); );
frontend = std::make_unique<LevelFrontend>( frontend = std::make_unique<LevelFrontend>(
engine, player, controller.get(), settings engine, *playerController, *controller, settings
); );
renderer = std::make_unique<WorldRenderer>( renderer = std::make_unique<WorldRenderer>(
engine, *frontend, *player engine, *frontend, *player

View file

@ -229,26 +229,8 @@ PlayerController::PlayerController(
} }
void PlayerController::onFootstep(const Hitbox& hitbox) { void PlayerController::onFootstep(const Hitbox& hitbox) {
const auto& pos = hitbox.position; if (footstepCallback) {
const auto& half = hitbox.getHalfSize(); footstepCallback(hitbox);
for (int offsetZ = -1; offsetZ <= 1; offsetZ++) {
for (int offsetX = -1; offsetX <= 1; offsetX++) {
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);
if (vox) {
auto& def = level.content.getIndices()->blocks.require(vox->id);
if (!def.obstacle) {
continue;
}
blocksController.onBlockInteraction(
&player, glm::ivec3(x, y, z), def, BlockInteraction::step
);
return;
}
}
} }
} }
@ -557,3 +539,7 @@ void PlayerController::updateInteraction(const Input& inputEvents, float delta)
Player& PlayerController::getPlayer() { Player& PlayerController::getPlayer() {
return player; return player;
} }
void PlayerController::setFootstepCallback(FootstepCallback&& callback) {
footstepCallback = std::move(callback);
}

View file

@ -18,6 +18,8 @@ struct Hitbox;
struct CameraSettings; struct CameraSettings;
struct EngineSettings; struct EngineSettings;
using FootstepCallback = std::function<void(const Hitbox&)>;
class CameraControl { class CameraControl {
Player& player; Player& player;
std::shared_ptr<Camera> camera; std::shared_ptr<Camera> camera;
@ -57,6 +59,7 @@ class PlayerController {
CameraControl camControl; CameraControl camControl;
BlocksController& blocksController; BlocksController& blocksController;
float interactionTimer = 0.0f; float interactionTimer = 0.0f;
FootstepCallback footstepCallback;
void updateKeyboard(const Input& inputEvents); void updateKeyboard(const Input& inputEvents);
void resetKeyboard(); void resetKeyboard();
@ -89,5 +92,8 @@ public:
void postUpdate( void postUpdate(
float delta, int windowHeight, const Input* inputEvents, bool pause float delta, int windowHeight, const Input* inputEvents, bool pause
); );
Player& getPlayer(); Player& getPlayer();
void setFootstepCallback(FootstepCallback&& callback);
}; };