Scripting WIP (#70)
* Scripting introduced * AppImage workflow fixes * AppImage workflow simplified * README.md update * README.md update * small fix
This commit is contained in:
parent
ce26f0c227
commit
acce49f188
4
.github/workflows/appimage.yml
vendored
4
.github/workflows/appimage.yml
vendored
@ -18,7 +18,9 @@ jobs:
|
||||
- name: install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y build-essential libglfw3-dev libglfw3 libglew-dev libglm-dev libpng-dev libopenal-dev cmake squashfs-tools
|
||||
sudo apt-get install -y build-essential libglfw3-dev libglfw3 libglew-dev libglm-dev libpng-dev libopenal-dev libluajit-5.1-dev cmake squashfs-tools
|
||||
sudo ln -s /usr/lib/x86_64-linux-gnu/libluajit-5.1.a /usr/lib/x86_64-linux-gnu/liblua5.1.a
|
||||
sudo ln -s /usr/include/luajit-2.1 /usr/include/lua
|
||||
- name: configure
|
||||
run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DVOXELENGINE_BUILD_APPDIR=1
|
||||
- name: build
|
||||
|
||||
8
.github/workflows/cmake.yml
vendored
8
.github/workflows/cmake.yml
vendored
@ -21,9 +21,15 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install packages
|
||||
# If libluajit-5.1-dev is not available, use this:
|
||||
# git clone https://luajit.org/git/luajit.git
|
||||
# cd luajit
|
||||
# make && make install INSTALL_INC=/usr/include/lua
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install libglfw3-dev libglfw3 libglew-dev libglm-dev libpng-dev libopenal-dev
|
||||
sudo apt-get install libglfw3-dev libglfw3 libglew-dev libglm-dev libpng-dev libopenal-dev libluajit-5.1-dev
|
||||
sudo ln -s /usr/lib/x86_64-linux-gnu/libluajit-5.1.a /usr/lib/x86_64-linux-gnu/liblua-5.1.a
|
||||
sudo ln -s /usr/include/luajit-2.1 /usr/include/lua
|
||||
|
||||
- name: Configure CMake
|
||||
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
|
||||
|
||||
@ -43,6 +43,8 @@ endif()
|
||||
find_package(OpenGL REQUIRED)
|
||||
find_package(GLEW REQUIRED)
|
||||
find_package(OpenAL REQUIRED)
|
||||
# luajit has no CMakeLists.txt to use it as subdirectory, so install it
|
||||
find_package(Lua REQUIRED)
|
||||
|
||||
if (WIN32)
|
||||
set(PNGLIB spng)
|
||||
@ -67,8 +69,8 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -no-pie")
|
||||
endif()
|
||||
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} ${LIBS} glfw OpenGL::GL ${OPENAL_LIBRARY} GLEW::GLEW ${PNGLIB})
|
||||
include_directories(${LUA_INCLUDE_DIR})
|
||||
target_link_libraries(${PROJECT_NAME} ${LIBS} glfw OpenGL::GL ${OPENAL_LIBRARY} GLEW::GLEW ${PNGLIB} ${LUA_LIBRARIES} ${CMAKE_DL_LIBS})
|
||||
|
||||
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/res DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
|
||||
40
README.md
40
README.md
@ -27,21 +27,49 @@ cmake --build .
|
||||
```
|
||||
|
||||
## Install libs:
|
||||
|
||||
#### Debian-based distro:
|
||||
`$ sudo apt install libglfw3-dev libglfw3 libglew-dev libglm-dev libpng-dev libopenal-dev`
|
||||
```sh
|
||||
sudo apt install libglfw3-dev libglfw3 libglew-dev libglm-dev libpng-dev libopenal-dev libluajit-5.1-dev
|
||||
```
|
||||
|
||||
CMake missing LUA_INCLUDE_DIR and LUA_LIBRARIES fix:
|
||||
```sh
|
||||
sudo ln -s /usr/lib/x86_64-linux-gnu/libluajit-5.1.a /usr/lib/x86_64-linux-gnu/liblua5.1.a
|
||||
sudo ln -s /usr/include/luajit-2.1 /usr/include/lua
|
||||
```
|
||||
|
||||
#### RHEL-based distro:
|
||||
`$ sudo dnf install glfw-devel glfw glew-devel glm-devel libpng-devel openal-devel`
|
||||
```sh
|
||||
sudo dnf install glfw-devel glfw glew-devel glm-devel libpng-devel openal-devel
|
||||
```
|
||||
|
||||
\+ install LuaJIT
|
||||
|
||||
#### Arch-based distro:
|
||||
If you use X11
|
||||
`$ sudo pacman -S glfw-x11 glew glm libpng openal`
|
||||
```sh
|
||||
sudo pacman -S glfw-x11 glew glm libpng openal
|
||||
```
|
||||
|
||||
If you use Wayland
|
||||
`$ sudo pacman -S glfw-wayland glew glm libpng openal`
|
||||
```sh
|
||||
sudo pacman -S glfw-wayland glew glm libpng openal
|
||||
```
|
||||
|
||||
\+ install LuaJIT
|
||||
|
||||
#### LuaJIT installation:
|
||||
```sh
|
||||
git clone https://luajit.org/git/luajit.git
|
||||
cd luajit
|
||||
make && sudo make install INSTALL_INC=/usr/include/lua
|
||||
```
|
||||
|
||||
#### macOS:
|
||||
|
||||
`$ brew install glfw3 glew glm libpng`
|
||||
```
|
||||
brew install glfw3 glew glm libpng
|
||||
```
|
||||
|
||||
Download, compile and install OpenAL
|
||||
Download, compile and install OpenAL and LuaJIT
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
"light-passing": true,
|
||||
"obstacle": false,
|
||||
"replaceable": true,
|
||||
"grounded": true,
|
||||
"model": "X",
|
||||
"hitbox": [0.15, 0.0, 0.15, 0.7, 0.7, 0.7]
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
"light-passing": true,
|
||||
"obstacle": false,
|
||||
"replaceable": true,
|
||||
"grounded": true,
|
||||
"model": "X",
|
||||
"hitbox": [0.15, 0.0, 0.15, 0.7, 0.7, 0.7]
|
||||
}
|
||||
}
|
||||
|
||||
20
res/content/base/scripts/grass_block.lua
Normal file
20
res/content/base/scripts/grass_block.lua
Normal file
@ -0,0 +1,20 @@
|
||||
function on_random_update(x, y, z)
|
||||
local dirtid = block_index('base:dirt');
|
||||
if is_solid_at(x, y+1, z) then
|
||||
set_block(x, y, z, dirtid)
|
||||
else
|
||||
local grassblockid = block_index('base:grass_block')
|
||||
for lx=-1,1 do
|
||||
for ly=-1,1 do
|
||||
for lz=-1,1 do
|
||||
if get_block(x + lx, y + ly, z + lz) == dirtid then
|
||||
if not is_solid_at(x + lx, y + ly + 1, z + lz) then
|
||||
set_block(x + lx, y + ly, z + lz, grassblockid)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
0
res/scripts/world.lua
Normal file
0
res/scripts/world.lua
Normal file
@ -12,6 +12,7 @@
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include "ContentPack.h"
|
||||
#include "../logic/scripting/scripting.h"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
@ -84,6 +85,7 @@ Block* ContentLoader::loadBlock(std::string name, fs::path file) {
|
||||
root->flag("light-passing", def->lightPassing);
|
||||
root->flag("breakable", def->breakable);
|
||||
root->flag("selectable", def->selectable);
|
||||
root->flag("grounded", def->grounded);
|
||||
root->flag("sky-light-passing", def->skyLightPassing);
|
||||
root->num("draw-group", def->drawGroup);
|
||||
|
||||
@ -100,8 +102,14 @@ void ContentLoader::load(ContentBuilder* builder) {
|
||||
if (blocksarr) {
|
||||
for (uint i = 0; i < blocksarr->size(); i++) {
|
||||
std::string name = blocksarr->str(i);
|
||||
std::string prefix = pack->id+":"+name;
|
||||
fs::path blockfile = folder/fs::path("blocks/"+name+".json");
|
||||
builder->add(loadBlock(pack->id+":"+name, blockfile));
|
||||
Block* block = loadBlock(prefix, blockfile);
|
||||
builder->add(block);
|
||||
fs::path scriptfile = folder/fs::path("scripts/"+name+".lua");
|
||||
if (fs::is_regular_file(scriptfile)) {
|
||||
scripting::load_block_script(prefix, scriptfile, &block->rt.funcsset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
#include "content/ContentPack.h"
|
||||
#include "content/ContentLoader.h"
|
||||
#include "frontend/locale/langs.h"
|
||||
#include "logic/scripting/scripting.h"
|
||||
|
||||
#include "definitions.h"
|
||||
|
||||
@ -45,6 +46,7 @@ Engine::Engine(EngineSettings& settings, EnginePaths* paths)
|
||||
}
|
||||
|
||||
auto resdir = paths->getResources();
|
||||
scripting::initialize(paths);
|
||||
|
||||
std::cout << "-- loading assets" << std::endl;
|
||||
std::vector<fs::path> roots {resdir};
|
||||
@ -117,6 +119,7 @@ void Engine::mainloop() {
|
||||
}
|
||||
|
||||
Engine::~Engine() {
|
||||
scripting::close();
|
||||
screen = nullptr;
|
||||
delete gui;
|
||||
|
||||
@ -128,40 +131,6 @@ Engine::~Engine() {
|
||||
std::cout << "-- engine finished" << std::endl;
|
||||
}
|
||||
|
||||
gui::GUI* Engine::getGUI() {
|
||||
return gui;
|
||||
}
|
||||
|
||||
EngineSettings& Engine::getSettings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
Assets* Engine::getAssets() {
|
||||
return assets.get();
|
||||
}
|
||||
|
||||
void Engine::setScreen(std::shared_ptr<Screen> screen) {
|
||||
this->screen = screen;
|
||||
}
|
||||
|
||||
const Content* Engine::getContent() const {
|
||||
return content.get();
|
||||
}
|
||||
|
||||
std::vector<ContentPack>& Engine::getContentPacks() {
|
||||
return contentPacks;
|
||||
}
|
||||
|
||||
EnginePaths* Engine::getPaths() {
|
||||
return paths;
|
||||
}
|
||||
|
||||
void Engine::setLanguage(std::string locale) {
|
||||
settings.ui.language = locale;
|
||||
langs::setup(paths->getResources(), locale, contentPacks);
|
||||
menus::create_menus(this, gui->getMenu());
|
||||
}
|
||||
|
||||
void Engine::loadContent() {
|
||||
auto resdir = paths->getResources();
|
||||
ContentBuilder contentBuilder;
|
||||
@ -197,3 +166,37 @@ void Engine::loadAllPacks() {
|
||||
contentPacks.clear();
|
||||
ContentPack::scan(resdir/fs::path("content"), contentPacks);
|
||||
}
|
||||
|
||||
void Engine::setScreen(std::shared_ptr<Screen> screen) {
|
||||
this->screen = screen;
|
||||
}
|
||||
|
||||
void Engine::setLanguage(std::string locale) {
|
||||
settings.ui.language = locale;
|
||||
langs::setup(paths->getResources(), locale, contentPacks);
|
||||
menus::create_menus(this, gui->getMenu());
|
||||
}
|
||||
|
||||
gui::GUI* Engine::getGUI() {
|
||||
return gui;
|
||||
}
|
||||
|
||||
EngineSettings& Engine::getSettings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
Assets* Engine::getAssets() {
|
||||
return assets.get();
|
||||
}
|
||||
|
||||
const Content* Engine::getContent() const {
|
||||
return content.get();
|
||||
}
|
||||
|
||||
std::vector<ContentPack>& Engine::getContentPacks() {
|
||||
return contentPacks;
|
||||
}
|
||||
|
||||
EnginePaths* Engine::getPaths() {
|
||||
return paths;
|
||||
}
|
||||
|
||||
@ -20,9 +20,9 @@
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <cstdint>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
const int SECTION_POSITION = 1;
|
||||
const int SECTION_ROTATION = 2;
|
||||
@ -94,7 +94,7 @@ WorldFiles::~WorldFiles(){
|
||||
}
|
||||
|
||||
WorldRegion* WorldFiles::getRegion(regionsmap& regions, int x, int z) {
|
||||
auto found = regions.find(ivec2(x, z));
|
||||
auto found = regions.find(glm::ivec2(x, z));
|
||||
if (found == regions.end())
|
||||
return nullptr;
|
||||
return found->second;
|
||||
@ -104,7 +104,7 @@ WorldRegion* WorldFiles::getOrCreateRegion(regionsmap& regions, int x, int z) {
|
||||
WorldRegion* region = getRegion(regions, x, z);
|
||||
if (region == nullptr) {
|
||||
region = new WorldRegion();
|
||||
regions[ivec2(x, z)] = region;
|
||||
regions[glm::ivec2(x, z)] = region;
|
||||
}
|
||||
return region;
|
||||
}
|
||||
@ -367,7 +367,7 @@ void WorldFiles::writeRegions(regionsmap& regions, const fs::path& folder, int l
|
||||
WorldRegion* region = it.second;
|
||||
if (region->getChunks() == nullptr || !region->isUnsaved())
|
||||
continue;
|
||||
ivec2 key = it.first;
|
||||
glm::ivec2 key = it.first;
|
||||
writeRegion(key.x, key.y, region, folder, layer);
|
||||
}
|
||||
}
|
||||
@ -458,7 +458,7 @@ bool WorldFiles::readWorldInfo(World* world) {
|
||||
}
|
||||
|
||||
void WorldFiles::writePlayer(Player* player){
|
||||
vec3 position = player->hitbox->position;
|
||||
glm::vec3 position = player->hitbox->position;
|
||||
json::JObject root;
|
||||
json::JArray& posarr = root.putArray("position");
|
||||
posarr.put(position.x);
|
||||
@ -484,7 +484,7 @@ bool WorldFiles::readPlayer(Player* player) {
|
||||
|
||||
std::unique_ptr<json::JObject> root(files::read_json(file));
|
||||
json::JArray* posarr = root->arr("position");
|
||||
vec3& position = player->hitbox->position;
|
||||
glm::vec3& position = player->hitbox->position;
|
||||
position.x = posarr->num(0);
|
||||
position.y = posarr->num(1);
|
||||
position.z = posarr->num(2);
|
||||
|
||||
@ -168,7 +168,7 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera){
|
||||
shader->uniform3f("u_cameraPos", camera->position);
|
||||
shader->uniform1i("u_cubemap", 1);
|
||||
{
|
||||
blockid_t id = level->player->choosenBlock;
|
||||
blockid_t id = level->player->chosenBlock;
|
||||
Block* block = contentIds->getBlockDef(id);
|
||||
assert(block != nullptr);
|
||||
float multiplier = 0.5f;
|
||||
|
||||
@ -256,7 +256,7 @@ void HudRenderer::drawContentAccess(const GfxContext& ctx, Player* player) {
|
||||
tint.g *= 1.2f;
|
||||
tint.b *= 1.2f;
|
||||
if (Events::jclicked(mousecode::BUTTON_1)) {
|
||||
player->choosenBlock = i+1;
|
||||
player->chosenBlock = i+1;
|
||||
}
|
||||
} else {
|
||||
tint = vec4(1.0f);
|
||||
@ -335,7 +335,7 @@ void HudRenderer::draw(const GfxContext& ctx){
|
||||
subctx.depthTest(true);
|
||||
subctx.cullFace(true);
|
||||
|
||||
Block* cblock = contentIds->getBlockDef(player->choosenBlock);
|
||||
Block* cblock = contentIds->getBlockDef(player->chosenBlock);
|
||||
assert(cblock != nullptr);
|
||||
blocksPreview->draw(cblock, width - 56, uicamera->getFov() - 56, 48, vec4(1.0f));
|
||||
//drawBlockPreview(cblock, width - 56, uicamera->fov - 56, 48, 48, vec4(1.0f));
|
||||
|
||||
120
src/logic/BlocksController.cpp
Normal file
120
src/logic/BlocksController.cpp
Normal file
@ -0,0 +1,120 @@
|
||||
#include "BlocksController.h"
|
||||
|
||||
#include "../voxels/voxel.h"
|
||||
#include "../voxels/Block.h"
|
||||
#include "../voxels/Chunk.h"
|
||||
#include "../voxels/Chunks.h"
|
||||
#include "../world/Level.h"
|
||||
#include "../content/Content.h"
|
||||
#include "../lighting/Lighting.h"
|
||||
#include "../util/timeutil.h"
|
||||
|
||||
#include "scripting/scripting.h"
|
||||
|
||||
Clock::Clock(int tickRate, int tickParts)
|
||||
: tickRate(tickRate),
|
||||
tickParts(tickParts) {
|
||||
}
|
||||
|
||||
bool Clock::update(float delta) {
|
||||
tickTimer += delta;
|
||||
float delay = 1.0f / float(tickRate);
|
||||
if (tickTimer > delay || tickPartsUndone) {
|
||||
if (tickPartsUndone) {
|
||||
tickPartsUndone--;
|
||||
} else {
|
||||
tickTimer = fmod(tickTimer, delay);
|
||||
tickPartsUndone = tickParts-1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int Clock::getParts() const {
|
||||
return tickParts;
|
||||
}
|
||||
|
||||
int Clock::getPart() const {
|
||||
return tickParts-tickPartsUndone-1;
|
||||
}
|
||||
|
||||
BlocksController::BlocksController(Level* level, uint padding)
|
||||
: level(level),
|
||||
chunks(level->chunks),
|
||||
lighting(level->lighting),
|
||||
randTickClock(20, 3),
|
||||
padding(padding) {
|
||||
}
|
||||
|
||||
void BlocksController::updateSides(int x, int y, int z) {
|
||||
updateBlock(x-1, y, z);
|
||||
updateBlock(x+1, y, z);
|
||||
updateBlock(x, y-1, z);
|
||||
updateBlock(x, y+1, z);
|
||||
updateBlock(x, y, z-1);
|
||||
updateBlock(x, y, z+1);
|
||||
}
|
||||
|
||||
void BlocksController::breakBlock(Player* player, const Block* def, int x, int y, int z) {
|
||||
chunks->set(x,y,z, 0, 0);
|
||||
lighting->onBlockSet(x,y,z, 0);
|
||||
if (def->rt.funcsset.onbroken) {
|
||||
scripting::on_block_broken(player, def, x, y, z);
|
||||
}
|
||||
updateSides(x, y, z);
|
||||
}
|
||||
|
||||
void BlocksController::updateBlock(int x, int y, int z) {
|
||||
voxel* vox = chunks->get(x, y, z);
|
||||
if (vox == nullptr)
|
||||
return;
|
||||
const Block* def = level->content->indices->getBlockDef(vox->id);
|
||||
if (def->grounded && !chunks->isSolid(x, y-1, z)) {
|
||||
breakBlock(nullptr, def, x, y, z);
|
||||
return;
|
||||
}
|
||||
if (def->rt.funcsset.update) {
|
||||
scripting::update_block(def, x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
void BlocksController::update(float delta) {
|
||||
if (randTickClock.update(delta)) {
|
||||
randomTick(randTickClock.getPart(), randTickClock.getParts());
|
||||
}
|
||||
}
|
||||
|
||||
void BlocksController::randomTick(int tickid, int parts) {
|
||||
// timeutil::ScopeLogTimer timer(5000+tickid);
|
||||
const int w = chunks->w;
|
||||
const int d = chunks->d;
|
||||
auto indices = level->content->indices;
|
||||
for (uint z = padding; z < d-padding; z++){
|
||||
for (uint x = padding; x < w-padding; x++){
|
||||
int index = z * w + x;
|
||||
if ((index + tickid) % parts != 0)
|
||||
continue;
|
||||
std::shared_ptr<Chunk> chunk = chunks->chunks[index];
|
||||
if (chunk == nullptr || !chunk->isLighted())
|
||||
continue;
|
||||
int segments = 4;
|
||||
int segheight = CHUNK_H / segments;
|
||||
for (int s = 0; s < segments; s++) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
int bx = rand() % CHUNK_W;
|
||||
int by = rand() % segheight + s * segheight;
|
||||
int bz = rand() % CHUNK_D;
|
||||
const voxel& vox = chunk->voxels[(by * CHUNK_D + bz) * CHUNK_W + bx];
|
||||
Block* block = indices->getBlockDef(vox.id);
|
||||
if (block->rt.funcsset.randupdate) {
|
||||
scripting::random_update_block(
|
||||
block,
|
||||
chunk->x * CHUNK_W + bx, by,
|
||||
chunk->z * CHUNK_D + bz);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
46
src/logic/BlocksController.h
Normal file
46
src/logic/BlocksController.h
Normal file
@ -0,0 +1,46 @@
|
||||
#ifndef LOGIC_BLOCKS_CONTROLLER_H_
|
||||
#define LOGIC_BLOCKS_CONTROLLER_H_
|
||||
|
||||
#include "../typedefs.h"
|
||||
|
||||
class Player;
|
||||
class Block;
|
||||
class Level;
|
||||
class Chunks;
|
||||
class Lighting;
|
||||
|
||||
class Clock {
|
||||
int tickRate;
|
||||
int tickParts;
|
||||
|
||||
float tickTimer = 0.0f;
|
||||
int tickId = 0;
|
||||
int tickPartsUndone = 0;
|
||||
public:
|
||||
Clock(int tickRate, int tickParts);
|
||||
|
||||
bool update(float delta);
|
||||
|
||||
int getParts() const;
|
||||
int getPart() const;
|
||||
};
|
||||
|
||||
class BlocksController {
|
||||
Level* level;
|
||||
Chunks* chunks;
|
||||
Lighting* lighting;
|
||||
Clock randTickClock;
|
||||
uint padding;
|
||||
public:
|
||||
BlocksController(Level* level, uint padding);
|
||||
|
||||
void updateSides(int x, int y, int z);
|
||||
void updateBlock(int x, int y, int z);
|
||||
|
||||
void breakBlock(Player* player, const Block* def, int x, int y, int z);
|
||||
|
||||
void update(float delta);
|
||||
void randomTick(int tickid, int parts);
|
||||
};
|
||||
|
||||
#endif // LOGIC_BLOCKS_CONTROLLER_H_
|
||||
@ -2,13 +2,13 @@
|
||||
|
||||
#include <limits.h>
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
|
||||
#include "../voxels/Block.h"
|
||||
#include "../voxels/Chunk.h"
|
||||
#include "../voxels/Chunks.h"
|
||||
#include "../voxels/ChunksStorage.h"
|
||||
#include "../voxels/WorldGenerator.h"
|
||||
#include "../content/Content.h"
|
||||
#include "../graphics/Mesh.h"
|
||||
#include "../lighting/Lighting.h"
|
||||
#include "../files/WorldFiles.h"
|
||||
@ -17,19 +17,14 @@
|
||||
#include "../maths/voxmaths.h"
|
||||
#include "../util/timeutil.h"
|
||||
|
||||
|
||||
const uint MAX_WORK_PER_FRAME = 64;
|
||||
const uint MIN_SURROUNDING = 9;
|
||||
|
||||
using std::unique_ptr;
|
||||
using std::shared_ptr;
|
||||
|
||||
ChunksController::ChunksController(Level* level,
|
||||
Chunks* chunks,
|
||||
Lighting* lighting,
|
||||
uint padding)
|
||||
ChunksController::ChunksController(Level* level, uint padding)
|
||||
: level(level),
|
||||
chunks(chunks),
|
||||
lighting(lighting),
|
||||
chunks(level->chunks),
|
||||
lighting(level->lighting),
|
||||
padding(padding),
|
||||
generator(new WorldGenerator(level->content)) {
|
||||
}
|
||||
@ -66,7 +61,7 @@ bool ChunksController::loadVisible(){
|
||||
for (uint z = padding; z < d-padding; z++){
|
||||
for (uint x = padding; x < w-padding; x++){
|
||||
int index = z * w + x;
|
||||
shared_ptr<Chunk> chunk = chunks->chunks[index];
|
||||
std::shared_ptr<Chunk> chunk = chunks->chunks[index];
|
||||
if (chunk != nullptr){
|
||||
int surrounding = 0;
|
||||
for (int oz = -1; oz <= 1; oz++){
|
||||
@ -98,7 +93,7 @@ bool ChunksController::loadVisible(){
|
||||
}
|
||||
|
||||
int index = nearZ * w + nearX;
|
||||
shared_ptr<Chunk> chunk = chunks->chunks[index];
|
||||
std::shared_ptr<Chunk> chunk = chunks->chunks[index];
|
||||
if (chunk != nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -6,9 +6,6 @@
|
||||
class Level;
|
||||
class Chunks;
|
||||
class Lighting;
|
||||
class WorldFiles;
|
||||
class VoxelRenderer;
|
||||
class ChunksLoader;
|
||||
class WorldGenerator;
|
||||
|
||||
/* ChunksController manages chunks dynamic loading/unloading */
|
||||
@ -26,7 +23,7 @@ private:
|
||||
/* Process one chunk: load it or calculate lights for it */
|
||||
bool loadVisible();
|
||||
public:
|
||||
ChunksController(Level* level, Chunks* chunks, Lighting* lighting, uint padding);
|
||||
ChunksController(Level* level, uint padding);
|
||||
~ChunksController();
|
||||
|
||||
/* @param maxDuration milliseconds reserved for chunks loading */
|
||||
|
||||
@ -2,28 +2,29 @@
|
||||
#include "../world/Level.h"
|
||||
|
||||
#include "PlayerController.h"
|
||||
#include "BlocksController.h"
|
||||
#include "ChunksController.h"
|
||||
|
||||
#include "scripting/scripting.h"
|
||||
|
||||
LevelController::LevelController(EngineSettings& settings, Level* level)
|
||||
: settings(settings), level(level) {
|
||||
chunks = new ChunksController(
|
||||
level,
|
||||
level->chunks,
|
||||
level->lighting,
|
||||
settings.chunks.padding);
|
||||
player = new PlayerController(level, settings);
|
||||
blocks = new BlocksController(level, settings.chunks.padding);
|
||||
chunks = new ChunksController(level, settings.chunks.padding);
|
||||
player = new PlayerController(level, settings, blocks);
|
||||
|
||||
scripting::on_world_load(level);
|
||||
}
|
||||
|
||||
LevelController::~LevelController() {
|
||||
scripting::on_world_quit();
|
||||
delete player;
|
||||
delete chunks;
|
||||
}
|
||||
|
||||
void LevelController::update(
|
||||
float delta,
|
||||
bool input,
|
||||
bool pause) {
|
||||
void LevelController::update(float delta, bool input, bool pause) {
|
||||
player->update(delta, input, pause);
|
||||
level->update();
|
||||
chunks->update(settings.chunks.loadSpeed);
|
||||
}
|
||||
blocks->update(delta);
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
#include "../settings.h"
|
||||
|
||||
class Level;
|
||||
class BlocksController;
|
||||
class ChunksController;
|
||||
class PlayerController;
|
||||
|
||||
@ -12,6 +13,7 @@ class LevelController {
|
||||
EngineSettings& settings;
|
||||
Level* level;
|
||||
// Sub-controllers
|
||||
BlocksController* blocks;
|
||||
ChunksController* chunks;
|
||||
PlayerController* player;
|
||||
public:
|
||||
|
||||
@ -12,6 +12,8 @@
|
||||
#include "../window/Camera.h"
|
||||
#include "../window/Events.h"
|
||||
#include "../window/input.h"
|
||||
#include "scripting/scripting.h"
|
||||
#include "BlocksController.h"
|
||||
|
||||
#include "../core_defs.h"
|
||||
|
||||
@ -25,9 +27,6 @@ const float RUN_ZOOM = 1.1f;
|
||||
const float C_ZOOM = 0.1f;
|
||||
const float CROUCH_SHIFT_Y = -0.2f;
|
||||
|
||||
using glm::vec2;
|
||||
using glm::vec3;
|
||||
using std::string;
|
||||
|
||||
CameraControl::CameraControl(Player* player, const CameraSettings& settings)
|
||||
: player(player),
|
||||
@ -55,27 +54,27 @@ void CameraControl::updateMouse(PlayerInput& input) {
|
||||
float& camY = player->camY;
|
||||
camX += rotX;
|
||||
camY += rotY;
|
||||
if (camY < -radians(89.9f)){
|
||||
camY = -radians(89.9f);
|
||||
if (camY < -glm::radians(89.9f)){
|
||||
camY = -glm::radians(89.9f);
|
||||
}
|
||||
if (camY > radians(89.9f)){
|
||||
camY = radians(89.9f);
|
||||
if (camY > glm::radians(89.9f)){
|
||||
camY = glm::radians(89.9f);
|
||||
}
|
||||
|
||||
camera->rotation = mat4(1.0f);
|
||||
camera->rotation = glm::mat4(1.0f);
|
||||
camera->rotate(camY, camX, 0);
|
||||
}
|
||||
|
||||
void CameraControl::update(PlayerInput& input, float delta, Chunks* chunks) {
|
||||
Hitbox* hitbox = player->hitbox;
|
||||
|
||||
offset = vec3(0.0f, 0.7f, 0.0f);
|
||||
offset = glm::vec3(0.0f, 0.7f, 0.0f);
|
||||
|
||||
if (settings.shaking && !input.cheat) {
|
||||
const float k = CAM_SHAKE_DELTA_K;
|
||||
const float oh = CAM_SHAKE_OFFSET;
|
||||
const float ov = CAM_SHAKE_OFFSET_Y;
|
||||
const vec3& vel = hitbox->velocity;
|
||||
const glm::vec3& vel = hitbox->velocity;
|
||||
|
||||
interpVel = interpVel * (1.0f - delta * 5) + vel * delta * 0.1f;
|
||||
if (hitbox->grounded && interpVel.y < 0.0f){
|
||||
@ -83,12 +82,12 @@ void CameraControl::update(PlayerInput& input, float delta, Chunks* chunks) {
|
||||
}
|
||||
shake = shake * (1.0f - delta * k);
|
||||
if (hitbox->grounded) {
|
||||
float f = length(vec2(vel.x, vel.z));
|
||||
float f = glm::length(glm::vec2(vel.x, vel.z));
|
||||
shakeTimer += delta * f * CAM_SHAKE_SPEED;
|
||||
shake += f * delta * k;
|
||||
}
|
||||
offset += camera->right * sin(shakeTimer) * oh * shake;
|
||||
offset += camera->up * abs(cos(shakeTimer)) * ov * shake;
|
||||
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);
|
||||
}
|
||||
|
||||
@ -98,7 +97,7 @@ void CameraControl::update(PlayerInput& input, float delta, Chunks* chunks) {
|
||||
float dt = fmin(1.0f, delta * ZOOM_SPEED);
|
||||
float zoomValue = 1.0f;
|
||||
if (crouch){
|
||||
offset += vec3(0.f, CROUCH_SHIFT_Y, 0.f);
|
||||
offset += glm::vec3(0.f, CROUCH_SHIFT_Y, 0.f);
|
||||
zoomValue = CROUCH_ZOOM;
|
||||
} else if (input.sprint){
|
||||
zoomValue = RUN_ZOOM;
|
||||
@ -128,16 +127,20 @@ void CameraControl::update(PlayerInput& input, float delta, Chunks* chunks) {
|
||||
}
|
||||
}
|
||||
|
||||
vec3 PlayerController::selectedBlockPosition;
|
||||
vec3 PlayerController::selectedPointPosition;
|
||||
ivec3 PlayerController::selectedBlockNormal;
|
||||
glm::vec3 PlayerController::selectedBlockPosition;
|
||||
glm::vec3 PlayerController::selectedPointPosition;
|
||||
glm::ivec3 PlayerController::selectedBlockNormal;
|
||||
int PlayerController::selectedBlockId = -1;
|
||||
int PlayerController::selectedBlockStates = 0;
|
||||
|
||||
PlayerController::PlayerController(Level* level, const EngineSettings& settings)
|
||||
PlayerController::PlayerController(
|
||||
Level* level,
|
||||
const EngineSettings& settings,
|
||||
BlocksController* blocksController)
|
||||
: level(level),
|
||||
player(level->player),
|
||||
camControl(level->player, settings.camera) {
|
||||
camControl(level->player, settings.camera),
|
||||
blocksController(blocksController) {
|
||||
}
|
||||
|
||||
void PlayerController::update(float delta, bool input, bool pause) {
|
||||
@ -177,7 +180,7 @@ void PlayerController::updateKeyboard() {
|
||||
// block choice
|
||||
for (int i = 1; i < 10; i++){
|
||||
if (Events::jpressed(keycode::NUM_0+i)){
|
||||
player->choosenBlock = i;
|
||||
player->chosenBlock = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -211,9 +214,9 @@ void PlayerController::updateInteraction(){
|
||||
Player* player = level->player;
|
||||
Lighting* lighting = level->lighting;
|
||||
Camera* camera = player->camera;
|
||||
vec3 end;
|
||||
ivec3 iend;
|
||||
ivec3 norm;
|
||||
glm::vec3 end;
|
||||
glm::ivec3 iend;
|
||||
glm::ivec3 norm;
|
||||
|
||||
bool xkey = Events::pressed(keycode::X);
|
||||
bool lclick = Events::jactive(BIND_PLAYER_ATTACK) ||
|
||||
@ -241,9 +244,9 @@ void PlayerController::updateInteraction(){
|
||||
int z = iend.z;
|
||||
uint8_t states = 0;
|
||||
|
||||
Block* def = contentIds->getBlockDef(player->choosenBlock);
|
||||
Block* def = contentIds->getBlockDef(player->chosenBlock);
|
||||
if (def->rotatable){
|
||||
const string& name = def->rotations.name;
|
||||
const std::string& name = def->rotations.name;
|
||||
if (name == "pipe") {
|
||||
if (norm.x < 0.0f) states = BLOCK_DIR_WEST;
|
||||
else if (norm.x > 0.0f) states = BLOCK_DIR_EAST;
|
||||
@ -252,7 +255,7 @@ void PlayerController::updateInteraction(){
|
||||
else if (norm.z > 0.0f) states = BLOCK_DIR_NORTH;
|
||||
else if (norm.z < 0.0f) states = BLOCK_DIR_SOUTH;
|
||||
} else if (name == "pane") {
|
||||
vec3 vec = camera->dir;
|
||||
glm::vec3 vec = camera->dir;
|
||||
if (abs(vec.x) > abs(vec.z)){
|
||||
if (vec.x > 0.0f) states = BLOCK_DIR_EAST;
|
||||
if (vec.x < 0.0f) states = BLOCK_DIR_WEST;
|
||||
@ -266,8 +269,7 @@ void PlayerController::updateInteraction(){
|
||||
|
||||
Block* block = contentIds->getBlockDef(vox->id);
|
||||
if (lclick && block->breakable){
|
||||
chunks->set(x,y,z, 0, 0);
|
||||
lighting->onBlockSet(x,y,z, 0);
|
||||
blocksController->breakBlock(player, block, x, y, z);
|
||||
}
|
||||
if (rclick){
|
||||
if (block->model != BlockModel::xsprite){
|
||||
@ -276,19 +278,30 @@ void PlayerController::updateInteraction(){
|
||||
z = (iend.z)+(norm.z);
|
||||
}
|
||||
vox = chunks->get(x, y, z);
|
||||
int chosenBlock = player->chosenBlock;
|
||||
if (vox && (block = contentIds->getBlockDef(vox->id))->replaceable) {
|
||||
if (!level->physics->isBlockInside(x,y,z, player->hitbox)
|
||||
|| !def->obstacle){
|
||||
chunks->set(x, y, z, player->choosenBlock, states);
|
||||
lighting->onBlockSet(x,y,z, player->choosenBlock);
|
||||
Block* def = contentIds->getBlockDef(chosenBlock);
|
||||
if (def->grounded && !chunks->isSolid(x, y-1, z)) {
|
||||
chosenBlock = 0;
|
||||
}
|
||||
if (chosenBlock != vox->id) {
|
||||
chunks->set(x, y, z, chosenBlock, states);
|
||||
lighting->onBlockSet(x,y,z, chosenBlock);
|
||||
if (def->rt.funcsset.onplaced) {
|
||||
scripting::on_block_placed(player, def, x, y, z);
|
||||
}
|
||||
blocksController->updateSides(x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Events::jactive(BIND_PLAYER_PICK)){
|
||||
player->choosenBlock = chunks->get(x,y,z)->id;
|
||||
player->chosenBlock = chunks->get(x,y,z)->id;
|
||||
}
|
||||
} else {
|
||||
selectedBlockId = -1;
|
||||
selectedBlockStates = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
|
||||
class Camera;
|
||||
class Level;
|
||||
class BlocksController;
|
||||
|
||||
class CameraControl {
|
||||
Player* player;
|
||||
@ -29,6 +30,7 @@ class PlayerController {
|
||||
Player* player;
|
||||
PlayerInput input;
|
||||
CameraControl camControl;
|
||||
BlocksController* blocksController;
|
||||
|
||||
void updateKeyboard();
|
||||
void updateCamera(float delta, bool movement);
|
||||
@ -42,7 +44,9 @@ public:
|
||||
static int selectedBlockId;
|
||||
static int selectedBlockStates;
|
||||
|
||||
PlayerController(Level* level, const EngineSettings& settings);
|
||||
PlayerController(Level* level,
|
||||
const EngineSettings& settings,
|
||||
BlocksController* blocksController);
|
||||
void update(float delta, bool input, bool pause);
|
||||
};
|
||||
|
||||
|
||||
65
src/logic/scripting/api_lua.cpp
Normal file
65
src/logic/scripting/api_lua.cpp
Normal file
@ -0,0 +1,65 @@
|
||||
#include "api_lua.h"
|
||||
#include "scripting.h"
|
||||
|
||||
#include "../../world/Level.h"
|
||||
#include "../../content/Content.h"
|
||||
#include "../../voxels/Block.h"
|
||||
#include "../../voxels/Chunks.h"
|
||||
#include "../../voxels/voxel.h"
|
||||
|
||||
int l_block_name(lua_State* L) {
|
||||
int id = lua_tointeger(L, 1);
|
||||
lua_pushstring(L, scripting::content->indices->getBlockDef(id)->name.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_is_solid_at(lua_State* L) {
|
||||
int x = lua_tointeger(L, 1);
|
||||
int y = lua_tointeger(L, 2);
|
||||
int z = lua_tointeger(L, 3);
|
||||
|
||||
lua_pushboolean(L, scripting::level->chunks->isSolid(x, y, z));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_blocks_count(lua_State* L) {
|
||||
lua_pushinteger(L, scripting::content->indices->countBlockDefs());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_block_index(lua_State* L) {
|
||||
auto name = lua_tostring(L, 1);
|
||||
lua_pushinteger(L, scripting::content->requireBlock(name)->rt.id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_set_block(lua_State* L) {
|
||||
int x = lua_tointeger(L, 1);
|
||||
int y = lua_tointeger(L, 2);
|
||||
int z = lua_tointeger(L, 3);
|
||||
int id = lua_tointeger(L, 4);
|
||||
scripting::level->chunks->set(x, y, z, id, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int l_get_block(lua_State* L) {
|
||||
int x = lua_tointeger(L, 1);
|
||||
int y = lua_tointeger(L, 2);
|
||||
int z = lua_tointeger(L, 3);
|
||||
voxel* vox = scripting::level->chunks->get(x, y, z);
|
||||
int id = vox == nullptr ? -1 : vox->id;
|
||||
lua_pushinteger(L, id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define lua_addfunc(L, FUNC, NAME) (lua_pushcfunction(L, FUNC),\
|
||||
lua_setglobal(L, NAME))
|
||||
|
||||
void apilua::create_funcs(lua_State* L) {
|
||||
lua_addfunc(L, l_block_index, "block_index");
|
||||
lua_addfunc(L, l_block_name, "block_name");
|
||||
lua_addfunc(L, l_blocks_count, "blocks_count");
|
||||
lua_addfunc(L, l_is_solid_at, "is_solid_at");
|
||||
lua_addfunc(L, l_set_block, "set_block");
|
||||
lua_addfunc(L, l_get_block, "get_block");
|
||||
}
|
||||
14
src/logic/scripting/api_lua.h
Normal file
14
src/logic/scripting/api_lua.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef LOGIC_SCRIPTING_API_LUA_H_
|
||||
#define LOGIC_SCRIPTING_API_LUA_H_
|
||||
|
||||
#include <lua.hpp>
|
||||
|
||||
#ifndef LUAJIT_VERSION
|
||||
#pragma message("better use LuaJIT instead of plain Lua")
|
||||
#endif // LUAJIT_VERSION
|
||||
|
||||
namespace apilua {
|
||||
extern void create_funcs(lua_State* L);
|
||||
}
|
||||
|
||||
#endif // LOGIC_SCRIPTING_API_LUA_H_
|
||||
140
src/logic/scripting/scripting.cpp
Normal file
140
src/logic/scripting/scripting.cpp
Normal file
@ -0,0 +1,140 @@
|
||||
#include "scripting.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <lua.hpp>
|
||||
|
||||
#include "../../files/engine_paths.h"
|
||||
#include "../../files/files.h"
|
||||
#include "../../util/timeutil.h"
|
||||
#include "../../world/Level.h"
|
||||
#include "../../voxels/Block.h"
|
||||
#include "api_lua.h"
|
||||
|
||||
using namespace scripting;
|
||||
|
||||
namespace scripting {
|
||||
extern lua_State* L;
|
||||
extern EnginePaths* paths;
|
||||
}
|
||||
|
||||
lua_State* scripting::L = nullptr;
|
||||
Level* scripting::level = nullptr;
|
||||
const Content* scripting::content = nullptr;
|
||||
EnginePaths* scripting::paths = nullptr;
|
||||
|
||||
void delete_global(lua_State* L, const char* name) {
|
||||
lua_pushnil(L);
|
||||
lua_setglobal(L, name);
|
||||
}
|
||||
|
||||
bool rename_global(lua_State* L, const char* src, const char* dst) {
|
||||
lua_getglobal(L, src);
|
||||
if (lua_isnil(L, lua_gettop(L))) {
|
||||
lua_pop(L, lua_gettop(L));
|
||||
return false;
|
||||
}
|
||||
lua_setglobal(L, dst);
|
||||
delete_global(L, src);
|
||||
return true;
|
||||
}
|
||||
|
||||
void call_func(lua_State* L, int argc, const std::string& name) {
|
||||
if (lua_pcall(L, argc, LUA_MULTRET, 0)) {
|
||||
std::cerr << "Lua error in " << name << ": ";
|
||||
std::cerr << lua_tostring(L,-1) << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void scripting::initialize(EnginePaths* paths) {
|
||||
scripting::paths = paths;
|
||||
|
||||
L = luaL_newstate();
|
||||
if (L == nullptr) {
|
||||
throw std::runtime_error("could not to initialize Lua");
|
||||
}
|
||||
luaopen_base(L);
|
||||
luaopen_math(L);
|
||||
|
||||
std::cout << LUA_VERSION << std::endl;
|
||||
# ifdef LUAJIT_VERSION
|
||||
luaopen_jit(L);
|
||||
std::cout << LUAJIT_VERSION << std::endl;
|
||||
# endif // LUAJIT_VERSION
|
||||
|
||||
apilua::create_funcs(L);
|
||||
}
|
||||
|
||||
void scripting::on_world_load(Level* level) {
|
||||
scripting::level = level;
|
||||
scripting::content = level->content;
|
||||
|
||||
fs::path file = paths->getResources()/fs::path("scripts/world.lua");
|
||||
std::string src = files::read_string(file);
|
||||
luaL_loadbuffer(L, src.c_str(), src.length(), file.string().c_str());
|
||||
call_func(L, 0, "<script>");
|
||||
}
|
||||
|
||||
void scripting::on_world_quit() {
|
||||
scripting::level = nullptr;
|
||||
scripting::content = nullptr;
|
||||
}
|
||||
|
||||
void scripting::update_block(const Block* block, int x, int y, int z) {
|
||||
std::string name = block->name+".update";
|
||||
lua_getglobal(L, name.c_str());
|
||||
lua_pushinteger(L, x);
|
||||
lua_pushinteger(L, y);
|
||||
lua_pushinteger(L, z);
|
||||
call_func(L, 3, name);
|
||||
}
|
||||
|
||||
void scripting::random_update_block(const Block* block, int x, int y, int z) {
|
||||
std::string name = block->name+".randupdate";
|
||||
lua_getglobal(L, name.c_str());
|
||||
lua_pushinteger(L, x);
|
||||
lua_pushinteger(L, y);
|
||||
lua_pushinteger(L, z);
|
||||
call_func(L, 3, name);
|
||||
}
|
||||
|
||||
void scripting::on_block_placed(Player* player, const Block* block, int x, int y, int z) {
|
||||
std::string name = block->name+".placed";
|
||||
lua_getglobal(L, name.c_str());
|
||||
lua_pushinteger(L, x);
|
||||
lua_pushinteger(L, y);
|
||||
lua_pushinteger(L, z);
|
||||
call_func(L, 3, name);
|
||||
}
|
||||
|
||||
void scripting::on_block_broken(Player* player, const Block* block, int x, int y, int z) {
|
||||
std::string name = block->name+".broken";
|
||||
lua_getglobal(L, name.c_str());
|
||||
lua_pushinteger(L, x);
|
||||
lua_pushinteger(L, y);
|
||||
lua_pushinteger(L, z);
|
||||
call_func(L, 3, name);
|
||||
}
|
||||
|
||||
void scripting::load_block_script(std::string prefix, fs::path file, block_funcs_set* funcsset) {
|
||||
std::string src = files::read_string(file);
|
||||
std::cout << "loading script " << file.u8string() << std::endl;
|
||||
if (luaL_loadbuffer(L, src.c_str(), src.size(), file.string().c_str())) {
|
||||
std::cerr << "Lua error:" << lua_tostring(L,-1) << std::endl;
|
||||
return;
|
||||
}
|
||||
call_func(L, 0, "<script>");
|
||||
funcsset->init=rename_global(L, "init", (prefix+".init").c_str());
|
||||
funcsset->update=rename_global(L, "on_update", (prefix+".update").c_str());
|
||||
funcsset->randupdate=rename_global(L, "on_random_update", (prefix+".randupdate").c_str());
|
||||
funcsset->onbroken=rename_global(L, "on_broken", (prefix+".broken").c_str());
|
||||
funcsset->onplaced=rename_global(L, "on_placed", (prefix+".placed").c_str());
|
||||
}
|
||||
|
||||
void scripting::close() {
|
||||
lua_close(L);
|
||||
|
||||
L = nullptr;
|
||||
content = nullptr;
|
||||
level = nullptr;
|
||||
}
|
||||
26
src/logic/scripting/scripting.h
Normal file
26
src/logic/scripting/scripting.h
Normal file
@ -0,0 +1,26 @@
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
class EnginePaths;
|
||||
class Content;
|
||||
class Level;
|
||||
class Block;
|
||||
class Player;
|
||||
struct block_funcs_set;
|
||||
|
||||
namespace scripting {
|
||||
extern const Content* content;
|
||||
extern Level* level;
|
||||
|
||||
void initialize(EnginePaths* paths);
|
||||
void on_world_load(Level* level);
|
||||
void on_world_quit();
|
||||
void update_block(const Block* block, int x, int y, int z);
|
||||
void random_update_block(const Block* block, int x, int y, int z);
|
||||
void on_block_placed(Player* player, const Block* block, int x, int y, int z);
|
||||
void on_block_broken(Player* player, const Block* block, int x, int y, int z);
|
||||
void load_block_script(std::string prefix, fs::path file, block_funcs_set* funcsset);
|
||||
void close();
|
||||
}
|
||||
@ -18,12 +18,12 @@ const float JUMP_FORCE = 8.0f;
|
||||
|
||||
Player::Player(glm::vec3 position, float speed) :
|
||||
speed(speed),
|
||||
choosenBlock(1) {
|
||||
chosenBlock(1) {
|
||||
camera = new Camera(position, glm::radians(90.0f));
|
||||
currentViewCamera = camera;
|
||||
SPCamera = new Camera(position, glm::radians(90.0f));
|
||||
TPCamera = new Camera(position, glm::radians(90.0f));
|
||||
hitbox = new Hitbox(position, vec3(0.3f,0.9f,0.3f));
|
||||
hitbox = new Hitbox(position, glm::vec3(0.3f,0.9f,0.3f));
|
||||
}
|
||||
|
||||
Player::~Player(){
|
||||
@ -49,7 +49,7 @@ void Player::update(
|
||||
speed *= RUN_SPEED_MUL;
|
||||
}
|
||||
|
||||
vec3 dir(0,0,0);
|
||||
glm::vec3 dir(0,0,0);
|
||||
if (input.moveForward){
|
||||
dir.x += camera->dir.x;
|
||||
dir.z += camera->dir.z;
|
||||
@ -66,8 +66,8 @@ void Player::update(
|
||||
dir.x -= camera->right.x;
|
||||
dir.z -= camera->right.z;
|
||||
}
|
||||
if (length(dir) > 0.0f){
|
||||
dir = normalize(dir);
|
||||
if (glm::length(dir) > 0.0f){
|
||||
dir = glm::normalize(dir);
|
||||
hitbox->velocity.x += dir.x * speed * delta * 9;
|
||||
hitbox->velocity.z += dir.z * speed * delta * 9;
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ public:
|
||||
bool flight = false;
|
||||
bool noclip = false;
|
||||
bool debug = false;
|
||||
int choosenBlock;
|
||||
int chosenBlock;
|
||||
voxel selectedVoxel {0, 0};
|
||||
|
||||
float camX = 0.0f;
|
||||
|
||||
@ -1,4 +1,8 @@
|
||||
#include "Hitbox.h"
|
||||
|
||||
Hitbox::Hitbox(vec3 position, vec3 halfsize) : position(position), halfsize(halfsize), velocity(0.0f,0.0f,0.0f), linear_damping(0.1f) {
|
||||
Hitbox::Hitbox(glm::vec3 position, glm::vec3 halfsize)
|
||||
: position(position),
|
||||
halfsize(halfsize),
|
||||
velocity(0.0f,0.0f,0.0f),
|
||||
linear_damping(0.1f) {
|
||||
}
|
||||
|
||||
@ -3,17 +3,15 @@
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
using namespace glm;
|
||||
|
||||
class Hitbox {
|
||||
public:
|
||||
vec3 position;
|
||||
vec3 halfsize;
|
||||
vec3 velocity;
|
||||
glm::vec3 position;
|
||||
glm::vec3 halfsize;
|
||||
glm::vec3 velocity;
|
||||
float linear_damping;
|
||||
bool grounded = false;
|
||||
|
||||
Hitbox(vec3 position, vec3 halfsize);
|
||||
Hitbox(glm::vec3 position, glm::vec3 halfsize);
|
||||
};
|
||||
|
||||
#endif /* PHYSICS_HITBOX_H_ */
|
||||
|
||||
@ -25,14 +25,14 @@ int main(int argc, char** argv) {
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
platform::configure_encoding();
|
||||
std::filesystem::path userfiles = paths.getUserfiles();
|
||||
fs::path userfiles = paths.getUserfiles();
|
||||
try {
|
||||
EngineSettings settings;
|
||||
std::unique_ptr<toml::Wrapper> wrapper (create_wrapper(settings));
|
||||
|
||||
fs::path settings_file = userfiles/fs::path(SETTINGS_FILE);
|
||||
fs::path controls_file = userfiles/fs::path(CONTROLS_FILE);
|
||||
if (std::filesystem::is_regular_file(settings_file)) {
|
||||
if (fs::is_regular_file(settings_file)) {
|
||||
std::cout << "-- loading settings" << std::endl;
|
||||
std::string text = files::read_string(settings_file);
|
||||
toml::Reader reader(wrapper.get(), settings_file.string(), text);
|
||||
@ -40,7 +40,7 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
setup_bindings();
|
||||
Engine engine(settings, &paths);
|
||||
if (std::filesystem::is_regular_file(controls_file)) {
|
||||
if (fs::is_regular_file(controls_file)) {
|
||||
std::cout << "-- loading controls" << std::endl;
|
||||
std::string text = files::read_string(controls_file);
|
||||
load_controls(controls_file.string(), text);
|
||||
|
||||
@ -16,6 +16,14 @@ const uint FACE_PZ = 5;
|
||||
|
||||
const uint BLOCK_AABB_GRID = 16;
|
||||
|
||||
struct block_funcs_set {
|
||||
bool init: 1;
|
||||
bool update: 1;
|
||||
bool onplaced: 1;
|
||||
bool onbroken: 1;
|
||||
bool randupdate: 1;
|
||||
};
|
||||
|
||||
struct CoordSystem {
|
||||
glm::ivec3 axisX;
|
||||
glm::ivec3 axisY;
|
||||
@ -70,6 +78,7 @@ public:
|
||||
bool replaceable = false;
|
||||
bool breakable = true;
|
||||
bool rotatable = false;
|
||||
bool grounded = false;
|
||||
AABB hitbox;
|
||||
BlockRotProfile rotations;
|
||||
|
||||
@ -78,6 +87,7 @@ public:
|
||||
bool solid = true;
|
||||
bool emissive = false;
|
||||
AABB hitboxes[BlockRotProfile::MAX_COUNT];
|
||||
block_funcs_set funcsset {};
|
||||
} rt;
|
||||
|
||||
Block(std::string name);
|
||||
|
||||
@ -90,6 +90,13 @@ const AABB* Chunks::isObstacle(float x, float y, float z){
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool Chunks::isSolid(int x, int y, int z) {
|
||||
voxel* v = get(x, y, z);
|
||||
if (v == nullptr)
|
||||
return false;
|
||||
return contentIds->getBlockDef(v->id)->rt.solid;
|
||||
}
|
||||
|
||||
ubyte Chunks::getLight(int x, int y, int z, int channel){
|
||||
x -= ox * CHUNK_W;
|
||||
z -= oz * CHUNK_D;
|
||||
@ -167,7 +174,7 @@ void Chunks::set(int x, int y, int z, int id, uint8_t states){
|
||||
else if (y + 1 > chunk->top) chunk->top = y + 1;
|
||||
else if (id == 0) chunk->updateHeights();
|
||||
|
||||
if (lx == 0 && (chunk = getChunk(cx+ox-1, cz+oz)))
|
||||
if (lx == 0 && (chunk = getChunk(cx+ox-1, cz+oz)))
|
||||
chunk->setModified(true);
|
||||
if (lz == 0 && (chunk = getChunk(cx+ox, cz+oz-1)))
|
||||
chunk->setModified(true);
|
||||
|
||||
@ -54,6 +54,7 @@ public:
|
||||
glm::vec3 rayCastToObstacle(glm::vec3 start, glm::vec3 dir, float maxDist);
|
||||
|
||||
const AABB* isObstacle(float x, float y, float z);
|
||||
bool isSolid(int x, int y, int z);
|
||||
|
||||
// does not move chunks inside
|
||||
void _setOffset(int x, int z);
|
||||
|
||||
@ -17,7 +17,7 @@ Level::Level(World* world, const Content* content, Player* player, EngineSetting
|
||||
chunksStorage(new ChunksStorage(this)),
|
||||
events(new LevelEvents()) ,
|
||||
settings(settings) {
|
||||
physics = new PhysicsSolver(vec3(0, -22.6f, 0));
|
||||
physics = new PhysicsSolver(glm::vec3(0, -22.6f, 0));
|
||||
|
||||
uint matrixSize = (settings.chunks.loadDistance+
|
||||
settings.chunks.padding) * 2;
|
||||
@ -40,7 +40,7 @@ Level::~Level(){
|
||||
}
|
||||
|
||||
void Level::update() {
|
||||
vec3 position = player->hitbox->position;
|
||||
glm::vec3 position = player->hitbox->position;
|
||||
chunks->setCenter(position.x, position.z);
|
||||
|
||||
int matrixSize = (settings.chunks.loadDistance+
|
||||
|
||||
@ -5,16 +5,13 @@
|
||||
#include "../settings.h"
|
||||
|
||||
class Content;
|
||||
class ContentIndices;
|
||||
class World;
|
||||
class Player;
|
||||
class Chunks;
|
||||
class LevelEvents;
|
||||
class Lighting;
|
||||
class PhysicsSolver;
|
||||
class ChunksController;
|
||||
class ChunksStorage;
|
||||
class PlayerController;
|
||||
|
||||
class Level {
|
||||
public:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user