mirror of
https://github.com/MihailRis/voxelcore.git
synced 2026-10-09 13:01:49 +00:00
commit
3f0c710a47
73 changed files with 750 additions and 305 deletions
5
res/content/base/block_materials/glass.json
Normal file
5
res/content/base/block_materials/glass.json
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"steps-sound": "steps/wood",
|
||||||
|
"place-sound": "blocks/wood_place",
|
||||||
|
"break-sound": "blocks/glass_break"
|
||||||
|
}
|
||||||
5
res/content/base/block_materials/grass.json
Normal file
5
res/content/base/block_materials/grass.json
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"steps-sound": "steps/grass",
|
||||||
|
"place-sound": "steps/grass",
|
||||||
|
"break-sound": "steps/grass"
|
||||||
|
}
|
||||||
5
res/content/base/block_materials/grass_block.json
Normal file
5
res/content/base/block_materials/grass_block.json
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"steps-sound": "steps/grass",
|
||||||
|
"place-sound": "blocks/ground_place",
|
||||||
|
"break-sound": "blocks/ground_break"
|
||||||
|
}
|
||||||
5
res/content/base/block_materials/ground.json
Normal file
5
res/content/base/block_materials/ground.json
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"steps-sound": "steps/ground",
|
||||||
|
"place-sound": "blocks/ground_place",
|
||||||
|
"break-sound": "blocks/ground_break"
|
||||||
|
}
|
||||||
5
res/content/base/block_materials/sand.json
Normal file
5
res/content/base/block_materials/sand.json
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"steps-sound": "steps/sand",
|
||||||
|
"steps-sound": "blocks/ground_place",
|
||||||
|
"break-sound": "blocks/ground_break"
|
||||||
|
}
|
||||||
5
res/content/base/block_materials/stone.json
Normal file
5
res/content/base/block_materials/stone.json
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"steps-sound": "steps/stone",
|
||||||
|
"place-sound": "blocks/stone_place",
|
||||||
|
"break-sound": "blocks/stone_break"
|
||||||
|
}
|
||||||
5
res/content/base/block_materials/wood.json
Normal file
5
res/content/base/block_materials/wood.json
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"steps-sound": "steps/wood",
|
||||||
|
"place-sound": "blocks/wood_place",
|
||||||
|
"break-sound": "blocks/wood_break"
|
||||||
|
}
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
{
|
{
|
||||||
"texture": "dirt"
|
"texture": "dirt",
|
||||||
|
"material": "base:ground"
|
||||||
}
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
{
|
{
|
||||||
"texture": "flower",
|
"texture": "flower",
|
||||||
|
"material": "base:grass",
|
||||||
"draw-group": 1,
|
"draw-group": 1,
|
||||||
"light-passing": true,
|
"light-passing": true,
|
||||||
"obstacle": false,
|
"obstacle": false,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
{
|
{
|
||||||
"texture": "glass",
|
"texture": "glass",
|
||||||
|
"material": "base:glass",
|
||||||
"draw-group": 2,
|
"draw-group": 2,
|
||||||
"light-passing": true,
|
"light-passing": true,
|
||||||
"sky-light-passing": true
|
"sky-light-passing": true
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
{
|
{
|
||||||
"texture": "grass",
|
"texture": "grass",
|
||||||
|
"material": "base:grass",
|
||||||
"draw-group": 1,
|
"draw-group": 1,
|
||||||
"light-passing": true,
|
"light-passing": true,
|
||||||
"obstacle": false,
|
"obstacle": false,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"material": "base:grass_block",
|
||||||
"texture-faces": [
|
"texture-faces": [
|
||||||
"grass_side",
|
"grass_side",
|
||||||
"grass_side",
|
"grass_side",
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
{
|
{
|
||||||
"texture": "leaves"
|
"texture": "leaves",
|
||||||
|
"material": "base:grass"
|
||||||
}
|
}
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
"pane",
|
"pane",
|
||||||
"pane"
|
"pane"
|
||||||
],
|
],
|
||||||
|
"material": "base:wood",
|
||||||
"model": "aabb",
|
"model": "aabb",
|
||||||
"hitbox": [0.0, 0.0, 0.0, 1.0, 1.0, 0.2],
|
"hitbox": [0.0, 0.0, 0.0, 1.0, 1.0, 0.2],
|
||||||
"light-passing": true,
|
"light-passing": true,
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
{
|
{
|
||||||
"texture": "planks"
|
"texture": "planks",
|
||||||
|
"material": "base:wood"
|
||||||
}
|
}
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
{
|
{
|
||||||
"texture": "sand"
|
"texture": "sand",
|
||||||
|
"material": "base:sand"
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
|
"material": "base:wood",
|
||||||
"texture-faces": [
|
"texture-faces": [
|
||||||
"wood",
|
"wood",
|
||||||
"wood",
|
"wood",
|
||||||
|
|
|
||||||
BIN
res/content/base/sounds/blocks/glass_break.ogg
Normal file
BIN
res/content/base/sounds/blocks/glass_break.ogg
Normal file
Binary file not shown.
BIN
res/content/base/sounds/blocks/ground_break.ogg
Normal file
BIN
res/content/base/sounds/blocks/ground_break.ogg
Normal file
Binary file not shown.
BIN
res/content/base/sounds/blocks/ground_place.ogg
Normal file
BIN
res/content/base/sounds/blocks/ground_place.ogg
Normal file
Binary file not shown.
BIN
res/content/base/sounds/blocks/stone_break.ogg
Normal file
BIN
res/content/base/sounds/blocks/stone_break.ogg
Normal file
Binary file not shown.
BIN
res/content/base/sounds/blocks/stone_place.ogg
Normal file
BIN
res/content/base/sounds/blocks/stone_place.ogg
Normal file
Binary file not shown.
BIN
res/content/base/sounds/blocks/wood_break.ogg
Normal file
BIN
res/content/base/sounds/blocks/wood_break.ogg
Normal file
Binary file not shown.
BIN
res/content/base/sounds/blocks/wood_place.ogg
Normal file
BIN
res/content/base/sounds/blocks/wood_place.ogg
Normal file
Binary file not shown.
BIN
res/content/base/sounds/steps/grass_0.ogg
Normal file
BIN
res/content/base/sounds/steps/grass_0.ogg
Normal file
Binary file not shown.
BIN
res/content/base/sounds/steps/grass_1.ogg
Normal file
BIN
res/content/base/sounds/steps/grass_1.ogg
Normal file
Binary file not shown.
BIN
res/content/base/sounds/steps/grass_2.ogg
Normal file
BIN
res/content/base/sounds/steps/grass_2.ogg
Normal file
Binary file not shown.
BIN
res/content/base/sounds/steps/grass_3.ogg
Normal file
BIN
res/content/base/sounds/steps/grass_3.ogg
Normal file
Binary file not shown.
BIN
res/content/base/sounds/steps/ground_0.ogg
Normal file
BIN
res/content/base/sounds/steps/ground_0.ogg
Normal file
Binary file not shown.
BIN
res/content/base/sounds/steps/ground_1.ogg
Normal file
BIN
res/content/base/sounds/steps/ground_1.ogg
Normal file
Binary file not shown.
BIN
res/content/base/sounds/steps/ground_2.ogg
Normal file
BIN
res/content/base/sounds/steps/ground_2.ogg
Normal file
Binary file not shown.
BIN
res/content/base/sounds/steps/ground_3.ogg
Normal file
BIN
res/content/base/sounds/steps/ground_3.ogg
Normal file
Binary file not shown.
BIN
res/content/base/sounds/steps/sand_0.ogg
Normal file
BIN
res/content/base/sounds/steps/sand_0.ogg
Normal file
Binary file not shown.
BIN
res/content/base/sounds/steps/sand_1.ogg
Normal file
BIN
res/content/base/sounds/steps/sand_1.ogg
Normal file
Binary file not shown.
BIN
res/content/base/sounds/steps/sand_2.ogg
Normal file
BIN
res/content/base/sounds/steps/sand_2.ogg
Normal file
Binary file not shown.
BIN
res/content/base/sounds/steps/sand_3.ogg
Normal file
BIN
res/content/base/sounds/steps/sand_3.ogg
Normal file
Binary file not shown.
BIN
res/content/base/sounds/steps/snow_0.ogg
Normal file
BIN
res/content/base/sounds/steps/snow_0.ogg
Normal file
Binary file not shown.
BIN
res/content/base/sounds/steps/snow_1.ogg
Normal file
BIN
res/content/base/sounds/steps/snow_1.ogg
Normal file
Binary file not shown.
BIN
res/content/base/sounds/steps/snow_2.ogg
Normal file
BIN
res/content/base/sounds/steps/snow_2.ogg
Normal file
Binary file not shown.
BIN
res/content/base/sounds/steps/snow_3.ogg
Normal file
BIN
res/content/base/sounds/steps/snow_3.ogg
Normal file
Binary file not shown.
BIN
res/content/base/sounds/steps/snow_4.ogg
Normal file
BIN
res/content/base/sounds/steps/snow_4.ogg
Normal file
Binary file not shown.
BIN
res/content/base/sounds/steps/stone_0.ogg
Normal file
BIN
res/content/base/sounds/steps/stone_0.ogg
Normal file
Binary file not shown.
BIN
res/content/base/sounds/steps/stone_1.ogg
Normal file
BIN
res/content/base/sounds/steps/stone_1.ogg
Normal file
Binary file not shown.
BIN
res/content/base/sounds/steps/stone_2.ogg
Normal file
BIN
res/content/base/sounds/steps/stone_2.ogg
Normal file
Binary file not shown.
BIN
res/content/base/sounds/steps/stone_3.ogg
Normal file
BIN
res/content/base/sounds/steps/stone_3.ogg
Normal file
Binary file not shown.
BIN
res/content/base/sounds/steps/wood_0.ogg
Normal file
BIN
res/content/base/sounds/steps/wood_0.ogg
Normal file
Binary file not shown.
BIN
res/content/base/sounds/steps/wood_1.ogg
Normal file
BIN
res/content/base/sounds/steps/wood_1.ogg
Normal file
Binary file not shown.
BIN
res/content/base/sounds/steps/wood_2.ogg
Normal file
BIN
res/content/base/sounds/steps/wood_2.ogg
Normal file
Binary file not shown.
BIN
res/content/base/sounds/steps/wood_3.ogg
Normal file
BIN
res/content/base/sounds/steps/wood_3.ogg
Normal file
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 6.2 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 6.7 KiB |
|
|
@ -61,6 +61,14 @@ void addLayouts(int env, const std::string& prefix, const fs::path& folder, Asse
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AssetsLoader::tryAddSound(std::string name) {
|
||||||
|
if (name.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fs::path file = SOUNDS_FOLDER"/"+name+".ogg";
|
||||||
|
add(ASSET_SOUND, file, name);
|
||||||
|
}
|
||||||
|
|
||||||
void AssetsLoader::addDefaults(AssetsLoader& loader, const Content* content) {
|
void AssetsLoader::addDefaults(AssetsLoader& loader, const Content* content) {
|
||||||
loader.add(ASSET_FONT, FONTS_FOLDER"/font", "normal");
|
loader.add(ASSET_FONT, FONTS_FOLDER"/font", "normal");
|
||||||
loader.add(ASSET_SHADER, SHADERS_FOLDER"/ui", "ui");
|
loader.add(ASSET_SHADER, SHADERS_FOLDER"/ui", "ui");
|
||||||
|
|
@ -81,6 +89,13 @@ void AssetsLoader::addDefaults(AssetsLoader& loader, const Content* content) {
|
||||||
loader.add(ASSET_TEXTURE, TEXTURES_FOLDER"/misc/sun.png", "misc/sun");
|
loader.add(ASSET_TEXTURE, TEXTURES_FOLDER"/misc/sun.png", "misc/sun");
|
||||||
loader.add(ASSET_TEXTURE, TEXTURES_FOLDER"/gui/crosshair.png", "gui/crosshair");
|
loader.add(ASSET_TEXTURE, TEXTURES_FOLDER"/gui/crosshair.png", "gui/crosshair");
|
||||||
|
|
||||||
|
for (auto& entry : content->getBlockMaterials()) {
|
||||||
|
auto& material = entry.second;
|
||||||
|
loader.tryAddSound(material.stepsSound);
|
||||||
|
loader.tryAddSound(material.placeSound);
|
||||||
|
loader.tryAddSound(material.breakSound);
|
||||||
|
}
|
||||||
|
|
||||||
addLayouts(0, "core", loader.getPaths()->getMainRoot()/fs::path("layouts"), loader);
|
addLayouts(0, "core", loader.getPaths()->getMainRoot()/fs::path("layouts"), loader);
|
||||||
for (auto& entry : content->getPacks()) {
|
for (auto& entry : content->getPacks()) {
|
||||||
auto pack = entry.second.get();
|
auto pack = entry.second.get();
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,8 @@ class AssetsLoader {
|
||||||
std::map<int, aloader_func> loaders;
|
std::map<int, aloader_func> loaders;
|
||||||
std::queue<aloader_entry> entries;
|
std::queue<aloader_entry> entries;
|
||||||
const ResPaths* paths;
|
const ResPaths* paths;
|
||||||
|
|
||||||
|
void tryAddSound(std::string name);
|
||||||
public:
|
public:
|
||||||
AssetsLoader(Assets* assets, const ResPaths* paths);
|
AssetsLoader(Assets* assets, const ResPaths* paths);
|
||||||
void addLoader(int tag, aloader_func func);
|
void addLoader(int tag, aloader_func func);
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,11 @@ ALStream::ALStream(ALAudio* al, std::shared_ptr<PCMStream> source, bool keepSour
|
||||||
ALStream::~ALStream() {
|
ALStream::~ALStream() {
|
||||||
bindSpeaker(0);
|
bindSpeaker(0);
|
||||||
source = nullptr;
|
source = nullptr;
|
||||||
|
|
||||||
|
while (!unusedBuffers.empty()) {
|
||||||
|
al->freeBuffer(unusedBuffers.front());
|
||||||
|
unusedBuffers.pop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<PCMStream> ALStream::getSource() const {
|
std::shared_ptr<PCMStream> ALStream::getSource() const {
|
||||||
|
|
@ -135,6 +140,11 @@ void ALStream::update(double delta) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ALSpeaker* alspeaker = dynamic_cast<ALSpeaker*>(speaker);
|
ALSpeaker* alspeaker = dynamic_cast<ALSpeaker*>(speaker);
|
||||||
|
if (alspeaker->stopped) {
|
||||||
|
speaker = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
uint alsource = alspeaker->source;
|
uint alsource = alspeaker->source;
|
||||||
|
|
||||||
unqueueBuffers(alsource);
|
unqueueBuffers(alsource);
|
||||||
|
|
@ -194,6 +204,8 @@ ALSpeaker::~ALSpeaker() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ALSpeaker::update(const Channel* channel, float masterVolume) {
|
void ALSpeaker::update(const Channel* channel, float masterVolume) {
|
||||||
|
if (source == 0)
|
||||||
|
return;
|
||||||
float gain = this->volume * channel->getVolume()*masterVolume;
|
float gain = this->volume * channel->getVolume()*masterVolume;
|
||||||
AL_CHECK(alSourcef(source, AL_GAIN, gain));
|
AL_CHECK(alSourcef(source, AL_GAIN, gain));
|
||||||
|
|
||||||
|
|
@ -265,7 +277,9 @@ void ALSpeaker::stop() {
|
||||||
AL_CHECK(alSourceUnqueueBuffers(source, 1, &buffer));
|
AL_CHECK(alSourceUnqueueBuffers(source, 1, &buffer));
|
||||||
al->freeBuffer(buffer);
|
al->freeBuffer(buffer);
|
||||||
}
|
}
|
||||||
|
AL_CHECK(alSourcei(source, AL_BUFFER, 0));
|
||||||
al->freeSource(source);
|
al->freeSource(source);
|
||||||
|
source = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -395,8 +409,9 @@ uint ALAudio::getFreeSource(){
|
||||||
}
|
}
|
||||||
ALuint id;
|
ALuint id;
|
||||||
alGenSources(1, &id);
|
alGenSources(1, &id);
|
||||||
if (!AL_GET_ERROR())
|
if (!AL_GET_ERROR()) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
allsources.push_back(id);
|
allsources.push_back(id);
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
#define AL_GET_ERROR() AL::check_errors(__FILE__, __LINE__)
|
#define AL_GET_ERROR() AL::check_errors(__FILE__, __LINE__)
|
||||||
|
|
||||||
namespace AL {
|
namespace AL {
|
||||||
|
/// @return true if no errors
|
||||||
bool check_errors(const std::string& filename, const std::uint_fast32_t line);
|
bool check_errors(const std::string& filename, const std::uint_fast32_t line);
|
||||||
|
|
||||||
/// @brief alGetSourcef wrapper
|
/// @brief alGetSourcef wrapper
|
||||||
|
|
@ -27,6 +28,8 @@ namespace AL {
|
||||||
/// @return field value or default
|
/// @return field value or default
|
||||||
inline float getSourcef(uint source, ALenum field, float def=0.0f) {
|
inline float getSourcef(uint source, ALenum field, float def=0.0f) {
|
||||||
float value = def;
|
float value = def;
|
||||||
|
if (source == 0)
|
||||||
|
return def;
|
||||||
AL_CHECK(alGetSourcef(source, field, &value));
|
AL_CHECK(alGetSourcef(source, field, &value));
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
@ -38,6 +41,8 @@ namespace AL {
|
||||||
/// @return field value or default
|
/// @return field value or default
|
||||||
inline glm::vec3 getSource3f(uint source, ALenum field, glm::vec3 def={}) {
|
inline glm::vec3 getSource3f(uint source, ALenum field, glm::vec3 def={}) {
|
||||||
glm::vec3 value = def;
|
glm::vec3 value = def;
|
||||||
|
if (source == 0)
|
||||||
|
return def;
|
||||||
AL_CHECK(alGetSource3f(source, field, &value.x, &value.y, &value.z));
|
AL_CHECK(alGetSource3f(source, field, &value.x, &value.y, &value.z));
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
@ -49,6 +54,8 @@ namespace AL {
|
||||||
/// @return field value or default
|
/// @return field value or default
|
||||||
inline float getSourcei(uint source, ALenum field, int def=0) {
|
inline float getSourcei(uint source, ALenum field, int def=0) {
|
||||||
int value = def;
|
int value = def;
|
||||||
|
if (source == 0)
|
||||||
|
return def;
|
||||||
AL_CHECK(alGetSourcei(source, field, &value));
|
AL_CHECK(alGetSourcei(source, field, &value));
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -249,6 +249,15 @@ speakerid_t audio::play(
|
||||||
int priority,
|
int priority,
|
||||||
int channel
|
int channel
|
||||||
) {
|
) {
|
||||||
|
if (sound == nullptr) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!sound->variants.empty()) {
|
||||||
|
size_t index = rand() % (sound->variants.size() + 1);
|
||||||
|
if (index < sound->variants.size()) {
|
||||||
|
sound = sound->variants.at(index).get();
|
||||||
|
}
|
||||||
|
}
|
||||||
Speaker* speaker = sound->newInstance(priority, channel);
|
Speaker* speaker = sound->newInstance(priority, channel);
|
||||||
if (speaker == nullptr) {
|
if (speaker == nullptr) {
|
||||||
remove_lower_priority_speaker(priority);
|
remove_lower_priority_speaker(priority);
|
||||||
|
|
@ -359,6 +368,10 @@ size_t audio::count_speakers() {
|
||||||
return speakers.size();
|
return speakers.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t audio::count_streams() {
|
||||||
|
return streams.size();
|
||||||
|
}
|
||||||
|
|
||||||
void audio::update(double delta) {
|
void audio::update(double delta) {
|
||||||
backend->update(delta);
|
backend->update(delta);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -484,6 +484,9 @@ namespace audio {
|
||||||
/// @brief Get alive speakers number (including paused)
|
/// @brief Get alive speakers number (including paused)
|
||||||
extern size_t count_speakers();
|
extern size_t count_speakers();
|
||||||
|
|
||||||
|
/// @brief Get playing streams number (including paused)
|
||||||
|
extern size_t count_streams();
|
||||||
|
|
||||||
/// @brief Update audio streams and sound instanced
|
/// @brief Update audio streams and sound instanced
|
||||||
/// @param delta time elapsed since the last update (seconds)
|
/// @param delta time elapsed since the last update (seconds)
|
||||||
extern void update(double delta);
|
extern void update(double delta);
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,7 @@
|
||||||
#include "ContentPack.h"
|
#include "ContentPack.h"
|
||||||
#include "../logic/scripting/scripting.h"
|
#include "../logic/scripting/scripting.h"
|
||||||
|
|
||||||
ContentBuilder::~ContentBuilder() {
|
ContentBuilder::~ContentBuilder() {}
|
||||||
}
|
|
||||||
|
|
||||||
void ContentBuilder::add(Block* def) {
|
void ContentBuilder::add(Block* def) {
|
||||||
checkIdentifier(def->name);
|
checkIdentifier(def->name);
|
||||||
|
|
@ -29,6 +28,10 @@ void ContentBuilder::add(ContentPackRuntime* pack) {
|
||||||
packs.emplace(pack->getId(), pack);
|
packs.emplace(pack->getId(), pack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ContentBuilder::add(BlockMaterial material) {
|
||||||
|
blockMaterials.emplace(material.name, material);
|
||||||
|
}
|
||||||
|
|
||||||
Block& ContentBuilder::createBlock(std::string id) {
|
Block& ContentBuilder::createBlock(std::string id) {
|
||||||
auto found = blockDefs.find(id);
|
auto found = blockDefs.find(id);
|
||||||
if (found != blockDefs.end()) {
|
if (found != blockDefs.end()) {
|
||||||
|
|
@ -110,7 +113,12 @@ Content* ContentBuilder::build() {
|
||||||
auto indices = new ContentIndices(blockDefsIndices, itemDefsIndices);
|
auto indices = new ContentIndices(blockDefsIndices, itemDefsIndices);
|
||||||
|
|
||||||
auto content = std::make_unique<Content>(
|
auto content = std::make_unique<Content>(
|
||||||
indices, std::move(groups), blockDefs, itemDefs, std::move(packs)
|
indices,
|
||||||
|
std::move(groups),
|
||||||
|
blockDefs,
|
||||||
|
itemDefs,
|
||||||
|
std::move(packs),
|
||||||
|
std::move(blockMaterials)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Now, it's time to resolve foreign keys
|
// Now, it's time to resolve foreign keys
|
||||||
|
|
@ -127,25 +135,27 @@ Content* ContentBuilder::build() {
|
||||||
|
|
||||||
ContentIndices::ContentIndices(
|
ContentIndices::ContentIndices(
|
||||||
std::vector<Block*> blockDefs,
|
std::vector<Block*> blockDefs,
|
||||||
std::vector<ItemDef*> itemDefs)
|
std::vector<ItemDef*> itemDefs
|
||||||
: blockDefs(blockDefs),
|
) : blockDefs(blockDefs),
|
||||||
itemDefs(itemDefs) {
|
itemDefs(itemDefs)
|
||||||
}
|
{}
|
||||||
|
|
||||||
Content::Content(ContentIndices* indices,
|
Content::Content(
|
||||||
std::unique_ptr<DrawGroups> drawGroups,
|
ContentIndices* indices,
|
||||||
std::unordered_map<std::string, Block*> blockDefs,
|
std::unique_ptr<DrawGroups> drawGroups,
|
||||||
std::unordered_map<std::string, ItemDef*> itemDefs,
|
std::unordered_map<std::string, Block*> blockDefs,
|
||||||
std::unordered_map<std::string, std::unique_ptr<ContentPackRuntime>> packs)
|
std::unordered_map<std::string, ItemDef*> itemDefs,
|
||||||
: blockDefs(blockDefs),
|
std::unordered_map<std::string, std::unique_ptr<ContentPackRuntime>> packs,
|
||||||
itemDefs(itemDefs),
|
std::unordered_map<std::string, BlockMaterial> blockMaterials
|
||||||
indices(indices),
|
) : blockDefs(blockDefs),
|
||||||
packs(std::move(packs)),
|
itemDefs(itemDefs),
|
||||||
drawGroups(std::move(drawGroups)) {
|
indices(indices),
|
||||||
}
|
packs(std::move(packs)),
|
||||||
|
blockMaterials(std::move(blockMaterials)),
|
||||||
|
drawGroups(std::move(drawGroups))
|
||||||
|
{}
|
||||||
|
|
||||||
Content::~Content() {
|
Content::~Content() {}
|
||||||
}
|
|
||||||
|
|
||||||
Block* Content::findBlock(std::string id) const {
|
Block* Content::findBlock(std::string id) const {
|
||||||
auto found = blockDefs.find(id);
|
auto found = blockDefs.find(id);
|
||||||
|
|
@ -179,6 +189,14 @@ ItemDef& Content::requireItem(std::string id) const {
|
||||||
return *found->second;
|
return *found->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const BlockMaterial* Content::findBlockMaterial(std::string id) const {
|
||||||
|
auto found = blockMaterials.find(id);
|
||||||
|
if (found == blockMaterials.end()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return &found->second;
|
||||||
|
}
|
||||||
|
|
||||||
const ContentPackRuntime* Content::getPackRuntime(std::string id) const {
|
const ContentPackRuntime* Content::getPackRuntime(std::string id) const {
|
||||||
auto found = packs.find(id);
|
auto found = packs.find(id);
|
||||||
if (found == packs.end()) {
|
if (found == packs.end()) {
|
||||||
|
|
@ -187,6 +205,10 @@ const ContentPackRuntime* Content::getPackRuntime(std::string id) const {
|
||||||
return found->second.get();
|
return found->second.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::unordered_map<std::string, BlockMaterial>& Content::getBlockMaterials() const {
|
||||||
|
return blockMaterials;
|
||||||
|
}
|
||||||
|
|
||||||
const std::unordered_map<std::string, std::unique_ptr<ContentPackRuntime>>& Content::getPacks() const {
|
const std::unordered_map<std::string, std::unique_ptr<ContentPackRuntime>>& Content::getPacks() const {
|
||||||
return packs;
|
return packs;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,10 @@
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
#include "../voxels/Block.h"
|
||||||
|
|
||||||
using DrawGroups = std::set<ubyte>;
|
using DrawGroups = std::set<ubyte>;
|
||||||
|
|
||||||
class Block;
|
|
||||||
class ItemDef;
|
class ItemDef;
|
||||||
class Content;
|
class Content;
|
||||||
class ContentPackRuntime;
|
class ContentPackRuntime;
|
||||||
|
|
@ -48,6 +48,8 @@ class ContentBuilder {
|
||||||
std::unordered_map<std::string, ItemDef*> itemDefs;
|
std::unordered_map<std::string, ItemDef*> itemDefs;
|
||||||
std::vector<std::string> itemIds;
|
std::vector<std::string> itemIds;
|
||||||
|
|
||||||
|
std::unordered_map<std::string, BlockMaterial> blockMaterials;
|
||||||
|
|
||||||
std::unordered_map<std::string, std::unique_ptr<ContentPackRuntime>> packs;
|
std::unordered_map<std::string, std::unique_ptr<ContentPackRuntime>> packs;
|
||||||
public:
|
public:
|
||||||
~ContentBuilder();
|
~ContentBuilder();
|
||||||
|
|
@ -55,6 +57,7 @@ public:
|
||||||
void add(Block* def);
|
void add(Block* def);
|
||||||
void add(ItemDef* def);
|
void add(ItemDef* def);
|
||||||
void add(ContentPackRuntime* pack);
|
void add(ContentPackRuntime* pack);
|
||||||
|
void add(BlockMaterial material);
|
||||||
|
|
||||||
Block& createBlock(std::string id);
|
Block& createBlock(std::string id);
|
||||||
ItemDef& createItem(std::string id);
|
ItemDef& createItem(std::string id);
|
||||||
|
|
@ -65,13 +68,15 @@ public:
|
||||||
Content* build();
|
Content* build();
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Runtime defs cache: indices */
|
/// @brief Runtime defs cache: indices
|
||||||
class ContentIndices {
|
class ContentIndices {
|
||||||
std::vector<Block*> blockDefs;
|
std::vector<Block*> blockDefs;
|
||||||
std::vector<ItemDef*> itemDefs;
|
std::vector<ItemDef*> itemDefs;
|
||||||
public:
|
public:
|
||||||
ContentIndices(std::vector<Block*> blockDefs,
|
ContentIndices(
|
||||||
std::vector<ItemDef*> itemDefs);
|
std::vector<Block*> blockDefs,
|
||||||
|
std::vector<ItemDef*> itemDefs
|
||||||
|
);
|
||||||
|
|
||||||
inline Block* getBlockDef(blockid_t id) const {
|
inline Block* getBlockDef(blockid_t id) const {
|
||||||
if (id >= blockDefs.size())
|
if (id >= blockDefs.size())
|
||||||
|
|
@ -109,14 +114,18 @@ class Content {
|
||||||
std::unordered_map<std::string, ItemDef*> itemDefs;
|
std::unordered_map<std::string, ItemDef*> itemDefs;
|
||||||
std::unique_ptr<ContentIndices> indices;
|
std::unique_ptr<ContentIndices> indices;
|
||||||
std::unordered_map<std::string, std::unique_ptr<ContentPackRuntime>> packs;
|
std::unordered_map<std::string, std::unique_ptr<ContentPackRuntime>> packs;
|
||||||
|
std::unordered_map<std::string, BlockMaterial> blockMaterials;
|
||||||
public:
|
public:
|
||||||
std::unique_ptr<DrawGroups> const drawGroups;
|
std::unique_ptr<DrawGroups> const drawGroups;
|
||||||
|
|
||||||
Content(ContentIndices* indices,
|
Content(
|
||||||
std::unique_ptr<DrawGroups> drawGroups,
|
ContentIndices* indices,
|
||||||
std::unordered_map<std::string, Block*> blockDefs,
|
std::unique_ptr<DrawGroups> drawGroups,
|
||||||
std::unordered_map<std::string, ItemDef*> itemDefs,
|
std::unordered_map<std::string, Block*> blockDefs,
|
||||||
std::unordered_map<std::string, std::unique_ptr<ContentPackRuntime>> packs);
|
std::unordered_map<std::string, ItemDef*> itemDefs,
|
||||||
|
std::unordered_map<std::string, std::unique_ptr<ContentPackRuntime>> packs,
|
||||||
|
std::unordered_map<std::string, BlockMaterial> blockMaterials
|
||||||
|
);
|
||||||
~Content();
|
~Content();
|
||||||
|
|
||||||
inline ContentIndices* getIndices() const {
|
inline ContentIndices* getIndices() const {
|
||||||
|
|
@ -129,8 +138,11 @@ public:
|
||||||
ItemDef* findItem(std::string id) const;
|
ItemDef* findItem(std::string id) const;
|
||||||
ItemDef& requireItem(std::string id) const;
|
ItemDef& requireItem(std::string id) const;
|
||||||
|
|
||||||
|
const BlockMaterial* findBlockMaterial(std::string id) const;
|
||||||
|
|
||||||
const ContentPackRuntime* getPackRuntime(std::string id) const;
|
const ContentPackRuntime* getPackRuntime(std::string id) const;
|
||||||
|
|
||||||
|
const std::unordered_map<std::string, BlockMaterial>& getBlockMaterials() const;
|
||||||
const std::unordered_map<std::string, std::unique_ptr<ContentPackRuntime>>& getPacks() const;
|
const std::unordered_map<std::string, std::unique_ptr<ContentPackRuntime>>& getPacks() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,9 @@ struct contententry {
|
||||||
|
|
||||||
// TODO: make it unified for all types of content
|
// TODO: make it unified for all types of content
|
||||||
|
|
||||||
/* Content indices lookup table or report
|
/// @brief Content indices lookup table or report
|
||||||
used to convert world with different indices
|
/// used to convert world with different indices
|
||||||
Building with indices.json */
|
/// Building with indices.json
|
||||||
class ContentLUT {
|
class ContentLUT {
|
||||||
std::vector<blockid_t> blocks;
|
std::vector<blockid_t> blocks;
|
||||||
std::vector<std::string> blockNames;
|
std::vector<std::string> blockNames;
|
||||||
|
|
|
||||||
|
|
@ -144,6 +144,8 @@ void ContentLoader::loadBlock(Block& def, std::string name, fs::path file) {
|
||||||
def.model = BlockModel::none;
|
def.model = BlockModel::none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
root->str("material", def.material);
|
||||||
|
|
||||||
// rotation profile
|
// rotation profile
|
||||||
std::string profile = "none";
|
std::string profile = "none";
|
||||||
root->str("rotation", profile);
|
root->str("rotation", profile);
|
||||||
|
|
@ -301,6 +303,15 @@ void ContentLoader::loadItem(ItemDef& def, std::string full, std::string name) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BlockMaterial ContentLoader::loadBlockMaterial(fs::path file, std::string full) {
|
||||||
|
auto root = files::read_json(file);
|
||||||
|
BlockMaterial material {full};
|
||||||
|
root->str("steps-sound", material.stepsSound);
|
||||||
|
root->str("place-sound", material.placeSound);
|
||||||
|
root->str("break-sound", material.breakSound);
|
||||||
|
return material;
|
||||||
|
}
|
||||||
|
|
||||||
void ContentLoader::load(ContentBuilder& builder) {
|
void ContentLoader::load(ContentBuilder& builder) {
|
||||||
std::cout << "-- loading pack [" << pack->id << "]" << std::endl;
|
std::cout << "-- loading pack [" << pack->id << "]" << std::endl;
|
||||||
|
|
||||||
|
|
@ -361,4 +372,13 @@ void ContentLoader::load(ContentBuilder& builder) {
|
||||||
stats.totalItems++;
|
stats.totalItems++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fs::path materialsDir = folder / fs::u8path("block_materials");
|
||||||
|
if (fs::is_directory(materialsDir)) {
|
||||||
|
for (auto entry : fs::directory_iterator(materialsDir)) {
|
||||||
|
fs::path file = entry.path();
|
||||||
|
std::string name = pack->id+":"+file.stem().u8string();
|
||||||
|
builder.add(loadBlockMaterial(file, name));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
#ifndef CONTENT_CONTENT_LOADER_H_
|
#ifndef CONTENT_CONTENT_LOADER_H_
|
||||||
#define CONTENT_CONTENT_LOADER_H_
|
#define CONTENT_CONTENT_LOADER_H_
|
||||||
|
|
||||||
|
#include "../voxels/Block.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
class Block;
|
|
||||||
class ItemDef;
|
class ItemDef;
|
||||||
struct ContentPack;
|
struct ContentPack;
|
||||||
class ContentBuilder;
|
class ContentBuilder;
|
||||||
|
|
@ -22,12 +23,15 @@ class ContentLoader {
|
||||||
void loadBlock(Block& def, std::string full, std::string name);
|
void loadBlock(Block& def, std::string full, std::string name);
|
||||||
void loadCustomBlockModel(Block& def, dynamic::Map* primitives);
|
void loadCustomBlockModel(Block& def, dynamic::Map* primitives);
|
||||||
void loadItem(ItemDef& def, std::string full, std::string name);
|
void loadItem(ItemDef& def, std::string full, std::string name);
|
||||||
|
BlockMaterial loadBlockMaterial(fs::path file, std::string full);
|
||||||
public:
|
public:
|
||||||
ContentLoader(ContentPack* pack);
|
ContentLoader(ContentPack* pack);
|
||||||
|
|
||||||
bool fixPackIndices(std::filesystem::path folder,
|
bool fixPackIndices(
|
||||||
dynamic::Map* indicesRoot,
|
fs::path folder,
|
||||||
std::string contentSection);
|
dynamic::Map* indicesRoot,
|
||||||
|
std::string contentSection
|
||||||
|
);
|
||||||
void fixPackIndices();
|
void fixPackIndices();
|
||||||
void loadBlock(Block& def, std::string name, fs::path file);
|
void loadBlock(Block& def, std::string name, fs::path file);
|
||||||
void loadItem(ItemDef& def, std::string name, fs::path file);
|
void loadItem(ItemDef& def, std::string name, fs::path file);
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,70 @@
|
||||||
#include "LevelFrontend.h"
|
#include "LevelFrontend.h"
|
||||||
|
|
||||||
#include "../world/Level.h"
|
|
||||||
#include "../assets/Assets.h"
|
|
||||||
#include "../graphics/Atlas.h"
|
|
||||||
#include "BlocksPreview.h"
|
#include "BlocksPreview.h"
|
||||||
#include "ContentGfxCache.h"
|
#include "ContentGfxCache.h"
|
||||||
|
|
||||||
|
#include "../audio/audio.h"
|
||||||
|
#include "../world/Level.h"
|
||||||
|
#include "../voxels/Block.h"
|
||||||
|
#include "../assets/Assets.h"
|
||||||
|
#include "../graphics/Atlas.h"
|
||||||
|
#include "../content/Content.h"
|
||||||
|
|
||||||
|
#include "../logic/LevelController.h"
|
||||||
|
#include "../logic/PlayerController.h"
|
||||||
|
|
||||||
LevelFrontend::LevelFrontend(Level* level, Assets* assets)
|
LevelFrontend::LevelFrontend(Level* level, Assets* assets)
|
||||||
: level(level),
|
: level(level),
|
||||||
assets(assets),
|
assets(assets),
|
||||||
contentCache(std::make_unique<ContentGfxCache>(level->content, assets)),
|
contentCache(std::make_unique<ContentGfxCache>(level->content, assets)),
|
||||||
blocksAtlas(BlocksPreview::build(contentCache.get(), assets, level->content)) {
|
blocksAtlas(BlocksPreview::build(contentCache.get(), assets, level->content))
|
||||||
|
{}
|
||||||
|
|
||||||
|
void LevelFrontend::observe(LevelController* controller) {
|
||||||
|
controller->getPlayerController()->listenBlockInteraction(
|
||||||
|
[=](Player*, glm::ivec3 pos, const Block* def, BlockInteraction type) {
|
||||||
|
auto material = level->content->findBlockMaterial(def->material);
|
||||||
|
if (material == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == BlockInteraction::step) {
|
||||||
|
auto sound = assets->getSound(material->stepsSound);
|
||||||
|
audio::play(
|
||||||
|
sound,
|
||||||
|
glm::vec3(),
|
||||||
|
true,
|
||||||
|
0.333f,
|
||||||
|
1.0f + (rand() % 6 - 3) * 0.05f,
|
||||||
|
false,
|
||||||
|
audio::PRIORITY_LOW,
|
||||||
|
audio::get_channel_index("regular")
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
audio::Sound* sound = nullptr;
|
||||||
|
switch (type) {
|
||||||
|
case BlockInteraction::placing:
|
||||||
|
sound = assets->getSound(material->placeSound);
|
||||||
|
break;
|
||||||
|
case BlockInteraction::destruction:
|
||||||
|
sound = assets->getSound(material->breakSound);
|
||||||
|
break;
|
||||||
|
case BlockInteraction::step:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
audio::play(
|
||||||
|
sound,
|
||||||
|
glm::vec3(pos.x, pos.y, pos.z) + 0.5f,
|
||||||
|
false,
|
||||||
|
1.0f,
|
||||||
|
1.0f + (rand() % 6 - 3) * 0.05f,
|
||||||
|
false,
|
||||||
|
audio::PRIORITY_NORMAL,
|
||||||
|
audio::get_channel_index("regular")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
LevelFrontend::~LevelFrontend() {
|
LevelFrontend::~LevelFrontend() {
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ class Level;
|
||||||
class Assets;
|
class Assets;
|
||||||
class BlocksPreview;
|
class BlocksPreview;
|
||||||
class ContentGfxCache;
|
class ContentGfxCache;
|
||||||
|
class LevelController;
|
||||||
|
|
||||||
class LevelFrontend {
|
class LevelFrontend {
|
||||||
Level* level;
|
Level* level;
|
||||||
|
|
@ -18,6 +19,8 @@ public:
|
||||||
LevelFrontend(Level* level, Assets* assets);
|
LevelFrontend(Level* level, Assets* assets);
|
||||||
~LevelFrontend();
|
~LevelFrontend();
|
||||||
|
|
||||||
|
void observe(LevelController* controller);
|
||||||
|
|
||||||
Level* getLevel() const;
|
Level* getLevel() const;
|
||||||
Assets* getAssets() const;
|
Assets* getAssets() const;
|
||||||
ContentGfxCache* getContentGfxCache() const;
|
ContentGfxCache* getContentGfxCache() const;
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "gui/controls.h"
|
#include "gui/controls.h"
|
||||||
|
#include "../audio/audio.h"
|
||||||
#include "../graphics/Mesh.h"
|
#include "../graphics/Mesh.h"
|
||||||
#include "../objects/Player.h"
|
#include "../objects/Player.h"
|
||||||
#include "../physics/Hitbox.h"
|
#include "../physics/Hitbox.h"
|
||||||
|
|
@ -52,6 +53,10 @@ std::shared_ptr<UINode> create_debug_panel(
|
||||||
panel->add(create_label([](){
|
panel->add(create_label([](){
|
||||||
return L"meshes: " + std::to_wstring(Mesh::meshesCount);
|
return L"meshes: " + std::to_wstring(Mesh::meshesCount);
|
||||||
}));
|
}));
|
||||||
|
panel->add(create_label([](){
|
||||||
|
return L"speakers: " + std::to_wstring(audio::count_speakers())+
|
||||||
|
L" streams: " + std::to_wstring(audio::count_streams());
|
||||||
|
}));
|
||||||
panel->add(create_label([=](){
|
panel->add(create_label([=](){
|
||||||
auto& settings = engine->getSettings();
|
auto& settings = engine->getSettings();
|
||||||
bool culling = settings.graphics.frustumCulling;
|
bool culling = settings.graphics.frustumCulling;
|
||||||
|
|
|
||||||
|
|
@ -100,6 +100,8 @@ LevelScreen::LevelScreen(Engine* engine, Level* level) : Screen(engine) {
|
||||||
worldRenderer = std::make_unique<WorldRenderer>(engine, frontend.get(), controller->getPlayer());
|
worldRenderer = std::make_unique<WorldRenderer>(engine, frontend.get(), controller->getPlayer());
|
||||||
hud = std::make_unique<Hud>(engine, frontend.get(), controller->getPlayer());
|
hud = std::make_unique<Hud>(engine, frontend.get(), controller->getPlayer());
|
||||||
|
|
||||||
|
frontend->observe(controller.get());
|
||||||
|
|
||||||
backlight = settings.graphics.backlight;
|
backlight = settings.graphics.backlight;
|
||||||
|
|
||||||
animator = std::make_unique<TextureAnimator>();
|
animator = std::make_unique<TextureAnimator>();
|
||||||
|
|
@ -156,9 +158,9 @@ void LevelScreen::update(float delta) {
|
||||||
auto player = controller->getPlayer();
|
auto player = controller->getPlayer();
|
||||||
auto camera = player->camera;
|
auto camera = player->camera;
|
||||||
audio::set_listener(
|
audio::set_listener(
|
||||||
camera->position,
|
camera->position-camera->dir,
|
||||||
player->hitbox->velocity,
|
player->hitbox->velocity,
|
||||||
camera->position+camera->dir,
|
camera->dir,
|
||||||
camera->up
|
camera->up
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,3 +57,7 @@ Level* LevelController::getLevel() {
|
||||||
Player* LevelController::getPlayer() {
|
Player* LevelController::getPlayer() {
|
||||||
return player->getPlayer();
|
return player->getPlayer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PlayerController* LevelController::getPlayerController() {
|
||||||
|
return player.get();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
class Level;
|
class Level;
|
||||||
class Player;
|
class Player;
|
||||||
|
|
||||||
/* LevelController manages other controllers */
|
/// @brief LevelController manages other controllers
|
||||||
class LevelController {
|
class LevelController {
|
||||||
EngineSettings& settings;
|
EngineSettings& settings;
|
||||||
std::unique_ptr<Level> level;
|
std::unique_ptr<Level> level;
|
||||||
|
|
@ -22,20 +22,22 @@ class LevelController {
|
||||||
public:
|
public:
|
||||||
LevelController(EngineSettings& settings, Level* level);
|
LevelController(EngineSettings& settings, Level* level);
|
||||||
|
|
||||||
/*
|
/// @param delta time elapsed since the last update
|
||||||
@param delta time elapsed since the last update
|
/// @param input is user input allowed to be handled
|
||||||
@param input is user input allowed to be handled
|
/// @param pause is world and player simulation paused
|
||||||
@param pause is world and player simulation paused
|
void update(
|
||||||
*/
|
float delta,
|
||||||
void update(float delta,
|
bool input,
|
||||||
bool input,
|
bool pause
|
||||||
bool pause);
|
);
|
||||||
|
|
||||||
void onWorldSave();
|
void onWorldSave();
|
||||||
void onWorldQuit();
|
void onWorldQuit();
|
||||||
|
|
||||||
Level* getLevel();
|
Level* getLevel();
|
||||||
Player* getPlayer();
|
Player* getPlayer();
|
||||||
|
|
||||||
|
PlayerController* getPlayerController();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // LOGIC_LEVEL_CONTROLLER_H_
|
#endif // LOGIC_LEVEL_CONTROLLER_H_
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,14 @@
|
||||||
|
|
||||||
#include "../core_defs.h"
|
#include "../core_defs.h"
|
||||||
|
|
||||||
|
#define _USE_MATH_DEFINES
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
const float CAM_SHAKE_OFFSET = 0.025f;
|
const float CAM_SHAKE_OFFSET = 0.025f;
|
||||||
const float CAM_SHAKE_OFFSET_Y = 0.031f;
|
const float CAM_SHAKE_OFFSET_Y = 0.031f;
|
||||||
const float CAM_SHAKE_SPEED = 1.75f;
|
const float CAM_SHAKE_SPEED = 1.75f;
|
||||||
const float CAM_SHAKE_DELTA_K = 10.0f;
|
const float CAM_SHAKE_DELTA_K = 10.0f;
|
||||||
|
const float STEPS_SPEED = 1.75f;
|
||||||
const float ZOOM_SPEED = 16.0f;
|
const float ZOOM_SPEED = 16.0f;
|
||||||
const float CROUCH_ZOOM = 0.9f;
|
const float CROUCH_ZOOM = 0.9f;
|
||||||
const float RUN_ZOOM = 1.1f;
|
const float RUN_ZOOM = 1.1f;
|
||||||
|
|
@ -32,11 +36,10 @@ const float CROUCH_SHIFT_Y = -0.2f;
|
||||||
|
|
||||||
|
|
||||||
CameraControl::CameraControl(std::shared_ptr<Player> player, const CameraSettings& settings)
|
CameraControl::CameraControl(std::shared_ptr<Player> player, const CameraSettings& settings)
|
||||||
: player(player),
|
: player(player),
|
||||||
camera(player->camera),
|
camera(player->camera),
|
||||||
currentViewCamera(player->currentCamera),
|
settings(settings),
|
||||||
settings(settings),
|
offset(0.0f, 0.7f, 0.0f) {
|
||||||
offset(0.0f, 0.7f, 0.0f) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CameraControl::refresh() {
|
void CameraControl::refresh() {
|
||||||
|
|
@ -46,7 +49,10 @@ void CameraControl::refresh() {
|
||||||
void CameraControl::updateMouse(PlayerInput& input) {
|
void CameraControl::updateMouse(PlayerInput& input) {
|
||||||
glm::vec2& cam = player->cam;
|
glm::vec2& cam = player->cam;
|
||||||
|
|
||||||
float sensitivity = (input.zoom ? settings.sensitivity / 4.f : settings.sensitivity);
|
float sensitivity = (input.zoom
|
||||||
|
? settings.sensitivity / 4.f
|
||||||
|
: settings.sensitivity);
|
||||||
|
|
||||||
cam -= glm::degrees(Events::delta / (float)Window::height * sensitivity);
|
cam -= glm::degrees(Events::delta / (float)Window::height * sensitivity);
|
||||||
|
|
||||||
if (cam.y < -89.9f) {
|
if (cam.y < -89.9f) {
|
||||||
|
|
@ -66,66 +72,93 @@ void CameraControl::updateMouse(PlayerInput& input) {
|
||||||
camera->rotate(glm::radians(cam.y), glm::radians(cam.x), 0);
|
camera->rotate(glm::radians(cam.y), glm::radians(cam.x), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CameraControl::update(PlayerInput& input, float delta, Chunks* chunks) {
|
glm::vec3 CameraControl::updateCameraShaking(float delta) {
|
||||||
Hitbox* hitbox = player->hitbox.get();
|
glm::vec3 offset {};
|
||||||
|
auto hitbox = player->hitbox.get();
|
||||||
|
const float k = CAM_SHAKE_DELTA_K;
|
||||||
|
const float oh = CAM_SHAKE_OFFSET;
|
||||||
|
const float ov = CAM_SHAKE_OFFSET_Y;
|
||||||
|
const glm::vec3& vel = hitbox->velocity;
|
||||||
|
|
||||||
|
interpVel = interpVel * (1.0f - delta * 5) + vel * delta * 0.1f;
|
||||||
|
if (hitbox->grounded && interpVel.y < 0.0f){
|
||||||
|
interpVel.y *= -30.0f;
|
||||||
|
}
|
||||||
|
shake = shake * (1.0f - delta * k);
|
||||||
|
if (hitbox->grounded) {
|
||||||
|
float f = glm::length(glm::vec2(vel.x, vel.z));
|
||||||
|
shakeTimer += delta * f * CAM_SHAKE_SPEED;
|
||||||
|
shake += f * delta * k;
|
||||||
|
}
|
||||||
|
offset += camera->right * glm::sin(shakeTimer) * oh * shake;
|
||||||
|
offset += camera->up * glm::abs(glm::cos(shakeTimer)) * ov * shake;
|
||||||
|
offset -= glm::min(interpVel * 0.05f, 1.0f);
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CameraControl::updateFovEffects(const PlayerInput& input, float delta) {
|
||||||
|
auto hitbox = player->hitbox.get();
|
||||||
|
bool crouch = input.shift && hitbox->grounded && !input.sprint;
|
||||||
|
|
||||||
|
float dt = fmin(1.0f, delta * ZOOM_SPEED);
|
||||||
|
float zoomValue = 1.0f;
|
||||||
|
if (crouch){
|
||||||
|
offset += glm::vec3(0.f, CROUCH_SHIFT_Y, 0.f);
|
||||||
|
zoomValue = CROUCH_ZOOM;
|
||||||
|
} else if (input.sprint){
|
||||||
|
zoomValue = RUN_ZOOM;
|
||||||
|
}
|
||||||
|
if (input.zoom)
|
||||||
|
zoomValue *= C_ZOOM;
|
||||||
|
camera->zoom = zoomValue * dt + camera->zoom * (1.0f - dt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// temporary solution
|
||||||
|
// more extensible but uglier
|
||||||
|
void CameraControl::switchCamera() {
|
||||||
|
const std::vector<std::shared_ptr<Camera>> playerCameras {
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
if (static_cast<size_t>(index) != playerCameras.size()) {
|
||||||
|
index = (index + 1) % playerCameras.size();
|
||||||
|
player->currentCamera = playerCameras.at(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CameraControl::update(PlayerInput& input, float delta, Chunks* chunks) {
|
||||||
offset = glm::vec3(0.0f, 0.7f, 0.0f);
|
offset = glm::vec3(0.0f, 0.7f, 0.0f);
|
||||||
|
|
||||||
if (settings.shaking && !input.cheat) {
|
if (settings.shaking && !input.cheat) {
|
||||||
const float k = CAM_SHAKE_DELTA_K;
|
offset += updateCameraShaking(delta);
|
||||||
const float oh = CAM_SHAKE_OFFSET;
|
|
||||||
const float ov = CAM_SHAKE_OFFSET_Y;
|
|
||||||
const glm::vec3& vel = hitbox->velocity;
|
|
||||||
|
|
||||||
interpVel = interpVel * (1.0f - delta * 5) + vel * delta * 0.1f;
|
|
||||||
if (hitbox->grounded && interpVel.y < 0.0f){
|
|
||||||
interpVel.y *= -30.0f;
|
|
||||||
}
|
|
||||||
shake = shake * (1.0f - delta * k);
|
|
||||||
if (hitbox->grounded) {
|
|
||||||
float f = glm::length(glm::vec2(vel.x, vel.z));
|
|
||||||
shakeTimer += delta * f * CAM_SHAKE_SPEED;
|
|
||||||
shake += f * delta * k;
|
|
||||||
}
|
|
||||||
offset += camera->right * glm::sin(shakeTimer) * oh * shake;
|
|
||||||
offset += camera->up * glm::abs(glm::cos(shakeTimer)) * ov * shake;
|
|
||||||
offset -= glm::min(interpVel * 0.05f, 1.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings.fovEvents){
|
if (settings.fovEvents){
|
||||||
bool crouch = input.shift && hitbox->grounded && !input.sprint;
|
updateFovEffects(input, delta);
|
||||||
|
}
|
||||||
float dt = fmin(1.0f, delta * ZOOM_SPEED);
|
if (input.cameraMode) {
|
||||||
float zoomValue = 1.0f;
|
switchCamera();
|
||||||
if (crouch){
|
|
||||||
offset += glm::vec3(0.f, CROUCH_SHIFT_Y, 0.f);
|
|
||||||
zoomValue = CROUCH_ZOOM;
|
|
||||||
} else if (input.sprint){
|
|
||||||
zoomValue = RUN_ZOOM;
|
|
||||||
}
|
|
||||||
if (input.zoom)
|
|
||||||
zoomValue *= C_ZOOM;
|
|
||||||
camera->zoom = zoomValue * dt + camera->zoom * (1.0f - dt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto spCamera = player->spCamera;
|
auto spCamera = player->spCamera;
|
||||||
auto tpCamera = player->tpCamera;
|
auto tpCamera = player->tpCamera;
|
||||||
|
|
||||||
if (input.cameraMode) { //ugly but effective
|
|
||||||
if (player->currentCamera == camera)
|
|
||||||
player->currentCamera = tpCamera;
|
|
||||||
else if (player->currentCamera == spCamera)
|
|
||||||
player->currentCamera = camera;
|
|
||||||
else if (player->currentCamera == tpCamera)
|
|
||||||
player->currentCamera = spCamera;
|
|
||||||
}
|
|
||||||
if (player->currentCamera == spCamera) {
|
if (player->currentCamera == spCamera) {
|
||||||
spCamera->position = chunks->rayCastToObstacle(camera->position, camera->front, 3.0f) - 0.2f*(camera->front);
|
spCamera->position = chunks->rayCastToObstacle(camera->position, camera->front, 3.0f) - 0.2f * camera->front;
|
||||||
spCamera->dir = -camera->dir;
|
spCamera->dir = -camera->dir;
|
||||||
spCamera->front = -camera->front;
|
spCamera->front = -camera->front;
|
||||||
}
|
}
|
||||||
else if (player->currentCamera == tpCamera) {
|
else if (player->currentCamera == tpCamera) {
|
||||||
tpCamera->position = chunks->rayCastToObstacle(camera->position, -camera->front, 3.0f) + 0.2f * (camera->front);
|
tpCamera->position = chunks->rayCastToObstacle(camera->position, -camera->front, 3.0f) + 0.2f * camera->front;
|
||||||
tpCamera->dir = camera->dir;
|
tpCamera->dir = camera->dir;
|
||||||
tpCamera->front = camera->front;
|
tpCamera->front = camera->front;
|
||||||
}
|
}
|
||||||
|
|
@ -140,11 +173,62 @@ int PlayerController::selectedBlockStates = 0;
|
||||||
PlayerController::PlayerController(
|
PlayerController::PlayerController(
|
||||||
Level* level,
|
Level* level,
|
||||||
const EngineSettings& settings,
|
const EngineSettings& settings,
|
||||||
BlocksController* blocksController)
|
BlocksController* blocksController
|
||||||
: level(level),
|
) : level(level),
|
||||||
player(level->getObject<Player>(0)),
|
player(level->getObject<Player>(0)),
|
||||||
camControl(player, settings.camera),
|
camControl(player, settings.camera),
|
||||||
blocksController(blocksController) {
|
blocksController(blocksController)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void PlayerController::onBlockInteraction(
|
||||||
|
glm::ivec3 pos,
|
||||||
|
const Block* def,
|
||||||
|
BlockInteraction type
|
||||||
|
) {
|
||||||
|
for (auto callback : blockInteractionCallbacks) {
|
||||||
|
callback(player.get(), pos, def, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerController::onFootstep() {
|
||||||
|
auto hitbox = player->hitbox.get();
|
||||||
|
glm::vec3 pos = hitbox->position;
|
||||||
|
glm::vec3 half = hitbox->halfsize;
|
||||||
|
|
||||||
|
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 = level->chunks->get(x, y, z);
|
||||||
|
if (vox) {
|
||||||
|
auto def = level->content->getIndices()->getBlockDef(vox->id);
|
||||||
|
if (!def->obstacle)
|
||||||
|
continue;
|
||||||
|
onBlockInteraction(
|
||||||
|
glm::ivec3(x, y, z), def,
|
||||||
|
BlockInteraction::step
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerController::updateFootsteps(float delta) {
|
||||||
|
auto hitbox = player->hitbox.get();
|
||||||
|
|
||||||
|
if (hitbox->grounded) {
|
||||||
|
const glm::vec3& vel = hitbox->velocity;
|
||||||
|
float f = glm::length(glm::vec2(vel.x, vel.z));
|
||||||
|
stepsTimer += delta * f * STEPS_SPEED;
|
||||||
|
if (stepsTimer >= M_PI) {
|
||||||
|
stepsTimer = fmod(stepsTimer, M_PI);
|
||||||
|
onFootstep();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
stepsTimer = M_PI;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerController::update(float delta, bool input, bool pause) {
|
void PlayerController::update(float delta, bool input, bool pause) {
|
||||||
|
|
@ -154,6 +238,7 @@ void PlayerController::update(float delta, bool input, bool pause) {
|
||||||
} else {
|
} else {
|
||||||
resetKeyboard();
|
resetKeyboard();
|
||||||
}
|
}
|
||||||
|
updateFootsteps(delta);
|
||||||
updateCamera(delta, input);
|
updateCamera(delta, input);
|
||||||
updateControls(delta);
|
updateControls(delta);
|
||||||
|
|
||||||
|
|
@ -289,12 +374,17 @@ void PlayerController::updateInteraction(){
|
||||||
uint8_t states = determine_rotation(def, norm, camera->dir);
|
uint8_t states = determine_rotation(def, norm, camera->dir);
|
||||||
|
|
||||||
if (lclick && !input.shift && item->rt.funcsset.on_block_break_by) {
|
if (lclick && !input.shift && item->rt.funcsset.on_block_break_by) {
|
||||||
|
// TODO: move scripting to interaction callbacks
|
||||||
if (scripting::on_item_break_block(player.get(), item, x, y, z))
|
if (scripting::on_item_break_block(player.get(), item, x, y, z))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Block* target = indices->getBlockDef(vox->id);
|
Block* target = indices->getBlockDef(vox->id);
|
||||||
if (lclick && target->breakable){
|
if (lclick && target->breakable){
|
||||||
|
onBlockInteraction(
|
||||||
|
glm::ivec3(x, y, z), target,
|
||||||
|
BlockInteraction::destruction
|
||||||
|
);
|
||||||
blocksController->breakBlock(player.get(), target, x, y, z);
|
blocksController->breakBlock(player.get(), target, x, y, z);
|
||||||
}
|
}
|
||||||
if (rclick && !input.shift) {
|
if (rclick && !input.shift) {
|
||||||
|
|
@ -331,9 +421,14 @@ void PlayerController::updateInteraction(){
|
||||||
chosenBlock = 0;
|
chosenBlock = 0;
|
||||||
}
|
}
|
||||||
if (chosenBlock != vox->id && chosenBlock) {
|
if (chosenBlock != vox->id && chosenBlock) {
|
||||||
|
onBlockInteraction(
|
||||||
|
glm::ivec3(x, y, z), def,
|
||||||
|
BlockInteraction::placing
|
||||||
|
);
|
||||||
chunks->set(x, y, z, chosenBlock, states);
|
chunks->set(x, y, z, chosenBlock, states);
|
||||||
lighting->onBlockSet(x,y,z, chosenBlock);
|
lighting->onBlockSet(x,y,z, chosenBlock);
|
||||||
if (def->rt.funcsset.onplaced) {
|
if (def->rt.funcsset.onplaced) {
|
||||||
|
// TODO: move scripting to interaction callbacks
|
||||||
scripting::on_block_placed(player.get(), def, x, y, z);
|
scripting::on_block_placed(player.get(), def, x, y, z);
|
||||||
}
|
}
|
||||||
blocksController->updateSides(x, y, z);
|
blocksController->updateSides(x, y, z);
|
||||||
|
|
@ -358,3 +453,7 @@ void PlayerController::updateInteraction(){
|
||||||
Player* PlayerController::getPlayer() {
|
Player* PlayerController::getPlayer() {
|
||||||
return player.get();
|
return player.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PlayerController::listenBlockInteraction(on_block_interaction callback) {
|
||||||
|
blockInteractionCallbacks.push_back(callback);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
#define PLAYER_CONTROL_H_
|
#define PLAYER_CONTROL_H_
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
#include <functional>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
#include "../settings.h"
|
#include "../settings.h"
|
||||||
|
|
@ -9,48 +11,87 @@
|
||||||
|
|
||||||
class Camera;
|
class Camera;
|
||||||
class Level;
|
class Level;
|
||||||
|
class Block;
|
||||||
class BlocksController;
|
class BlocksController;
|
||||||
|
|
||||||
class CameraControl {
|
class CameraControl {
|
||||||
std::shared_ptr<Player> player;
|
std::shared_ptr<Player> player;
|
||||||
std::shared_ptr<Camera> camera, currentViewCamera;
|
std::shared_ptr<Camera> camera;
|
||||||
const CameraSettings& settings;
|
const CameraSettings& settings;
|
||||||
glm::vec3 offset;
|
glm::vec3 offset;
|
||||||
float shake = 0.0f;
|
float shake = 0.0f;
|
||||||
float shakeTimer = 0.0f;
|
float shakeTimer = 0.0f;
|
||||||
glm::vec3 interpVel {0.0f};
|
glm::vec3 interpVel {0.0f};
|
||||||
|
|
||||||
|
/// @brief Update shaking timer and calculate camera offset
|
||||||
|
/// @param delta delta time
|
||||||
|
/// @return camera offset
|
||||||
|
glm::vec3 updateCameraShaking(float delta);
|
||||||
|
|
||||||
|
/// @brief Update field-of-view effects
|
||||||
|
/// @param input player inputs
|
||||||
|
/// @param delta delta time
|
||||||
|
void updateFovEffects(const PlayerInput& input, float delta);
|
||||||
|
|
||||||
|
/// @brief Switch active player camera
|
||||||
|
void switchCamera();
|
||||||
public:
|
public:
|
||||||
CameraControl(std::shared_ptr<Player> player, const CameraSettings& settings);
|
CameraControl(std::shared_ptr<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();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class BlockInteraction {
|
||||||
|
step,
|
||||||
|
destruction,
|
||||||
|
placing
|
||||||
|
};
|
||||||
|
|
||||||
|
using on_block_interaction = std::function<void(
|
||||||
|
Player*, glm::ivec3, const Block*, BlockInteraction type
|
||||||
|
)>;
|
||||||
|
|
||||||
class PlayerController {
|
class PlayerController {
|
||||||
Level* level;
|
Level* level;
|
||||||
std::shared_ptr<Player> player;
|
std::shared_ptr<Player> player;
|
||||||
PlayerInput input;
|
PlayerInput input;
|
||||||
CameraControl camControl;
|
CameraControl camControl;
|
||||||
BlocksController* blocksController;
|
BlocksController* blocksController;
|
||||||
|
|
||||||
void updateKeyboard();
|
std::vector<on_block_interaction> blockInteractionCallbacks;
|
||||||
void updateCamera(float delta, bool movement);
|
|
||||||
void resetKeyboard();
|
|
||||||
void updateControls(float delta);
|
|
||||||
void updateInteraction();
|
|
||||||
public:
|
|
||||||
static glm::vec3 selectedBlockPosition;
|
|
||||||
static glm::ivec3 selectedBlockNormal;
|
|
||||||
static glm::vec3 selectedPointPosition;
|
|
||||||
static int selectedBlockId;
|
|
||||||
static int selectedBlockStates;
|
|
||||||
|
|
||||||
PlayerController(Level* level,
|
void updateKeyboard();
|
||||||
const EngineSettings& settings,
|
void updateCamera(float delta, bool movement);
|
||||||
BlocksController* blocksController);
|
void resetKeyboard();
|
||||||
void update(float delta, bool input, bool pause);
|
void updateControls(float delta);
|
||||||
|
void updateInteraction();
|
||||||
|
void onBlockInteraction(
|
||||||
|
glm::ivec3 pos,
|
||||||
|
const Block* def,
|
||||||
|
BlockInteraction type
|
||||||
|
);
|
||||||
|
|
||||||
|
float stepsTimer = 0.0f;
|
||||||
|
void onFootstep();
|
||||||
|
void updateFootsteps(float delta);
|
||||||
|
public:
|
||||||
|
static glm::vec3 selectedBlockPosition;
|
||||||
|
static glm::ivec3 selectedBlockNormal;
|
||||||
|
static glm::vec3 selectedPointPosition;
|
||||||
|
static int selectedBlockId;
|
||||||
|
static int selectedBlockStates;
|
||||||
|
|
||||||
|
PlayerController(
|
||||||
|
Level* level,
|
||||||
|
const EngineSettings& settings,
|
||||||
|
BlocksController* blocksController
|
||||||
|
);
|
||||||
|
void update(float delta, bool input, bool pause);
|
||||||
|
|
||||||
Player* getPlayer();
|
Player* getPlayer();
|
||||||
|
|
||||||
|
void listenBlockInteraction(on_block_interaction callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* PLAYER_CONTROL_H_ */
|
#endif /* PLAYER_CONTROL_H_ */
|
||||||
|
|
|
||||||
|
|
@ -19,14 +19,14 @@ const float CHEAT_SPEED_MUL = 5.0f;
|
||||||
const float JUMP_FORCE = 8.0f;
|
const float JUMP_FORCE = 8.0f;
|
||||||
|
|
||||||
Player::Player(glm::vec3 position, float speed, std::shared_ptr<Inventory> inv) :
|
Player::Player(glm::vec3 position, float speed, std::shared_ptr<Inventory> inv) :
|
||||||
speed(speed),
|
speed(speed),
|
||||||
chosenSlot(0),
|
chosenSlot(0),
|
||||||
inventory(inv),
|
inventory(inv),
|
||||||
camera(new Camera(position, glm::radians(90.0f))),
|
camera(std::make_shared<Camera>(position, glm::radians(90.0f))),
|
||||||
spCamera(new Camera(position, glm::radians(90.0f))),
|
spCamera(std::make_shared<Camera>(position, glm::radians(90.0f))),
|
||||||
tpCamera(new Camera(position, glm::radians(90.0f))),
|
tpCamera(std::make_shared<Camera>(position, glm::radians(90.0f))),
|
||||||
currentCamera(camera),
|
currentCamera(camera),
|
||||||
hitbox(new Hitbox(position, glm::vec3(0.3f,0.9f,0.3f)))
|
hitbox(std::make_unique<Hitbox>(position, glm::vec3(0.3f,0.9f,0.3f)))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -34,116 +34,123 @@ Player::~Player() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::updateInput(
|
void Player::updateInput(
|
||||||
Level* level,
|
Level* level,
|
||||||
PlayerInput& input,
|
PlayerInput& input,
|
||||||
float delta) {
|
float delta) {
|
||||||
bool crouch = input.shift && hitbox->grounded && !input.sprint;
|
bool crouch = input.shift && hitbox->grounded && !input.sprint;
|
||||||
float speed = this->speed;
|
float speed = this->speed;
|
||||||
if (flight){
|
if (flight){
|
||||||
speed *= FLIGHT_SPEED_MUL;
|
speed *= FLIGHT_SPEED_MUL;
|
||||||
}
|
}
|
||||||
if (input.cheat){
|
if (input.cheat){
|
||||||
speed *= CHEAT_SPEED_MUL;
|
speed *= CHEAT_SPEED_MUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (crouch) {
|
if (crouch) {
|
||||||
speed *= CROUCH_SPEED_MUL;
|
speed *= CROUCH_SPEED_MUL;
|
||||||
} else if (input.sprint) {
|
} else if (input.sprint) {
|
||||||
speed *= RUN_SPEED_MUL;
|
speed *= RUN_SPEED_MUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec3 dir(0,0,0);
|
glm::vec3 dir(0,0,0);
|
||||||
if (input.moveForward){
|
if (input.moveForward){
|
||||||
dir.x += camera->dir.x;
|
dir.x += camera->dir.x;
|
||||||
dir.z += camera->dir.z;
|
dir.z += camera->dir.z;
|
||||||
}
|
}
|
||||||
if (input.moveBack){
|
if (input.moveBack){
|
||||||
dir.x -= camera->dir.x;
|
dir.x -= camera->dir.x;
|
||||||
dir.z -= camera->dir.z;
|
dir.z -= camera->dir.z;
|
||||||
}
|
}
|
||||||
if (input.moveRight){
|
if (input.moveRight){
|
||||||
dir.x += camera->right.x;
|
dir.x += camera->right.x;
|
||||||
dir.z += camera->right.z;
|
dir.z += camera->right.z;
|
||||||
}
|
}
|
||||||
if (input.moveLeft){
|
if (input.moveLeft){
|
||||||
dir.x -= camera->right.x;
|
dir.x -= camera->right.x;
|
||||||
dir.z -= camera->right.z;
|
dir.z -= camera->right.z;
|
||||||
}
|
}
|
||||||
if (glm::length(dir) > 0.0f){
|
if (glm::length(dir) > 0.0f){
|
||||||
dir = glm::normalize(dir);
|
dir = glm::normalize(dir);
|
||||||
hitbox->velocity.x += dir.x * speed * delta * 9;
|
hitbox->velocity.x += dir.x * speed * delta * 9;
|
||||||
hitbox->velocity.z += dir.z * speed * delta * 9;
|
hitbox->velocity.z += dir.z * speed * delta * 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
float vel = std::max(glm::length(hitbox->velocity * 0.25f), 1.0f);
|
float vel = std::max(glm::length(hitbox->velocity * 0.25f), 1.0f);
|
||||||
int substeps = int(delta * vel * 1000);
|
int substeps = int(delta * vel * 1000);
|
||||||
substeps = std::min(100, std::max(1, substeps));
|
substeps = std::min(100, std::max(1, substeps));
|
||||||
level->physics->step(level->chunks.get(), hitbox.get(),
|
level->physics->step(
|
||||||
delta, substeps,
|
level->chunks.get(),
|
||||||
crouch, flight ? 0.0f : 1.0f,
|
hitbox.get(),
|
||||||
!noclip);
|
delta,
|
||||||
|
substeps,
|
||||||
|
crouch,
|
||||||
|
flight ? 0.0f : 1.0f,
|
||||||
|
!noclip
|
||||||
|
);
|
||||||
|
|
||||||
if (flight && hitbox->grounded) {
|
if (flight && hitbox->grounded) {
|
||||||
flight = false;
|
flight = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.jump && hitbox->grounded){
|
if (input.jump && hitbox->grounded){
|
||||||
hitbox->velocity.y = JUMP_FORCE;
|
hitbox->velocity.y = JUMP_FORCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((input.flight && !noclip) ||
|
if ((input.flight && !noclip) ||
|
||||||
(input.noclip && flight == noclip)){
|
(input.noclip && flight == noclip)){
|
||||||
flight = !flight;
|
flight = !flight;
|
||||||
if (flight){
|
if (flight){
|
||||||
hitbox->grounded = false;
|
hitbox->grounded = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (input.noclip) {
|
if (input.noclip) {
|
||||||
noclip = !noclip;
|
noclip = !noclip;
|
||||||
}
|
}
|
||||||
|
|
||||||
hitbox->linear_damping = PLAYER_GROUND_DAMPING;
|
hitbox->linear_damping = PLAYER_GROUND_DAMPING;
|
||||||
if (flight){
|
if (flight){
|
||||||
hitbox->linear_damping = PLAYER_AIR_DAMPING;
|
hitbox->linear_damping = PLAYER_AIR_DAMPING;
|
||||||
hitbox->velocity.y *= 1.0f - delta * 9;
|
hitbox->velocity.y *= 1.0f - delta * 9;
|
||||||
if (input.jump){
|
if (input.jump){
|
||||||
hitbox->velocity.y += speed * delta * 9;
|
hitbox->velocity.y += speed * delta * 9;
|
||||||
}
|
}
|
||||||
if (input.shift){
|
if (input.shift){
|
||||||
hitbox->velocity.y -= speed * delta * 9;
|
hitbox->velocity.y -= speed * delta * 9;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!hitbox->grounded) {
|
if (!hitbox->grounded) {
|
||||||
hitbox->linear_damping = PLAYER_AIR_DAMPING;
|
hitbox->linear_damping = PLAYER_AIR_DAMPING;
|
||||||
}
|
}
|
||||||
|
|
||||||
input.noclip = false;
|
input.noclip = false;
|
||||||
input.flight = false;
|
input.flight = false;
|
||||||
|
|
||||||
if (spawnpoint.y <= 0.1) {
|
if (spawnpoint.y <= 0.1) {
|
||||||
attemptToFindSpawnpoint(level);
|
attemptToFindSpawnpoint(level);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::teleport(glm::vec3 position) {
|
void Player::teleport(glm::vec3 position) {
|
||||||
hitbox->position = position;
|
hitbox->position = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::attemptToFindSpawnpoint(Level* level) {
|
void Player::attemptToFindSpawnpoint(Level* level) {
|
||||||
glm::vec3 ppos = hitbox->position;
|
glm::vec3 ppos = hitbox->position;
|
||||||
glm::vec3 newpos {ppos.x + (rand() % 200 - 100),
|
glm::vec3 newpos (
|
||||||
rand() % 80 + 100,
|
ppos.x + (rand() % 200 - 100),
|
||||||
ppos.z + (rand() % 200 - 100)};
|
rand() % 80 + 100,
|
||||||
while (newpos.y > 0 && !level->chunks->isObstacleBlock(newpos.x, newpos.y-2, newpos.z)) {
|
ppos.z + (rand() % 200 - 100)
|
||||||
newpos.y--;
|
);
|
||||||
}
|
while (newpos.y > 0 && !level->chunks->isObstacleBlock(newpos.x, newpos.y-2, newpos.z)) {
|
||||||
|
newpos.y--;
|
||||||
|
}
|
||||||
|
|
||||||
voxel* headvox = level->chunks->get(newpos.x, newpos.y+1, newpos.z);
|
voxel* headvox = level->chunks->get(newpos.x, newpos.y+1, newpos.z);
|
||||||
if (level->chunks->isObstacleBlock(newpos.x, newpos.y, newpos.z) ||
|
if (level->chunks->isObstacleBlock(newpos.x, newpos.y, newpos.z) ||
|
||||||
headvox == nullptr || headvox->id != 0)
|
headvox == nullptr || headvox->id != 0)
|
||||||
return;
|
return;
|
||||||
spawnpoint = newpos + glm::vec3(0.5f, 0.0f, 0.5f);
|
spawnpoint = newpos + glm::vec3(0.5f, 0.0f, 0.5f);
|
||||||
teleport(spawnpoint);
|
teleport(spawnpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::setChosenSlot(int index) {
|
void Player::setChosenSlot(int index) {
|
||||||
|
|
@ -155,7 +162,7 @@ int Player::getChosenSlot() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
float Player::getSpeed() const {
|
float Player::getSpeed() const {
|
||||||
return speed;
|
return speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Inventory> Player::getInventory() const {
|
std::shared_ptr<Inventory> Player::getInventory() const {
|
||||||
|
|
@ -163,62 +170,62 @@ std::shared_ptr<Inventory> Player::getInventory() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::setSpawnPoint(glm::vec3 spawnpoint) {
|
void Player::setSpawnPoint(glm::vec3 spawnpoint) {
|
||||||
this->spawnpoint = spawnpoint;
|
this->spawnpoint = spawnpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec3 Player::getSpawnPoint() const {
|
glm::vec3 Player::getSpawnPoint() const {
|
||||||
return spawnpoint;
|
return spawnpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<dynamic::Map> Player::serialize() const {
|
std::unique_ptr<dynamic::Map> Player::serialize() const {
|
||||||
glm::vec3 position = hitbox->position;
|
glm::vec3 position = hitbox->position;
|
||||||
auto root = std::make_unique<dynamic::Map>();
|
auto root = std::make_unique<dynamic::Map>();
|
||||||
auto& posarr = root->putList("position");
|
auto& posarr = root->putList("position");
|
||||||
posarr.put(position.x);
|
posarr.put(position.x);
|
||||||
posarr.put(position.y);
|
posarr.put(position.y);
|
||||||
posarr.put(position.z);
|
posarr.put(position.z);
|
||||||
|
|
||||||
auto& rotarr = root->putList("rotation");
|
auto& rotarr = root->putList("rotation");
|
||||||
rotarr.put(cam.x);
|
rotarr.put(cam.x);
|
||||||
rotarr.put(cam.y);
|
rotarr.put(cam.y);
|
||||||
|
|
||||||
auto& sparr = root->putList("spawnpoint");
|
auto& sparr = root->putList("spawnpoint");
|
||||||
sparr.put(spawnpoint.x);
|
sparr.put(spawnpoint.x);
|
||||||
sparr.put(spawnpoint.y);
|
sparr.put(spawnpoint.y);
|
||||||
sparr.put(spawnpoint.z);
|
sparr.put(spawnpoint.z);
|
||||||
|
|
||||||
root->put("flight", flight);
|
root->put("flight", flight);
|
||||||
root->put("noclip", noclip);
|
root->put("noclip", noclip);
|
||||||
root->put("chosen-slot", chosenSlot);
|
root->put("chosen-slot", chosenSlot);
|
||||||
root->put("inventory", inventory->serialize().release());
|
root->put("inventory", inventory->serialize().release());
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::deserialize(dynamic::Map *src) {
|
void Player::deserialize(dynamic::Map *src) {
|
||||||
auto posarr = src->list("position");
|
auto posarr = src->list("position");
|
||||||
glm::vec3& position = hitbox->position;
|
glm::vec3& position = hitbox->position;
|
||||||
position.x = posarr->num(0);
|
position.x = posarr->num(0);
|
||||||
position.y = posarr->num(1);
|
position.y = posarr->num(1);
|
||||||
position.z = posarr->num(2);
|
position.z = posarr->num(2);
|
||||||
camera->position = position;
|
camera->position = position;
|
||||||
|
|
||||||
auto rotarr = src->list("rotation");
|
auto rotarr = src->list("rotation");
|
||||||
cam.x = rotarr->num(0);
|
cam.x = rotarr->num(0);
|
||||||
cam.y = rotarr->num(1);
|
cam.y = rotarr->num(1);
|
||||||
|
|
||||||
if (src->has("spawnpoint")) {
|
if (src->has("spawnpoint")) {
|
||||||
auto sparr = src->list("spawnpoint");
|
auto sparr = src->list("spawnpoint");
|
||||||
setSpawnPoint(glm::vec3(
|
setSpawnPoint(glm::vec3(
|
||||||
sparr->num(0),
|
sparr->num(0),
|
||||||
sparr->num(1),
|
sparr->num(1),
|
||||||
sparr->num(2)
|
sparr->num(2)
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
setSpawnPoint(position);
|
setSpawnPoint(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
src->flag("flight", flight);
|
src->flag("flight", flight);
|
||||||
src->flag("noclip", noclip);
|
src->flag("noclip", noclip);
|
||||||
setChosenSlot(src->getInt("chosen-slot", getChosenSlot()));
|
setChosenSlot(src->getInt("chosen-slot", getChosenSlot()));
|
||||||
|
|
||||||
auto invmap = src->map("inventory");
|
auto invmap = src->map("inventory");
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,8 @@
|
||||||
|
|
||||||
#include "../core_defs.h"
|
#include "../core_defs.h"
|
||||||
|
|
||||||
using glm::vec3;
|
|
||||||
|
|
||||||
CoordSystem::CoordSystem(glm::ivec3 axisX, glm::ivec3 axisY, glm::ivec3 axisZ)
|
CoordSystem::CoordSystem(glm::ivec3 axisX, glm::ivec3 axisY, glm::ivec3 axisZ)
|
||||||
: axisX(axisX), axisY(axisY), axisZ(axisZ)
|
: axisX(axisX), axisY(axisY), axisZ(axisZ)
|
||||||
{
|
{
|
||||||
fix = glm::ivec3(0);
|
fix = glm::ivec3(0);
|
||||||
if (isVectorHasNegatives(axisX)) fix -= axisX;
|
if (isVectorHasNegatives(axisX)) fix -= axisX;
|
||||||
|
|
@ -14,9 +12,9 @@ CoordSystem::CoordSystem(glm::ivec3 axisX, glm::ivec3 axisY, glm::ivec3 axisZ)
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoordSystem::transform(AABB& aabb) const {
|
void CoordSystem::transform(AABB& aabb) const {
|
||||||
vec3 X(axisX);
|
glm::vec3 X(axisX);
|
||||||
vec3 Y(axisY);
|
glm::vec3 Y(axisY);
|
||||||
vec3 Z(axisZ);
|
glm::vec3 Z(axisZ);
|
||||||
aabb.a = X * aabb.a.x + Y * aabb.a.y + Z * aabb.a.z;
|
aabb.a = X * aabb.a.x + Y * aabb.a.y + Z * aabb.a.z;
|
||||||
aabb.b = X * aabb.b.x + Y * aabb.b.y + Z * aabb.b.z;
|
aabb.b = X * aabb.b.x + Y * aabb.b.y + Z * aabb.b.z;
|
||||||
aabb.a += fix;
|
aabb.a += fix;
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,12 @@ inline constexpr uint FACE_PY = 3;
|
||||||
inline constexpr uint FACE_MZ = 4;
|
inline constexpr uint FACE_MZ = 4;
|
||||||
inline constexpr uint FACE_PZ = 5;
|
inline constexpr uint FACE_PZ = 5;
|
||||||
|
|
||||||
|
/// @brief Grid size used for physics solver collision checking with
|
||||||
|
/// complex hitboxes
|
||||||
inline constexpr uint BLOCK_AABB_GRID = 16;
|
inline constexpr uint BLOCK_AABB_GRID = 16;
|
||||||
|
|
||||||
|
inline std::string DEFAULT_MATERIAL = "base:stone";
|
||||||
|
|
||||||
struct block_funcs_set {
|
struct block_funcs_set {
|
||||||
bool init: 1;
|
bool init: 1;
|
||||||
bool update: 1;
|
bool update: 1;
|
||||||
|
|
@ -35,7 +39,7 @@ struct CoordSystem {
|
||||||
glm::ivec3 axisY;
|
glm::ivec3 axisY;
|
||||||
glm::ivec3 axisZ;
|
glm::ivec3 axisZ;
|
||||||
|
|
||||||
// Grid 3d position fix offset (for negative vectors)
|
/// @brief Grid 3d position fix offset (for negative vectors)
|
||||||
glm::ivec3 fix;
|
glm::ivec3 fix;
|
||||||
|
|
||||||
CoordSystem() = default;
|
CoordSystem() = default;
|
||||||
|
|
@ -43,11 +47,8 @@ struct CoordSystem {
|
||||||
|
|
||||||
void transform(AABB& aabb) const;
|
void transform(AABB& aabb) const;
|
||||||
|
|
||||||
static bool isVectorHasNegatives(glm::ivec3 vec) {
|
inline bool isVectorHasNegatives(glm::ivec3 vec) {
|
||||||
if (vec.x < 0 || vec.y < 0 || vec.z < 0) {
|
return (vec.x < 0 || vec.y < 0 || vec.z < 0);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else return false;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -56,56 +57,127 @@ struct BlockRotProfile {
|
||||||
std::string name;
|
std::string name;
|
||||||
CoordSystem variants[MAX_COUNT];
|
CoordSystem variants[MAX_COUNT];
|
||||||
|
|
||||||
/* Wood logs, pillars, pipes */
|
/// @brief Wood logs, pillars, pipes
|
||||||
static const BlockRotProfile PIPE;
|
static const BlockRotProfile PIPE;
|
||||||
/* Doors, signs and other panes */
|
|
||||||
|
/// @brief Doors, signs and other panes
|
||||||
static const BlockRotProfile PANE;
|
static const BlockRotProfile PANE;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class BlockModel {
|
enum class BlockModel {
|
||||||
none, // invisible
|
/// @brief invisible
|
||||||
block, // default shape
|
none,
|
||||||
xsprite, // X-shape (grass)
|
/// @brief default cube shape
|
||||||
aabb, // box shaped as block hitbox
|
block,
|
||||||
|
/// @brief X-shape (grass)
|
||||||
|
xsprite,
|
||||||
|
/// @brief box shape sized as block hitbox
|
||||||
|
aabb,
|
||||||
|
/// @brief custom model defined in json
|
||||||
custom
|
custom
|
||||||
};
|
};
|
||||||
|
|
||||||
using BoxModel = AABB;
|
using BoxModel = AABB;
|
||||||
|
|
||||||
|
|
||||||
|
/// @brief Common kit of block properties applied to groups of blocks
|
||||||
|
struct BlockMaterial {
|
||||||
|
std::string name;
|
||||||
|
std::string stepsSound {""};
|
||||||
|
std::string placeSound {""};
|
||||||
|
std::string breakSound {""};
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @brief Block properties definition
|
||||||
class Block {
|
class Block {
|
||||||
public:
|
public:
|
||||||
|
/// @brief Block string id (with prefix included)
|
||||||
std::string const name;
|
std::string const name;
|
||||||
// 0 1 2 3 4 5
|
|
||||||
|
/// @brief Textures set applied to block sides
|
||||||
std::string textureFaces[6]; // -x,x, -y,y, -z,z
|
std::string textureFaces[6]; // -x,x, -y,y, -z,z
|
||||||
|
|
||||||
std::vector<std::string> modelTextures = {};
|
std::vector<std::string> modelTextures = {};
|
||||||
std::vector<BoxModel> modelBoxes = {};
|
std::vector<BoxModel> modelBoxes = {};
|
||||||
std::vector<glm::vec3> modelExtraPoints = {}; //initially made for tetragons
|
std::vector<glm::vec3> modelExtraPoints = {}; //initially made for tetragons
|
||||||
std::vector<UVRegion> modelUVs = {}; // boxes' tex-UVs also there
|
std::vector<UVRegion> modelUVs = {}; // boxes' tex-UVs also there
|
||||||
|
|
||||||
|
/// @brief id of used BlockMaterial, may specify non-existing material
|
||||||
|
std::string material = DEFAULT_MATERIAL;
|
||||||
|
|
||||||
|
/// @brief Light emission R, G, B, S (sky lights: sun, moon, radioactive clouds)
|
||||||
uint8_t emission[4] {0, 0, 0, 0};
|
uint8_t emission[4] {0, 0, 0, 0};
|
||||||
|
|
||||||
|
/// @brief Influences visible block sides for transparent blocks
|
||||||
uint8_t drawGroup = 0;
|
uint8_t drawGroup = 0;
|
||||||
|
|
||||||
|
/// @brief Block model type
|
||||||
BlockModel model = BlockModel::block;
|
BlockModel model = BlockModel::block;
|
||||||
|
|
||||||
|
/// @brief Does the block passing lights into itself
|
||||||
bool lightPassing = false;
|
bool lightPassing = false;
|
||||||
|
|
||||||
|
/// @brief Does the block passing top-down sky lights into itself
|
||||||
bool skyLightPassing = false;
|
bool skyLightPassing = false;
|
||||||
|
|
||||||
|
/// @brief Is the block a physical obstacle
|
||||||
bool obstacle = true;
|
bool obstacle = true;
|
||||||
|
|
||||||
|
/// @brief Can the block be selected
|
||||||
bool selectable = true;
|
bool selectable = true;
|
||||||
|
|
||||||
|
/// @brief Can the block be replaced with other.
|
||||||
|
/// Examples of replaceable blocks: air, flower, water
|
||||||
bool replaceable = false;
|
bool replaceable = false;
|
||||||
|
|
||||||
|
/// @brief Can player destroy the block
|
||||||
bool breakable = true;
|
bool breakable = true;
|
||||||
|
|
||||||
|
/// @brief Can the block be oriented different ways
|
||||||
bool rotatable = false;
|
bool rotatable = false;
|
||||||
|
|
||||||
|
/// @brief Can the block exist without physical support be a solid block below
|
||||||
bool grounded = false;
|
bool grounded = false;
|
||||||
|
|
||||||
|
/// @brief Turns off block item generation
|
||||||
bool hidden = false;
|
bool hidden = false;
|
||||||
|
|
||||||
|
/// @brief Set of block physical hitboxes
|
||||||
std::vector<AABB> hitboxes;
|
std::vector<AABB> hitboxes;
|
||||||
|
|
||||||
|
/// @brief Set of available block rotations (coord-systems)
|
||||||
BlockRotProfile rotations;
|
BlockRotProfile rotations;
|
||||||
|
|
||||||
|
/// @brief Item will be picked on MMB click on the block
|
||||||
std::string pickingItem = name+BLOCK_ITEM_SUFFIX;
|
std::string pickingItem = name+BLOCK_ITEM_SUFFIX;
|
||||||
|
|
||||||
|
/// @brief Block script name in blocks/ without extension
|
||||||
std::string scriptName = name.substr(name.find(':')+1);
|
std::string scriptName = name.substr(name.find(':')+1);
|
||||||
|
|
||||||
|
/// @brief Default block layout will be used by hud.open_block(...)
|
||||||
std::string uiLayout = name;
|
std::string uiLayout = name;
|
||||||
|
|
||||||
|
/// @brief Block inventory size. 0 - no inventory
|
||||||
uint inventorySize = 0;
|
uint inventorySize = 0;
|
||||||
|
|
||||||
|
/// @brief Runtime indices (content indexing results)
|
||||||
struct {
|
struct {
|
||||||
|
/// @brief block runtime integer id
|
||||||
blockid_t id;
|
blockid_t id;
|
||||||
|
|
||||||
|
/// @brief is the block completely opaque for render and raycast
|
||||||
bool solid = true;
|
bool solid = true;
|
||||||
|
|
||||||
|
/// @brief does the block emit any lights
|
||||||
bool emissive = false;
|
bool emissive = false;
|
||||||
|
|
||||||
|
/// @brief set of hitboxes sets with all coord-systems precalculated
|
||||||
std::vector<AABB> hitboxes[BlockRotProfile::MAX_COUNT];
|
std::vector<AABB> hitboxes[BlockRotProfile::MAX_COUNT];
|
||||||
|
|
||||||
|
/// @brief set of block callbacks flags
|
||||||
block_funcs_set funcsset {};
|
block_funcs_set funcsset {};
|
||||||
|
|
||||||
|
/// @brief picking item integer id
|
||||||
itemid_t pickingItem = 0;
|
itemid_t pickingItem = 0;
|
||||||
} rt;
|
} rt;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue