Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a8ca1edaef | |||
| 54a7662952 | |||
| 04d1969084 | |||
| 7ab2d5a083 | |||
| 85ddc90883 | |||
| d02d751275 | |||
| 3ad54bd59d | |||
| cf53a42620 | |||
| 66a04d3119 | |||
| 73c2aaadfb | |||
| b1dfcd9eda | |||
| 1b04ebe068 | |||
| 8b1538c602 | |||
| 5aeb2eb8c0 |
@@ -11,13 +11,15 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
- name: Install build tools
|
- name: Install build tools
|
||||||
run: |
|
run: |
|
||||||
# echo "deb [signed-by=/usr/share/keyrings/ubuntu-archive-keyring.gpg] http://archive.ubuntu.com/ubuntu noble main" | sudo tee /tmp/only.list
|
# echo "deb [signed-by=/usr/share/keyrings/ubuntu-archive-keyring.gpg] http://archive.ubuntu.com/ubuntu noble main" | sudo tee /tmp/only.list
|
||||||
# sudo apt-get update -o Dir::Etc::sourcelist=/tmp/only.list -o Dir::Etc::sourceparts="-" -qq
|
# sudo apt-get update -o Dir::Etc::sourcelist=/tmp/only.list -o Dir::Etc::sourceparts="-" -qq
|
||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt install -y build-essential cmake zip unzip make libxrandr-dev g++-mingw-w64-x86-64 gcc-mingw-w64-x86-64 libxinerama-dev libxcursor-dev libxi-dev libgl-dev
|
sudo apt install -y build-essential cmake zip unzip make libxrandr-dev g++-mingw-w64-x86-64 gcc-mingw-w64-x86-64 g++-mingw-w64-i686 gcc-mingw-w64-i686 libxinerama-dev libxcursor-dev libxi-dev libgl-dev
|
||||||
|
|
||||||
- name: Build makeheaders
|
- name: Build makeheaders
|
||||||
run: |
|
run: |
|
||||||
@@ -25,61 +27,26 @@ jobs:
|
|||||||
make
|
make
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
- name: Fetch libraries
|
|
||||||
run: |
|
|
||||||
cd ${{ gitea.workspace }}/src/libraries
|
|
||||||
rm enet -r
|
|
||||||
rm Lua -r
|
|
||||||
rm raylib -r
|
|
||||||
rm yaml-cpp -r
|
|
||||||
|
|
||||||
wget https://github.com/zpl-c/enet/archive/refs/heads/master.zip
|
|
||||||
unzip master.zip
|
|
||||||
mv enet-master enet
|
|
||||||
rm master.zip
|
|
||||||
|
|
||||||
wget https://github.com/walterschell/Lua/archive/refs/heads/master.zip
|
|
||||||
unzip master.zip
|
|
||||||
mv Lua-master Lua
|
|
||||||
rm master.zip
|
|
||||||
|
|
||||||
wget https://github.com/raysan5/raylib/archive/refs/heads/master.zip
|
|
||||||
unzip master.zip
|
|
||||||
mv raylib-master raylib
|
|
||||||
rm master.zip
|
|
||||||
|
|
||||||
wget https://github.com/jbeder/yaml-cpp/archive/refs/heads/master.zip
|
|
||||||
unzip master.zip
|
|
||||||
mv yaml-cpp-master yaml-cpp
|
|
||||||
rm master.zip
|
|
||||||
|
|
||||||
ls -r
|
|
||||||
|
|
||||||
cd ../..
|
|
||||||
|
|
||||||
|
|
||||||
- name: Compile
|
- name: Compile
|
||||||
run: |
|
run: |
|
||||||
chmod +x ${{ gitea.workspace }}/compile.sh
|
chmod +x ${{ gitea.workspace }}/compile.sh
|
||||||
sh ${{ gitea.workspace }}/compile.sh
|
sh ${{ gitea.workspace }}/compile.sh
|
||||||
zip -r release-linux.zip OUTPUT-Linux || true
|
|
||||||
zip -r release-w64.zip OUTPUT-w64 || true
|
|
||||||
zip -r release-w32.zip OUTPUT-w32 || true
|
|
||||||
|
|
||||||
- name: Upload Linux Release
|
- name: Upload Linux Release
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: release-linux
|
name: release-linux
|
||||||
path: release-linux.zip
|
path: OUTPUT-Linux
|
||||||
|
|
||||||
- name: Upload Windows64 Release
|
- name: Upload Windows64 Release
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: release-w64
|
name: release-w64
|
||||||
path: release-w64.zip
|
path: OUTPUT-w64
|
||||||
|
|
||||||
- name: Upload Windows32 Release
|
- name: Upload Windows32 Release
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: release-w32
|
name: release-w32
|
||||||
path: release-w32.zip
|
path: OUTPUT-w32
|
||||||
|
|||||||
@@ -9,3 +9,5 @@ snapshots
|
|||||||
OUTPUT-Linux
|
OUTPUT-Linux
|
||||||
OUTPUT-w64
|
OUTPUT-w64
|
||||||
OUTPUT-w32
|
OUTPUT-w32
|
||||||
|
makeheaders/makeheaders.exe
|
||||||
|
makeheaders/makeheaders
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
[submodule "src/libraries/enet"]
|
||||||
|
path = src/libraries/enet
|
||||||
|
url = https://github.com/lsalzman/enet
|
||||||
|
[submodule "src/libraries/Lua"]
|
||||||
|
path = src/libraries/Lua
|
||||||
|
url = https://github.com/walterschell/Lua
|
||||||
|
[submodule "src/libraries/raylib"]
|
||||||
|
path = src/libraries/raylib
|
||||||
|
url = https://github.com/raysan5/raylib
|
||||||
|
[submodule "src/libraries/yaml-cpp"]
|
||||||
|
path = src/libraries/yaml-cpp
|
||||||
|
url = https://github.com/jbeder/yaml-cpp
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# Compiling
|
||||||
|
! NOTICE: Compile with `-recursive`, e.g `git clone ... -recursive`
|
||||||
|
## Compiling on Linux
|
||||||
|
1) Install tools.
|
||||||
|
**Debian-based distros:**
|
||||||
|
Essential:
|
||||||
|
```sh
|
||||||
|
sudo apt install build-essential cmake zip unzip make libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libgl-dev
|
||||||
|
```
|
||||||
|
If you also want to compile for Windows:
|
||||||
|
```sh
|
||||||
|
sudo apt install g++-mingw-w64-x86-64 gcc-mingw-w64-x86-64 g++-mingw-w64-i686 gcc-mingw-w64-i686
|
||||||
|
```
|
||||||
|
|
||||||
|
**Arch-based distros:**
|
||||||
|
Essential:
|
||||||
|
`TODO`
|
||||||
|
If you also want to compile for Windows:
|
||||||
|
`TODO`
|
||||||
|
|
||||||
|
2) Run `compile.sh` to compile for Linux, 64-bit Windows & 32-bit Windows.
|
||||||
|
Run `compile_linux.sh` to compile for Linux only.
|
||||||
|
|
||||||
|
## Compiling on Windows
|
||||||
|
1) Install [CMake](https://cmake.org/download/), [Ninja](https://ninja-build.org/) and [MinGW](https://www.mingw-w64.org/).
|
||||||
|
Try them out in the terminal: `cmake -version`, `ninja --version`, `gcc -version`, `g++ -version`.
|
||||||
|
If some are missing, add them to PATH.
|
||||||
|
|
||||||
|
2) From the terminal, run `compile.ps1`.
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
cd makeheaders
|
||||||
|
make
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
./makeheaders/makeheaders.exe -h src/helpers/vars.hpp src/helpers/chunks.cpp src/helpers/debug.cpp src/helpers/entities.cpp src/helpers/input.cpp src/helpers/menu.cpp src/helpers/mesher.cpp src/helpers/networking.cpp src/helpers/utils.cpp src/helpers/inlines.hpp src/helpers/inventory.cpp src/helpers/locale.cpp src/helpers/recipes.cpp src/helpers/particles.cpp src/helpers/player.cpp src/helpers/multisound.cpp -v > tmp.hpp
|
||||||
|
Get-Content .\additions.hpp, .\tmp.hpp | Out-File .\src\helpers\common.hpp -Encoding UTF8
|
||||||
|
rm tmp.hpp
|
||||||
|
|
||||||
|
echo Building x86-64 Windows...
|
||||||
|
rm build
|
||||||
|
cmake -DCMAKE_TOOLCHAIN_FILE='toolchains/mingw-w64-native.cmake' . -DWIN32=ON -DWIN32=true -B build -G "Ninja"
|
||||||
|
cmake --build build
|
||||||
|
mkdir OUTPUT-w64
|
||||||
|
cp build/src/RCRAFT.exe OUTPUT-w64/CubeGame.exe
|
||||||
|
cp -r data/resources OUTPUT-w64
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
#/usr/bin/bash
|
#/usr/bin/bash
|
||||||
|
|
||||||
|
cd makeheaders
|
||||||
|
make
|
||||||
|
cd ..
|
||||||
|
|
||||||
sh compile_linux.sh
|
sh compile_linux.sh
|
||||||
sh compile_windows_64.sh
|
sh compile_windows_64.sh
|
||||||
sh compile_windows.sh
|
sh compile_windows.sh
|
||||||
+3
-7
@@ -1,17 +1,13 @@
|
|||||||
#/usr/bin/bash
|
#/usr/bin/bash
|
||||||
|
|
||||||
./makeheaders/makeheaders -h src/helpers/vars.hpp src/helpers/chunks.cpp src/helpers/debug.cpp src/helpers/entities.cpp src/helpers/input.cpp src/helpers/menu.cpp src/helpers/mesher.cpp src/helpers/networking.cpp src/helpers/utils.cpp src/helpers/inlines.hpp src/helpers/inventory.cpp src/helpers/locale.cpp src/helpers/recipes.cpp src/helpers/particles.cpp src/helpers/player.cpp src/helpers/multisound.cpp src/helpers/svlib.cpp -v > tmp.hpp
|
./makeheaders/makeheaders -h src/helpers/vars.hpp src/helpers/chunks.cpp src/helpers/debug.cpp src/helpers/entities.cpp src/helpers/input.cpp src/helpers/menu.cpp src/helpers/mesher.cpp src/helpers/networking.cpp src/helpers/utils.cpp src/helpers/inlines.hpp src/helpers/inventory.cpp src/helpers/locale.cpp src/helpers/recipes.cpp src/helpers/particles.cpp src/helpers/player.cpp src/helpers/multisound.cpp -v > tmp.hpp
|
||||||
cat additions.hpp tmp.hpp > src/helpers/common.hpp
|
cat additions.hpp tmp.hpp > src/helpers/common.hpp
|
||||||
rm tmp.hpp
|
rm tmp.hpp
|
||||||
|
|
||||||
echo Building x86-64 Linux...
|
echo Building x86-64 Linux...
|
||||||
rm -rf build
|
rm -rf build
|
||||||
cmake -B build -DUNIX=ON -DUNIX=true
|
cmake -B build -DUNIX=ON -DUNIX=true -DCMAKE_BUILD_TYPE=Debug
|
||||||
cd build
|
cmake --build build
|
||||||
make -j12
|
|
||||||
cd ..
|
|
||||||
mkdir OUTPUT-Linux
|
mkdir OUTPUT-Linux
|
||||||
cp build/src/RCRAFT OUTPUT-Linux/CubeGame
|
cp build/src/RCRAFT OUTPUT-Linux/CubeGame
|
||||||
cp -r data/resources OUTPUT-Linux
|
cp -r data/resources OUTPUT-Linux
|
||||||
mkdir OUTPUT-Linux/user
|
|
||||||
mkdir OUTPUT-Linux/user/worlds
|
|
||||||
+1
-5
@@ -7,11 +7,7 @@ rm tmp.hpp
|
|||||||
echo Building i686 Windows...
|
echo Building i686 Windows...
|
||||||
rm -rf build
|
rm -rf build
|
||||||
cmake -DCMAKE_TOOLCHAIN_FILE=toolchains/mingw-w32.cmake -DWIN32=ON -DWIN32=true -B build
|
cmake -DCMAKE_TOOLCHAIN_FILE=toolchains/mingw-w32.cmake -DWIN32=ON -DWIN32=true -B build
|
||||||
cd build
|
cmake --build build
|
||||||
make -j12
|
|
||||||
cd ..
|
|
||||||
mkdir OUTPUT-w32
|
mkdir OUTPUT-w32
|
||||||
cp build/src/RCRAFT.exe OUTPUT-w32/CubeGame.exe
|
cp build/src/RCRAFT.exe OUTPUT-w32/CubeGame.exe
|
||||||
cp -r data/resources OUTPUT-w32
|
cp -r data/resources OUTPUT-w32
|
||||||
mkdir OUTPUT-w32/user
|
|
||||||
mkdir OUTPUT-w32/user/worlds
|
|
||||||
@@ -7,11 +7,7 @@ rm tmp.hpp
|
|||||||
echo Building x86-64 Windows...
|
echo Building x86-64 Windows...
|
||||||
rm -rf build
|
rm -rf build
|
||||||
cmake -DCMAKE_TOOLCHAIN_FILE=toolchains/mingw-w64.cmake -DWIN32=ON -DWIN32=true -B build
|
cmake -DCMAKE_TOOLCHAIN_FILE=toolchains/mingw-w64.cmake -DWIN32=ON -DWIN32=true -B build
|
||||||
cd build
|
cmake --build build
|
||||||
make -j12
|
|
||||||
cd ..
|
|
||||||
mkdir OUTPUT-w64
|
mkdir OUTPUT-w64
|
||||||
cp build/src/RCRAFT.exe OUTPUT-w64/CubeGame.exe
|
cp build/src/RCRAFT.exe OUTPUT-w64/CubeGame.exe
|
||||||
cp -r data/resources OUTPUT-w64
|
cp -r data/resources OUTPUT-w64
|
||||||
mkdir OUTPUT-w64/user
|
|
||||||
mkdir OUTPUT-w64/user/worlds
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
211d25
|
|
||||||
413d42
|
|
||||||
5c5b63
|
|
||||||
7c808b
|
|
||||||
a5b0b6
|
|
||||||
d6dede
|
|
||||||
ffffff
|
|
||||||
dcded1
|
|
||||||
aab1a1
|
|
||||||
7b8375
|
|
||||||
585f57
|
|
||||||
3c3c3c
|
|
||||||
635d5a
|
|
||||||
8d837d
|
|
||||||
b4aea4
|
|
||||||
dedcd1
|
|
||||||
eadedf
|
|
||||||
bcacb1
|
|
||||||
8f8189
|
|
||||||
685d66
|
|
||||||
643747
|
|
||||||
b2434d
|
|
||||||
e55858
|
|
||||||
fa8971
|
|
||||||
ffb999
|
|
||||||
ffe0b7
|
|
||||||
ffbdc1
|
|
||||||
ef93b5
|
|
||||||
c971a2
|
|
||||||
944e89
|
|
||||||
4c3d57
|
|
||||||
5d558f
|
|
||||||
777dc4
|
|
||||||
96b1e7
|
|
||||||
bedef6
|
|
||||||
aae3db
|
|
||||||
5ac5ce
|
|
||||||
4694a8
|
|
||||||
346376
|
|
||||||
2a3b4a
|
|
||||||
29684a
|
|
||||||
379648
|
|
||||||
79b547
|
|
||||||
b8cf61
|
|
||||||
f3db6f
|
|
||||||
f4ba7a
|
|
||||||
e79055
|
|
||||||
ce6442
|
|
||||||
944940
|
|
||||||
91555d
|
|
||||||
b76f6b
|
|
||||||
cd9383
|
|
||||||
e1ba9e
|
|
||||||
facafb
|
|
||||||
d49ce5
|
|
||||||
9f76b8
|
|
||||||
725689
|
|
||||||
edb762
|
|
||||||
fcfbc9
|
|
||||||
de9463
|
|
||||||
b66a4d
|
|
||||||
333f29
|
|
||||||
4e5c2c
|
|
||||||
708939
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 308 B |
@@ -14,12 +14,14 @@ speed_up: Fly faster
|
|||||||
fly: Toggle flying
|
fly: Toggle flying
|
||||||
chat: Open chat
|
chat: Open chat
|
||||||
swap_mouse: Swap LMB/RMB
|
swap_mouse: Swap LMB/RMB
|
||||||
|
inventory: Open inventory
|
||||||
# Menu
|
# Menu
|
||||||
select_level: Singleplayer
|
select_level: Singleplayer
|
||||||
multiplayer: Multiplayer
|
multiplayer: Multiplayer
|
||||||
join: Join
|
join: Join
|
||||||
exit: Exit
|
exit: Exit
|
||||||
options: Options
|
options: Options
|
||||||
|
create_world: Create world
|
||||||
# Multiplayer errors
|
# Multiplayer errors
|
||||||
error_notfound: Host not found!
|
error_notfound: Host not found!
|
||||||
error_internal: Internal enet error!
|
error_internal: Internal enet error!
|
||||||
@@ -41,21 +43,17 @@ item.dirt: "Dirt"
|
|||||||
item.sand: "Sand"
|
item.sand: "Sand"
|
||||||
item.water: "Water"
|
item.water: "Water"
|
||||||
item.planks: "Wooden Planks"
|
item.planks: "Wooden Planks"
|
||||||
item.gray_bricks: "Gray Bricks"
|
item.stone_bricks: "Stone Bricks"
|
||||||
item.red_bricks: "Red Bricks"
|
item.copper_block: "Copper Block"
|
||||||
item.blue_bricks: "Blue Bricks"
|
item.silver_block: "Silver Block"
|
||||||
item.green_bricks: "Green Bricks"
|
item.gold_block: "Gold Block"
|
||||||
item.glass: "Glass"
|
item.glass: "Glass"
|
||||||
item.log: "Log"
|
item.log: "Log"
|
||||||
item.spruce_planks: "Spruce Planks"
|
item.spruce_planks: "Spruce Planks"
|
||||||
item.red_block: "Red Block"
|
item.red_block: "Red Block"
|
||||||
item.green_block: "Green Block"
|
item.green_block: "Green Block"
|
||||||
item.blue_block: "Blue Block"
|
item.blue_block: "Blue Block"
|
||||||
item.yellow_block: "Yellow Block"
|
|
||||||
item.cyan_block: "Cyan Block"
|
|
||||||
item.magenta_block: "Magenta Block"
|
|
||||||
item.white_block: "White Block"
|
item.white_block: "White Block"
|
||||||
item.black_block: "Black Block"
|
|
||||||
item.leaves: "Leaves"
|
item.leaves: "Leaves"
|
||||||
item.copper_ore: "Copper Ore"
|
item.copper_ore: "Copper Ore"
|
||||||
item.silver_ore: "Silver Ore"
|
item.silver_ore: "Silver Ore"
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 4.5 KiB |
@@ -0,0 +1,37 @@
|
|||||||
|
#version 330
|
||||||
|
|
||||||
|
in vec2 fragTexCoord;
|
||||||
|
in vec4 fragColor;
|
||||||
|
in vec3 fragPosition;
|
||||||
|
in vec3 fragNormal;
|
||||||
|
|
||||||
|
uniform sampler2D texture0;
|
||||||
|
uniform vec4 sunlightColor;
|
||||||
|
|
||||||
|
uniform vec3 lightDir;
|
||||||
|
|
||||||
|
out vec4 finalColor;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec4 texelColor = texture(texture0, fragTexCoord);
|
||||||
|
|
||||||
|
vec3 N = normalize(fragNormal);
|
||||||
|
vec3 L = normalize(lightDir);
|
||||||
|
|
||||||
|
float ndotl = max(dot(N, L), 0.0);
|
||||||
|
float ambient = 0.1;
|
||||||
|
float sunfactor = ambient + (1.0 - ambient) * ndotl;
|
||||||
|
|
||||||
|
sunfactor *= 1+min(0, L.y);
|
||||||
|
vec3 Lmoon = normalize(-lightDir);
|
||||||
|
float ndotlMoon = max(dot(N, Lmoon), 0.0);
|
||||||
|
float moonfactor = (ambient + (1.0 - ambient) * ndotlMoon) * 8;
|
||||||
|
moonfactor *= max(0, -L.y);
|
||||||
|
|
||||||
|
// In fragColor, 'r' is blocklight R, 'g' is blocklight G, 'b' is blocklight B and 'a' is sunlight
|
||||||
|
texelColor.r *= fragColor.a * sunlightColor.r * (sunfactor+moonfactor) + fragColor.r;
|
||||||
|
texelColor.g *= fragColor.a * sunlightColor.g * (sunfactor+moonfactor) + fragColor.g;
|
||||||
|
texelColor.b *= fragColor.a * sunlightColor.b * (sunfactor+moonfactor) + fragColor.b;
|
||||||
|
finalColor = texelColor;
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
#version 330
|
||||||
|
|
||||||
|
// Input vertex attributes
|
||||||
|
in vec3 vertexPosition;
|
||||||
|
in vec2 vertexTexCoord;
|
||||||
|
in vec3 vertexNormal;
|
||||||
|
in vec4 vertexColor;
|
||||||
|
|
||||||
|
// Input uniform values
|
||||||
|
uniform mat4 mvp;
|
||||||
|
uniform mat4 matModel;
|
||||||
|
uniform mat4 matNormal;
|
||||||
|
|
||||||
|
// Output vertex attributes (to fragment shader)
|
||||||
|
out vec3 fragPosition;
|
||||||
|
out vec2 fragTexCoord;
|
||||||
|
out vec4 fragColor;
|
||||||
|
out vec3 fragNormal;
|
||||||
|
|
||||||
|
// NOTE: Add your custom variables here
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
// Send vertex attributes to fragment shader
|
||||||
|
fragPosition = vec3(matModel*vec4(vertexPosition, 1.0));
|
||||||
|
fragTexCoord = vertexTexCoord;
|
||||||
|
fragColor = vertexColor;
|
||||||
|
fragNormal = normalize(vec3(matNormal*vec4(vertexNormal, 1.0)));
|
||||||
|
|
||||||
|
// Calculate final vertex position
|
||||||
|
gl_Position = mvp*vec4(vertexPosition, 1.0);
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
#version 330
|
||||||
|
|
||||||
|
in vec2 fragTexCoord;
|
||||||
|
in vec4 fragColor;
|
||||||
|
in vec3 fragPosition;
|
||||||
|
in vec3 fragNormal;
|
||||||
|
|
||||||
|
uniform sampler2D texture0;
|
||||||
|
uniform vec4 sunlightColor;
|
||||||
|
uniform vec4 skyColor;
|
||||||
|
|
||||||
|
uniform vec3 lightDir;
|
||||||
|
|
||||||
|
out vec4 finalColor;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec4 texelColor = texture(texture0, fragTexCoord);
|
||||||
|
|
||||||
|
vec3 N = normalize(fragNormal);
|
||||||
|
vec3 L = normalize(lightDir);
|
||||||
|
|
||||||
|
float ndotl = max(dot(N, L), 0.0);
|
||||||
|
float ambient = 0.1;
|
||||||
|
float sunfactor = ambient + (1.0 - ambient) * ndotl;
|
||||||
|
|
||||||
|
sunfactor *= 1+min(0, L.y);
|
||||||
|
vec3 Lmoon = normalize(-lightDir);
|
||||||
|
float ndotlMoon = max(dot(N, Lmoon), 0.0);
|
||||||
|
float moonfactor = (ambient + (1.0 - ambient) * ndotlMoon) * 8;
|
||||||
|
moonfactor *= max(0, -L.y);
|
||||||
|
|
||||||
|
// In fragColor, 'r' is blocklight R, 'g' is blocklight G, 'b' is blocklight B and 'a' is sunlight
|
||||||
|
float sunlight = fragColor.a;
|
||||||
|
texelColor.r *= sunlight * sunlightColor.r * (sunfactor+moonfactor) + fragColor.r;
|
||||||
|
texelColor.g *= sunlight * sunlightColor.g * (sunfactor+moonfactor) + fragColor.g;
|
||||||
|
texelColor.b *= sunlight * sunlightColor.b * (sunfactor+moonfactor) + fragColor.b;
|
||||||
|
float highlight = texelColor.a;
|
||||||
|
if(highlight < 0.25) highlight = 0;
|
||||||
|
float highlight_final = abs(N.y)*highlight * 4;
|
||||||
|
vec3 highlightColor = sunlightColor.rgb*highlight_final*sunlight;
|
||||||
|
highlightColor.r += fragColor.r*highlight_final;
|
||||||
|
highlightColor.g += fragColor.g*highlight_final;
|
||||||
|
highlightColor.b += fragColor.b*highlight_final;
|
||||||
|
finalColor = texelColor + vec4(highlightColor, min(1.0, highlight_final));
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
#version 330
|
||||||
|
|
||||||
|
// Input vertex attributes
|
||||||
|
in vec3 vertexPosition;
|
||||||
|
in vec2 vertexTexCoord;
|
||||||
|
in vec3 vertexNormal;
|
||||||
|
in vec4 vertexColor;
|
||||||
|
|
||||||
|
// Input uniform values
|
||||||
|
uniform mat4 mvp;
|
||||||
|
uniform mat4 matModel;
|
||||||
|
uniform mat4 matNormal;
|
||||||
|
uniform float time;
|
||||||
|
|
||||||
|
// Output vertex attributes (to fragment shader)
|
||||||
|
out vec3 fragPosition;
|
||||||
|
out vec2 fragTexCoord;
|
||||||
|
out vec4 fragColor;
|
||||||
|
out vec3 fragNormal;
|
||||||
|
|
||||||
|
// NOTE: Add your custom variables here
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
// Send vertex attributes to fragment shader
|
||||||
|
fragPosition = vec3(matModel*vec4(vertexPosition, 1.0));
|
||||||
|
fragTexCoord = vertexTexCoord;
|
||||||
|
fragColor = vertexColor;
|
||||||
|
fragNormal = normalize(vec3(matNormal*vec4(vertexNormal, 1.0)));
|
||||||
|
|
||||||
|
// Calculate final vertex position
|
||||||
|
vec3 pos = vertexPosition + vec3(0, sin(time * 2.0 + vertexPosition.x * 1.5) / 20.0 + cos(time * 2.0 + vertexPosition.z * 1.5) / 20.0-0.1, 0);
|
||||||
|
gl_Position = mvp*vec4(pos, 1.0);
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 901 B |
Binary file not shown.
|
After Width: | Height: | Size: 2.0 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.2 KiB |
Binary file not shown.
+1
-1
@@ -5,7 +5,7 @@ add_subdirectory(helpers)
|
|||||||
|
|
||||||
set(YAML_BUILD_SHARED_LIBS OFF)
|
set(YAML_BUILD_SHARED_LIBS OFF)
|
||||||
set(YAML_MSVC_SHARED_RT OFF)
|
set(YAML_MSVC_SHARED_RT OFF)
|
||||||
set(OPENGL_VERSION 1.1)
|
set(OPENGL_VERSION 3.3)
|
||||||
|
|
||||||
add_subdirectory(libraries/raylib)
|
add_subdirectory(libraries/raylib)
|
||||||
add_subdirectory(libraries/enet)
|
add_subdirectory(libraries/enet)
|
||||||
|
|||||||
+2441
File diff suppressed because it is too large
Load Diff
@@ -1,659 +0,0 @@
|
|||||||
//----------------------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// siv::PerlinNoise
|
|
||||||
// Perlin noise library for modern C++
|
|
||||||
//
|
|
||||||
// Copyright (C) 2013-2021 Ryo Suzuki <reputeless@gmail.com>
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
// of this software and associated documentation files(the "Software"), to deal
|
|
||||||
// in the Software without restriction, including without limitation the rights
|
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
|
||||||
// furnished to do so, subject to the following conditions :
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in
|
|
||||||
// all copies or substantial portions of the Software.
|
|
||||||
//
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
// THE SOFTWARE.
|
|
||||||
//
|
|
||||||
//----------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
# pragma once
|
|
||||||
# include <cstdint>
|
|
||||||
# include <algorithm>
|
|
||||||
# include <array>
|
|
||||||
# include <iterator>
|
|
||||||
# include <numeric>
|
|
||||||
# include <random>
|
|
||||||
# include <type_traits>
|
|
||||||
|
|
||||||
# if __has_include(<concepts>) && defined(__cpp_concepts)
|
|
||||||
# include <concepts>
|
|
||||||
# endif
|
|
||||||
|
|
||||||
|
|
||||||
// Library major version
|
|
||||||
# define SIVPERLIN_VERSION_MAJOR 3
|
|
||||||
|
|
||||||
// Library minor version
|
|
||||||
# define SIVPERLIN_VERSION_MINOR 0
|
|
||||||
|
|
||||||
// Library revision version
|
|
||||||
# define SIVPERLIN_VERSION_REVISION 0
|
|
||||||
|
|
||||||
// Library version
|
|
||||||
# define SIVPERLIN_VERSION ((SIVPERLIN_VERSION_MAJOR * 100 * 100) + (SIVPERLIN_VERSION_MINOR * 100) + (SIVPERLIN_VERSION_REVISION))
|
|
||||||
|
|
||||||
|
|
||||||
// [[nodiscard]] for constructors
|
|
||||||
# if (201907L <= __has_cpp_attribute(nodiscard))
|
|
||||||
# define SIVPERLIN_NODISCARD_CXX20 [[nodiscard]]
|
|
||||||
# else
|
|
||||||
# define SIVPERLIN_NODISCARD_CXX20
|
|
||||||
# endif
|
|
||||||
|
|
||||||
|
|
||||||
// std::uniform_random_bit_generator concept
|
|
||||||
# if __cpp_lib_concepts
|
|
||||||
# define SIVPERLIN_CONCEPT_URBG template <std::uniform_random_bit_generator URBG>
|
|
||||||
# define SIVPERLIN_CONCEPT_URBG_ template <std::uniform_random_bit_generator URBG>
|
|
||||||
# else
|
|
||||||
# define SIVPERLIN_CONCEPT_URBG template <class URBG, std::enable_if_t<std::conjunction_v<std::is_invocable<URBG&>, std::is_unsigned<std::invoke_result_t<URBG&>>>>* = nullptr>
|
|
||||||
# define SIVPERLIN_CONCEPT_URBG_ template <class URBG, std::enable_if_t<std::conjunction_v<std::is_invocable<URBG&>, std::is_unsigned<std::invoke_result_t<URBG&>>>>*>
|
|
||||||
# endif
|
|
||||||
|
|
||||||
|
|
||||||
// arbitrary value for increasing entropy
|
|
||||||
# ifndef SIVPERLIN_DEFAULT_Y
|
|
||||||
# define SIVPERLIN_DEFAULT_Y (0.12345)
|
|
||||||
# endif
|
|
||||||
|
|
||||||
// arbitrary value for increasing entropy
|
|
||||||
# ifndef SIVPERLIN_DEFAULT_Z
|
|
||||||
# define SIVPERLIN_DEFAULT_Z (0.34567)
|
|
||||||
# endif
|
|
||||||
|
|
||||||
|
|
||||||
namespace siv
|
|
||||||
{
|
|
||||||
template <class Float>
|
|
||||||
class BasicPerlinNoise
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
static_assert(std::is_floating_point_v<Float>);
|
|
||||||
|
|
||||||
///////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Typedefs
|
|
||||||
//
|
|
||||||
|
|
||||||
using state_type = std::array<std::uint8_t, 256>;
|
|
||||||
|
|
||||||
using value_type = Float;
|
|
||||||
|
|
||||||
using default_random_engine = std::mt19937;
|
|
||||||
|
|
||||||
using seed_type = typename default_random_engine::result_type;
|
|
||||||
|
|
||||||
///////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Constructors
|
|
||||||
//
|
|
||||||
|
|
||||||
SIVPERLIN_NODISCARD_CXX20
|
|
||||||
constexpr BasicPerlinNoise() noexcept;
|
|
||||||
|
|
||||||
SIVPERLIN_NODISCARD_CXX20
|
|
||||||
explicit BasicPerlinNoise(seed_type seed);
|
|
||||||
|
|
||||||
SIVPERLIN_CONCEPT_URBG
|
|
||||||
SIVPERLIN_NODISCARD_CXX20
|
|
||||||
explicit BasicPerlinNoise(URBG&& urbg);
|
|
||||||
|
|
||||||
///////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Reseed
|
|
||||||
//
|
|
||||||
|
|
||||||
void reseed(seed_type seed);
|
|
||||||
|
|
||||||
SIVPERLIN_CONCEPT_URBG
|
|
||||||
void reseed(URBG&& urbg);
|
|
||||||
|
|
||||||
///////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Serialization
|
|
||||||
//
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
constexpr const state_type& serialize() const noexcept;
|
|
||||||
|
|
||||||
constexpr void deserialize(const state_type& state) noexcept;
|
|
||||||
|
|
||||||
///////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Noise (The result is in the range [-1, 1])
|
|
||||||
//
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
value_type noise1D(value_type x) const noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
value_type noise2D(value_type x, value_type y) const noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
value_type noise3D(value_type x, value_type y, value_type z) const noexcept;
|
|
||||||
|
|
||||||
///////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Noise (The result is remapped to the range [0, 1])
|
|
||||||
//
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
value_type noise1D_01(value_type x) const noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
value_type noise2D_01(value_type x, value_type y) const noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
value_type noise3D_01(value_type x, value_type y, value_type z) const noexcept;
|
|
||||||
|
|
||||||
///////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Octave noise (The result can be out of the range [-1, 1])
|
|
||||||
//
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
value_type octave1D(value_type x, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
value_type octave2D(value_type x, value_type y, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
value_type octave3D(value_type x, value_type y, value_type z, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
|
|
||||||
|
|
||||||
///////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Octave noise (The result is clamped to the range [-1, 1])
|
|
||||||
//
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
value_type octave1D_11(value_type x, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
value_type octave2D_11(value_type x, value_type y, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
value_type octave3D_11(value_type x, value_type y, value_type z, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
|
|
||||||
|
|
||||||
///////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Octave noise (The result is clamped and remapped to the range [0, 1])
|
|
||||||
//
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
value_type octave1D_01(value_type x, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
value_type octave2D_01(value_type x, value_type y, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
value_type octave3D_01(value_type x, value_type y, value_type z, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
|
|
||||||
|
|
||||||
///////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Octave noise (The result is normalized to the range [-1, 1])
|
|
||||||
//
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
value_type normalizedOctave1D(value_type x, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
value_type normalizedOctave2D(value_type x, value_type y, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
value_type normalizedOctave3D(value_type x, value_type y, value_type z, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
|
|
||||||
|
|
||||||
///////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Octave noise (The result is normalized and remapped to the range [0, 1])
|
|
||||||
//
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
value_type normalizedOctave1D_01(value_type x, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
value_type normalizedOctave2D_01(value_type x, value_type y, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
value_type normalizedOctave3D_01(value_type x, value_type y, value_type z, std::int32_t octaves, value_type persistence = value_type(0.5)) const noexcept;
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
state_type m_permutation;
|
|
||||||
};
|
|
||||||
|
|
||||||
using PerlinNoise = BasicPerlinNoise<double>;
|
|
||||||
|
|
||||||
namespace perlin_detail
|
|
||||||
{
|
|
||||||
////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// These functions are provided for consistency.
|
|
||||||
// You may get different results from std::shuffle() with different standard library implementations.
|
|
||||||
//
|
|
||||||
SIVPERLIN_CONCEPT_URBG
|
|
||||||
[[nodiscard]]
|
|
||||||
inline std::uint64_t Random(const std::uint64_t max, URBG&& urbg)
|
|
||||||
{
|
|
||||||
return (urbg() % (max + 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class RandomIt, class URBG>
|
|
||||||
inline void Shuffle(RandomIt first, RandomIt last, URBG&& urbg)
|
|
||||||
{
|
|
||||||
if (first == last)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
using difference_type = typename std::iterator_traits<RandomIt>::difference_type;
|
|
||||||
|
|
||||||
for (RandomIt it = first + 1; it < last; ++it)
|
|
||||||
{
|
|
||||||
const std::uint64_t n = static_cast<std::uint64_t>(it - first);
|
|
||||||
std::iter_swap(it, first + static_cast<difference_type>(Random(n, std::forward<URBG>(urbg))));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//
|
|
||||||
////////////////////////////////////////////////
|
|
||||||
|
|
||||||
template <class Float>
|
|
||||||
[[nodiscard]]
|
|
||||||
inline constexpr Float Fade(const Float t) noexcept
|
|
||||||
{
|
|
||||||
return t * t * t * (t * (t * 6 - 15) + 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Float>
|
|
||||||
[[nodiscard]]
|
|
||||||
inline constexpr Float Lerp(const Float a, const Float b, const Float t) noexcept
|
|
||||||
{
|
|
||||||
return (a + (b - a) * t);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Float>
|
|
||||||
[[nodiscard]]
|
|
||||||
inline constexpr Float Grad(const std::uint8_t hash, const Float x, const Float y, const Float z) noexcept
|
|
||||||
{
|
|
||||||
const std::uint8_t h = hash & 15;
|
|
||||||
const Float u = h < 8 ? x : y;
|
|
||||||
const Float v = h < 4 ? y : h == 12 || h == 14 ? x : z;
|
|
||||||
return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Float>
|
|
||||||
[[nodiscard]]
|
|
||||||
inline constexpr Float Remap_01(const Float x) noexcept
|
|
||||||
{
|
|
||||||
return (x * Float(0.5) + Float(0.5));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Float>
|
|
||||||
[[nodiscard]]
|
|
||||||
inline constexpr Float Clamp_11(const Float x) noexcept
|
|
||||||
{
|
|
||||||
return std::clamp(x, Float(-1.0), Float(1.0));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Float>
|
|
||||||
[[nodiscard]]
|
|
||||||
inline constexpr Float RemapClamp_01(const Float x) noexcept
|
|
||||||
{
|
|
||||||
if (x <= Float(-1.0))
|
|
||||||
{
|
|
||||||
return Float(0.0);
|
|
||||||
}
|
|
||||||
else if (Float(1.0) <= x)
|
|
||||||
{
|
|
||||||
return Float(1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (x * Float(0.5) + Float(0.5));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Noise, class Float>
|
|
||||||
[[nodiscard]]
|
|
||||||
inline auto Octave1D(const Noise& noise, Float x, const std::int32_t octaves, const Float persistence) noexcept
|
|
||||||
{
|
|
||||||
using value_type = Float;
|
|
||||||
value_type result = 0;
|
|
||||||
value_type amplitude = 1;
|
|
||||||
|
|
||||||
for (std::int32_t i = 0; i < octaves; ++i)
|
|
||||||
{
|
|
||||||
result += (noise.noise1D(x) * amplitude);
|
|
||||||
x *= 2;
|
|
||||||
amplitude *= persistence;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Noise, class Float>
|
|
||||||
[[nodiscard]]
|
|
||||||
inline auto Octave2D(const Noise& noise, Float x, Float y, const std::int32_t octaves, const Float persistence) noexcept
|
|
||||||
{
|
|
||||||
using value_type = Float;
|
|
||||||
value_type result = 0;
|
|
||||||
value_type amplitude = 1;
|
|
||||||
|
|
||||||
for (std::int32_t i = 0; i < octaves; ++i)
|
|
||||||
{
|
|
||||||
result += (noise.noise2D(x, y) * amplitude);
|
|
||||||
x *= 2;
|
|
||||||
y *= 2;
|
|
||||||
amplitude *= persistence;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Noise, class Float>
|
|
||||||
[[nodiscard]]
|
|
||||||
inline auto Octave3D(const Noise& noise, Float x, Float y, Float z, const std::int32_t octaves, const Float persistence) noexcept
|
|
||||||
{
|
|
||||||
using value_type = Float;
|
|
||||||
value_type result = 0;
|
|
||||||
value_type amplitude = 1;
|
|
||||||
|
|
||||||
for (std::int32_t i = 0; i < octaves; ++i)
|
|
||||||
{
|
|
||||||
result += (noise.noise3D(x, y, z) * amplitude);
|
|
||||||
x *= 2;
|
|
||||||
y *= 2;
|
|
||||||
z *= 2;
|
|
||||||
amplitude *= persistence;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Float>
|
|
||||||
[[nodiscard]]
|
|
||||||
inline constexpr Float MaxAmplitude(const std::int32_t octaves, const Float persistence) noexcept
|
|
||||||
{
|
|
||||||
using value_type = Float;
|
|
||||||
value_type result = 0;
|
|
||||||
value_type amplitude = 1;
|
|
||||||
|
|
||||||
for (std::int32_t i = 0; i < octaves; ++i)
|
|
||||||
{
|
|
||||||
result += amplitude;
|
|
||||||
amplitude *= persistence;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////
|
|
||||||
|
|
||||||
template <class Float>
|
|
||||||
inline constexpr BasicPerlinNoise<Float>::BasicPerlinNoise() noexcept
|
|
||||||
: m_permutation{ 151,160,137,91,90,15,
|
|
||||||
131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
|
|
||||||
190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
|
|
||||||
88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
|
|
||||||
77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
|
|
||||||
102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
|
|
||||||
135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
|
|
||||||
5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
|
|
||||||
223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
|
|
||||||
129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
|
|
||||||
251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
|
|
||||||
49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
|
|
||||||
138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180 } {}
|
|
||||||
|
|
||||||
template <class Float>
|
|
||||||
inline BasicPerlinNoise<Float>::BasicPerlinNoise(const seed_type seed)
|
|
||||||
{
|
|
||||||
reseed(seed);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Float>
|
|
||||||
SIVPERLIN_CONCEPT_URBG_
|
|
||||||
inline BasicPerlinNoise<Float>::BasicPerlinNoise(URBG&& urbg)
|
|
||||||
{
|
|
||||||
reseed(std::forward<URBG>(urbg));
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////
|
|
||||||
|
|
||||||
template <class Float>
|
|
||||||
inline void BasicPerlinNoise<Float>::reseed(const seed_type seed)
|
|
||||||
{
|
|
||||||
reseed(default_random_engine{ seed });
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Float>
|
|
||||||
SIVPERLIN_CONCEPT_URBG_
|
|
||||||
inline void BasicPerlinNoise<Float>::reseed(URBG&& urbg)
|
|
||||||
{
|
|
||||||
std::iota(m_permutation.begin(), m_permutation.end(), uint8_t{ 0 });
|
|
||||||
|
|
||||||
perlin_detail::Shuffle(m_permutation.begin(), m_permutation.end(), std::forward<URBG>(urbg));
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////
|
|
||||||
|
|
||||||
template <class Float>
|
|
||||||
inline constexpr const typename BasicPerlinNoise<Float>::state_type& BasicPerlinNoise<Float>::serialize() const noexcept
|
|
||||||
{
|
|
||||||
return m_permutation;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Float>
|
|
||||||
inline constexpr void BasicPerlinNoise<Float>::deserialize(const state_type& state) noexcept
|
|
||||||
{
|
|
||||||
m_permutation = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////
|
|
||||||
|
|
||||||
template <class Float>
|
|
||||||
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::noise1D(const value_type x) const noexcept
|
|
||||||
{
|
|
||||||
return noise3D(x,
|
|
||||||
static_cast<value_type>(SIVPERLIN_DEFAULT_Y),
|
|
||||||
static_cast<value_type>(SIVPERLIN_DEFAULT_Z));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Float>
|
|
||||||
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::noise2D(const value_type x, const value_type y) const noexcept
|
|
||||||
{
|
|
||||||
return noise3D(x,
|
|
||||||
y,
|
|
||||||
static_cast<value_type>(SIVPERLIN_DEFAULT_Z));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Float>
|
|
||||||
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::noise3D(const value_type x, const value_type y, const value_type z) const noexcept
|
|
||||||
{
|
|
||||||
const value_type _x = std::floor(x);
|
|
||||||
const value_type _y = std::floor(y);
|
|
||||||
const value_type _z = std::floor(z);
|
|
||||||
|
|
||||||
const std::int32_t ix = static_cast<std::int32_t>(_x) & 255;
|
|
||||||
const std::int32_t iy = static_cast<std::int32_t>(_y) & 255;
|
|
||||||
const std::int32_t iz = static_cast<std::int32_t>(_z) & 255;
|
|
||||||
|
|
||||||
const value_type fx = (x - _x);
|
|
||||||
const value_type fy = (y - _y);
|
|
||||||
const value_type fz = (z - _z);
|
|
||||||
|
|
||||||
const value_type u = perlin_detail::Fade(fx);
|
|
||||||
const value_type v = perlin_detail::Fade(fy);
|
|
||||||
const value_type w = perlin_detail::Fade(fz);
|
|
||||||
|
|
||||||
const std::uint8_t A = (m_permutation[ix & 255] + iy) & 255;
|
|
||||||
const std::uint8_t B = (m_permutation[(ix + 1) & 255] + iy) & 255;
|
|
||||||
|
|
||||||
const std::uint8_t AA = (m_permutation[A] + iz) & 255;
|
|
||||||
const std::uint8_t AB = (m_permutation[(A + 1) & 255] + iz) & 255;
|
|
||||||
|
|
||||||
const std::uint8_t BA = (m_permutation[B] + iz) & 255;
|
|
||||||
const std::uint8_t BB = (m_permutation[(B + 1) & 255] + iz) & 255;
|
|
||||||
|
|
||||||
const value_type p0 = perlin_detail::Grad(m_permutation[AA], fx, fy, fz);
|
|
||||||
const value_type p1 = perlin_detail::Grad(m_permutation[BA], fx - 1, fy, fz);
|
|
||||||
const value_type p2 = perlin_detail::Grad(m_permutation[AB], fx, fy - 1, fz);
|
|
||||||
const value_type p3 = perlin_detail::Grad(m_permutation[BB], fx - 1, fy - 1, fz);
|
|
||||||
const value_type p4 = perlin_detail::Grad(m_permutation[(AA + 1) & 255], fx, fy, fz - 1);
|
|
||||||
const value_type p5 = perlin_detail::Grad(m_permutation[(BA + 1) & 255], fx - 1, fy, fz - 1);
|
|
||||||
const value_type p6 = perlin_detail::Grad(m_permutation[(AB + 1) & 255], fx, fy - 1, fz - 1);
|
|
||||||
const value_type p7 = perlin_detail::Grad(m_permutation[(BB + 1) & 255], fx - 1, fy - 1, fz - 1);
|
|
||||||
|
|
||||||
const value_type q0 = perlin_detail::Lerp(p0, p1, u);
|
|
||||||
const value_type q1 = perlin_detail::Lerp(p2, p3, u);
|
|
||||||
const value_type q2 = perlin_detail::Lerp(p4, p5, u);
|
|
||||||
const value_type q3 = perlin_detail::Lerp(p6, p7, u);
|
|
||||||
|
|
||||||
const value_type r0 = perlin_detail::Lerp(q0, q1, v);
|
|
||||||
const value_type r1 = perlin_detail::Lerp(q2, q3, v);
|
|
||||||
|
|
||||||
return perlin_detail::Lerp(r0, r1, w);
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////
|
|
||||||
|
|
||||||
template <class Float>
|
|
||||||
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::noise1D_01(const value_type x) const noexcept
|
|
||||||
{
|
|
||||||
return perlin_detail::Remap_01(noise1D(x));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Float>
|
|
||||||
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::noise2D_01(const value_type x, const value_type y) const noexcept
|
|
||||||
{
|
|
||||||
return perlin_detail::Remap_01(noise2D(x, y));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Float>
|
|
||||||
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::noise3D_01(const value_type x, const value_type y, const value_type z) const noexcept
|
|
||||||
{
|
|
||||||
return perlin_detail::Remap_01(noise3D(x, y, z));
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////
|
|
||||||
|
|
||||||
template <class Float>
|
|
||||||
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::octave1D(const value_type x, const std::int32_t octaves, const value_type persistence) const noexcept
|
|
||||||
{
|
|
||||||
return perlin_detail::Octave1D(*this, x, octaves, persistence);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Float>
|
|
||||||
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::octave2D(const value_type x, const value_type y, const std::int32_t octaves, const value_type persistence) const noexcept
|
|
||||||
{
|
|
||||||
return perlin_detail::Octave2D(*this, x, y, octaves, persistence);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Float>
|
|
||||||
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::octave3D(const value_type x, const value_type y, const value_type z, const std::int32_t octaves, const value_type persistence) const noexcept
|
|
||||||
{
|
|
||||||
return perlin_detail::Octave3D(*this, x, y, z, octaves, persistence);
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////
|
|
||||||
|
|
||||||
template <class Float>
|
|
||||||
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::octave1D_11(const value_type x, const std::int32_t octaves, const value_type persistence) const noexcept
|
|
||||||
{
|
|
||||||
return perlin_detail::Clamp_11(octave1D(x, octaves, persistence));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Float>
|
|
||||||
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::octave2D_11(const value_type x, const value_type y, const std::int32_t octaves, const value_type persistence) const noexcept
|
|
||||||
{
|
|
||||||
return perlin_detail::Clamp_11(octave2D(x, y, octaves, persistence));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Float>
|
|
||||||
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::octave3D_11(const value_type x, const value_type y, const value_type z, const std::int32_t octaves, const value_type persistence) const noexcept
|
|
||||||
{
|
|
||||||
return perlin_detail::Clamp_11(octave3D(x, y, z, octaves, persistence));
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////
|
|
||||||
|
|
||||||
template <class Float>
|
|
||||||
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::octave1D_01(const value_type x, const std::int32_t octaves, const value_type persistence) const noexcept
|
|
||||||
{
|
|
||||||
return perlin_detail::RemapClamp_01(octave1D(x, octaves, persistence));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Float>
|
|
||||||
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::octave2D_01(const value_type x, const value_type y, const std::int32_t octaves, const value_type persistence) const noexcept
|
|
||||||
{
|
|
||||||
return perlin_detail::RemapClamp_01(octave2D(x, y, octaves, persistence));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Float>
|
|
||||||
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::octave3D_01(const value_type x, const value_type y, const value_type z, const std::int32_t octaves, const value_type persistence) const noexcept
|
|
||||||
{
|
|
||||||
return perlin_detail::RemapClamp_01(octave3D(x, y, z, octaves, persistence));
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////
|
|
||||||
|
|
||||||
template <class Float>
|
|
||||||
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::normalizedOctave1D(const value_type x, const std::int32_t octaves, const value_type persistence) const noexcept
|
|
||||||
{
|
|
||||||
return (octave1D(x, octaves, persistence) / perlin_detail::MaxAmplitude(octaves, persistence));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Float>
|
|
||||||
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::normalizedOctave2D(const value_type x, const value_type y, const std::int32_t octaves, const value_type persistence) const noexcept
|
|
||||||
{
|
|
||||||
return (octave2D(x, y, octaves, persistence) / perlin_detail::MaxAmplitude(octaves, persistence));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Float>
|
|
||||||
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::normalizedOctave3D(const value_type x, const value_type y, const value_type z, const std::int32_t octaves, const value_type persistence) const noexcept
|
|
||||||
{
|
|
||||||
return (octave3D(x, y, z, octaves, persistence) / perlin_detail::MaxAmplitude(octaves, persistence));
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////
|
|
||||||
|
|
||||||
template <class Float>
|
|
||||||
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::normalizedOctave1D_01(const value_type x, const std::int32_t octaves, const value_type persistence) const noexcept
|
|
||||||
{
|
|
||||||
return perlin_detail::Remap_01(normalizedOctave1D(x, octaves, persistence));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Float>
|
|
||||||
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::normalizedOctave2D_01(const value_type x, const value_type y, const std::int32_t octaves, const value_type persistence) const noexcept
|
|
||||||
{
|
|
||||||
return perlin_detail::Remap_01(normalizedOctave2D(x, y, octaves, persistence));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Float>
|
|
||||||
inline typename BasicPerlinNoise<Float>::value_type BasicPerlinNoise<Float>::normalizedOctave3D_01(const value_type x, const value_type y, const value_type z, const std::int32_t octaves, const value_type persistence) const noexcept
|
|
||||||
{
|
|
||||||
return perlin_detail::Remap_01(normalizedOctave3D(x, y, z, octaves, persistence));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# undef SIVPERLIN_NODISCARD_CXX20
|
|
||||||
# undef SIVPERLIN_CONCEPT_URBG
|
|
||||||
# undef SIVPERLIN_CONCEPT_URBG_
|
|
||||||
@@ -15,7 +15,6 @@ add_library(helpers STATIC
|
|||||||
particles.cpp
|
particles.cpp
|
||||||
player.cpp
|
player.cpp
|
||||||
multisound.cpp
|
multisound.cpp
|
||||||
svlib.cpp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
@@ -24,6 +23,7 @@ if (WIN32)
|
|||||||
target_link_libraries(helpers INTERFACE winmm ws2_32)
|
target_link_libraries(helpers INTERFACE winmm ws2_32)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
add_compile_options(-Wno-narrowing)
|
||||||
execute_process(COMMAND date +v.%yw%W OUTPUT_VARIABLE BUILD_DATE OUTPUT_STRIP_TRAILING_WHITESPACE)
|
execute_process(COMMAND date +v.%yw%W OUTPUT_VARIABLE BUILD_DATE OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
add_compile_definitions(GAME_VERSION="${BUILD_DATE}")
|
add_compile_definitions(GAME_VERSION="${BUILD_DATE}")
|
||||||
|
|
||||||
|
|||||||
+492
-105
@@ -1,3 +1,4 @@
|
|||||||
|
#include <unordered_set>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "common.hpp"
|
#include "common.hpp"
|
||||||
@@ -6,10 +7,14 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
|
#define FNL_IMPL
|
||||||
|
#include "../FastNoiseLite.h"
|
||||||
|
|
||||||
#define HUMIDITY_OFFSET 12.3f
|
#define HUMIDITY_OFFSET 12.3f
|
||||||
#define CAVE_OFFSET 45.6f
|
#define CAVE_OFFSET 45.6f
|
||||||
#define SCALE 0.01f
|
#define SCALE 0.1f
|
||||||
#define CAVE_COEFF 0.06
|
#define CAVE_COEFF 0.06
|
||||||
#define EDGES_FADE 64
|
#define EDGES_FADE 64
|
||||||
#define CLOUD_SCALE 0.25f
|
#define CLOUD_SCALE 0.25f
|
||||||
@@ -17,11 +22,13 @@
|
|||||||
#define BIOME_FOREST 0
|
#define BIOME_FOREST 0
|
||||||
#define BIOME_TAIGA 1
|
#define BIOME_TAIGA 1
|
||||||
|
|
||||||
static const siv::PerlinNoise perlin;
|
static fnl_state perlin;
|
||||||
|
static fnl_state perlin2;
|
||||||
|
static fnl_state perlinLofi;
|
||||||
|
|
||||||
static int world_type = 0;
|
static int world_type = 0;
|
||||||
|
|
||||||
const BlockDef BLOCKS[] = {
|
std::vector<BlockDef> BLOCKS = {
|
||||||
BlockDef{ "air", R_Translucent, B_Stone, 0, 0, 0},
|
BlockDef{ "air", R_Translucent, B_Stone, 0, 0, 0},
|
||||||
BlockDef{ "stone", R_Normal, B_Stone, 7, 0, 3},
|
BlockDef{ "stone", R_Normal, B_Stone, 7, 0, 3},
|
||||||
BlockDef{ "grass", R_TriSide, B_Grass, 1, 0, 0, 1, 2},
|
BlockDef{ "grass", R_TriSide, B_Grass, 1, 0, 0, 1, 2},
|
||||||
@@ -29,21 +36,21 @@ const BlockDef BLOCKS[] = {
|
|||||||
BlockDef{ "sand", R_Normal, B_Dirt, 2, 0, 4},
|
BlockDef{ "sand", R_Normal, B_Dirt, 2, 0, 4},
|
||||||
BlockDef{ "water", R_Translucent, B_Stone, 0, 0, 14},
|
BlockDef{ "water", R_Translucent, B_Stone, 0, 0, 14},
|
||||||
BlockDef{ "planks", R_Normal, B_Wood, 3, 0, 11},
|
BlockDef{ "planks", R_Normal, B_Wood, 3, 0, 11},
|
||||||
BlockDef{ "gray_bricks", R_Normal, B_Stone, 5, 1, 16},
|
BlockDef{ "stone_bricks", R_Normal, B_Stone, 5, 1, 16},
|
||||||
BlockDef{ "red_bricks", R_Normal, B_Stone, 5, 1, 17},
|
BlockDef{ "copper_block", R_Normal, B_Stone, 5, 1, 17},
|
||||||
BlockDef{ "blue_bricks", R_Normal, B_Stone, 5, 1, 18},
|
BlockDef{ "silver_block", R_Normal, B_Stone, 5, 1, 18},
|
||||||
BlockDef{ "green_bricks", R_Normal, B_Stone, 5, 1, 19},
|
BlockDef{ "gold_block", R_Normal, B_Stone, 5, 1, 19},
|
||||||
BlockDef{ "glass", R_Translucent, B_Stone, 3, 1, 12},
|
BlockDef{ "glass", R_Translucent, B_Stone, 3, 1, 12},
|
||||||
BlockDef{ "log", R_TriSide, B_Wood, 5, 0, 10, 9, 10},
|
BlockDef{ "log", R_TriSide, B_Wood, 5, 0, 10, 9, 10},
|
||||||
BlockDef{ "spruce_planks", R_Normal, B_Wood, 3, 0, 13},
|
BlockDef{ "spruce_planks", R_Normal, B_Wood, 3, 0, 13},
|
||||||
BlockDef{ "spruce_log", R_TriSide, B_Wood, 5, 0, 21, 20, 21},
|
BlockDef{ "spruce_log", R_TriSide, B_Wood, 5, 0, 21, 20, 21},
|
||||||
BlockDef{ "workbench", R_TranslucentAllSides, B_Stone, 3, 0, 23, 22, 23},
|
BlockDef{ "workbench", R_TranslucentAllSides, B_Stone, 3, 0, 23, 22, 23},
|
||||||
BlockDef{ "blue_block", R_Normal, B_Stone, 5, 0, 22},
|
BlockDef{ "undefined", R_Normal, B_Stone, 5, 0, 22},
|
||||||
BlockDef{ "yellow_block", R_Normal, B_Stone, 5, 0, 23},
|
BlockDef{ "undefined", R_Normal, B_Stone, 5, 0, 23},
|
||||||
BlockDef{ "cyan_block", R_Normal, B_Stone, 5, 0, 24},
|
BlockDef{ "red_block", R_Normal, B_Stone, 5, 0, 24},
|
||||||
BlockDef{ "magenta_block", R_Normal, B_Stone, 5, 0, 25},
|
BlockDef{ "green_block", R_Normal, B_Stone, 5, 0, 25},
|
||||||
BlockDef{ "white_block", R_Normal, B_Stone, 5, 0, 26},
|
BlockDef{ "blue_block", R_Normal, B_Stone, 5, 0, 26},
|
||||||
BlockDef{ "black_block", R_Normal, B_Stone, 5, 0, 27},
|
BlockDef{ "white_block", R_Normal, B_Stone, 5, 0, 27},
|
||||||
BlockDef{ "leaves", R_TranslucentAllSides, B_Grass, 1, 0, 28},
|
BlockDef{ "leaves", R_TranslucentAllSides, B_Grass, 1, 0, 28},
|
||||||
BlockDef{ "copper_ore", R_Normal, B_Stone, 7, 1, 5},
|
BlockDef{ "copper_ore", R_Normal, B_Stone, 7, 1, 5},
|
||||||
BlockDef{ "silver_ore", R_Normal, B_Stone, 7, 2, 6},
|
BlockDef{ "silver_ore", R_Normal, B_Stone, 7, 2, 6},
|
||||||
@@ -51,33 +58,52 @@ const BlockDef BLOCKS[] = {
|
|||||||
BlockDef{ "coal_ore", R_Normal, B_Stone, 7, 0, 8},
|
BlockDef{ "coal_ore", R_Normal, B_Stone, 7, 0, 8},
|
||||||
BlockDef{ "unobtainium", R_Normal, B_Stone, 7, 999, 3}, // Bedrock?
|
BlockDef{ "unobtainium", R_Normal, B_Stone, 7, 999, 3}, // Bedrock?
|
||||||
};
|
};
|
||||||
|
BlockDef &GetBlockDefinition(int id) {
|
||||||
|
return BLOCKS[id];
|
||||||
|
}
|
||||||
|
void LoadBlocks() {
|
||||||
|
|
||||||
|
}
|
||||||
int GetNumericIDFromString(std::string s) {
|
int GetNumericIDFromString(std::string s) {
|
||||||
int count = sizeof(BLOCKS) / sizeof(BLOCKS[0]);
|
for (int i = 0; i < BLOCKS.size(); ++i) {
|
||||||
for (int i = 0; i < count; ++i) {
|
|
||||||
if (BLOCKS[i].name == s) return i;
|
if (BLOCKS[i].name == s) return i;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
static std::bitset<256> marked;
|
static std::bitset<256> marked;
|
||||||
|
|
||||||
static int GetBlockRegularWorld(int x, int y, int z) {
|
static int GetBlockRegularWorld(int _x, int y, int _z) {
|
||||||
float fade_x = (fmax(EDGES_FADE - x, 0) + fmax(EDGES_FADE - WORLD_SIZE_BLOCKS + x, 0)) / (float)EDGES_FADE;
|
int x = _x + 0;
|
||||||
float fade_z = (fmax(EDGES_FADE - z, 0) + fmax(EDGES_FADE - WORLD_SIZE_BLOCKS + z, 0)) / (float)EDGES_FADE;
|
int z = _z + 0;
|
||||||
float fade = 1 - (fade_x + fade_z);
|
const int SEA_HEIGHT = 64;
|
||||||
|
const int BEACH_DEPTH = 3;
|
||||||
|
const float heightBias = 24;
|
||||||
|
float p0 = fnlGetNoise3D(&perlin, (float)x, y / 2.0f, z);
|
||||||
|
float p1 = fnlGetNoise3D(&perlin2, x, y / 2.0f, z);
|
||||||
|
float pr = fnlGetNoise3D(&perlinLofi, x, y / 2.0f, z)*12.75f;
|
||||||
|
float P = 0;
|
||||||
|
if(pr >= 1) P = p1;
|
||||||
|
if(pr <= 0) P = p0;
|
||||||
|
if(pr>0&&pr<1) P = Lerp(p0, p1, pr);
|
||||||
|
float density = P + (WORLD_HEIGHT-(y+60)) / heightBias;
|
||||||
|
if(density > 0.5f) {
|
||||||
|
return BLOCK_STONE;
|
||||||
|
}
|
||||||
|
if(density > 0) {
|
||||||
|
return BLOCK_DIRT;
|
||||||
|
}
|
||||||
|
if(y < SEA_HEIGHT) {
|
||||||
|
return BLOCK_WATERS;
|
||||||
|
}
|
||||||
|
//float height0 = (fnlGetNoise3D(&perlin, x, y, z) + 1.0f ) / 2.0f * 8.0f;
|
||||||
|
//float height1 = (fnlGetNoise3D(&perlin2, x, y, z) + 1.0f ) / 2.0f * 16.0f;
|
||||||
|
|
||||||
const int SEA_HEIGHT = 32; // sea surface y
|
//int height = Lerp(height0, height1, fnlGetNoise2D(&perlinLofi, x, z)) + 26 + 48;
|
||||||
const int BEACH_DEPTH = 3; // how many blocks below surface become sand
|
//float dist = Vector2Distance({(float)x, (float)z}, {MAX_WORLD_SIZE*CHUNK_SIZE/2, MAX_WORLD_SIZE*CHUNK_SIZE/2});
|
||||||
|
|
||||||
float height0 = (perlin.noise2D((double)x * 1.5f * SCALE, (double)z * 1.5f * SCALE) + 1.0f ) / 2.0f * 16.0f;
|
//height = Lerp(32, height, fmin(1.0f, -fmin(0.0f, dist - (MAX_WORLD_SIZE*CHUNK_SIZE/2)-48)/96.0f));
|
||||||
float mountains = pow((perlin.noise2D((double)x * 0.5f, (double)z * 0.5f * SCALE) + 1.0f ) / 2.0f, 16);
|
/*if (y <= height) {
|
||||||
float height1 = (perlin.noise2D((double)x * 4.5f * SCALE, (double)z * 4.5f * SCALE) + 1.0f ) / 2.0f * 24.0f * mountains;
|
//if(caveNoise < 0.02f) return BLOCK_AIR;
|
||||||
|
|
||||||
int height = floor((height0 + height1) * fade) + 26;
|
|
||||||
|
|
||||||
float caveNoise = fabs(perlin.noise3D((double)x * 1.0f * SCALE + CAVE_OFFSET, (double)y * 4.0f * SCALE + CAVE_OFFSET, (double)z * 1.0f * SCALE + CAVE_OFFSET));
|
|
||||||
|
|
||||||
if (y <= height) {
|
|
||||||
if(caveNoise < 0.02f) return BLOCK_AIR;
|
|
||||||
if (y == height) {
|
if (y == height) {
|
||||||
if (height <= SEA_HEIGHT) {
|
if (height <= SEA_HEIGHT) {
|
||||||
return BLOCK_SAND;
|
return BLOCK_SAND;
|
||||||
@@ -89,27 +115,119 @@ static int GetBlockRegularWorld(int x, int y, int z) {
|
|||||||
if (y > height - BEACH_DEPTH && height <= SEA_HEIGHT + 2) {
|
if (y > height - BEACH_DEPTH && height <= SEA_HEIGHT + 2) {
|
||||||
return BLOCK_SAND;
|
return BLOCK_SAND;
|
||||||
}
|
}
|
||||||
if(caveNoise < 0.2f || y < 4) return BLOCK_STONE;
|
//if(caveNoise < 0.2f || y < 4) return BLOCK_STONE;
|
||||||
return BLOCK_DIRT;
|
return BLOCK_DIRT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (y <= SEA_HEIGHT && height < SEA_HEIGHT) {
|
if (y <= SEA_HEIGHT && height < SEA_HEIGHT) {
|
||||||
return BLOCK_WATERS;
|
return BLOCK_WATERS;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
return BLOCK_AIR;
|
return BLOCK_AIR;
|
||||||
}
|
}
|
||||||
|
int GetBlock(World &world, int x, int y, int z) {
|
||||||
|
if(CheckOOBWorld(x, y, z)) return 0;
|
||||||
|
int locX = x % CHUNK_SIZE;
|
||||||
|
int locZ = z % CHUNK_SIZE;
|
||||||
|
int cx = x / CHUNK_SIZE;
|
||||||
|
int cz = z / CHUNK_SIZE;
|
||||||
|
return fetch_block(world.chunks[GetIndexWorld(cx, cz)], locX, y, locZ);
|
||||||
|
}
|
||||||
|
int GetHighestBlock(World &world, int x, int z) {
|
||||||
|
if(CheckOOBWorld(x, 0, z)) return 0;
|
||||||
|
int locX = x % CHUNK_SIZE;
|
||||||
|
int locZ = z % CHUNK_SIZE;
|
||||||
|
int cx = x / CHUNK_SIZE;
|
||||||
|
int cz = z / CHUNK_SIZE;
|
||||||
|
return world.chunks[GetIndexWorld(cx, cz)].highestBlock[GetIndexChunk2D(locX, locZ)];
|
||||||
|
}
|
||||||
|
int GetSkyLight(World &world, int x, int y, int z) {
|
||||||
|
if(CheckOOBWorld(x, y, z)) return 15;
|
||||||
|
int locX = x % CHUNK_SIZE;
|
||||||
|
int locZ = z % CHUNK_SIZE;
|
||||||
|
int cx = x / CHUNK_SIZE;
|
||||||
|
int cz = z / CHUNK_SIZE;
|
||||||
|
uint16_t light = world.chunks[GetIndexWorld(cx, cz)].light[GetIndexChunk(locX, y, locZ)];
|
||||||
|
int skyLight = (light >> 12) & 0xF;
|
||||||
|
return skyLight;
|
||||||
|
}
|
||||||
|
int GetRLight(World &world, int x, int y, int z) {
|
||||||
|
if(CheckOOBWorld(x, y, z)) return 0;
|
||||||
|
int locX = x % CHUNK_SIZE;
|
||||||
|
int locZ = z % CHUNK_SIZE;
|
||||||
|
int cx = x / CHUNK_SIZE;
|
||||||
|
int cz = z / CHUNK_SIZE;
|
||||||
|
uint16_t light = world.chunks[GetIndexWorld(cx, cz)].light[GetIndexChunk(locX, y, locZ)];
|
||||||
|
int skyLight = (light >> 8) & 0xF;
|
||||||
|
return skyLight;
|
||||||
|
}
|
||||||
|
int GetGLight(World &world, int x, int y, int z) {
|
||||||
|
if(CheckOOBWorld(x, y, z)) return 0;
|
||||||
|
int locX = x % CHUNK_SIZE;
|
||||||
|
int locZ = z % CHUNK_SIZE;
|
||||||
|
int cx = x / CHUNK_SIZE;
|
||||||
|
int cz = z / CHUNK_SIZE;
|
||||||
|
uint16_t light = world.chunks[GetIndexWorld(cx, cz)].light[GetIndexChunk(locX, y, locZ)];
|
||||||
|
int skyLight = (light >> 4) & 0xF;
|
||||||
|
return skyLight;
|
||||||
|
}
|
||||||
|
int GetBLight(World &world, int x, int y, int z) {
|
||||||
|
if(CheckOOBWorld(x, y, z)) return 0;
|
||||||
|
int locX = x % CHUNK_SIZE;
|
||||||
|
int locZ = z % CHUNK_SIZE;
|
||||||
|
int cx = x / CHUNK_SIZE;
|
||||||
|
int cz = z / CHUNK_SIZE;
|
||||||
|
uint16_t light = world.chunks[GetIndexWorld(cx, cz)].light[GetIndexChunk(locX, y, locZ)];
|
||||||
|
int skyLight = light & 0xF;
|
||||||
|
return skyLight;
|
||||||
|
}
|
||||||
|
Color GetSunlightColor();
|
||||||
|
Color GetLight(World &world, int x, int y, int z) {
|
||||||
|
if(CheckOOBWorld(x, y, z)) return {0, 0, 0, 0};
|
||||||
|
int locX = x % CHUNK_SIZE;
|
||||||
|
int locZ = z % CHUNK_SIZE;
|
||||||
|
int cx = x / CHUNK_SIZE;
|
||||||
|
int cz = z / CHUNK_SIZE;
|
||||||
|
uint16_t light = world.chunks[GetIndexWorld(cx, cz)].light[GetIndexChunk(locX, y, locZ)];
|
||||||
|
int skyLight = powf(((light >> 12) & 0xF) / 15.0f, 1) * 255;
|
||||||
|
Color r = {((light >> 8) & 0xF) * 16, 0, 0, 255};
|
||||||
|
Color g = {0, ((light >> 4) & 0xF) * 16, 0, 255};
|
||||||
|
Color b = {0, 0, ((light >> 0) & 0xF) * 16, 255};
|
||||||
|
Color sun = GetSunlightColor();
|
||||||
|
return {
|
||||||
|
fmax((int)skyLight * (sun.r/255.0f), (int)r.r),
|
||||||
|
fmax((int)skyLight * (sun.g/255.0f), (int)g.g),
|
||||||
|
fmax((int)skyLight * (sun.b/255.0f), (int)b.b),
|
||||||
|
255
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Color GetLightMesher(World &world, int x, int y, int z) {
|
||||||
|
if(CheckOOBWorld(x, y, z)) return {0, 0, 0, 0};
|
||||||
|
int locX = x % CHUNK_SIZE;
|
||||||
|
int locZ = z % CHUNK_SIZE;
|
||||||
|
int cx = x / CHUNK_SIZE;
|
||||||
|
int cz = z / CHUNK_SIZE;
|
||||||
|
uint16_t light = world.chunks[GetIndexWorld(cx, cz)].light[GetIndexChunk(locX, y, locZ)];
|
||||||
|
int skyLight = powf(((light >> 12) & 0xF) / 15.0f, 1) * 255;
|
||||||
|
return {
|
||||||
|
((light >> 8) & 0xF) * 16,
|
||||||
|
((light >> 4) & 0xF) * 16,
|
||||||
|
((light >> 0) & 0xF) * 16,
|
||||||
|
skyLight
|
||||||
|
};
|
||||||
|
}
|
||||||
bool CanTick(int blockType) { // TODO: make smarter in case other blocks can tick too!
|
bool CanTick(int blockType) { // TODO: make smarter in case other blocks can tick too!
|
||||||
return blockType == BLOCK_SAND;
|
return blockType == BLOCK_SAND;
|
||||||
}
|
}
|
||||||
bool GetCloud(int x, int z) {
|
bool GetCloud(int x, int z) {
|
||||||
return (perlin.noise2D((x / 8) * 1.5f * CLOUD_SCALE, (z / 8) * 1.5f * CLOUD_SCALE) + 1.0f) / 2.0f > 0.5f;
|
//return (perlin.noise2D((x / 8) * 1.5f * CLOUD_SCALE, (z / 8) * 1.5f * CLOUD_SCALE) + 1.0f) / 2.0f > 0.5f;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
static int GetBlockCaveWorld(int x, int y, int z) {
|
static int GetBlockCaveWorld(int x, int y, int z) {
|
||||||
float caveNoise = (perlin.noise3D((float)x * 3.0f * SCALE + CAVE_OFFSET, (float)y * 3.0f * SCALE + CAVE_OFFSET, (float)z * 3.0f * SCALE + CAVE_OFFSET) + 1.0f) / 2.0f;
|
/*float caveNoise = (perlin.noise3D((float)x * 3.0f * SCALE + CAVE_OFFSET, (float)y * 3.0f * SCALE + CAVE_OFFSET, (float)z * 3.0f * SCALE + CAVE_OFFSET) + 1.0f) / 2.0f;
|
||||||
if(caveNoise > 0.5f) {
|
if(caveNoise > 0.5f) {
|
||||||
return BLOCK_STONE;
|
return BLOCK_STONE;
|
||||||
}
|
}*/
|
||||||
return BLOCK_AIR;
|
return BLOCK_AIR;
|
||||||
}
|
}
|
||||||
static int has_block(int x, int y, int z)
|
static int has_block(int x, int y, int z)
|
||||||
@@ -174,15 +292,15 @@ void SetBlockChunk(Chunk *c, int x, int y, int z, int t) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void RebuildHeightmap(Chunk *c) {
|
void RebuildHeightmap(Chunk &c) {
|
||||||
for (int x = 0; x < CHUNK_SIZE; x++)
|
for (int x = 0; x < CHUNK_SIZE; x++)
|
||||||
{
|
{
|
||||||
for (int z = 0; z < CHUNK_SIZE; z++)
|
for (int z = 0; z < CHUNK_SIZE; z++)
|
||||||
{
|
{
|
||||||
for (int y = WORLD_HEIGHT-1; y >= 0; y--)
|
for (int y = WORLD_HEIGHT-1; y >= 0; y--)
|
||||||
{
|
{
|
||||||
if(c->blocks[GetIndexChunk(x,y,z)] != 0) {
|
if(c.blocks[GetIndexChunk(x,y,z)] != 0) {
|
||||||
c->highestBlock[GetIndexChunk2D(x, z)] = y;
|
c.highestBlock[GetIndexChunk2D(x, z)] = y;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -195,21 +313,63 @@ int GetBiome(int sx, int sy) {
|
|||||||
void SetBlockChunkFast(Chunk *c, int i, int t) {
|
void SetBlockChunkFast(Chunk *c, int i, int t) {
|
||||||
c->blocks[i] = t;
|
c->blocks[i] = t;
|
||||||
}
|
}
|
||||||
void SetBlock(Chunk world[], int x, int y, int z, int t) {
|
void SetBlock(World &world, int x, int y, int z, int t) {
|
||||||
if(CheckOOBWorld(x, y, z)) { return; }
|
if(CheckOOBWorld(x, y, z)) { return; }
|
||||||
int locX = x % CHUNK_SIZE;
|
int locX = x % CHUNK_SIZE;
|
||||||
int locZ = z % CHUNK_SIZE;
|
int locZ = z % CHUNK_SIZE;
|
||||||
int cx = x / CHUNK_SIZE;
|
int cx = x / CHUNK_SIZE;
|
||||||
int cz = z / CHUNK_SIZE;
|
int cz = z / CHUNK_SIZE;
|
||||||
SetBlockChunk(&world[GetIndexWorld(cx, cz)], locX, y, locZ, t);
|
SetBlockChunk(&world.chunks[GetIndexWorld(cx, cz)], locX, y, locZ, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetLightChunk(Chunk *c, int x, int y, int z, uint8_t sky, uint8_t r, uint8_t g, uint8_t b) {
|
||||||
|
int target = c->light[GetIndexChunk(x,y,z)];
|
||||||
|
if(sky > 0) {
|
||||||
|
target |= sky << 12;
|
||||||
|
}
|
||||||
|
if(r > 0) {
|
||||||
|
target |= r << 8;
|
||||||
|
}
|
||||||
|
if(g > 0) {
|
||||||
|
target |= g << 4;
|
||||||
|
}
|
||||||
|
if(b > 0) {
|
||||||
|
target |= b;
|
||||||
|
}
|
||||||
|
c->light[GetIndexChunk(x,y,z)] = target;
|
||||||
|
}
|
||||||
|
void SetLight(World &world, int x, int y, int z, uint8_t sky, uint8_t r, uint8_t g, uint8_t b) {
|
||||||
|
if(CheckOOBWorld(x, y, z)) { return; }
|
||||||
|
int locX = x % CHUNK_SIZE;
|
||||||
|
int locZ = z % CHUNK_SIZE;
|
||||||
|
int cx = x / CHUNK_SIZE;
|
||||||
|
int cz = z / CHUNK_SIZE;
|
||||||
|
SetLightChunk(&world.chunks[GetIndexWorld(cx, cz)], locX, y, locZ, sky, r, g, b);
|
||||||
|
}
|
||||||
|
|
||||||
void InitWorldgen(int worldType) {
|
void InitWorldgen(int worldType) {
|
||||||
const siv::PerlinNoise::seed_type seed = 123456u;
|
perlin = fnlCreateState();
|
||||||
const siv::PerlinNoise perlin{ seed };
|
perlin.noise_type = FNL_NOISE_OPENSIMPLEX2;
|
||||||
|
perlin.fractal_type = FNL_FRACTAL_FBM;
|
||||||
|
perlin.frequency = 0.00522f;
|
||||||
|
perlin.octaves = 8;
|
||||||
|
|
||||||
|
perlinLofi = fnlCreateState();
|
||||||
|
perlinLofi.noise_type = FNL_NOISE_OPENSIMPLEX2;
|
||||||
|
perlinLofi.fractal_type = FNL_FRACTAL_FBM;
|
||||||
|
perlinLofi.frequency = 0.01671f;
|
||||||
|
perlinLofi.octaves = 4;
|
||||||
|
|
||||||
|
perlin2 = fnlCreateState();
|
||||||
|
perlin2.noise_type = FNL_NOISE_OPENSIMPLEX2;
|
||||||
|
perlin2.fractal_type = FNL_FRACTAL_FBM;
|
||||||
|
perlin2.frequency = 0.00522f;
|
||||||
|
perlin2.octaves = 8;
|
||||||
|
|
||||||
constexpr size_t MAX = 128; // allowed range: 0..MAX-1
|
constexpr size_t MAX = 128; // allowed range: 0..MAX-1
|
||||||
for (int i = 0; i < sizeof(BLOCKS) / sizeof(BlockDef); i++)
|
for (int i = 0; i < BLOCKS.size(); i++)
|
||||||
{
|
{
|
||||||
BlockDef def = BLOCKS[i];
|
BlockDef def = GetBlockDefinition(i);
|
||||||
if(def.render == R_Translucent || def.render == R_TranslucentAllSides || def.render == R_TranslucentTriSide) {
|
if(def.render == R_Translucent || def.render == R_TranslucentAllSides || def.render == R_TranslucentTriSide) {
|
||||||
marked.set(i);
|
marked.set(i);
|
||||||
}
|
}
|
||||||
@@ -224,21 +384,16 @@ Chunk GenerateChunk(int _x, int _y) {
|
|||||||
Chunk new_chunk = { 0 };
|
Chunk new_chunk = { 0 };
|
||||||
new_chunk.x = _x;
|
new_chunk.x = _x;
|
||||||
new_chunk.z = _y;
|
new_chunk.z = _y;
|
||||||
|
memset(&new_chunk.light, 0, sizeof(new_chunk.light));
|
||||||
for (int x = 0; x < CHUNK_SIZE; x++)
|
|
||||||
{
|
|
||||||
for (int y = 0; y < WORLD_HEIGHT; y++)
|
for (int y = 0; y < WORLD_HEIGHT; y++)
|
||||||
{
|
for (int x = 0; x < CHUNK_SIZE; x++)
|
||||||
for (int z = 0; z < CHUNK_SIZE; z++)
|
for (int z = 0; z < CHUNK_SIZE; z++) {
|
||||||
{
|
|
||||||
int id = has_block(_x * CHUNK_SIZE + x,y,_y * CHUNK_SIZE + z);
|
int id = has_block(_x * CHUNK_SIZE + x,y,_y * CHUNK_SIZE + z);
|
||||||
SetBlockChunk(&new_chunk, x, y, z, id);
|
SetBlockChunk(&new_chunk, x, y, z, id);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
return new_chunk;
|
return new_chunk;
|
||||||
}
|
}
|
||||||
void GenerateWorldAdditional(Chunk world[]) {
|
void GenerateWorldAdditional(World &world) {
|
||||||
int biome = GetBiome(0, 0);
|
int biome = GetBiome(0, 0);
|
||||||
SetRandomSeed(0);
|
SetRandomSeed(0);
|
||||||
switch (world_type)
|
switch (world_type)
|
||||||
@@ -247,36 +402,11 @@ void GenerateWorldAdditional(Chunk world[]) {
|
|||||||
for (int x = 0; x < WORLD_SIZE_BLOCKS; x++)
|
for (int x = 0; x < WORLD_SIZE_BLOCKS; x++)
|
||||||
{
|
{
|
||||||
for (int z = 0; z < WORLD_SIZE_BLOCKS; z++) {
|
for (int z = 0; z < WORLD_SIZE_BLOCKS; z++) {
|
||||||
Chunk c = world[GetIndexWorld(x / CHUNK_SIZE, z / CHUNK_SIZE)];
|
Chunk c = world.chunks[GetIndexWorld(x / CHUNK_SIZE, z / CHUNK_SIZE)];
|
||||||
int highestY = c.highestBlock[GetIndexChunk2D(x % CHUNK_SIZE, z % CHUNK_SIZE)];
|
int highestY = c.highestBlock[GetIndexChunk2D(x % CHUNK_SIZE, z % CHUNK_SIZE)];
|
||||||
int b = fetch_block(c, x % CHUNK_SIZE, highestY, z % CHUNK_SIZE);
|
int b = fetch_block(c, x % CHUNK_SIZE, highestY, z % CHUNK_SIZE);
|
||||||
for (int _ = 0; _ < GetRandomValue(0, 6); _++)
|
if(b == BLOCK_DIRT) {
|
||||||
{
|
SetBlock(world, x, highestY, z, BLOCK_GRASS);
|
||||||
if(GetRandomValue(0, 800) == 0) {
|
|
||||||
int max = GetRandomValue(10, 120);
|
|
||||||
Vector3 pos = {x, GetRandomValue(12, WORLD_HEIGHT-32), z};
|
|
||||||
Vector3 direction = {GetRandomValue(-100, 100) / 100.0f, GetRandomValue(-100, -5) / 100.0f, GetRandomValue(-100, 100) / 100.0f};
|
|
||||||
int radius = 2;
|
|
||||||
for (int _ = 0; _ < max; _++)
|
|
||||||
{
|
|
||||||
for (int x = -radius; x < radius; x++)
|
|
||||||
{
|
|
||||||
for (int y = -radius; y < radius; y++)
|
|
||||||
{
|
|
||||||
for (int z = -radius; z < radius; z++)
|
|
||||||
{
|
|
||||||
if(Vector3Distance({pos.x + x, pos.y + y, pos.z + z}, pos) <= radius) {
|
|
||||||
if(!CheckOOBWorld(pos.x + x, pos.y + y, pos.z + z)) {
|
|
||||||
SetBlock(world, pos.x + x, pos.y + y, pos.z + z, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
direction += {GetRandomValue(-100, 100) / 100.0f, GetRandomValue(-100, -5) / 100.0f, GetRandomValue(-100, 100) / 100.0f};
|
|
||||||
pos += direction;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for (int _ = 0; _ < GetRandomValue(8, 24); _++)
|
for (int _ = 0; _ < GetRandomValue(8, 24); _++)
|
||||||
{
|
{
|
||||||
@@ -314,10 +444,10 @@ void GenerateWorldAdditional(Chunk world[]) {
|
|||||||
for (int x = 0; x < WORLD_SIZE_BLOCKS; x++)
|
for (int x = 0; x < WORLD_SIZE_BLOCKS; x++)
|
||||||
{
|
{
|
||||||
for (int z = 0; z < WORLD_SIZE_BLOCKS; z++) {
|
for (int z = 0; z < WORLD_SIZE_BLOCKS; z++) {
|
||||||
Chunk c = world[GetIndexWorld(x / CHUNK_SIZE, z / CHUNK_SIZE)];
|
Chunk c = world.chunks[GetIndexWorld(x / CHUNK_SIZE, z / CHUNK_SIZE)];
|
||||||
int highestY = c.highestBlock[GetIndexChunk2D(x % CHUNK_SIZE, z % CHUNK_SIZE)];
|
int highestY = c.highestBlock[GetIndexChunk2D(x % CHUNK_SIZE, z % CHUNK_SIZE)];
|
||||||
int b = fetch_block(c, x % CHUNK_SIZE, highestY, z % CHUNK_SIZE);
|
int b = fetch_block(c, x % CHUNK_SIZE, highestY, z % CHUNK_SIZE);
|
||||||
if(b == BLOCK_GRASS && GetRandomValue(0, 100) < 4 && biome == BIOME_FOREST) { // Regular trees
|
if(b == BLOCK_GRASS && GetRandomValue(0, 100) == 0 && biome == BIOME_FOREST) { // Regular trees
|
||||||
SetBlock(world, x, highestY, z, BLOCK_DIRT);
|
SetBlock(world, x, highestY, z, BLOCK_DIRT);
|
||||||
int maxY = GetRandomValue(5, 7);
|
int maxY = GetRandomValue(5, 7);
|
||||||
for (int y = 1; y < maxY; y++)
|
for (int y = 1; y < maxY; y++)
|
||||||
@@ -334,7 +464,7 @@ void GenerateWorldAdditional(Chunk world[]) {
|
|||||||
SetBlock(world, x, wy, z, 12); // log
|
SetBlock(world, x, wy, z, 12); // log
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(b == BLOCK_GRASS && GetRandomValue(0, 100) < 2 && biome == BIOME_TAIGA) { // Spruce
|
if(b == BLOCK_GRASS && GetRandomValue(0, 100) == 0 && biome == BIOME_TAIGA) { // Spruce
|
||||||
SetBlock(world, x, highestY, z, BLOCK_DIRT);
|
SetBlock(world, x, highestY, z, BLOCK_DIRT);
|
||||||
int maxY = 8;
|
int maxY = 8;
|
||||||
for (int y = 1; y < maxY; y++)
|
for (int y = 1; y < maxY; y++)
|
||||||
@@ -421,7 +551,7 @@ void GenerateWorldAdditional(Chunk world[]) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void TickBlock(Chunk world[], int wx, int wy, int wz) {
|
void TickBlock(World &world, int wx, int wy, int wz) {
|
||||||
if(CheckOOBWorld(wx, wy, wz)) return;
|
if(CheckOOBWorld(wx, wy, wz)) return;
|
||||||
int tile = GetBlock(world, wx, wy, wz);
|
int tile = GetBlock(world, wx, wy, wz);
|
||||||
if(tile == BLOCK_SAND) {
|
if(tile == BLOCK_SAND) {
|
||||||
@@ -436,7 +566,7 @@ void TickBlock(Chunk world[], int wx, int wy, int wz) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void TickChunk(Chunk *chunk, Chunk *world, int wx, int wz) {
|
void TickChunk(Chunk *chunk, World &world, int wx, int wz) {
|
||||||
for (int y = WORLD_HEIGHT-1; y > 1; y--) {
|
for (int y = WORLD_HEIGHT-1; y > 1; y--) {
|
||||||
for (int x = 0; x < CHUNK_SIZE; x++)
|
for (int x = 0; x < CHUNK_SIZE; x++)
|
||||||
{
|
{
|
||||||
@@ -472,36 +602,242 @@ void TickChunk(Chunk *chunk, Chunk *world, int wx, int wz) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void RebuildOpaqueMask(Chunk *chunk) {
|
struct LightNode {
|
||||||
|
Vector3I position;
|
||||||
|
int value;
|
||||||
|
};
|
||||||
|
void RebuildOpaqueMask(Chunk &chunk) {
|
||||||
const int GROUP = 16;
|
const int GROUP = 16;
|
||||||
const int GROUPS = CHUNK_DATA_SIZE / GROUP;
|
const int GROUPS = CHUNK_DATA_SIZE / GROUP;
|
||||||
|
|
||||||
uint16_t oMask[GROUPS] = { 0 };
|
uint16_t oMask[GROUPS] = { 0 };
|
||||||
uint16_t aMask[GROUPS] = { 0 };
|
uint16_t aMask[GROUPS] = { 0 };
|
||||||
uint8_t blocks[CHUNK_DATA_SIZE];
|
uint8_t blocks[CHUNK_DATA_SIZE];
|
||||||
memcpy(blocks, chunk->blocks, sizeof(blocks));
|
memcpy(blocks, chunk.blocks, sizeof(blocks));
|
||||||
|
|
||||||
for (int i = 0; i < CHUNK_DATA_SIZE; ++i) {
|
for (int i = 0; i < CHUNK_DATA_SIZE; ++i) {
|
||||||
int g = i / GROUP;
|
int g = i / GROUP;
|
||||||
int bit = i % GROUP;
|
int bit = i % GROUP;
|
||||||
if (chunk->blocks[i] == 0) {
|
if (chunk.blocks[i] == 0) {
|
||||||
aMask[g] |= 1 << bit;
|
aMask[g] |= 1 << bit;
|
||||||
}
|
}
|
||||||
if (!IsTranslucent(chunk->blocks[i])) {
|
if (!IsTranslucent(chunk.blocks[i])) {
|
||||||
oMask[g] |= 1 << bit;
|
oMask[g] |= 1 << bit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(chunk->opaqueMask, oMask, sizeof(oMask));
|
memcpy(chunk.opaqueMask, oMask, sizeof(oMask));
|
||||||
memcpy(chunk->airMask, aMask, sizeof(aMask));
|
memcpy(chunk.airMask, aMask, sizeof(aMask));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RebuildLighting(World &world, int startX, int startZ) {
|
||||||
|
const Vector3I dirs[6] = { (Vector3I){ 1, 0, 0 }, (Vector3I){ -1, 0, 0 }, (Vector3I){ 0, 1, 0 }, (Vector3I){ 0,-1, 0 }, (Vector3I){ 0, 0, 1 }, (Vector3I){ 0, 0,-1 } };
|
||||||
|
|
||||||
|
// sky lighting
|
||||||
|
std::queue<LightNode> nodes;
|
||||||
|
|
||||||
|
for (int cx = -1; cx <= 1; cx++)
|
||||||
|
{
|
||||||
|
for (int cz = -1; cz <= 1; cz++) {
|
||||||
|
Chunk &chunk = world.chunks[GetIndexWorld(startX+cx, startZ+cz)];
|
||||||
|
memset(&chunk.light, 0, sizeof(chunk.light));
|
||||||
|
for (int x = 0; x < CHUNK_SIZE; x++) {
|
||||||
|
for (int z = 0; z < CHUNK_SIZE; z++) {
|
||||||
|
int highest = chunk.highestBlock[GetIndexChunk2D(x, z)];
|
||||||
|
const int neighbors[4] = {
|
||||||
|
chunk.highestBlock[GetIndexChunk2D(x-1, z)],
|
||||||
|
chunk.highestBlock[GetIndexChunk2D(x+1, z)],
|
||||||
|
chunk.highestBlock[GetIndexChunk2D(x, z-1)],
|
||||||
|
chunk.highestBlock[GetIndexChunk2D(x, z+1)]
|
||||||
|
};
|
||||||
|
int highestNeighbor = fmax(neighbors[0], fmax(neighbors[1], fmax(neighbors[2], neighbors[3])));
|
||||||
|
|
||||||
|
Vector3I pos = { x + chunk.x * CHUNK_SIZE, highest + 1, z + chunk.z * CHUNK_SIZE };
|
||||||
|
|
||||||
|
for (int y = highest + 1; y <= WORLD_HEIGHT; ++y)
|
||||||
|
{
|
||||||
|
SetLightChunk(&chunk, x, y, z, 15, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (highest == highestNeighbor) continue;
|
||||||
|
|
||||||
|
|
||||||
|
for (int y = highest+1; y < highestNeighbor+1; y++)
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
GetSkyLight(world, pos.x-1, y, pos.z) < 15 && !TestOpaqueMaskWorld(world, pos.x-1, y, pos.z)
|
||||||
|
) nodes.push({(Vector3I){pos.x-1, y, pos.z}, 15});
|
||||||
|
if (
|
||||||
|
GetSkyLight(world, pos.x+1, y, pos.z) < 15 && !TestOpaqueMaskWorld(world, pos.x+1, y, pos.z)
|
||||||
|
) nodes.push({(Vector3I){pos.x+1, y, pos.z}, 15});
|
||||||
|
if (
|
||||||
|
GetSkyLight(world, pos.x, y, pos.z-1) < 15 && !TestOpaqueMaskWorld(world, pos.x, y, pos.z-1)
|
||||||
|
) nodes.push({(Vector3I){pos.x, y, pos.z-1}, 15});
|
||||||
|
if (
|
||||||
|
GetSkyLight(world, pos.x, y, pos.z+1) < 15 && !TestOpaqueMaskWorld(world, pos.x, y, pos.z+1)
|
||||||
|
) nodes.push({(Vector3I){pos.x, y, pos.z+1}, 15});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (!nodes.empty()) {
|
||||||
|
LightNode node = nodes.front();
|
||||||
|
nodes.pop();
|
||||||
|
|
||||||
|
for (int i = 0; i < 6; i++) {
|
||||||
|
int newValue = node.value - 1;
|
||||||
|
if (newValue <= 0) continue;
|
||||||
|
Vector3I newPos = {
|
||||||
|
node.position.x + dirs[i].x,
|
||||||
|
node.position.y + dirs[i].y,
|
||||||
|
node.position.z + dirs[i].z
|
||||||
|
};
|
||||||
|
|
||||||
|
if (CheckOOBWorld(newPos.x, newPos.y, newPos.z)) continue;
|
||||||
|
if (TestOpaqueMaskWorld(world, newPos.x, newPos.y, newPos.z)) continue;
|
||||||
|
|
||||||
|
if (GetSkyLight(world, newPos.x, newPos.y, newPos.z) >= newValue) continue;
|
||||||
|
|
||||||
|
SetLight(world, newPos.x, newPos.y, newPos.z, newValue, 0, 0, 0);
|
||||||
|
nodes.push({ newPos, newValue });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// red lighting
|
||||||
|
std::queue<LightNode> nodesR;
|
||||||
|
|
||||||
|
for (int cx = -1; cx <= 1; cx++)
|
||||||
|
{
|
||||||
|
for (int cz = -1; cz <= 1; cz++) {
|
||||||
|
Chunk &chunk = world.chunks[GetIndexWorld(startX+cx, startZ+cz)];
|
||||||
|
for (int i = 0; i < CHUNK_DATA_SIZE; i++)
|
||||||
|
{
|
||||||
|
int x, y, z;
|
||||||
|
GetXYZFromIndex(i, &x, &y, &z);
|
||||||
|
if (CheckOOBWorld(x, y, z)) continue;
|
||||||
|
if(chunk.blocks[i] != 18 && chunk.blocks[i] != 21) continue;
|
||||||
|
Vector3I pos = { x + chunk.x * CHUNK_SIZE, y, z + chunk.z * CHUNK_SIZE };
|
||||||
|
LightNode node{pos, 15};
|
||||||
|
nodesR.push(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!nodesR.empty()) {
|
||||||
|
LightNode node = nodesR.front();
|
||||||
|
nodesR.pop();
|
||||||
|
|
||||||
|
for (int i = 0; i < 6; i++) {
|
||||||
|
Vector3I newPos = {
|
||||||
|
node.position.x + dirs[i].x,
|
||||||
|
node.position.y + dirs[i].y,
|
||||||
|
node.position.z + dirs[i].z
|
||||||
|
};
|
||||||
|
|
||||||
|
if (CheckOOBWorld(newPos.x, newPos.y, newPos.z)) continue;
|
||||||
|
if (TestOpaqueMaskWorld(world, newPos.x, newPos.y, newPos.z)) continue;
|
||||||
|
int newValue = node.value - 1;
|
||||||
|
if (newValue <= 0) continue;
|
||||||
|
|
||||||
|
if (GetRLight(world, newPos.x, newPos.y, newPos.z) >= newValue) continue;
|
||||||
|
|
||||||
|
SetLight(world, newPos.x, newPos.y, newPos.z, 0, newValue, 0, 0);
|
||||||
|
nodesR.push({ newPos, newValue });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// green lighting
|
||||||
|
std::queue<LightNode> nodesG;
|
||||||
|
|
||||||
|
for (int cx = -1; cx <= 1; cx++)
|
||||||
|
{
|
||||||
|
for (int cz = -1; cz <= 1; cz++) {
|
||||||
|
Chunk &chunk = world.chunks[GetIndexWorld(startX+cx, startZ+cz)];
|
||||||
|
for (int i = 0; i < CHUNK_DATA_SIZE; i++)
|
||||||
|
{
|
||||||
|
int x, y, z;
|
||||||
|
GetXYZFromIndex(i, &x, &y, &z);
|
||||||
|
if (CheckOOBWorld(x, y, z)) continue;
|
||||||
|
if(chunk.blocks[i] != 19 && chunk.blocks[i] != 21) continue;
|
||||||
|
Vector3I pos = { x + chunk.x * CHUNK_SIZE, y, z + chunk.z * CHUNK_SIZE };
|
||||||
|
LightNode node{pos, 15};
|
||||||
|
nodesG.push(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!nodesG.empty()) {
|
||||||
|
LightNode node = nodesG.front();
|
||||||
|
nodesG.pop();
|
||||||
|
|
||||||
|
for (int i = 0; i < 6; i++) {
|
||||||
|
Vector3I newPos = {
|
||||||
|
node.position.x + dirs[i].x,
|
||||||
|
node.position.y + dirs[i].y,
|
||||||
|
node.position.z + dirs[i].z
|
||||||
|
};
|
||||||
|
|
||||||
|
if (CheckOOBWorld(newPos.x, newPos.y, newPos.z)) continue;
|
||||||
|
if (TestOpaqueMaskWorld(world, newPos.x, newPos.y, newPos.z)) continue;
|
||||||
|
int newValue = node.value - 1;
|
||||||
|
if (newValue <= 0) continue;
|
||||||
|
|
||||||
|
if (GetGLight(world, newPos.x, newPos.y, newPos.z) >= newValue) continue;
|
||||||
|
|
||||||
|
SetLight(world, newPos.x, newPos.y, newPos.z, 0, 0, newValue, 0);
|
||||||
|
nodesG.push({ newPos, newValue });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// blue lighting
|
||||||
|
std::queue<LightNode> nodesB;
|
||||||
|
|
||||||
|
for (int cx = -1; cx <= 1; cx++)
|
||||||
|
{
|
||||||
|
for (int cz = -1; cz <= 1; cz++) {
|
||||||
|
Chunk &chunk = world.chunks[GetIndexWorld(startX+cx, startZ+cz)];
|
||||||
|
for (int i = 0; i < CHUNK_DATA_SIZE; i++)
|
||||||
|
{
|
||||||
|
int x, y, z;
|
||||||
|
GetXYZFromIndex(i, &x, &y, &z);
|
||||||
|
if (CheckOOBWorld(x, y, z)) continue;
|
||||||
|
if(chunk.blocks[i] != 20 && chunk.blocks[i] != 21) continue;
|
||||||
|
Vector3I pos = { x + chunk.x * CHUNK_SIZE, y, z + chunk.z * CHUNK_SIZE };
|
||||||
|
LightNode node{pos, 15};
|
||||||
|
nodesB.push(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!nodesB.empty()) {
|
||||||
|
LightNode node = nodesB.front();
|
||||||
|
nodesB.pop();
|
||||||
|
|
||||||
|
for (int i = 0; i < 6; i++) {
|
||||||
|
Vector3I newPos = {
|
||||||
|
node.position.x + dirs[i].x,
|
||||||
|
node.position.y + dirs[i].y,
|
||||||
|
node.position.z + dirs[i].z
|
||||||
|
};
|
||||||
|
|
||||||
|
if (CheckOOBWorld(newPos.x, newPos.y, newPos.z)) continue;
|
||||||
|
if (TestOpaqueMaskWorld(world, newPos.x, newPos.y, newPos.z)) continue;
|
||||||
|
int newValue = node.value - 1;
|
||||||
|
if (newValue <= 0) continue;
|
||||||
|
|
||||||
|
if (GetBLight(world, newPos.x, newPos.y, newPos.z) >= newValue) continue;
|
||||||
|
|
||||||
|
SetLight(world, newPos.x, newPos.y, newPos.z, 0, 0, 0, newValue);
|
||||||
|
nodesB.push({ newPos, newValue });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
//Generates an opaque CRD (ChunkRenderData). Outputs the CRD.
|
//Generates an opaque CRD (ChunkRenderData). Outputs the CRD.
|
||||||
ChunkRenderData GenerateCRDOpaque(const Chunk &chunk, Chunk world[]) {
|
ChunkRenderData GenerateCRDOpaque(Chunk &chunk, World &world) {
|
||||||
struct ChunkRenderData new_chunk = { 0 };
|
struct ChunkRenderData new_chunk = { 0 };
|
||||||
uint16_t mask[CHUNK_DATA_SIZE/16];
|
uint16_t *mask = chunk.opaqueMask;
|
||||||
memcpy(mask, chunk.opaqueMask, sizeof(chunk.opaqueMask));
|
|
||||||
|
|
||||||
const int cxw = chunk.x * CHUNK_SIZE;
|
const int cxw = chunk.x * CHUNK_SIZE;
|
||||||
const int cxz = chunk.z * CHUNK_SIZE;
|
const int cxz = chunk.z * CHUNK_SIZE;
|
||||||
@@ -517,8 +853,6 @@ ChunkRenderData GenerateCRDOpaque(const Chunk &chunk, Chunk world[]) {
|
|||||||
int _x = bit;
|
int _x = bit;
|
||||||
int y = step >> 4;
|
int y = step >> 4;
|
||||||
int _z = step & 0xF;
|
int _z = step & 0xF;
|
||||||
//int _x, y, _z;
|
|
||||||
//GetXYZFromIndex(i2, &_x, &y, &_z);
|
|
||||||
if (!TestMask(mask, i2)) continue; // Skip if this is translucent
|
if (!TestMask(mask, i2)) continue; // Skip if this is translucent
|
||||||
|
|
||||||
int x = _x + cxw;
|
int x = _x + cxw;
|
||||||
@@ -544,7 +878,7 @@ ChunkRenderData GenerateCRDOpaque(const Chunk &chunk, Chunk world[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Generates a translucent CRD (ChunkRenderData). Outputs the CRD.
|
//Generates a translucent CRD (ChunkRenderData). Outputs the CRD.
|
||||||
ChunkRenderData GenerateCRDTranslucent(Chunk chunk, Chunk world[]) {
|
ChunkRenderData GenerateCRDTranslucent(Chunk chunk, World &world) {
|
||||||
struct ChunkRenderData new_chunk = { 0 };
|
struct ChunkRenderData new_chunk = { 0 };
|
||||||
uint16_t *mask0= chunk.opaqueMask;
|
uint16_t *mask0= chunk.opaqueMask;
|
||||||
uint16_t *mask = chunk.airMask;
|
uint16_t *mask = chunk.airMask;
|
||||||
@@ -569,6 +903,55 @@ ChunkRenderData GenerateCRDTranslucent(Chunk chunk, Chunk world[]) {
|
|||||||
new_chunk.sides[i2] = 0xFF;
|
new_chunk.sides[i2] = 0xFF;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if(BLOCKS[fetch_block(chunk, _x, y, _z)].name == "water") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int x = _x + chunk.x * CHUNK_SIZE;
|
||||||
|
int z = _z + chunk.z * CHUNK_SIZE;
|
||||||
|
bool l = (_x > 0) ? !TestMask(mask, i2-1) : !TestAirMaskWorld(world, x - 1, y, z);
|
||||||
|
bool r = (_x < CHUNK_SIZE-1) ? !TestMask(mask, i2+1) : !TestAirMaskWorld(world, x + 1, y, z);
|
||||||
|
bool u = (y==WORLD_HEIGHT-1) ? false : !TestMask(mask, i2+CHUNK_SIZE_SQR);
|
||||||
|
bool d = (y==0) ? true : !TestMask(mask, i2-CHUNK_SIZE_SQR);
|
||||||
|
bool b = (_z==0) ? !TestAirMaskWorld(world, x, y, z - 1) : !TestMask(mask, i2-CHUNK_SIZE);
|
||||||
|
bool f = (_z==CHUNK_SIZE-1) ? !TestAirMaskWorld(world, x, y, z + 1) : !TestMask(mask, i2+CHUNK_SIZE);
|
||||||
|
new_chunk.sides[i2] = pack6(
|
||||||
|
!l,
|
||||||
|
!r,
|
||||||
|
!u,
|
||||||
|
!d,
|
||||||
|
!b,
|
||||||
|
!f
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new_chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Generates a CRD for water (ChunkRenderData). Outputs the CRD.
|
||||||
|
ChunkRenderData GenerateCRDWater(Chunk chunk, World &world) {
|
||||||
|
struct ChunkRenderData new_chunk = { 0 };
|
||||||
|
uint16_t *mask0= chunk.opaqueMask;
|
||||||
|
uint16_t *mask = chunk.airMask;
|
||||||
|
for (int step = 0; step < CHUNK_DATA_SIZE/16; ++step)
|
||||||
|
{
|
||||||
|
uint16_t m = ~(mask[step]);
|
||||||
|
if(m == 0) continue;
|
||||||
|
|
||||||
|
while (m) {
|
||||||
|
int bit = __builtin_ctz(m);
|
||||||
|
m &= m - 1;
|
||||||
|
int i2 = (step<<4) + bit;
|
||||||
|
int _x = bit;
|
||||||
|
int y = step >> 4;
|
||||||
|
int _z = step & 0xF;
|
||||||
|
|
||||||
|
if (TestMask(mask0, i2)) {
|
||||||
|
new_chunk.sides[i2] = 0;
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
if(BLOCKS[fetch_block(chunk, _x, y, _z)].name != "water") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
int x = _x + chunk.x * CHUNK_SIZE;
|
int x = _x + chunk.x * CHUNK_SIZE;
|
||||||
int z = _z + chunk.z * CHUNK_SIZE;
|
int z = _z + chunk.z * CHUNK_SIZE;
|
||||||
bool l = (_x > 0) ? !TestMask(mask, i2-1) : !TestAirMaskWorld(world, x - 1, y, z);
|
bool l = (_x > 0) ? !TestMask(mask, i2-1) : !TestAirMaskWorld(world, x - 1, y, z);
|
||||||
@@ -592,7 +975,7 @@ ChunkRenderData GenerateCRDTranslucent(Chunk chunk, Chunk world[]) {
|
|||||||
#endif
|
#endif
|
||||||
#define SAVE_FORMAT 0
|
#define SAVE_FORMAT 0
|
||||||
|
|
||||||
void SaveWorld(Chunk world[], const char* path) {
|
void SaveWorld(World &world, const char* path) {
|
||||||
std::ofstream data(path, std::ios::binary);
|
std::ofstream data(path, std::ios::binary);
|
||||||
if (!data) return;
|
if (!data) return;
|
||||||
|
|
||||||
@@ -601,7 +984,7 @@ void SaveWorld(Chunk world[], const char* path) {
|
|||||||
data.write(&fmt, 1);
|
data.write(&fmt, 1);
|
||||||
|
|
||||||
for (int i = 0; i < MAX_WORLD_AREA; ++i) {
|
for (int i = 0; i < MAX_WORLD_AREA; ++i) {
|
||||||
const Chunk &c = world[i];
|
const Chunk &c = world.chunks[i];
|
||||||
|
|
||||||
std::vector<uint8_t> temp;
|
std::vector<uint8_t> temp;
|
||||||
int last_type = -1;
|
int last_type = -1;
|
||||||
@@ -639,7 +1022,8 @@ void SaveWorld(Chunk world[], const char* path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Debug_Write(const std::string &stuff);
|
void Debug_Write(const std::string &stuff);
|
||||||
bool LoadWorld(Chunk world[], const char* path) {
|
|
||||||
|
bool LoadWorld(World &world, const char* path) {
|
||||||
std::ifstream data(path, std::ios::binary);
|
std::ifstream data(path, std::ios::binary);
|
||||||
if (!data) return false;
|
if (!data) return false;
|
||||||
|
|
||||||
@@ -668,19 +1052,22 @@ bool LoadWorld(Chunk world[], const char* path) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Chunk *c = &world[i];
|
Chunk c = {0};
|
||||||
|
c.x = i % 16;
|
||||||
|
c.z = i >> 4;
|
||||||
int outIndex = 0;
|
int outIndex = 0;
|
||||||
for (size_t p = 0; p + 1 < size; p += 2) {
|
for (size_t p = 0; p + 1 < size; p += 2) {
|
||||||
uint8_t count = temp[p];
|
uint8_t count = temp[p];
|
||||||
uint8_t value = temp[p + 1];
|
uint8_t value = temp[p + 1];
|
||||||
for (uint8_t k = 0; k < count; ++k) {
|
for (uint8_t k = 0; k < count; ++k) {
|
||||||
SetBlockChunkFast(c, outIndex++, value);
|
SetBlockChunkFast(&c, outIndex++, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (outIndex < CHUNK_DATA_SIZE) {
|
while (outIndex < CHUNK_DATA_SIZE) {
|
||||||
SetBlockChunkFast(c, outIndex++, 0);
|
SetBlockChunkFast(&c, outIndex++, 0);
|
||||||
}
|
}
|
||||||
RebuildHeightmap(c);
|
RebuildHeightmap(c);
|
||||||
|
memcpy(&world.chunks[i], &c, sizeof(c));
|
||||||
}
|
}
|
||||||
free(temp);
|
free(temp);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
+77
-51
@@ -1,4 +1,4 @@
|
|||||||
#ifdef WIN32 // FUCK WINDOWS
|
#ifdef WIN32 // FUCK WINDOWS
|
||||||
#include "external/fix_win32_compatibility.h"
|
#include "external/fix_win32_compatibility.h"
|
||||||
#undef PlaySound
|
#undef PlaySound
|
||||||
#endif
|
#endif
|
||||||
@@ -9,8 +9,8 @@
|
|||||||
#undef PlaySound
|
#undef PlaySound
|
||||||
#undef Sound
|
#undef Sound
|
||||||
#endif
|
#endif
|
||||||
|
#include <functional>
|
||||||
#include "glfw_keycodes_to_string.h"
|
#include "glfw_keycodes_to_string.h"
|
||||||
#include "../PerlinNoise.hpp"
|
|
||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
#include "raymath.h"
|
#include "raymath.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@@ -75,7 +75,7 @@
|
|||||||
#define GAME_NAME "CubeGame"
|
#define GAME_NAME "CubeGame"
|
||||||
#define GAME_VERSION_INT 0
|
#define GAME_VERSION_INT 0
|
||||||
#define DEFAULT_FONT_SIZE 16
|
#define DEFAULT_FONT_SIZE 16
|
||||||
#define TPS 30.0
|
#define TPS 30
|
||||||
#define TPS_DIV 1.0 / TPS
|
#define TPS_DIV 1.0 / TPS
|
||||||
#define RENDER_DISTANCE 16
|
#define RENDER_DISTANCE 16
|
||||||
#define RENDER_DISTANCE_SQUARED RENDER_DISTANCE*RENDER_DISTANCE
|
#define RENDER_DISTANCE_SQUARED RENDER_DISTANCE*RENDER_DISTANCE
|
||||||
@@ -86,6 +86,8 @@
|
|||||||
#define INVENTORY_WIDTH 8
|
#define INVENTORY_WIDTH 8
|
||||||
#define INVENTORY_HEIGHT 6
|
#define INVENTORY_HEIGHT 6
|
||||||
#define INVENTORY_SIZE INVENTORY_WIDTH*INVENTORY_HEIGHT
|
#define INVENTORY_SIZE INVENTORY_WIDTH*INVENTORY_HEIGHT
|
||||||
|
#define WORLD_TIME_SECONDS (24*60)
|
||||||
|
#define WORLD_TIME_TICKS WORLD_TIME_SECONDS*TPS
|
||||||
enum BlockType {
|
enum BlockType {
|
||||||
B_Wood,
|
B_Wood,
|
||||||
B_Stone,
|
B_Stone,
|
||||||
@@ -152,7 +154,7 @@ struct Chunk {
|
|||||||
uint16_t opaqueMask[CHUNK_DATA_SIZE/16];
|
uint16_t opaqueMask[CHUNK_DATA_SIZE/16];
|
||||||
uint16_t airMask[CHUNK_DATA_SIZE/16];
|
uint16_t airMask[CHUNK_DATA_SIZE/16];
|
||||||
uint8_t highestBlock[CHUNK_SIZE*CHUNK_SIZE];
|
uint8_t highestBlock[CHUNK_SIZE*CHUNK_SIZE];
|
||||||
|
uint16_t light[CHUNK_DATA_SIZE];
|
||||||
};
|
};
|
||||||
#if !defined(SERVER)
|
#if !defined(SERVER)
|
||||||
typedef struct ChunkRenderData ChunkRenderData;
|
typedef struct ChunkRenderData ChunkRenderData;
|
||||||
@@ -195,9 +197,19 @@ struct Quad2D {
|
|||||||
#endif
|
#endif
|
||||||
typedef struct Vector3I Vector3I;
|
typedef struct Vector3I Vector3I;
|
||||||
struct Vector3I {
|
struct Vector3I {
|
||||||
int x;
|
int x, y, z;
|
||||||
int y;
|
bool operator==(const Vector3I& other) const {
|
||||||
int z;
|
return (x == other.x && y == other.y && z == other.z);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
typedef struct Vector3IHash Vector3IHash;
|
||||||
|
struct Vector3IHash {
|
||||||
|
size_t operator()(const Vector3I& p) const noexcept {
|
||||||
|
size_t h1 = std::hash<int>{}(p.x);
|
||||||
|
size_t h2 = std::hash<int>{}(p.y);
|
||||||
|
size_t h3 = std::hash<int>{}(p.z);
|
||||||
|
return h1 ^ (h2 << 1) ^ (h3 << 2);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
typedef struct Entity Entity;
|
typedef struct Entity Entity;
|
||||||
struct Entity {
|
struct Entity {
|
||||||
@@ -288,28 +300,46 @@ struct Particle {
|
|||||||
int lifetime;
|
int lifetime;
|
||||||
int data[8];
|
int data[8];
|
||||||
};
|
};
|
||||||
extern const BlockDef BLOCKS[];
|
typedef struct World World;
|
||||||
|
struct World {
|
||||||
|
Chunk chunks[MAX_WORLD_AREA];
|
||||||
|
};
|
||||||
|
BlockDef&GetBlockDefinition(int id);
|
||||||
|
void LoadBlocks();
|
||||||
|
int GetBlock(World&world,int x,int y,int z);
|
||||||
|
int GetHighestBlock(World&world,int x,int z);
|
||||||
|
int GetSkyLight(World&world,int x,int y,int z);
|
||||||
|
int GetRLight(World&world,int x,int y,int z);
|
||||||
|
int GetGLight(World&world,int x,int y,int z);
|
||||||
|
int GetBLight(World&world,int x,int y,int z);
|
||||||
|
Color GetSunlightColor();
|
||||||
|
Color GetLight(World&world,int x,int y,int z);
|
||||||
|
Color GetLightMesher(World&world,int x,int y,int z);
|
||||||
bool CanTick(int blockType);
|
bool CanTick(int blockType);
|
||||||
bool GetCloud(int x,int z);
|
bool GetCloud(int x,int z);
|
||||||
bool IsTranslucent(int blockType);
|
bool IsTranslucent(int blockType);
|
||||||
void SetBlockChunk(Chunk *c,int x,int y,int z,int t);
|
void SetBlockChunk(Chunk *c,int x,int y,int z,int t);
|
||||||
void RebuildHeightmap(Chunk *c);
|
void RebuildHeightmap(Chunk&c);
|
||||||
int GetBiome(int sx,int sy);
|
int GetBiome(int sx,int sy);
|
||||||
void SetBlockChunkFast(Chunk *c,int i,int t);
|
void SetBlockChunkFast(Chunk *c,int i,int t);
|
||||||
void SetBlock(Chunk world[],int x,int y,int z,int t);
|
void SetBlock(World&world,int x,int y,int z,int t);
|
||||||
|
void SetLightChunk(Chunk *c,int x,int y,int z,uint8_t sky,uint8_t r,uint8_t g,uint8_t b);
|
||||||
|
void SetLight(World&world,int x,int y,int z,uint8_t sky,uint8_t r,uint8_t g,uint8_t b);
|
||||||
void InitWorldgen(int worldType);
|
void InitWorldgen(int worldType);
|
||||||
Vector3 WorldPosition(int cx,int cz,int localX,int y,int localZ);
|
Vector3 WorldPosition(int cx,int cz,int localX,int y,int localZ);
|
||||||
Chunk GenerateChunk(int _x,int _y);
|
Chunk GenerateChunk(int _x,int _y);
|
||||||
void GenerateWorldAdditional(Chunk world[]);
|
void GenerateWorldAdditional(World&world);
|
||||||
void TickBlock(Chunk world[],int wx,int wy,int wz);
|
void TickBlock(World&world,int wx,int wy,int wz);
|
||||||
void TickChunk(Chunk *chunk,Chunk *world,int wx,int wz);
|
void TickChunk(Chunk *chunk,World&world,int wx,int wz);
|
||||||
void RebuildOpaqueMask(Chunk *chunk);
|
void RebuildOpaqueMask(Chunk&chunk);
|
||||||
|
void RebuildLighting(World&world,int startX,int startZ);
|
||||||
#if !defined(SERVER)
|
#if !defined(SERVER)
|
||||||
ChunkRenderData GenerateCRDOpaque(const Chunk&chunk,Chunk world[]);
|
ChunkRenderData GenerateCRDOpaque(Chunk&chunk,World&world);
|
||||||
ChunkRenderData GenerateCRDTranslucent(Chunk chunk,Chunk world[]);
|
ChunkRenderData GenerateCRDTranslucent(Chunk chunk,World&world);
|
||||||
|
ChunkRenderData GenerateCRDWater(Chunk chunk,World&world);
|
||||||
#endif
|
#endif
|
||||||
void SaveWorld(Chunk world[],const char *path);
|
void SaveWorld(World&world,const char *path);
|
||||||
bool LoadWorld(Chunk world[],const char *path);
|
bool LoadWorld(World&world,const char *path);
|
||||||
extern long nsTotal;
|
extern long nsTotal;
|
||||||
void Debug_StartMeasure();
|
void Debug_StartMeasure();
|
||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
@@ -356,11 +386,11 @@ extern Vector3 player_velocity;
|
|||||||
extern Vector3 player_velocity;
|
extern Vector3 player_velocity;
|
||||||
#if !defined(SERVER)
|
#if !defined(SERVER)
|
||||||
void TakeDamage(float amount);
|
void TakeDamage(float amount);
|
||||||
void SetBlockNetwork(Chunk world[],int bx,int by,int bz,int t);
|
void SetBlockNetwork(World&world,int bx,int by,int bz,int t);
|
||||||
#endif
|
#endif
|
||||||
Entity NewEntity();
|
Entity NewEntity();
|
||||||
void AddEntity(Entity ent);
|
void AddEntity(Entity ent);
|
||||||
void UpdateEntities(Chunk world[],float dt);
|
void UpdateEntities(World&world,float dt);
|
||||||
extern float globalCounter;
|
extern float globalCounter;
|
||||||
#if !defined(SERVER)
|
#if !defined(SERVER)
|
||||||
void DrawEntities(float dt);
|
void DrawEntities(float dt);
|
||||||
@@ -401,7 +431,7 @@ char *DrawChat();
|
|||||||
void DrawLogoCenter();
|
void DrawLogoCenter();
|
||||||
#endif
|
#endif
|
||||||
#if !defined(LEGACY_GL) && !defined(SERVER)
|
#if !defined(LEGACY_GL) && !defined(SERVER)
|
||||||
MeshData GenerateChunkMesh(ChunkRenderData chunkRenderData,Chunk chunk,int chunkWorldX,int chunkWorldY,uint8_t sideMask);
|
MeshData GenerateChunkMesh(World&world,ChunkRenderData chunkRenderData,Chunk chunk,int chunkWorldX,int chunkWorldY,uint8_t sideMask);
|
||||||
MeshData MergeMeshData(const MeshData&a,const MeshData&b);
|
MeshData MergeMeshData(const MeshData&a,const MeshData&b);
|
||||||
MeshData CreateCubeMeshData(const BlockDef&def,float cx,float cy,float cz);
|
MeshData CreateCubeMeshData(const BlockDef&def,float cx,float cy,float cz);
|
||||||
Mesh GenChunkMesh(MeshData meshData);
|
Mesh GenChunkMesh(MeshData meshData);
|
||||||
@@ -418,10 +448,12 @@ const char *Pathify(const char *src);
|
|||||||
const char *PathifyUser(const char *src);
|
const char *PathifyUser(const char *src);
|
||||||
#if !defined(SERVER)
|
#if !defined(SERVER)
|
||||||
void DrawCubeTexture(Texture2D texture,Vector3 position,float width,float height,float length,Color color,int offsetX,int offsetY,int sizeX,int sizeY);
|
void DrawCubeTexture(Texture2D texture,Vector3 position,float width,float height,float length,Color color,int offsetX,int offsetY,int sizeX,int sizeY);
|
||||||
void DrawCubeBlock(Texture2D texture,Vector3 position,float width,float height,float length,BlockDef def);
|
void DrawCubeBlock(Texture2D texture,Vector3 position,float width,float height,float length,BlockDef def,Color tint);
|
||||||
void DrawTextCodepoint3D(Font font,int codepoint,Vector3 position,float fontSize,bool backface,Color tint);
|
void DrawTextCodepoint3D(Font font,int codepoint,Vector3 position,float fontSize,bool backface,Color tint);
|
||||||
void DrawText3D(Font font,const char *text,Vector3 position,float fontSize,float fontSpacing,float lineSpacing,bool backface,Color tint);
|
void DrawText3D(Font font,const char *text,Vector3 position,float fontSize,float fontSpacing,float lineSpacing,bool backface,Color tint);
|
||||||
#endif
|
#endif
|
||||||
|
RenderTexture2D LoadRenderTextureDepthTex(int width,int height);
|
||||||
|
void UnloadRenderTextureDepthTex(RenderTexture2D target);
|
||||||
inline uint8_t pack6(bool b0,bool b1,bool b2,bool b3,bool b4,bool b5){
|
inline uint8_t pack6(bool b0,bool b1,bool b2,bool b3,bool b4,bool b5){
|
||||||
return (uint8_t)(
|
return (uint8_t)(
|
||||||
((uint8_t)(b0 ? 1 : 0) << 0) |
|
((uint8_t)(b0 ? 1 : 0) << 0) |
|
||||||
@@ -441,10 +473,10 @@ inline void unpack6(uint8_t v,bool *b0,bool *b1,bool *b2,bool *b3,bool *b4,bool
|
|||||||
*b5 = (v >> 5) & 1;
|
*b5 = (v >> 5) & 1;
|
||||||
};
|
};
|
||||||
inline void GetXYZFromIndex(int index,int *x,int *y,int *z){
|
inline void GetXYZFromIndex(int index,int *x,int *y,int *z){
|
||||||
*x = index & 15;
|
*y = index / (CHUNK_SIZE * CHUNK_SIZE);
|
||||||
int tmp = index << 4;
|
int rem = index % (CHUNK_SIZE * CHUNK_SIZE);
|
||||||
*z = tmp & 15;
|
*z = rem / CHUNK_SIZE;
|
||||||
*y = tmp << 4;
|
*x = rem % CHUNK_SIZE;
|
||||||
};
|
};
|
||||||
inline int GetIndexChunk(int x,int y,int z){
|
inline int GetIndexChunk(int x,int y,int z){
|
||||||
if(x < 0 || y < 0 || z < 0 || x >= CHUNK_SIZE || y >= WORLD_HEIGHT || z >= CHUNK_SIZE) return 0;
|
if(x < 0 || y < 0 || z < 0 || x >= CHUNK_SIZE || y >= WORLD_HEIGHT || z >= CHUNK_SIZE) return 0;
|
||||||
@@ -454,36 +486,40 @@ inline int GetIndexChunk2D(int x,int z){
|
|||||||
if(x < 0 || z < 0 || x >= CHUNK_SIZE || z >= CHUNK_SIZE) return 0;
|
if(x < 0 || z < 0 || x >= CHUNK_SIZE || z >= CHUNK_SIZE) return 0;
|
||||||
return x + CHUNK_SIZE * z;
|
return x + CHUNK_SIZE * z;
|
||||||
};
|
};
|
||||||
|
inline bool CheckOOBWorld(int x,int y,int z){
|
||||||
|
return (x < 0 || y < 0 || z < 0 || x >= WORLD_SIZE_BLOCKS || y >= WORLD_HEIGHT || z >= WORLD_SIZE_BLOCKS);
|
||||||
|
};
|
||||||
|
inline bool CheckOOBWorldChunk(int x,int z){
|
||||||
|
return (x < 0 || z < 0 || x >= MAX_WORLD_SIZE || z >= MAX_WORLD_SIZE);
|
||||||
|
};
|
||||||
inline int GetIndexWorld(int x,int z){
|
inline int GetIndexWorld(int x,int z){
|
||||||
|
if(CheckOOBWorld(x << 4, 0, z << 4)) return 0;
|
||||||
return x + MAX_WORLD_SIZE * z;
|
return x + MAX_WORLD_SIZE * z;
|
||||||
};
|
};
|
||||||
inline void GetXZFromIndex(int index,int *x,int *z){
|
inline void GetXZFromIndex(int index,int *x,int *z){
|
||||||
*z = index / MAX_WORLD_SIZE;
|
*z = index / MAX_WORLD_SIZE;
|
||||||
*x = index % MAX_WORLD_SIZE;
|
*x = index % MAX_WORLD_SIZE;
|
||||||
};
|
};
|
||||||
inline bool TestMask(uint16_t *maskArray,int position){
|
inline bool TestMask(const uint16_t *maskArray,int position){
|
||||||
|
if (position < 0 || position >= CHUNK_DATA_SIZE) return false;
|
||||||
int index = position >> 4;
|
int index = position >> 4;
|
||||||
int bit = position & 15;
|
int bit = position & 15;
|
||||||
int maskArrayLen = CHUNK_DATA_SIZE << 4;
|
|
||||||
return (maskArray[index] & (1u << bit)) != 0;
|
return (maskArray[index] & (1u << bit)) != 0;
|
||||||
};
|
};
|
||||||
inline bool CheckOOBWorld(int x,int y,int z){
|
|
||||||
return (x < 0 || y < 0 || z < 0 || x >= WORLD_SIZE_BLOCKS || y >= WORLD_HEIGHT || z >= WORLD_SIZE_BLOCKS);
|
|
||||||
};
|
|
||||||
inline bool CheckOOBChunk(int x,int y,int z){
|
inline bool CheckOOBChunk(int x,int y,int z){
|
||||||
return (x < 0 || y < 0 || z < 0 || x >= CHUNK_SIZE || y >= WORLD_HEIGHT || z >= CHUNK_SIZE);
|
return (x < 0 || y < 0 || z < 0 || x >= CHUNK_SIZE || y >= WORLD_HEIGHT || z >= CHUNK_SIZE);
|
||||||
};
|
};
|
||||||
inline bool TestOpaqueMaskWorld(Chunk world[],int x,int y,int z){
|
inline bool TestOpaqueMaskWorld(const World&world,int x,int y,int z){
|
||||||
if(CheckOOBWorld(x, y, z)) return true;
|
if(CheckOOBWorld(x, y, z)) return true;
|
||||||
Chunk* c = &world[GetIndexWorld(x >> 4, z >> 4)];
|
const Chunk c = world.chunks[GetIndexWorld(x >> 4, z >> 4)];
|
||||||
int localIndex = GetIndexChunk((uint8_t)x & 15, y, (uint8_t)z & 15);
|
const int localIndex = GetIndexChunk((uint8_t)x & 15, y, (uint8_t)z & 15);
|
||||||
return TestMask(c->opaqueMask, localIndex);
|
return TestMask(c.opaqueMask, localIndex);
|
||||||
};
|
};
|
||||||
inline bool TestAirMaskWorld(Chunk world[],int x,int y,int z){
|
inline bool TestAirMaskWorld(const World&world,int x,int y,int z){
|
||||||
if(CheckOOBWorld(x, y, z)) return true;
|
if(CheckOOBWorld(x, y, z)) return true;
|
||||||
Chunk* c = &world[GetIndexWorld(x >> 4, z >> 4)];
|
const Chunk c = world.chunks[GetIndexWorld(x >> 4, z >> 4)];
|
||||||
int localIndex = GetIndexChunk((uint8_t)x & 15, y, (uint8_t)z & 15);
|
const int localIndex = GetIndexChunk((uint8_t)x & 15, y, (uint8_t)z & 15);
|
||||||
return TestMask(c->airMask, localIndex);
|
return TestMask(c.airMask, localIndex);
|
||||||
};
|
};
|
||||||
inline int fetch_block(Chunk chunk,int x,int y,int z){
|
inline int fetch_block(Chunk chunk,int x,int y,int z){
|
||||||
if(x<0||x>=CHUNK_SIZE||y<0||y>=WORLD_HEIGHT||z<0||z>=CHUNK_SIZE) return 0;
|
if(x<0||x>=CHUNK_SIZE||y<0||y>=WORLD_HEIGHT||z<0||z>=CHUNK_SIZE) return 0;
|
||||||
@@ -493,14 +529,6 @@ inline int fetch_block_ptr(Chunk *chunk,int x,int y,int z){
|
|||||||
if(x<0||x>=CHUNK_SIZE||y<0||y>=WORLD_HEIGHT||z<0||z>=CHUNK_SIZE) return 0;
|
if(x<0||x>=CHUNK_SIZE||y<0||y>=WORLD_HEIGHT||z<0||z>=CHUNK_SIZE) return 0;
|
||||||
return chunk->blocks[GetIndexChunk(x, y, z)];
|
return chunk->blocks[GetIndexChunk(x, y, z)];
|
||||||
};
|
};
|
||||||
inline int GetBlock(Chunk world[],int x,int y,int z){
|
|
||||||
if(CheckOOBWorld(x, y, z)) return 0;
|
|
||||||
int locX = x % CHUNK_SIZE;
|
|
||||||
int locZ = z % CHUNK_SIZE;
|
|
||||||
int cx = x / CHUNK_SIZE;
|
|
||||||
int cz = z / CHUNK_SIZE;
|
|
||||||
return fetch_block(world[GetIndexWorld(cx, cz)], locX, y, locZ);
|
|
||||||
};
|
|
||||||
inline void *grow(void *ptr,size_t oldBytes,size_t newBytes){
|
inline void *grow(void *ptr,size_t oldBytes,size_t newBytes){
|
||||||
if (!ptr) return malloc(newBytes);
|
if (!ptr) return malloc(newBytes);
|
||||||
return realloc(ptr, newBytes);
|
return realloc(ptr, newBytes);
|
||||||
@@ -597,13 +625,13 @@ void HotbarAddItemLots(Item *registry,int damage,int amount);
|
|||||||
void InitHotbar();
|
void InitHotbar();
|
||||||
void DrawHotbar();
|
void DrawHotbar();
|
||||||
InventoryItem HotbarGetSelected();
|
InventoryItem HotbarGetSelected();
|
||||||
void DrawSelectedItem();
|
void DrawSelectedItem(Color tint);
|
||||||
void CloseInventory();
|
void CloseInventory();
|
||||||
void UpdateHotbar();
|
void UpdateHotbar();
|
||||||
void LocaleUpdate();
|
void LocaleUpdate();
|
||||||
void LoadRecipes();
|
void LoadRecipes();
|
||||||
#endif
|
#endif
|
||||||
void ParticlesUpdate(float dt,Chunk world[]);
|
void ParticlesUpdate(float dt,World&world);
|
||||||
void ParticlesDraw();
|
void ParticlesDraw();
|
||||||
void AddParticle(Particle part);
|
void AddParticle(Particle part);
|
||||||
Particle NewParticle(Vector3 position);
|
Particle NewParticle(Vector3 position);
|
||||||
@@ -616,8 +644,6 @@ void SavePlayerData();
|
|||||||
bool LoadPlayerData();
|
bool LoadPlayerData();
|
||||||
void MS_PlaySound(Sound src,float pitch,float volume,Vector3 position);
|
void MS_PlaySound(Sound src,float pitch,float volume,Vector3 position);
|
||||||
void MS_Update(float dt,Camera camera);
|
void MS_Update(float dt,Camera camera);
|
||||||
void ServerNetworkUpdate();
|
|
||||||
void StopInternalServer();
|
|
||||||
#define INTERFACE 0
|
#define INTERFACE 0
|
||||||
#define EXPORT_INTERFACE 0
|
#define EXPORT_INTERFACE 0
|
||||||
#define LOCAL_INTERFACE 0
|
#define LOCAL_INTERFACE 0
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ extern bool online;
|
|||||||
extern Vector3 player_position;
|
extern Vector3 player_position;
|
||||||
extern Vector3 player_velocity;
|
extern Vector3 player_velocity;
|
||||||
void TakeDamage(float amount);
|
void TakeDamage(float amount);
|
||||||
void SetBlockNetwork(Chunk world[], int bx, int by, int bz, int t);
|
void SetBlockNetwork(World &world, int bx, int by, int bz, int t);
|
||||||
#else
|
#else
|
||||||
bool online = true;
|
bool online = true;
|
||||||
#endif
|
#endif
|
||||||
@@ -48,7 +48,7 @@ void AddEntity(Entity ent) {
|
|||||||
entities.push_back(ent);
|
entities.push_back(ent);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void UpdateEntityPhysics(Chunk world[], Entity& ent, float dt) {
|
static void UpdateEntityPhysics(World &world, Entity& ent, float dt) {
|
||||||
Vector3 velocityTgt = Vector3Add(ent.velocity, {0, -dt * 20.0f, 0});
|
Vector3 velocityTgt = Vector3Add(ent.velocity, {0, -dt * 20.0f, 0});
|
||||||
Vector3 tgt = Vector3Add(ent.position, Vector3Scale(velocityTgt, dt));
|
Vector3 tgt = Vector3Add(ent.position, Vector3Scale(velocityTgt, dt));
|
||||||
Vector3 final = ent.position;
|
Vector3 final = ent.position;
|
||||||
@@ -67,7 +67,7 @@ static void UpdateEntityPhysics(Chunk world[], Entity& ent, float dt) {
|
|||||||
ent.velocity = velocityTgt;
|
ent.velocity = velocityTgt;
|
||||||
ent.position = final;
|
ent.position = final;
|
||||||
}
|
}
|
||||||
void UpdateEntities(Chunk world[], float dt) {
|
void UpdateEntities(World &world, float dt) {
|
||||||
if(entities.size() > 0) {
|
if(entities.size() > 0) {
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
for(Entity& ent : entities) {
|
for(Entity& ent : entities) {
|
||||||
@@ -363,7 +363,7 @@ void DrawEntities(float dt) {
|
|||||||
DrawCube(pos_lerped, 1, 1, 1, RED);
|
DrawCube(pos_lerped, 1, 1, 1, RED);
|
||||||
}
|
}
|
||||||
if(ent.type == 4) {
|
if(ent.type == 4) {
|
||||||
DrawCubeBlock(terrain, pos_lerped, 1,1,1, BLOCKS[ent.data[1]]);
|
DrawCubeBlock(terrain, pos_lerped, 1,1,1, GetBlockDefinition(ent.data[1]), WHITE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-26
@@ -21,13 +21,14 @@ inline void unpack6(uint8_t v, bool *b0, bool *b1, bool *b2, bool *b3, bool *b4,
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void GetXYZFromIndex(int index, int* x, int* y, int* z) {
|
inline void GetXYZFromIndex(int index, int* x, int* y, int* z) {
|
||||||
*x = index & 15;
|
*y = index / (CHUNK_SIZE * CHUNK_SIZE);
|
||||||
int tmp = index << 4;
|
int rem = index % (CHUNK_SIZE * CHUNK_SIZE);
|
||||||
*z = tmp & 15;
|
*z = rem / CHUNK_SIZE;
|
||||||
*y = tmp << 4;
|
*x = rem % CHUNK_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
inline int GetIndexChunk(int x, int y, int z) {
|
inline int GetIndexChunk(int x, int y, int z) {
|
||||||
if(x < 0 || y < 0 || z < 0 || x >= CHUNK_SIZE || y >= WORLD_HEIGHT || z >= CHUNK_SIZE) return 0;
|
if(x < 0 || y < 0 || z < 0 || x >= CHUNK_SIZE || y >= WORLD_HEIGHT || z >= CHUNK_SIZE) return 0;
|
||||||
return x + CHUNK_SIZE * (z + CHUNK_SIZE * y);
|
return x + CHUNK_SIZE * (z + CHUNK_SIZE * y);
|
||||||
@@ -36,7 +37,14 @@ inline int GetIndexChunk2D(int x, int z) {
|
|||||||
if(x < 0 || z < 0 || x >= CHUNK_SIZE || z >= CHUNK_SIZE) return 0;
|
if(x < 0 || z < 0 || x >= CHUNK_SIZE || z >= CHUNK_SIZE) return 0;
|
||||||
return x + CHUNK_SIZE * z;
|
return x + CHUNK_SIZE * z;
|
||||||
}
|
}
|
||||||
|
inline bool CheckOOBWorld(int x, int y, int z) {
|
||||||
|
return (x < 0 || y < 0 || z < 0 || x >= WORLD_SIZE_BLOCKS || y >= WORLD_HEIGHT || z >= WORLD_SIZE_BLOCKS);
|
||||||
|
}
|
||||||
|
inline bool CheckOOBWorldChunk(int x, int z) {
|
||||||
|
return (x < 0 || z < 0 || x >= MAX_WORLD_SIZE || z >= MAX_WORLD_SIZE);
|
||||||
|
}
|
||||||
inline int GetIndexWorld(int x, int z) {
|
inline int GetIndexWorld(int x, int z) {
|
||||||
|
if(CheckOOBWorld(x << 4, 0, z << 4)) return 0;
|
||||||
return x + MAX_WORLD_SIZE * z;
|
return x + MAX_WORLD_SIZE * z;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,32 +53,29 @@ inline void GetXZFromIndex(int index, int *x, int *z) {
|
|||||||
*x = index % MAX_WORLD_SIZE;
|
*x = index % MAX_WORLD_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool TestMask(uint16_t *maskArray, int position)
|
inline bool TestMask(const uint16_t *maskArray, int position)
|
||||||
{
|
{
|
||||||
|
if (position < 0 || position >= CHUNK_DATA_SIZE) return false;
|
||||||
int index = position >> 4;
|
int index = position >> 4;
|
||||||
int bit = position & 15;
|
int bit = position & 15;
|
||||||
int maskArrayLen = CHUNK_DATA_SIZE << 4;
|
|
||||||
return (maskArray[index] & (1u << bit)) != 0;
|
return (maskArray[index] & (1u << bit)) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool CheckOOBWorld(int x, int y, int z) {
|
|
||||||
return (x < 0 || y < 0 || z < 0 || x >= WORLD_SIZE_BLOCKS || y >= WORLD_HEIGHT || z >= WORLD_SIZE_BLOCKS);
|
|
||||||
}
|
|
||||||
inline bool CheckOOBChunk(int x, int y, int z) {
|
inline bool CheckOOBChunk(int x, int y, int z) {
|
||||||
return (x < 0 || y < 0 || z < 0 || x >= CHUNK_SIZE || y >= WORLD_HEIGHT || z >= CHUNK_SIZE);
|
return (x < 0 || y < 0 || z < 0 || x >= CHUNK_SIZE || y >= WORLD_HEIGHT || z >= CHUNK_SIZE);
|
||||||
}
|
}
|
||||||
inline bool TestOpaqueMaskWorld(Chunk world[], int x, int y, int z) {
|
inline bool TestOpaqueMaskWorld(const World& world, int x, int y, int z) {
|
||||||
if(CheckOOBWorld(x, y, z)) return true;
|
if(CheckOOBWorld(x, y, z)) return true;
|
||||||
Chunk* c = &world[GetIndexWorld(x >> 4, z >> 4)];
|
const Chunk c = world.chunks[GetIndexWorld(x >> 4, z >> 4)];
|
||||||
int localIndex = GetIndexChunk((uint8_t)x & 15, y, (uint8_t)z & 15);
|
const int localIndex = GetIndexChunk((uint8_t)x & 15, y, (uint8_t)z & 15);
|
||||||
return TestMask(c->opaqueMask, localIndex);
|
return TestMask(c.opaqueMask, localIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool TestAirMaskWorld(Chunk world[], int x, int y, int z) {
|
inline bool TestAirMaskWorld(const World& world, int x, int y, int z) {
|
||||||
if(CheckOOBWorld(x, y, z)) return true;
|
if(CheckOOBWorld(x, y, z)) return true;
|
||||||
Chunk* c = &world[GetIndexWorld(x >> 4, z >> 4)];
|
const Chunk c = world.chunks[GetIndexWorld(x >> 4, z >> 4)];
|
||||||
int localIndex = GetIndexChunk((uint8_t)x & 15, y, (uint8_t)z & 15);
|
const int localIndex = GetIndexChunk((uint8_t)x & 15, y, (uint8_t)z & 15);
|
||||||
return TestMask(c->airMask, localIndex);
|
return TestMask(c.airMask, localIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int fetch_block(Chunk chunk, int x, int y, int z) {
|
inline int fetch_block(Chunk chunk, int x, int y, int z) {
|
||||||
@@ -83,15 +88,6 @@ inline int fetch_block_ptr(Chunk *chunk, int x, int y, int z) {
|
|||||||
return chunk->blocks[GetIndexChunk(x, y, z)];
|
return chunk->blocks[GetIndexChunk(x, y, z)];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int GetBlock(Chunk world[], int x, int y, int z) {
|
|
||||||
if(CheckOOBWorld(x, y, z)) return 0;
|
|
||||||
int locX = x % CHUNK_SIZE;
|
|
||||||
int locZ = z % CHUNK_SIZE;
|
|
||||||
int cx = x / CHUNK_SIZE;
|
|
||||||
int cz = z / CHUNK_SIZE;
|
|
||||||
return fetch_block(world[GetIndexWorld(cx, cz)], locX, y, locZ);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void *grow(void *ptr, size_t oldBytes, size_t newBytes) {
|
inline void *grow(void *ptr, size_t oldBytes, size_t newBytes) {
|
||||||
if (!ptr) return malloc(newBytes);
|
if (!ptr) return malloc(newBytes);
|
||||||
return realloc(ptr, newBytes);
|
return realloc(ptr, newBytes);
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ Vector2 InputGetWalkAxis() {
|
|||||||
float y = 0;
|
float y = 0;
|
||||||
if(isJoystick) {
|
if(isJoystick) {
|
||||||
x = GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X);
|
x = GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X);
|
||||||
y = GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y);
|
y = -GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y);
|
||||||
if(abs(x) < 0.5f) {
|
if(abs(x) < 0.5f) {
|
||||||
x = 0;
|
x = 0;
|
||||||
}
|
}
|
||||||
@@ -84,8 +84,8 @@ Vector2 InputGetLookAxis() {
|
|||||||
float x = 0;
|
float x = 0;
|
||||||
float y = 0;
|
float y = 0;
|
||||||
if(isJoystick) {
|
if(isJoystick) {
|
||||||
x = GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_X);
|
x = GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_X)*3.0f;
|
||||||
y = GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_Y);
|
y = GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_Y)*3.0f;
|
||||||
if(abs(x) < 0.1f) {
|
if(abs(x) < 0.1f) {
|
||||||
x = 0;
|
x = 0;
|
||||||
}
|
}
|
||||||
@@ -108,6 +108,7 @@ Vector2 InputGetDPAD() {
|
|||||||
if (IsGamepadButtonPressed(0, GAMEPAD_BUTTON_LEFT_FACE_RIGHT)) { x = 1; }
|
if (IsGamepadButtonPressed(0, GAMEPAD_BUTTON_LEFT_FACE_RIGHT)) { x = 1; }
|
||||||
if (IsGamepadButtonPressed(0, GAMEPAD_BUTTON_LEFT_FACE_LEFT)) { x = -1; }
|
if (IsGamepadButtonPressed(0, GAMEPAD_BUTTON_LEFT_FACE_LEFT)) { x = -1; }
|
||||||
}
|
}
|
||||||
|
|
||||||
return {x, y};
|
return {x, y};
|
||||||
}
|
}
|
||||||
void InputWriteControls() {
|
void InputWriteControls() {
|
||||||
@@ -136,7 +137,6 @@ void InputInit() {
|
|||||||
controls[key] = val;
|
controls[key] = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
swap_mouse = config["Swap mouse buttons"].as<bool>();
|
swap_mouse = config["Swap mouse buttons"].as<bool>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-10
@@ -40,7 +40,7 @@ void DrawItem(InventoryItem item, int x, int y) {
|
|||||||
if(item.item->type == IType_Block) {
|
if(item.item->type == IType_Block) {
|
||||||
atlas = terrain;
|
atlas = terrain;
|
||||||
atl_size = ATLAS_SIZE_W;
|
atl_size = ATLAS_SIZE_W;
|
||||||
tex = BLOCKS[item.damage].textureTop;
|
tex = GetBlockDefinition(item.damage).textureTop;
|
||||||
}
|
}
|
||||||
DrawTexturePro(atlas,
|
DrawTexturePro(atlas,
|
||||||
{
|
{
|
||||||
@@ -198,9 +198,9 @@ static bool GetTaggedItem(std::string tag, InventoryItem* item) {
|
|||||||
bool isBlock;
|
bool isBlock;
|
||||||
bool found;
|
bool found;
|
||||||
for(int blk = 0; blk < MAX_BLOCK_ID; blk++) {
|
for(int blk = 0; blk < MAX_BLOCK_ID; blk++) {
|
||||||
if(IDTagMatch(tag, BLOCKS[blk].name)) {
|
if(IDTagMatch(tag, GetBlockDefinition(blk).name)) {
|
||||||
isBlock = true;
|
isBlock = true;
|
||||||
id = GetNumericIDFromString(BLOCKS[blk].name);
|
id = GetNumericIDFromString(GetBlockDefinition(blk).name);
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
@@ -307,7 +307,7 @@ void DrawHotbar() {
|
|||||||
if(item.item != nullptr) {
|
if(item.item != nullptr) {
|
||||||
bool blockCond = item.item->type == IType_Block && ingredient.type == IType_Block && item.damage == GetNumericIDFromString(ingredient.id);
|
bool blockCond = item.item->type == IType_Block && ingredient.type == IType_Block && item.damage == GetNumericIDFromString(ingredient.id);
|
||||||
bool genericCond = item.item->type != IType_Block && ingredient.type == IType_Generic && item.item->id == ingredient.id;
|
bool genericCond = item.item->type != IType_Block && ingredient.type == IType_Generic && item.item->id == ingredient.id;
|
||||||
bool tagBlockCond = item.item->type == IType_Block && ingredient.type == IType_Special_Tag && IDTagMatch(ingredient.id, BLOCKS[item.damage].name);
|
bool tagBlockCond = item.item->type == IType_Block && ingredient.type == IType_Special_Tag && IDTagMatch(ingredient.id, GetBlockDefinition(item.damage).name);
|
||||||
bool tagItemCond = item.item->type != IType_Block && ingredient.type == IType_Special_Tag && IDTagMatch(ingredient.id, item.item->id);
|
bool tagItemCond = item.item->type != IType_Block && ingredient.type == IType_Special_Tag && IDTagMatch(ingredient.id, item.item->id);
|
||||||
if(blockCond || genericCond || tagBlockCond || tagItemCond) {
|
if(blockCond || genericCond || tagBlockCond || tagItemCond) {
|
||||||
items.push_back(i);
|
items.push_back(i);
|
||||||
@@ -366,7 +366,7 @@ void DrawHotbar() {
|
|||||||
if(item.item != nullptr) {
|
if(item.item != nullptr) {
|
||||||
bool blockCond = item.item->type == IType_Block && ingredient.type == IType_Block && item.damage == GetNumericIDFromString(ingredient.id);
|
bool blockCond = item.item->type == IType_Block && ingredient.type == IType_Block && item.damage == GetNumericIDFromString(ingredient.id);
|
||||||
bool genericCond = item.item->type != IType_Block && ingredient.type == IType_Generic && item.item->id == ingredient.id;
|
bool genericCond = item.item->type != IType_Block && ingredient.type == IType_Generic && item.item->id == ingredient.id;
|
||||||
bool tagBlockCond = item.item->type == IType_Block && ingredient.type == IType_Special_Tag && IDTagMatch(ingredient.id, BLOCKS[item.damage].name);
|
bool tagBlockCond = item.item->type == IType_Block && ingredient.type == IType_Special_Tag && IDTagMatch(ingredient.id, GetBlockDefinition(item.damage).name);
|
||||||
bool tagItemCond = item.item->type != IType_Block && ingredient.type == IType_Special_Tag && IDTagMatch(ingredient.id, item.item->id);
|
bool tagItemCond = item.item->type != IType_Block && ingredient.type == IType_Special_Tag && IDTagMatch(ingredient.id, item.item->id);
|
||||||
if(blockCond || genericCond || tagBlockCond || tagItemCond) {
|
if(blockCond || genericCond || tagBlockCond || tagItemCond) {
|
||||||
items[i] = ingredient.quantity;
|
items[i] = ingredient.quantity;
|
||||||
@@ -432,7 +432,7 @@ void DrawHotbar() {
|
|||||||
DrawItem(*movingItem, GetMouseX(), GetMouseY());
|
DrawItem(*movingItem, GetMouseX(), GetMouseY());
|
||||||
std::string name = "item."+movingItem->item->id;
|
std::string name = "item."+movingItem->item->id;
|
||||||
if(movingItem->item->type == IType_Block) {
|
if(movingItem->item->type == IType_Block) {
|
||||||
name = "item."+BLOCKS[movingItem->damage].name;
|
name = "item."+GetBlockDefinition(movingItem->damage).name;
|
||||||
}
|
}
|
||||||
DrawTextB(LocaleGet(name).c_str(), GetMouseX()-16, GetMouseY()+56, 16, WHITE);
|
DrawTextB(LocaleGet(name).c_str(), GetMouseX()-16, GetMouseY()+56, 16, WHITE);
|
||||||
}
|
}
|
||||||
@@ -441,7 +441,7 @@ void DrawHotbar() {
|
|||||||
InventoryItem HotbarGetSelected() {
|
InventoryItem HotbarGetSelected() {
|
||||||
return hotbar[selected];
|
return hotbar[selected];
|
||||||
}
|
}
|
||||||
void DrawSelectedItem() {
|
void DrawSelectedItem(Color tint) {
|
||||||
InventoryItem item = hotbar[selected];
|
InventoryItem item = hotbar[selected];
|
||||||
Vector3 center = {-0.75f, -0.45f, 0.5f};
|
Vector3 center = {-0.75f, -0.45f, 0.5f};
|
||||||
rlPushMatrix();
|
rlPushMatrix();
|
||||||
@@ -458,16 +458,16 @@ void DrawSelectedItem() {
|
|||||||
|
|
||||||
rlRotatef(-45, 1, 0, 0);
|
rlRotatef(-45, 1, 0, 0);
|
||||||
rlRotatef(25, 0, 0, 1);
|
rlRotatef(25, 0, 0, 1);
|
||||||
DrawCubeTexture(playerTex, {0, -12*PIXUNIT/2, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 44,20,4,4);
|
DrawCubeTexture(playerTex, {0, -12*PIXUNIT/2, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, tint, 44,20,4,4);
|
||||||
if(item.item != nullptr) {
|
if(item.item != nullptr) {
|
||||||
if(item.item->type == IType_Block) {
|
if(item.item->type == IType_Block) {
|
||||||
DrawCubeBlock(terrain, {0, -12*PIXUNIT - 0.25f, 0}, 0.5f, 0.5f, 0.5f, BLOCKS[item.damage]);
|
DrawCubeBlock(terrain, {0, -12*PIXUNIT - 0.25f, 0}, 0.5f, 0.5f, 0.5f, GetBlockDefinition(item.damage), tint);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
UVCorners left = GetUVTex(item.item->texture);
|
UVCorners left = GetUVTex(item.item->texture);
|
||||||
rlSetTexture(item_atlas.id);
|
rlSetTexture(item_atlas.id);
|
||||||
rlBegin(RL_QUADS);
|
rlBegin(RL_QUADS);
|
||||||
rlColor4ub(255, 255, 255, 255);
|
rlColor4ub(tint.r, tint.g, tint.b, 255);
|
||||||
rlNormal3f(1.0f, 0.0f, 0.0f);
|
rlNormal3f(1.0f, 0.0f, 0.0f);
|
||||||
const float size = 0.5f;
|
const float size = 0.5f;
|
||||||
rlTexCoord2f(left.corner0.x, left.corner0.y); rlVertex3f(0, -12*PIXUNIT - size, 0.25f - size);
|
rlTexCoord2f(left.corner0.x, left.corner0.y); rlVertex3f(0, -12*PIXUNIT - size, 0.25f - size);
|
||||||
|
|||||||
@@ -488,10 +488,10 @@ void DrawWorldSelect() {
|
|||||||
DrawBackground();
|
DrawBackground();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for(std::filesystem::path path : worldList) {
|
for(std::filesystem::path path : worldList) {
|
||||||
if(Button(reinterpret_cast<const char*>(path.filename().u8string().c_str()), GetScreenWidth()/2-64, i*48+8, 128, 0)) {
|
if(Button(reinterpret_cast<const char*>(path.filename().string().c_str()), GetScreenWidth()/2-64, i*48+8, 128, 0)) {
|
||||||
online = false;
|
online = false;
|
||||||
SetTargetFPS(-1);
|
SetTargetFPS(-1);
|
||||||
_LoadWorld(reinterpret_cast<const char*>(path.u8string().c_str()));
|
_LoadWorld(reinterpret_cast<const char*>(path.string().c_str()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
@@ -503,7 +503,8 @@ void DrawWorldSelect() {
|
|||||||
}
|
}
|
||||||
if (Button(LocaleGet("create_world").c_str(), GetScreenWidth()/2+196-128, GetScreenHeight()-48, 128, 0)) {
|
if (Button(LocaleGet("create_world").c_str(), GetScreenWidth()/2+196-128, GetScreenHeight()-48, 128, 0)) {
|
||||||
UIResetMousePos();
|
UIResetMousePos();
|
||||||
//InitSingleplayer();
|
InitWorldgen(0);
|
||||||
|
state = GAME_STATE_LOADING;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (Button(LocaleGet("create_world").c_str(), GetScreenWidth()/2+196-128, GetScreenHeight()-48-48, 128, 0)) {
|
if (Button(LocaleGet("create_world").c_str(), GetScreenWidth()/2+196-128, GetScreenHeight()-48-48, 128, 0)) {
|
||||||
|
|||||||
+21
-20
@@ -10,7 +10,7 @@
|
|||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
#ifndef LEGACY_GL
|
#ifndef LEGACY_GL
|
||||||
|
|
||||||
MeshData GenerateChunkMesh(ChunkRenderData chunkRenderData, Chunk chunk, int chunkWorldX, int chunkWorldY, uint8_t sideMask)
|
MeshData GenerateChunkMesh(World &world, ChunkRenderData chunkRenderData, Chunk chunk, int chunkWorldX, int chunkWorldY, uint8_t sideMask)
|
||||||
{
|
{
|
||||||
MeshData out = {0};
|
MeshData out = {0};
|
||||||
|
|
||||||
@@ -23,17 +23,20 @@ MeshData GenerateChunkMesh(ChunkRenderData chunkRenderData, Chunk chunk, int chu
|
|||||||
std::vector<unsigned short> indices;
|
std::vector<unsigned short> indices;
|
||||||
|
|
||||||
int face = 0;
|
int face = 0;
|
||||||
for (int x = 0; x < CHUNK_SIZE; ++x)
|
for (int index = 0; index < CHUNK_DATA_SIZE; index++)
|
||||||
for (int y = 0; y < WORLD_HEIGHT; ++y)
|
|
||||||
for (int z = 0; z < CHUNK_SIZE; ++z)
|
|
||||||
{
|
{
|
||||||
int index = GetIndexChunk(x,y,z);
|
|
||||||
uint8_t crdata = chunkRenderData.sides[index];
|
uint8_t crdata = chunkRenderData.sides[index];
|
||||||
if (crdata == 0) continue;
|
if (crdata == 0) continue;
|
||||||
|
|
||||||
|
int x, y, z;
|
||||||
|
GetXYZFromIndex(index, &x, &y, &z);
|
||||||
|
int wx = (chunkWorldX * CHUNK_SIZE + x);
|
||||||
|
int wy = (y);
|
||||||
|
int wz = (chunkWorldY * CHUNK_SIZE + z);
|
||||||
|
|
||||||
int this_block = fetch_block(chunk, x,y,z);
|
int this_block = fetch_block(chunk, x,y,z);
|
||||||
|
|
||||||
BlockDef definition = BLOCKS[this_block];
|
BlockDef definition = GetBlockDefinition(this_block);
|
||||||
|
|
||||||
UVCorners UVside = GetUVTex(definition.textureSide);
|
UVCorners UVside = GetUVTex(definition.textureSide);
|
||||||
UVCorners UVtop = GetUVTex(definition.textureTop);
|
UVCorners UVtop = GetUVTex(definition.textureTop);
|
||||||
@@ -46,9 +49,6 @@ MeshData GenerateChunkMesh(ChunkRenderData chunkRenderData, Chunk chunk, int chu
|
|||||||
Color color = {255, 255, 255, 255};
|
Color color = {255, 255, 255, 255};
|
||||||
Color colorShaded = {128, 128, 172, 255};
|
Color colorShaded = {128, 128, 172, 255};
|
||||||
|
|
||||||
float wx = (float)(chunkWorldX * CHUNK_SIZE + x);
|
|
||||||
float wy = (float)(y);
|
|
||||||
float wz = (float)(chunkWorldY * CHUNK_SIZE + z);
|
|
||||||
/*if(GetCloud(wx, wz)) {
|
/*if(GetCloud(wx, wz)) {
|
||||||
color = ColorLerp(color, colorShaded, 0.5f);
|
color = ColorLerp(color, colorShaded, 0.5f);
|
||||||
}*/
|
}*/
|
||||||
@@ -72,7 +72,8 @@ MeshData GenerateChunkMesh(ChunkRenderData chunkRenderData, Chunk chunk, int chu
|
|||||||
positions.push_back(verts[3]);
|
positions.push_back(verts[3]);
|
||||||
|
|
||||||
normals.push_back(normal);
|
normals.push_back(normal);
|
||||||
colors.push_back(colorShaded);
|
Color clr = GetLightMesher(world, wx-1, wy, wz);
|
||||||
|
colors.push_back(clr);
|
||||||
|
|
||||||
uvs.push_back(corners[0]);
|
uvs.push_back(corners[0]);
|
||||||
uvs.push_back(corners[1]);
|
uvs.push_back(corners[1]);
|
||||||
@@ -111,7 +112,8 @@ MeshData GenerateChunkMesh(ChunkRenderData chunkRenderData, Chunk chunk, int chu
|
|||||||
positions.push_back(verts[3]);
|
positions.push_back(verts[3]);
|
||||||
|
|
||||||
normals.push_back(normal);
|
normals.push_back(normal);
|
||||||
colors.push_back(colorShaded);
|
Color clr = GetLightMesher(world, wx+1, wy, wz);
|
||||||
|
colors.push_back(clr);
|
||||||
|
|
||||||
uvs.push_back(corners[0]);
|
uvs.push_back(corners[0]);
|
||||||
uvs.push_back(corners[1]);
|
uvs.push_back(corners[1]);
|
||||||
@@ -150,7 +152,8 @@ MeshData GenerateChunkMesh(ChunkRenderData chunkRenderData, Chunk chunk, int chu
|
|||||||
positions.push_back(verts[3]);
|
positions.push_back(verts[3]);
|
||||||
|
|
||||||
normals.push_back(normal);
|
normals.push_back(normal);
|
||||||
colors.push_back(colorShaded);
|
Color clr = GetLightMesher(world, wx, wy-1, wz);
|
||||||
|
colors.push_back(clr);
|
||||||
|
|
||||||
uvs.push_back(corners[0]);
|
uvs.push_back(corners[0]);
|
||||||
uvs.push_back(corners[1]);
|
uvs.push_back(corners[1]);
|
||||||
@@ -189,12 +192,8 @@ MeshData GenerateChunkMesh(ChunkRenderData chunkRenderData, Chunk chunk, int chu
|
|||||||
positions.push_back(verts[3]);
|
positions.push_back(verts[3]);
|
||||||
|
|
||||||
normals.push_back(normal);
|
normals.push_back(normal);
|
||||||
if(shaded) {
|
Color clr = GetLightMesher(world, wx, wy+1, wz);
|
||||||
colors.push_back(colorShaded);
|
colors.push_back(clr);
|
||||||
}
|
|
||||||
else {
|
|
||||||
colors.push_back(color);
|
|
||||||
}
|
|
||||||
|
|
||||||
uvs.push_back(corners[0]);
|
uvs.push_back(corners[0]);
|
||||||
uvs.push_back(corners[1]);
|
uvs.push_back(corners[1]);
|
||||||
@@ -233,7 +232,8 @@ MeshData GenerateChunkMesh(ChunkRenderData chunkRenderData, Chunk chunk, int chu
|
|||||||
positions.push_back(verts[3]);
|
positions.push_back(verts[3]);
|
||||||
|
|
||||||
normals.push_back(normal);
|
normals.push_back(normal);
|
||||||
colors.push_back(colorShaded);
|
Color clr = GetLightMesher(world, wx, wy, wz+1);
|
||||||
|
colors.push_back(clr);
|
||||||
|
|
||||||
uvs.push_back(corners[0]);
|
uvs.push_back(corners[0]);
|
||||||
uvs.push_back(corners[1]);
|
uvs.push_back(corners[1]);
|
||||||
@@ -272,7 +272,8 @@ MeshData GenerateChunkMesh(ChunkRenderData chunkRenderData, Chunk chunk, int chu
|
|||||||
positions.push_back(verts[3]);
|
positions.push_back(verts[3]);
|
||||||
|
|
||||||
normals.push_back(normal);
|
normals.push_back(normal);
|
||||||
colors.push_back(colorShaded);
|
Color clr = GetLightMesher(world, wx, wy, wz-1);
|
||||||
|
colors.push_back(clr);
|
||||||
|
|
||||||
uvs.push_back(corners[0]);
|
uvs.push_back(corners[0]);
|
||||||
uvs.push_back(corners[1]);
|
uvs.push_back(corners[1]);
|
||||||
|
|||||||
@@ -65,11 +65,12 @@ static void DrawParticle(Particle particle, Color color)
|
|||||||
|
|
||||||
rlSetTexture(0);
|
rlSetTexture(0);
|
||||||
}
|
}
|
||||||
void ParticlesUpdate(float dt, Chunk world[]) {
|
void ParticlesUpdate(float dt, World &world) {
|
||||||
particles.remove_if([](Particle x) { return x.lifetime > 200; });
|
//particles.remove_if([](Particle x) { return x.lifetime > 0; });
|
||||||
for (Particle &part : particles)
|
particles.remove_if([](Particle x) { return true; });
|
||||||
|
/*for (Particle &part : particles)
|
||||||
{
|
{
|
||||||
part.lifetime++;
|
art.lifetime++;p
|
||||||
if(part.physicsType == Phys_Falling) {
|
if(part.physicsType == Phys_Falling) {
|
||||||
Vector3 velocityTgt = Vector3Clamp(Vector3Add(part.velocity, {0, -dt * 9.8f, 0}), {-30.0f, -30.0f, 0-30.0f}, {30.0f, 30.0f, 30.0f});
|
Vector3 velocityTgt = Vector3Clamp(Vector3Add(part.velocity, {0, -dt * 9.8f, 0}), {-30.0f, -30.0f, 0-30.0f}, {30.0f, 30.0f, 30.0f});
|
||||||
|
|
||||||
@@ -99,7 +100,7 @@ void ParticlesUpdate(float dt, Chunk world[]) {
|
|||||||
part.position = final;
|
part.position = final;
|
||||||
part.velocity = velocityTgt;
|
part.velocity = velocityTgt;
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
void ParticlesDraw() {
|
void ParticlesDraw() {
|
||||||
for (Particle part : particles)
|
for (Particle part : particles)
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ void LoadRecipes() {
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
Recipe _recipe;
|
Recipe _recipe;
|
||||||
const std::string path = dir_entry.path().u8string();
|
const std::string path = dir_entry.path().string();
|
||||||
std::cout << "loading " << path << std::endl;
|
std::cout << "loading " << path << std::endl;
|
||||||
YAML::Node recipe = YAML::LoadFile(path);
|
YAML::Node recipe = YAML::LoadFile(path);
|
||||||
_recipe.requiredStation = recipe["station"].as<std::string>();
|
_recipe.requiredStation = recipe["station"].as<std::string>();
|
||||||
|
|||||||
@@ -1,361 +0,0 @@
|
|||||||
#include "common.hpp"
|
|
||||||
#include <iostream>
|
|
||||||
#include <cstring>
|
|
||||||
#include <list>
|
|
||||||
#include <unordered_set>
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
#include <memory>
|
|
||||||
#include <filesystem>
|
|
||||||
#include <lua.hpp>
|
|
||||||
#include <atomic>
|
|
||||||
|
|
||||||
static std::list<NetPlayer> players;
|
|
||||||
static Chunk world[MAX_WORLD_AREA];
|
|
||||||
static ENetHost* server;
|
|
||||||
|
|
||||||
struct LuaPlugin {
|
|
||||||
std::string name;
|
|
||||||
lua_State* L;
|
|
||||||
bool has_on_connect = false;
|
|
||||||
bool has_on_disconnect = false;
|
|
||||||
bool has_on_packet = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
static std::vector<std::unique_ptr<LuaPlugin>> plugins;
|
|
||||||
|
|
||||||
static int l_server_send(lua_State* L) {
|
|
||||||
int peer_id = (int)luaL_checkinteger(L, 1);
|
|
||||||
size_t len;
|
|
||||||
const char* data = luaL_checklstring(L, 2, &len);
|
|
||||||
for (const NetPlayer &p : players) {
|
|
||||||
if (p.id == peer_id) {
|
|
||||||
SendPacketR(p.peer, (void*)data, (int)len);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int l_server_broadcast(lua_State* L) {
|
|
||||||
size_t len;
|
|
||||||
const char* data = luaL_checklstring(L, 1, &len);
|
|
||||||
if (len > 0) {
|
|
||||||
BroadcastPacketR(server, (void*)data, (int)len);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int l_get_players(lua_State* L) {
|
|
||||||
lua_newtable(L);
|
|
||||||
int idx = 1;
|
|
||||||
for (const NetPlayer &p : players) {
|
|
||||||
lua_pushinteger(L, p.id);
|
|
||||||
lua_rawseti(L, -2, idx++);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void RegisterLuaAPI(lua_State* L) {
|
|
||||||
lua_newtable(L);
|
|
||||||
lua_pushcfunction(L, l_server_send);
|
|
||||||
lua_setfield(L, -2, "send");
|
|
||||||
lua_pushcfunction(L, l_server_broadcast);
|
|
||||||
lua_setfield(L, -2, "broadcast");
|
|
||||||
lua_pushcfunction(L, l_get_players);
|
|
||||||
lua_setfield(L, -2, "get_players");
|
|
||||||
lua_setglobal(L, "server");
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool LoadPluginFile(const std::filesystem::path& path) {
|
|
||||||
auto plugin = std::make_unique<LuaPlugin>();
|
|
||||||
plugin->name = path.filename().string();
|
|
||||||
plugin->L = luaL_newstate();
|
|
||||||
if (!plugin->L) return false;
|
|
||||||
luaL_openlibs(plugin->L);
|
|
||||||
|
|
||||||
RegisterLuaAPI(plugin->L);
|
|
||||||
|
|
||||||
int rc = luaL_dofile(plugin->L, path.string().c_str());
|
|
||||||
if (rc != LUA_OK) {
|
|
||||||
const char* err = lua_tostring(plugin->L, -1);
|
|
||||||
std::cerr << "Error loading plugin " << plugin->name << ": " << (err ? err : "unknown") << std::endl;
|
|
||||||
lua_close(plugin->L);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
lua_getglobal(plugin->L, "on_connect");
|
|
||||||
if (lua_isfunction(plugin->L, -1)) plugin->has_on_connect = true;
|
|
||||||
lua_pop(plugin->L, 1);
|
|
||||||
|
|
||||||
lua_getglobal(plugin->L, "on_disconnect");
|
|
||||||
if (lua_isfunction(plugin->L, -1)) plugin->has_on_disconnect = true;
|
|
||||||
lua_pop(plugin->L, 1);
|
|
||||||
|
|
||||||
lua_getglobal(plugin->L, "on_packet");
|
|
||||||
if (lua_isfunction(plugin->L, -1)) plugin->has_on_packet = true;
|
|
||||||
lua_pop(plugin->L, 1);
|
|
||||||
|
|
||||||
plugins.push_back(std::move(plugin));
|
|
||||||
std::cout << "Loaded plugin: " << path.filename().string() << std::endl;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void LoadPluginsFromFolder(const std::string& folder) {
|
|
||||||
try {
|
|
||||||
if (!std::filesystem::exists(folder)) {
|
|
||||||
std::cout << "Plugins folder does not exist; skipping: " << folder << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (auto& p : std::filesystem::directory_iterator(folder)) {
|
|
||||||
if (!p.is_regular_file()) continue;
|
|
||||||
auto ext = p.path().extension().string();
|
|
||||||
if (ext == ".lua") LoadPluginFile(p.path());
|
|
||||||
}
|
|
||||||
} catch (const std::exception& e) {
|
|
||||||
std::cerr << "Error enumerating plugins: " << e.what() << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void CallPluginOnConnect(int peer_id) {
|
|
||||||
for (auto &pl : plugins) {
|
|
||||||
if (!pl->has_on_connect) continue;
|
|
||||||
lua_State* L = pl->L;
|
|
||||||
lua_getglobal(L, "on_connect");
|
|
||||||
lua_pushinteger(L, peer_id);
|
|
||||||
if (lua_pcall(L, 1, 0, 0) != LUA_OK) {
|
|
||||||
std::cerr << "Plugin " << pl->name << " on_connect error: " << lua_tostring(L, -1) << std::endl;
|
|
||||||
lua_pop(L, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void CallPluginOnDisconnect(int peer_id) {
|
|
||||||
for (auto &pl : plugins) {
|
|
||||||
if (!pl->has_on_disconnect) continue;
|
|
||||||
lua_State* L = pl->L;
|
|
||||||
lua_getglobal(L, "on_disconnect");
|
|
||||||
lua_pushinteger(L, peer_id);
|
|
||||||
if (lua_pcall(L, 1, 0, 0) != LUA_OK) {
|
|
||||||
std::cerr << "Plugin " << pl->name << " on_disconnect error: " << lua_tostring(L, -1) << std::endl;
|
|
||||||
lua_pop(L, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void CallPluginOnPacket(int peer_id, const unsigned char* data, int len) {
|
|
||||||
for (auto &pl : plugins) {
|
|
||||||
if (!pl->has_on_packet) continue;
|
|
||||||
lua_State* L = pl->L;
|
|
||||||
lua_getglobal(L, "on_packet");
|
|
||||||
lua_pushinteger(L, peer_id);
|
|
||||||
lua_pushlstring(L, (const char*)data, len);
|
|
||||||
if (lua_pcall(L, 2, 0, 0) != LUA_OK) {
|
|
||||||
std::cerr << "Plugin " << pl->name << " on_packet error: " << lua_tostring(L, -1) << std::endl;
|
|
||||||
lua_pop(L, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int PeerToPlayerID(ENetPeer* peer) {
|
|
||||||
for (const NetPlayer &p : players) {
|
|
||||||
if (p.addr == peer->address.host && p.port == peer->address.port) return p.id;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool CompareAddress(NetPlayer plr, ENetPeer* peer) {
|
|
||||||
return plr.addr == peer->address.host && plr.port == (int)(peer->address.port);
|
|
||||||
}
|
|
||||||
static void ParseData(ENetPacket* packet, ENetPeer* peer) {
|
|
||||||
int len = packet->dataLength;
|
|
||||||
unsigned char data[len];
|
|
||||||
memcpy(&data, packet->data, len);
|
|
||||||
|
|
||||||
int pid = PeerToPlayerID(peer);
|
|
||||||
if (pid >= 0) CallPluginOnPacket(pid, data, len);
|
|
||||||
|
|
||||||
unsigned char response[16];
|
|
||||||
switch (data[0])
|
|
||||||
{
|
|
||||||
case NET_ARG_REQWORLD:
|
|
||||||
puts("Client requested world; sending");
|
|
||||||
for (int i = 0; i < 256; i++)
|
|
||||||
{
|
|
||||||
unsigned char responseChunk[2+CHUNK_DATA_SIZE+CHUNK_SIZE*CHUNK_SIZE];
|
|
||||||
responseChunk[0] = NET_ARG_CHUNKF;
|
|
||||||
responseChunk[1] = i;
|
|
||||||
|
|
||||||
memcpy(responseChunk+2, world[i].blocks, CHUNK_DATA_SIZE);
|
|
||||||
memcpy(responseChunk+2+CHUNK_DATA_SIZE, world[i].highestBlock, CHUNK_SIZE*CHUNK_SIZE);
|
|
||||||
SendPacket(peer, responseChunk, sizeof(responseChunk));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case NET_ARG_PLAYERMOVE:
|
|
||||||
response[0] = NET_ARG_ECHOMOVE;
|
|
||||||
for (NetPlayer &plr : players)
|
|
||||||
{
|
|
||||||
if(CompareAddress(plr, peer)) {
|
|
||||||
float x = DeserializeFloat(data[1], data[2]);
|
|
||||||
float y = DeserializeFloat(data[3], data[4]);
|
|
||||||
float z = DeserializeFloat(data[5], data[6]);
|
|
||||||
plr.x = x;
|
|
||||||
plr.y = y;
|
|
||||||
plr.z = z;
|
|
||||||
response[1] = plr.id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
response[2] = data[1]; response[3] = data[2];
|
|
||||||
response[4] = data[3]; response[5] = data[4];
|
|
||||||
response[6] = data[5]; response[7] = data[6];
|
|
||||||
response[8] = data[7];
|
|
||||||
BroadcastPacketR(server, response, 9);
|
|
||||||
break;
|
|
||||||
case NET_ARG_PLAYERYAW:
|
|
||||||
response[0] = NET_ARG_ECHOYAW;
|
|
||||||
for (NetPlayer &plr : players)
|
|
||||||
{
|
|
||||||
if(CompareAddress(plr, peer)) {
|
|
||||||
response[1] = plr.id;
|
|
||||||
plr.yaw = data[1];
|
|
||||||
response[2] = plr.yaw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BroadcastPacketR(server, response, 3);
|
|
||||||
break;
|
|
||||||
case NET_ARG_REQPLAYERS:
|
|
||||||
puts("Client requested players; sending");
|
|
||||||
|
|
||||||
for (NetPlayer &plr : players)
|
|
||||||
{
|
|
||||||
unsigned char responseP[9];
|
|
||||||
responseP[0] = NET_ARG_PLRREG;
|
|
||||||
if(!CompareAddress(plr, peer)) {
|
|
||||||
SerializeFloat2Data(plr.x, responseP, 2);
|
|
||||||
SerializeFloat2Data(plr.y, responseP, 4);
|
|
||||||
SerializeFloat2Data(plr.z, responseP, 6);
|
|
||||||
responseP[1] = plr.id;
|
|
||||||
responseP[8] = plr.yaw;
|
|
||||||
SendPacketR(peer, responseP, 9);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case NET_ARG_BLOCKDELTA:
|
|
||||||
response[0] = NET_ARG_BLOCK;
|
|
||||||
for (NetPlayer &plr : players)
|
|
||||||
{
|
|
||||||
if(CompareAddress(plr, peer)) {
|
|
||||||
unsigned char responseB[6];
|
|
||||||
responseB[0] = NET_ARG_BLOCK;
|
|
||||||
responseB[1] = plr.id;
|
|
||||||
responseB[2] = data[1];
|
|
||||||
responseB[3] = data[2];
|
|
||||||
responseB[4] = data[3];
|
|
||||||
responseB[5] = data[4];
|
|
||||||
SetBlock(world, data[1], data[2], data[3], data[4]);
|
|
||||||
BroadcastPacketR(server, responseB, 6);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int FirstFreeID(const std::list<NetPlayer>& players) {
|
|
||||||
std::unordered_set<int> used;
|
|
||||||
used.reserve(players.size());
|
|
||||||
for (const auto &p : players) used.insert(p.id);
|
|
||||||
|
|
||||||
int id = 0;
|
|
||||||
while (used.find(id) != used.end()) ++id;
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
static bool serverStarted = false;
|
|
||||||
void StartInternalServer(std::atomic_bool& started) {
|
|
||||||
int worldType = 0;
|
|
||||||
InitWorldgen(worldType);
|
|
||||||
std::cout << "Building chunks..." << std::endl;
|
|
||||||
Chunk chunk = GenerateChunk(8, 8);
|
|
||||||
for (int x = 0; x < MAX_WORLD_SIZE; x++)
|
|
||||||
{
|
|
||||||
for (int y = 0; y < MAX_WORLD_SIZE; y++)
|
|
||||||
{
|
|
||||||
memcpy(&world[x + y * MAX_WORLD_SIZE], &chunk, sizeof(Chunk));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LoadPluginsFromFolder("plugins");
|
|
||||||
std::cout << "Starting server..." << std::endl;
|
|
||||||
server = StartServer();
|
|
||||||
std::cout << "Serving on port: " << PORT << std::endl;
|
|
||||||
serverStarted = true;
|
|
||||||
started = true;
|
|
||||||
}
|
|
||||||
void ServerNetworkUpdate() {
|
|
||||||
if(serverStarted) {
|
|
||||||
ENetEvent event;
|
|
||||||
while(enet_host_service (server, &event, 0) > 0)
|
|
||||||
{
|
|
||||||
switch (event.type)
|
|
||||||
{
|
|
||||||
int id;
|
|
||||||
char response[2];
|
|
||||||
case ENET_EVENT_TYPE_CONNECT:
|
|
||||||
printf ("A new client connected from %x:%u.\n",
|
|
||||||
event.peer -> address.host,
|
|
||||||
event.peer -> address.port);
|
|
||||||
response[0] = NET_ARG_PLRID;
|
|
||||||
id = FirstFreeID(players);
|
|
||||||
response[1] = id;
|
|
||||||
SendPacketR(event.peer, response, sizeof(response));
|
|
||||||
{
|
|
||||||
NetPlayer netPlayer;
|
|
||||||
netPlayer.id = id;
|
|
||||||
netPlayer.addr = event.peer->address.host;
|
|
||||||
netPlayer.port = (int)(event.peer->address.port);
|
|
||||||
netPlayer.peer = event.peer;
|
|
||||||
players.push_back(netPlayer);
|
|
||||||
|
|
||||||
response[0] = NET_ARG_PLRCON;
|
|
||||||
response[1] = netPlayer.id;
|
|
||||||
BroadcastPacketR(server, response, sizeof(response));
|
|
||||||
}
|
|
||||||
CallPluginOnConnect(id);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ENET_EVENT_TYPE_RECEIVE:
|
|
||||||
ParseData(event.packet, event.peer);
|
|
||||||
enet_packet_destroy (event.packet);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ENET_EVENT_TYPE_DISCONNECT:
|
|
||||||
printf ("%s disconnected.\n", event.peer -> data);
|
|
||||||
event.peer -> data = NULL;
|
|
||||||
for (auto it = players.begin(); it != players.end(); ++it) {
|
|
||||||
if (CompareAddress(*it, event.peer)) {
|
|
||||||
char responseD[2];
|
|
||||||
responseD[0] = NET_ARG_PLRDCN;
|
|
||||||
responseD[1] = it->id;
|
|
||||||
BroadcastPacketR(server, (unsigned char*)responseD, sizeof(responseD));
|
|
||||||
|
|
||||||
int disconnected_id = it->id;
|
|
||||||
it = players.erase(it);
|
|
||||||
|
|
||||||
// notify plugins
|
|
||||||
CallPluginOnDisconnect(disconnected_id);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void StopInternalServer() {
|
|
||||||
for (auto &pl : plugins) {
|
|
||||||
lua_close(pl->L);
|
|
||||||
}
|
|
||||||
|
|
||||||
enet_host_destroy(server);
|
|
||||||
}
|
|
||||||
+55
-2
@@ -87,7 +87,7 @@ void DrawCubeTexture(Texture2D texture, Vector3 position, float width, float hei
|
|||||||
|
|
||||||
rlSetTexture(0);
|
rlSetTexture(0);
|
||||||
}
|
}
|
||||||
void DrawCubeBlock(Texture2D texture, Vector3 position, float width, float height, float length, BlockDef def)
|
void DrawCubeBlock(Texture2D texture, Vector3 position, float width, float height, float length, BlockDef def, Color tint)
|
||||||
{
|
{
|
||||||
float x = position.x;
|
float x = position.x;
|
||||||
float y = position.y;
|
float y = position.y;
|
||||||
@@ -104,7 +104,7 @@ void DrawCubeBlock(Texture2D texture, Vector3 position, float width, float heigh
|
|||||||
UVCorners right = GetUVTex(def.textureSide);
|
UVCorners right = GetUVTex(def.textureSide);
|
||||||
rlSetTexture(texture.id);
|
rlSetTexture(texture.id);
|
||||||
rlBegin(RL_QUADS);
|
rlBegin(RL_QUADS);
|
||||||
rlColor4ub(255, 255, 255, 255);
|
rlColor4ub(tint.r, tint.g, tint.b, 255);
|
||||||
// Front Face
|
// Front Face
|
||||||
rlNormal3f(0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer
|
rlNormal3f(0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer
|
||||||
rlTexCoord2f(front.corner0.x, front.corner0.y); rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom Left Of The Texture and Quad
|
rlTexCoord2f(front.corner0.x, front.corner0.y); rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom Left Of The Texture and Quad
|
||||||
@@ -254,3 +254,56 @@ void DrawText3D(Font font, const char *text, Vector3 position, float fontSize, f
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
RenderTexture2D LoadRenderTextureDepthTex(int width, int height)
|
||||||
|
{
|
||||||
|
RenderTexture2D target = { 0 };
|
||||||
|
|
||||||
|
target.id = rlLoadFramebuffer(); // Load an empty framebuffer
|
||||||
|
|
||||||
|
if (target.id > 0)
|
||||||
|
{
|
||||||
|
rlEnableFramebuffer(target.id);
|
||||||
|
|
||||||
|
// Create color texture (default to RGBA)
|
||||||
|
target.texture.id = rlLoadTexture(0, width, height, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, 1);
|
||||||
|
target.texture.width = width;
|
||||||
|
target.texture.height = height;
|
||||||
|
target.texture.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
|
||||||
|
target.texture.mipmaps = 1;
|
||||||
|
|
||||||
|
// Create depth texture buffer (instead of raylib default renderbuffer)
|
||||||
|
target.depth.id = rlLoadTextureDepth(width, height, false);
|
||||||
|
target.depth.width = width;
|
||||||
|
target.depth.height = height;
|
||||||
|
target.depth.format = 19; // DEPTH_COMPONENT_24BIT: Not defined in raylib
|
||||||
|
target.depth.mipmaps = 1;
|
||||||
|
|
||||||
|
// Attach color texture and depth texture to FBO
|
||||||
|
rlFramebufferAttach(target.id, target.texture.id, RL_ATTACHMENT_COLOR_CHANNEL0, RL_ATTACHMENT_TEXTURE2D, 0);
|
||||||
|
rlFramebufferAttach(target.id, target.depth.id, RL_ATTACHMENT_DEPTH, RL_ATTACHMENT_TEXTURE2D, 0);
|
||||||
|
|
||||||
|
// Check if fbo is complete with attachments (valid)
|
||||||
|
if (rlFramebufferComplete(target.id)) TRACELOG(LOG_INFO, "FBO: [ID %i] Framebuffer object created successfully", target.id);
|
||||||
|
|
||||||
|
rlDisableFramebuffer();
|
||||||
|
}
|
||||||
|
else TRACELOG(LOG_WARNING, "FBO: Framebuffer object can not be created");
|
||||||
|
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unload render texture from GPU memory (VRAM)
|
||||||
|
void UnloadRenderTextureDepthTex(RenderTexture2D target)
|
||||||
|
{
|
||||||
|
if (target.id > 0)
|
||||||
|
{
|
||||||
|
// Color texture attached to FBO is deleted
|
||||||
|
rlUnloadTexture(target.texture.id);
|
||||||
|
rlUnloadTexture(target.depth.id);
|
||||||
|
|
||||||
|
// NOTE: Depth texture is automatically
|
||||||
|
// queried and deleted before deleting framebuffer
|
||||||
|
rlUnloadFramebuffer(target.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
+22
-6
@@ -1,10 +1,10 @@
|
|||||||
|
#include <functional>
|
||||||
#if INTERFACE
|
#if INTERFACE
|
||||||
|
|
||||||
#ifdef Escape
|
#ifdef Escape
|
||||||
#undef Escape
|
#undef Escape
|
||||||
#endif
|
#endif
|
||||||
#include "glfw_keycodes_to_string.h"
|
#include "glfw_keycodes_to_string.h"
|
||||||
#include "../PerlinNoise.hpp"
|
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#include "external/fix_win32_compatibility.h"
|
#include "external/fix_win32_compatibility.h"
|
||||||
@@ -98,7 +98,7 @@
|
|||||||
#define GAME_VERSION_INT 0
|
#define GAME_VERSION_INT 0
|
||||||
|
|
||||||
#define DEFAULT_FONT_SIZE 16
|
#define DEFAULT_FONT_SIZE 16
|
||||||
#define TPS 30.0
|
#define TPS 30
|
||||||
#define TPS_DIV 1.0 / TPS
|
#define TPS_DIV 1.0 / TPS
|
||||||
//Rendering
|
//Rendering
|
||||||
#define RENDER_DISTANCE 16
|
#define RENDER_DISTANCE 16
|
||||||
@@ -114,6 +114,8 @@
|
|||||||
#define INVENTORY_HEIGHT 6
|
#define INVENTORY_HEIGHT 6
|
||||||
#define INVENTORY_SIZE INVENTORY_WIDTH*INVENTORY_HEIGHT
|
#define INVENTORY_SIZE INVENTORY_WIDTH*INVENTORY_HEIGHT
|
||||||
|
|
||||||
|
#define WORLD_TIME_SECONDS (24*60)
|
||||||
|
#define WORLD_TIME_TICKS WORLD_TIME_SECONDS*TPS
|
||||||
enum BlockType {
|
enum BlockType {
|
||||||
B_Wood,
|
B_Wood,
|
||||||
B_Stone,
|
B_Stone,
|
||||||
@@ -179,7 +181,7 @@ struct Chunk {
|
|||||||
uint16_t opaqueMask[CHUNK_DATA_SIZE/16];
|
uint16_t opaqueMask[CHUNK_DATA_SIZE/16];
|
||||||
uint16_t airMask[CHUNK_DATA_SIZE/16];
|
uint16_t airMask[CHUNK_DATA_SIZE/16];
|
||||||
uint8_t highestBlock[CHUNK_SIZE*CHUNK_SIZE];
|
uint8_t highestBlock[CHUNK_SIZE*CHUNK_SIZE];
|
||||||
|
uint16_t light[CHUNK_DATA_SIZE];
|
||||||
};
|
};
|
||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
struct ChunkRenderData {
|
struct ChunkRenderData {
|
||||||
@@ -220,10 +222,20 @@ struct Quad2D {
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
struct Vector3I {
|
struct Vector3I {
|
||||||
int x;
|
int x, y, z;
|
||||||
int y;
|
bool operator==(const Vector3I& other) const {
|
||||||
int z;
|
return (x == other.x && y == other.y && z == other.z);
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
struct Vector3IHash {
|
||||||
|
size_t operator()(const Vector3I& p) const noexcept {
|
||||||
|
size_t h1 = std::hash<int>{}(p.x);
|
||||||
|
size_t h2 = std::hash<int>{}(p.y);
|
||||||
|
size_t h3 = std::hash<int>{}(p.z);
|
||||||
|
return h1 ^ (h2 << 1) ^ (h3 << 2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct Entity {
|
struct Entity {
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
uint8_t id;
|
uint8_t id;
|
||||||
@@ -307,3 +319,7 @@ struct Particle {
|
|||||||
int lifetime;
|
int lifetime;
|
||||||
int data[8];
|
int data[8];
|
||||||
};
|
};
|
||||||
|
struct World
|
||||||
|
{
|
||||||
|
Chunk chunks[MAX_WORLD_AREA];
|
||||||
|
};
|
||||||
|
|||||||
+1
-1
Submodule src/libraries/enet updated: 8be2368a80...5a9c537fd4
+1
-1
Submodule src/libraries/raylib updated: cf9f27db54...db0870f31f
+1
-1
Submodule src/libraries/yaml-cpp updated: 4861d04953...2decf96e91
+228
-88
@@ -15,8 +15,7 @@
|
|||||||
#include <list>
|
#include <list>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <thread>
|
#include <map>
|
||||||
#include <atomic>
|
|
||||||
#define MAX_RAY_DISTANCE 8.0f
|
#define MAX_RAY_DISTANCE 8.0f
|
||||||
struct MessageData {
|
struct MessageData {
|
||||||
std::string message;
|
std::string message;
|
||||||
@@ -59,15 +58,21 @@ static Sound wood_place;
|
|||||||
static Sound stone_place;
|
static Sound stone_place;
|
||||||
static Sound dirt_place;
|
static Sound dirt_place;
|
||||||
static Sound grass_place;
|
static Sound grass_place;
|
||||||
bool tick_entities;
|
static Texture2D sun;
|
||||||
|
static Texture2D moon;
|
||||||
|
static Texture2D stars;
|
||||||
|
bool tick_entities = true;
|
||||||
const std::string LocaleGet(std::string loc);
|
const std::string LocaleGet(std::string loc);
|
||||||
bool InputGetKeyDown(const std::string name);
|
bool InputGetKeyDown(const std::string name);
|
||||||
bool InputGetKeyPressed(const std::string name);
|
bool InputGetKeyPressed(const std::string name);
|
||||||
|
|
||||||
extern std::list<Entity> entities;
|
extern std::list<Entity> entities;
|
||||||
std::bitset<WORLD_SIZE_BLOCKS*WORLD_SIZE_BLOCKS/8/8> clouds;
|
std::bitset<WORLD_SIZE_BLOCKS*WORLD_SIZE_BLOCKS/8/8> clouds;
|
||||||
std::queue<Vector3I> tickedBlocks;
|
std::queue<Vector3I> tickedBlocks;
|
||||||
struct MeshUnit {
|
struct MeshUnit {
|
||||||
Model model;
|
Model model;
|
||||||
|
Model modelTransparent;
|
||||||
|
Model modelWater;
|
||||||
int vertices;
|
int vertices;
|
||||||
};
|
};
|
||||||
struct ProfilerPart {
|
struct ProfilerPart {
|
||||||
@@ -91,10 +96,19 @@ static Vector3 CameraForwardFromYawPitch(float yaw, float pitch)
|
|||||||
f.z = cosf(pitch) * sinf(yaw);
|
f.z = cosf(pitch) * sinf(yaw);
|
||||||
return Vector3Normalize(f);
|
return Vector3Normalize(f);
|
||||||
}
|
}
|
||||||
Chunk world[MAX_WORLD_AREA];
|
World world;
|
||||||
static MeshUnit rendering[MAX_WORLD_AREA];
|
static MeshUnit rendering[MAX_WORLD_AREA];
|
||||||
static MeshUnit renderingT[MAX_WORLD_AREA];
|
|
||||||
|
|
||||||
|
std::map<std::string, Shader> loadedShaders;
|
||||||
|
static void LoadNewShader(std::string name) {
|
||||||
|
Shader temp = LoadShader(
|
||||||
|
TextFormat("%s/shaders/%s.vs", PATH_APPEND, name.c_str()),
|
||||||
|
TextFormat("%s/shaders/%s.fs", PATH_APPEND, name.c_str())
|
||||||
|
);
|
||||||
|
temp.locs[SHADER_LOC_MATRIX_MODEL] = GetShaderLocation(temp, "matModel");
|
||||||
|
temp.locs[SHADER_LOC_VECTOR_VIEW] = GetShaderLocation(temp, "viewPos");
|
||||||
|
loadedShaders[name] = temp;
|
||||||
|
}
|
||||||
GameState state = GAME_STATE_MAINMENU;
|
GameState state = GAME_STATE_MAINMENU;
|
||||||
bool loaderParam_remeshOnly = false;
|
bool loaderParam_remeshOnly = false;
|
||||||
int worldCreationProgress = 0;
|
int worldCreationProgress = 0;
|
||||||
@@ -265,35 +279,48 @@ static void ResolveCollisions(float dt)
|
|||||||
|
|
||||||
bool loadedChunks[MAX_WORLD_AREA] = { false };
|
bool loadedChunks[MAX_WORLD_AREA] = { false };
|
||||||
bool dirtyChunks[MAX_WORLD_AREA] = { false };
|
bool dirtyChunks[MAX_WORLD_AREA] = { false };
|
||||||
|
const Vector3I dirs2d[4] = {
|
||||||
|
(Vector3I){ 1, 0, 0},
|
||||||
|
(Vector3I){ 0, 0, 1},
|
||||||
|
(Vector3I){-1, 0, 0},
|
||||||
|
(Vector3I){ 0, 0, -1},
|
||||||
|
};
|
||||||
void Debug_EndMeasure(const std::string &stuff);
|
void Debug_EndMeasure(const std::string &stuff);
|
||||||
void Debug_EndMeasureLoops(const std::string &stuff, int loops);
|
void Debug_EndMeasureLoops(const std::string &stuff, int loops);
|
||||||
static void RemeshChunk(int x, int y) {
|
static void RemeshChunk(int x, int y) {
|
||||||
int idx = x + y * MAX_WORLD_SIZE;
|
int idx = GetIndexWorld(x, y);
|
||||||
if(loadedChunks[idx]) {
|
if(loadedChunks[idx]) {
|
||||||
UnloadModel(renderingT[idx].model);
|
|
||||||
UnloadModel(rendering[idx].model);
|
UnloadModel(rendering[idx].model);
|
||||||
|
UnloadModel(rendering[idx].modelTransparent);
|
||||||
|
UnloadModel(rendering[idx].modelWater);
|
||||||
}
|
}
|
||||||
Chunk chunk = world[idx];
|
Chunk &chunk = world.chunks[idx];
|
||||||
RebuildOpaqueMask(&chunk);
|
RebuildOpaqueMask(chunk);
|
||||||
|
RebuildLighting(world, chunk.x, chunk.z);
|
||||||
|
|
||||||
MeshData renderDataOpq = GenerateChunkMesh(GenerateCRDOpaque(chunk, world), chunk, x, y, 0xFF);
|
|
||||||
MeshData renderDataTsl = GenerateChunkMesh(GenerateCRDTranslucent(chunk, world), chunk, x, y, 0xFF);
|
|
||||||
|
|
||||||
Model model = LoadModelFromMesh(GenChunkMesh(renderDataOpq));
|
MeshData renderDataOpq = GenerateChunkMesh(world, GenerateCRDOpaque(chunk, world), chunk, x, y, 0xFF);
|
||||||
model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = terrain;
|
Model model0 = LoadModelFromMesh(GenChunkMesh(renderDataOpq));
|
||||||
|
model0.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = terrain;
|
||||||
|
model0.materials[0].shader = loadedShaders["terrain"];
|
||||||
MeshUnit munit0;
|
MeshUnit munit0;
|
||||||
munit0.model = model;
|
munit0.model = model0;
|
||||||
munit0.vertices += renderDataOpq.vertexCount;
|
munit0.vertices += renderDataOpq.vertexCount;
|
||||||
rendering[idx] = munit0;
|
|
||||||
model = LoadModelFromMesh(GenChunkMesh(renderDataTsl));
|
|
||||||
model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = terrain;
|
|
||||||
MeshUnit munit1;
|
|
||||||
munit1.model = model;
|
|
||||||
munit1.vertices += renderDataTsl.vertexCount;
|
|
||||||
renderingT[idx] = munit1;
|
|
||||||
loadedChunks[idx] = true;
|
|
||||||
|
|
||||||
|
MeshData renderDataTsl = GenerateChunkMesh(world, GenerateCRDTranslucent(chunk, world), chunk, x, y, 0xFF);
|
||||||
|
Model model1 = LoadModelFromMesh(GenChunkMesh(renderDataTsl));
|
||||||
|
model1.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = terrain;
|
||||||
|
model1.materials[0].shader = loadedShaders["terrain"];
|
||||||
|
munit0.modelTransparent = model1;
|
||||||
|
|
||||||
|
MeshData renderDataWtr = GenerateChunkMesh(world, GenerateCRDWater(chunk, world), chunk, x, y, 0xFF);
|
||||||
|
Model model2 = LoadModelFromMesh(GenChunkMesh(renderDataWtr));
|
||||||
|
model2.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = terrain;
|
||||||
|
model2.materials[0].shader = loadedShaders["water"];
|
||||||
|
munit0.modelWater = model2;
|
||||||
|
|
||||||
|
loadedChunks[idx] = true;
|
||||||
|
rendering[idx] = munit0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool RaycastBlock(Vector3 origin, Vector3 dir, float maxDist, Vector3 *outBlock, Vector3 *outPrev)
|
static bool RaycastBlock(Vector3 origin, Vector3 dir, float maxDist, Vector3 *outBlock, Vector3 *outPrev)
|
||||||
@@ -387,7 +414,7 @@ void PlayRandomMusic() {
|
|||||||
PlayMusicStream(currentMusic);
|
PlayMusicStream(currentMusic);
|
||||||
}
|
}
|
||||||
static int _blockPlacedC = 0;
|
static int _blockPlacedC = 0;
|
||||||
void SetBlockNetwork(Chunk world[], int bx, int by, int bz, int t) {
|
void SetBlockNetwork(World &world, int bx, int by, int bz, int t) {
|
||||||
float pitch = GetRandomValue(-100, 100) / 100.0f * 0.25f + 1.0f;
|
float pitch = GetRandomValue(-100, 100) / 100.0f * 0.25f + 1.0f;
|
||||||
int sound = B_Stone;
|
int sound = B_Stone;
|
||||||
tickedBlocks.push({bx, by, bz});
|
tickedBlocks.push({bx, by, bz});
|
||||||
@@ -398,11 +425,11 @@ void SetBlockNetwork(Chunk world[], int bx, int by, int bz, int t) {
|
|||||||
tickedBlocks.push({bx, by, bz-1});
|
tickedBlocks.push({bx, by, bz-1});
|
||||||
tickedBlocks.push({bx, by, bz+1});
|
tickedBlocks.push({bx, by, bz+1});
|
||||||
if(t != 0) {
|
if(t != 0) {
|
||||||
sound = BLOCKS[t].type;
|
sound = GetBlockDefinition(t).type;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int id = GetBlock(world, bx, by, bz);
|
int id = GetBlock(world, bx, by, bz);
|
||||||
BlockDef block = BLOCKS[id];
|
BlockDef block = GetBlockDefinition(id);
|
||||||
if(id != 0) {
|
if(id != 0) {
|
||||||
sound = block.type;
|
sound = block.type;
|
||||||
for (int x = 0; x < 4; x++)
|
for (int x = 0; x < 4; x++)
|
||||||
@@ -451,7 +478,7 @@ void SetBlockNetwork(Chunk world[], int bx, int by, int bz, int t) {
|
|||||||
data[2] = (uint8_t)by;
|
data[2] = (uint8_t)by;
|
||||||
data[3] = (uint8_t)bz;
|
data[3] = (uint8_t)bz;
|
||||||
data[4] = (uint8_t)t;
|
data[4] = (uint8_t)t;
|
||||||
SendPacketR(peer, data, sizeof(data));
|
SendPacketR(peer, data, 5);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
SetBlock(world, bx, by, bz, t);
|
SetBlock(world, bx, by, bz, t);
|
||||||
@@ -482,9 +509,9 @@ static void TickAvailableBlocks() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::atomic_bool serverStarted;
|
|
||||||
int TryConnect(const char* hostname) {
|
int TryConnect(const char* hostname) {
|
||||||
client = StartClient();
|
/*client = StartClient();
|
||||||
|
|
||||||
if(client == NULL)
|
if(client == NULL)
|
||||||
{
|
{
|
||||||
@@ -499,7 +526,7 @@ int TryConnect(const char* hostname) {
|
|||||||
int s = enet_address_set_host (& address, hostname);
|
int s = enet_address_set_host (& address, hostname);
|
||||||
address.port = PORT;
|
address.port = PORT;
|
||||||
|
|
||||||
peer = enet_host_connect(client, &address, 1, 0);
|
peer = enet_host_connect(client, &address, 1);
|
||||||
|
|
||||||
if (peer == NULL)
|
if (peer == NULL)
|
||||||
{
|
{
|
||||||
@@ -514,7 +541,7 @@ int TryConnect(const char* hostname) {
|
|||||||
puts ("Connection succeeded.");
|
puts ("Connection succeeded.");
|
||||||
char data[1];
|
char data[1];
|
||||||
data[0] = NET_ARG_REQWORLD;
|
data[0] = NET_ARG_REQWORLD;
|
||||||
SendPacketR(peer, data, 1);
|
SendPacketR(peer, data, 1); // Tell the server to send all chunks
|
||||||
online = true;
|
online = true;
|
||||||
state = GAME_STATE_LOADING;
|
state = GAME_STATE_LOADING;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -524,30 +551,9 @@ int TryConnect(const char* hostname) {
|
|||||||
enet_peer_reset (peer);
|
enet_peer_reset (peer);
|
||||||
|
|
||||||
return NET_ERROR_FAILED;
|
return NET_ERROR_FAILED;
|
||||||
}
|
}*/
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//std::thread serverThread;
|
|
||||||
std::atomic_bool stop_server = false;
|
|
||||||
void StartInternalServer(std::atomic_bool& started);
|
|
||||||
/*void ServerThread(std::atomic_bool& started) {
|
|
||||||
StartInternalServer(started);
|
|
||||||
stop_server = false;
|
|
||||||
while(true) {
|
|
||||||
if (stop_server)
|
|
||||||
return;
|
|
||||||
ServerNetworkUpdate();
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
/*void InitSingleplayer() {
|
|
||||||
online = true;
|
|
||||||
serverThread = std::thread(ServerThread, std::ref(serverStarted));
|
|
||||||
int result = TryConnect("localhost");
|
|
||||||
if(result == NET_ERROR_FAILED) {
|
|
||||||
state = GAME_STATE_MAINMENU;
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
std::vector<MessageData> messages;
|
std::vector<MessageData> messages;
|
||||||
bool survival = false;
|
bool survival = false;
|
||||||
bool chatOpen = false;
|
bool chatOpen = false;
|
||||||
@@ -559,6 +565,54 @@ void TakeDamage(float amount) {
|
|||||||
int currentlyTickedChunk = 0;
|
int currentlyTickedChunk = 0;
|
||||||
Vector3 highlightBlock = {-1, -1, -1};
|
Vector3 highlightBlock = {-1, -1, -1};
|
||||||
|
|
||||||
|
float GetDayProgression() {
|
||||||
|
return (float)(worldTime % (unsigned long long)(WORLD_TIME_TICKS)) / (float)(WORLD_TIME_TICKS);
|
||||||
|
}
|
||||||
|
Color GetSkyColor() {
|
||||||
|
float progression = GetDayProgression();
|
||||||
|
Color night = ColorBrightness(BLUE, -0.9f);
|
||||||
|
Color sunrise = ColorBrightness(ORANGE, -0.25f);
|
||||||
|
Color noon = BLUE;
|
||||||
|
if(progression > 0.5f) {
|
||||||
|
progression = 1 - progression;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(progression < 0.20f) {
|
||||||
|
return night;
|
||||||
|
}
|
||||||
|
if(progression>=0.20f&&progression<0.30f) {
|
||||||
|
return ColorLerp(night, sunrise, (progression - 0.2f) / 0.1f);
|
||||||
|
}
|
||||||
|
if(progression>=0.30f&&progression<0.35f) {
|
||||||
|
return ColorLerp(sunrise, noon, (progression - 0.3f) / 0.05f);
|
||||||
|
}
|
||||||
|
return noon;
|
||||||
|
}
|
||||||
|
Color GetSunlightColor() {
|
||||||
|
float progression = GetDayProgression();
|
||||||
|
Color night = ColorBrightness(BLUE, -0.9f);
|
||||||
|
Color sunrise = ColorBrightness(ORANGE, -0.25f);
|
||||||
|
Color noon = WHITE;
|
||||||
|
if(progression > 0.5f) {
|
||||||
|
progression = 1 - progression;
|
||||||
|
}
|
||||||
|
if(progression < 0.20f) {
|
||||||
|
return night;
|
||||||
|
}
|
||||||
|
if(progression>=0.20f&&progression<0.30f) {
|
||||||
|
return ColorLerp(night, sunrise, (progression - 0.2f) / 0.1f);
|
||||||
|
}
|
||||||
|
if(progression>=0.30f&&progression<0.35f) {
|
||||||
|
return ColorLerp(sunrise, noon, (progression - 0.3f) / 0.05f);
|
||||||
|
}
|
||||||
|
return noon;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Vector3 GetSunDirection() {
|
||||||
|
float time = GetDayProgression() - 0.25f;
|
||||||
|
return Vector3Normalize({-sinf(time*PI*2), -sinf(time*PI*2)/2.0f, -cosf(time*PI*2)});
|
||||||
|
}
|
||||||
|
|
||||||
static void GameUpdate(Camera camera, float &time) {
|
static void GameUpdate(Camera camera, float &time) {
|
||||||
if (player_position.y < 0 ||
|
if (player_position.y < 0 ||
|
||||||
player_position.x < 0 ||
|
player_position.x < 0 ||
|
||||||
@@ -701,6 +755,9 @@ static void GameUpdate(Camera camera, float &time) {
|
|||||||
if(IsKeyPressed(KEY_F10)) {
|
if(IsKeyPressed(KEY_F10)) {
|
||||||
tick_entities = !tick_entities;
|
tick_entities = !tick_entities;
|
||||||
}
|
}
|
||||||
|
if(IsKeyDown(KEY_F11)) {
|
||||||
|
worldTime+=8;
|
||||||
|
}
|
||||||
if(IsKeyPressed(KEY_B) && !online) {
|
if(IsKeyPressed(KEY_B) && !online) {
|
||||||
Entity temp = NewEntity();
|
Entity temp = NewEntity();
|
||||||
temp.type = 3;
|
temp.type = 3;
|
||||||
@@ -740,7 +797,7 @@ static void GameUpdate(Camera camera, float &time) {
|
|||||||
tier = selected_item->tier;
|
tier = selected_item->tier;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BlockDef block = BLOCKS[GetBlock(world, bx, by, bz)];
|
BlockDef block = GetBlockDefinition(GetBlock(world, bx, by, bz));
|
||||||
float hardnessMultiplier = block.hardness / 4.0f;
|
float hardnessMultiplier = block.hardness / 4.0f;
|
||||||
if(player_break_parts_time >= 0.05f) {
|
if(player_break_parts_time >= 0.05f) {
|
||||||
Vector3 v = {0, 1, 0};
|
Vector3 v = {0, 1, 0};
|
||||||
@@ -887,7 +944,7 @@ static void GameUpdate(Camera camera, float &time) {
|
|||||||
}
|
}
|
||||||
double PROFCOUNT = GetTime();
|
double PROFCOUNT = GetTime();
|
||||||
if (bestIdx != -1) {
|
if (bestIdx != -1) {
|
||||||
RebuildOpaqueMask(&world[bestIdx]);
|
RebuildOpaqueMask(world.chunks[bestIdx]);
|
||||||
int bx, by;
|
int bx, by;
|
||||||
GetXZFromIndex(bestIdx, &bx, &by);
|
GetXZFromIndex(bestIdx, &bx, &by);
|
||||||
RemeshChunk(bx, by);
|
RemeshChunk(bx, by);
|
||||||
@@ -898,12 +955,13 @@ static void GameUpdate(Camera camera, float &time) {
|
|||||||
|
|
||||||
PROFCOUNT = GetTime();
|
PROFCOUNT = GetTime();
|
||||||
if(tick_entities) {
|
if(tick_entities) {
|
||||||
entUpdateCounter += dt;
|
entUpdateCounter += dt / 2.0f;
|
||||||
if(entUpdateCounter > TPS_DIV) {
|
if(entUpdateCounter > TPS_DIV) {
|
||||||
while (entUpdateCounter > 0)
|
while (entUpdateCounter > 0)
|
||||||
{
|
{
|
||||||
UpdateEntities(world, TPS_DIV / 2.0f);
|
UpdateEntities(world, TPS_DIV / 2.0f);
|
||||||
entUpdateCounter-= TPS_DIV;
|
entUpdateCounter-= TPS_DIV;
|
||||||
|
worldTime++;
|
||||||
}
|
}
|
||||||
TickAvailableBlocks();
|
TickAvailableBlocks();
|
||||||
entUpdateCounter = 0.0f;
|
entUpdateCounter = 0.0f;
|
||||||
@@ -927,12 +985,56 @@ static void GameUpdate(Camera camera, float &time) {
|
|||||||
UpdateCamera(&camera, CAMERA_CUSTOM);
|
UpdateCamera(&camera, CAMERA_CUSTOM);
|
||||||
|
|
||||||
unsigned int debug_verts_opaque = 0;
|
unsigned int debug_verts_opaque = 0;
|
||||||
unsigned int debug_verts_transparent = 0;
|
|
||||||
UpdateHotbar();
|
UpdateHotbar();
|
||||||
Frustum frustum = ExtractFrustumPlanes(camera, (float)GetScreenWidth() / (float)GetScreenHeight());
|
Frustum frustum = ExtractFrustumPlanes(camera, (float)GetScreenWidth() / (float)GetScreenHeight());
|
||||||
BeginDrawing();
|
BeginDrawing();
|
||||||
ClearBackground(RAYWHITE);
|
UpdateCamera(&camera, CAMERA_CUSTOM);
|
||||||
DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), BLUE);
|
|
||||||
|
ClearBackground(GetSkyColor());
|
||||||
|
|
||||||
|
BeginMode3D(camera);
|
||||||
|
float time = GetDayProgression() - 0.25f;
|
||||||
|
Vector3 sunOffset = Vector3Negate(GetSunDirection());
|
||||||
|
Vector3 _forward = Vector3Subtract(camera.target, camera.position);
|
||||||
|
Vector3 up = { 0.0f, 1.0f, 0.0f };
|
||||||
|
Vector3 _right = Vector3CrossProduct(up, _forward);
|
||||||
|
up = Vector3CrossProduct(_forward, _right);
|
||||||
|
up = Vector3Normalize(up);
|
||||||
|
SetRandomSeed(1337);
|
||||||
|
time += 0.25f;
|
||||||
|
if(time > 0.5f) {
|
||||||
|
time = 1-time;
|
||||||
|
}
|
||||||
|
float starAlpha = 0.0f;
|
||||||
|
if(time > 0.2f && time <= 0.3f) {
|
||||||
|
starAlpha = 1-(time - 0.2f) / 0.1f;
|
||||||
|
}
|
||||||
|
if(time <= 0.2f) {
|
||||||
|
starAlpha = 1;
|
||||||
|
}
|
||||||
|
rlSetBlendMode(BLEND_ADDITIVE);
|
||||||
|
DrawBillboardPro(camera, sun, {0, 0, 64, 64}, player_position+sunOffset*1000, up, {150, 150}, {0.5f, 0.5f}, 0, WHITE);
|
||||||
|
DrawBillboardPro(camera, moon, {0, 0, 64, 64}, player_position-sunOffset*1000, up, {150, 150}, {0.5f, 0.5f}, 0, WHITE);
|
||||||
|
for (int i = 0; i < 120; i++)
|
||||||
|
{
|
||||||
|
float u = GetRandomValue(0, 100) / 100.0f;
|
||||||
|
float v = GetRandomValue(0, 100) / 100.0f;
|
||||||
|
double theta = 2.0 * M_PI * u;
|
||||||
|
double z = v;
|
||||||
|
double r = std::sqrt(1.0 - z*z);
|
||||||
|
|
||||||
|
Vector3 starOffset = {
|
||||||
|
r * std::cos(theta),
|
||||||
|
z,
|
||||||
|
r * std::sin(theta)
|
||||||
|
};
|
||||||
|
Vector3 tgt = starOffset*1000;
|
||||||
|
float alphaModMoon = fmax(0, fmin(1, Vector3Distance(starOffset, (Vector3Negate(sunOffset)))/0.25f-1));
|
||||||
|
float alphaModSun = fmax(0, fmin(1, Vector3Distance(starOffset, sunOffset)/0.25f-0.25f));
|
||||||
|
DrawBillboardPro(camera, stars, {(float)GetRandomValue(0, stars.width/8)*8, 0, 8, 8}, player_position+tgt, up, {10, 10}, {0.5f, 0.5f}, GetRandomValue(0, 360), ColorAlpha(WHITE, starAlpha*alphaModMoon*alphaModSun));
|
||||||
|
}
|
||||||
|
rlSetBlendMode(BLEND_ALPHA);
|
||||||
|
EndMode3D();
|
||||||
|
|
||||||
BeginMode3D(camera);
|
BeginMode3D(camera);
|
||||||
|
|
||||||
@@ -946,7 +1048,7 @@ static void GameUpdate(Camera camera, float &time) {
|
|||||||
_z *= CHUNK_SIZE;
|
_z *= CHUNK_SIZE;
|
||||||
|
|
||||||
if(!loadedChunks[x]) continue;
|
if(!loadedChunks[x]) continue;
|
||||||
if(!IsChunkInFrustum(frustum, world[x], _x, _z)) continue;
|
if(!IsChunkInFrustum(frustum, world.chunks[x], _x, _z)) continue;
|
||||||
DrawModel(rendering[x].model, {0, 0, 0}, 1, WHITE);
|
DrawModel(rendering[x].model, {0, 0, 0}, 1, WHITE);
|
||||||
debug_verts_opaque += rendering[x].vertices;
|
debug_verts_opaque += rendering[x].vertices;
|
||||||
}
|
}
|
||||||
@@ -1014,7 +1116,7 @@ static void GameUpdate(Camera camera, float &time) {
|
|||||||
if (!loadedChunks[i]) continue;
|
if (!loadedChunks[i]) continue;
|
||||||
int cx, cz;
|
int cx, cz;
|
||||||
GetXZFromIndex(i, &cx, &cz);
|
GetXZFromIndex(i, &cx, &cz);
|
||||||
if (!IsChunkInFrustum(frustum, world[i], cx*CHUNK_SIZE, cz*CHUNK_SIZE)) continue;
|
if (!IsChunkInFrustum(frustum, world.chunks[i], cx*CHUNK_SIZE, cz*CHUNK_SIZE)) continue;
|
||||||
float wx = cx * CHUNK_SIZE + CHUNK_SIZE * 0.5f;
|
float wx = cx * CHUNK_SIZE + CHUNK_SIZE * 0.5f;
|
||||||
float wz = cz * CHUNK_SIZE + CHUNK_SIZE * 0.5f;
|
float wz = cz * CHUNK_SIZE + CHUNK_SIZE * 0.5f;
|
||||||
float dx = wx - camera.position.x;
|
float dx = wx - camera.position.x;
|
||||||
@@ -1027,8 +1129,8 @@ static void GameUpdate(Camera camera, float &time) {
|
|||||||
|
|
||||||
for (auto &p : distances) {
|
for (auto &p : distances) {
|
||||||
int idx = p.second;
|
int idx = p.second;
|
||||||
DrawModel(renderingT[idx].model, {0, 0, 0}, 1.0f, WHITE);
|
DrawModel(rendering[idx].modelTransparent, {0, 0, 0}, 1.0f, WHITE);
|
||||||
debug_verts_transparent += renderingT[idx].vertices;
|
DrawModel(rendering[idx].modelWater, {0, 0, 0}, 1.0f, WHITE);
|
||||||
}
|
}
|
||||||
AddProfilerPart("chunk render tsl", GetTime()-PROFCOUNT, RED);
|
AddProfilerPart("chunk render tsl", GetTime()-PROFCOUNT, RED);
|
||||||
if (highlightValid)
|
if (highlightValid)
|
||||||
@@ -1047,7 +1149,7 @@ static void GameUpdate(Camera camera, float &time) {
|
|||||||
BeginMode3D(camera);
|
BeginMode3D(camera);
|
||||||
rlDisableDepthMask();
|
rlDisableDepthMask();
|
||||||
rlDisableDepthTest();
|
rlDisableDepthTest();
|
||||||
DrawSelectedItem();
|
DrawSelectedItem(GetLight(world, (int)player_position.x, (int)player_position.y, (int)player_position.z));
|
||||||
rlEnableDepthTest();
|
rlEnableDepthTest();
|
||||||
rlEnableDepthMask();
|
rlEnableDepthMask();
|
||||||
EndMode3D();
|
EndMode3D();
|
||||||
@@ -1063,7 +1165,7 @@ static void GameUpdate(Camera camera, float &time) {
|
|||||||
oxygen += dt * 20.0f;
|
oxygen += dt * 20.0f;
|
||||||
oxygen = Clamp(oxygen, 0, MAX_HP);
|
oxygen = Clamp(oxygen, 0, MAX_HP);
|
||||||
}
|
}
|
||||||
if(!hide_ui && !taking_panorama) {
|
if(!hide_ui && !taking_panorama) { // DEBUG MENU!!!!
|
||||||
char text[128];
|
char text[128];
|
||||||
sprintf(text, "%s %s", GAME_NAME, GAME_VERSION);
|
sprintf(text, "%s %s", GAME_NAME, GAME_VERSION);
|
||||||
DrawTextB(text, 20, 20, DEFAULT_FONT_SIZE, WHITE);
|
DrawTextB(text, 20, 20, DEFAULT_FONT_SIZE, WHITE);
|
||||||
@@ -1078,8 +1180,21 @@ static void GameUpdate(Camera camera, float &time) {
|
|||||||
float virtualmem = m.virtualSize / 1024.0f / 1024.0f;
|
float virtualmem = m.virtualSize / 1024.0f / 1024.0f;
|
||||||
sprintf(text, "Mem %.2fMiB/%.2fMiB", residentmem, virtualmem);
|
sprintf(text, "Mem %.2fMiB/%.2fMiB", residentmem, virtualmem);
|
||||||
DrawTextB(text, 20, 80, DEFAULT_FONT_SIZE, WHITE);
|
DrawTextB(text, 20, 80, DEFAULT_FONT_SIZE, WHITE);
|
||||||
sprintf(text, "Drawing %d verts", debug_verts_opaque+debug_verts_transparent);
|
Vector3I ppos = {floorf(player_position.x), floorf(player_position.y), floorf(player_position.z)};
|
||||||
DrawTextB(text, 120, 40, DEFAULT_FONT_SIZE, WHITE);
|
sprintf(text, "skylight %d | blocklight: r %d g %d b %d",
|
||||||
|
GetSkyLight(world, ppos.x, ppos.y, ppos.z),
|
||||||
|
GetRLight(world, ppos.x, ppos.y, ppos.z),
|
||||||
|
GetGLight(world, ppos.x, ppos.y, ppos.z),
|
||||||
|
GetBLight(world, ppos.x, ppos.y, ppos.z)
|
||||||
|
);
|
||||||
|
DrawTextB(text, 20, 100, DEFAULT_FONT_SIZE, WHITE);
|
||||||
|
sprintf(text, "world time %dt (%.1fs)", worldTime, worldTime * TPS_DIV);
|
||||||
|
DrawTextB(text, 20, 120, DEFAULT_FONT_SIZE, WHITE);
|
||||||
|
float progress = GetDayProgression();
|
||||||
|
int hours = progress*24;
|
||||||
|
int minutes = (int)(progress*24*60)%60;
|
||||||
|
sprintf(text, "%02d:%02d", hours, minutes);
|
||||||
|
DrawTextB(text, 20, 140, DEFAULT_FONT_SIZE, WHITE);
|
||||||
DrawRectangle(GetScreenWidth()/2-3, GetScreenHeight()/2-3, 6, 6, BLACK);
|
DrawRectangle(GetScreenWidth()/2-3, GetScreenHeight()/2-3, 6, 6, BLACK);
|
||||||
DrawRectangle(GetScreenWidth()/2-2, GetScreenHeight()/2-2, 4, 4, WHITE);
|
DrawRectangle(GetScreenWidth()/2-2, GetScreenHeight()/2-2, 4, 4, WHITE);
|
||||||
|
|
||||||
@@ -1157,10 +1272,12 @@ static void GameUpdate(Camera camera, float &time) {
|
|||||||
if(msg != nullptr) {
|
if(msg != nullptr) {
|
||||||
chatOpen = false;
|
chatOpen = false;
|
||||||
DisableCursor();
|
DisableCursor();
|
||||||
|
if(online) {
|
||||||
char data[1+MAX_MESSAGE_LENGTH];
|
char data[1+MAX_MESSAGE_LENGTH];
|
||||||
data[0] = NET_ARG_MESSAGEC;
|
data[0] = NET_ARG_MESSAGEC;
|
||||||
memcpy(data+1, msg, MAX_MESSAGE_LENGTH);
|
memcpy(data+1, msg, MAX_MESSAGE_LENGTH);
|
||||||
SendPacketR(peer, data, 1+MAX_MESSAGE_LENGTH);
|
SendPacketR(peer, data, 1+MAX_MESSAGE_LENGTH);
|
||||||
|
}
|
||||||
memset(msg, 0, MAX_MESSAGE_LENGTH);
|
memset(msg, 0, MAX_MESSAGE_LENGTH);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1178,6 +1295,7 @@ static void GameUpdate(Camera camera, float &time) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
static void GameStart() {
|
static void GameStart() {
|
||||||
|
|
||||||
const int cloudMapSize = MAX_WORLD_SIZE*CHUNK_SIZE/8;
|
const int cloudMapSize = MAX_WORLD_SIZE*CHUNK_SIZE/8;
|
||||||
for (int x = 0; x < cloudMapSize; x++)
|
for (int x = 0; x < cloudMapSize; x++)
|
||||||
{
|
{
|
||||||
@@ -1187,9 +1305,13 @@ static void GameStart() {
|
|||||||
}
|
}
|
||||||
LoadPlayerData();
|
LoadPlayerData();
|
||||||
//PlayRandomMusic();
|
//PlayRandomMusic();
|
||||||
|
if(online) {
|
||||||
char data[1];
|
char data[1];
|
||||||
data[0] = NET_ARG_REQPLAYERS;
|
data[0] = NET_ARG_REQPLAYERS;
|
||||||
SendPacketR(peer, data, 1);
|
SendPacketR(peer, data, 1); // Tell the server to fetch all players
|
||||||
|
}
|
||||||
|
|
||||||
|
worldTime = (int)(WORLD_TIME_TICKS * 0.3f);
|
||||||
|
|
||||||
camera = { 0 };
|
camera = { 0 };
|
||||||
camera.position = (Vector3){ MAX_WORLD_SIZE / 2 * CHUNK_SIZE, 12.0f, MAX_WORLD_SIZE / 2 * CHUNK_SIZE};
|
camera.position = (Vector3){ MAX_WORLD_SIZE / 2 * CHUNK_SIZE, 12.0f, MAX_WORLD_SIZE / 2 * CHUNK_SIZE};
|
||||||
@@ -1200,7 +1322,7 @@ static void GameStart() {
|
|||||||
|
|
||||||
int center = MAX_WORLD_SIZE / 2 * CHUNK_SIZE;
|
int center = MAX_WORLD_SIZE / 2 * CHUNK_SIZE;
|
||||||
player_position = (Vector3){ MAX_WORLD_SIZE / 2 * CHUNK_SIZE, 128.0f, MAX_WORLD_SIZE / 2 * CHUNK_SIZE};
|
player_position = (Vector3){ MAX_WORLD_SIZE / 2 * CHUNK_SIZE, 128.0f, MAX_WORLD_SIZE / 2 * CHUNK_SIZE};
|
||||||
player_position.y = world[GetIndexWorld(center / 16, center / 16)].highestBlock[0] + 2;
|
player_position.y = world.chunks[GetIndexWorld(center / 16, center / 16)].highestBlock[0] + 2;
|
||||||
player_velocity = (Vector3){ 0, 0, 0 };
|
player_velocity = (Vector3){ 0, 0, 0 };
|
||||||
|
|
||||||
DisableCursor();
|
DisableCursor();
|
||||||
@@ -1251,6 +1373,8 @@ static void ParseData(ENetPacket* packet) {
|
|||||||
{
|
{
|
||||||
a_data.push_back(packet->data[i]);
|
a_data.push_back(packet->data[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
switch (a_data[0])
|
switch (a_data[0])
|
||||||
{
|
{
|
||||||
case NET_ARG_CHUNKF:
|
case NET_ARG_CHUNKF:
|
||||||
@@ -1403,21 +1527,9 @@ void NetworkUpdate() {
|
|||||||
|
|
||||||
void GameModeCleanupFull() {
|
void GameModeCleanupFull() {
|
||||||
if(online) {
|
if(online) {
|
||||||
|
|
||||||
enet_host_destroy(client);
|
enet_host_destroy(client);
|
||||||
online = false;
|
online = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
stop_server = true;
|
|
||||||
//serverThread.join();
|
|
||||||
|
|
||||||
for (int idx = 0; idx < MAX_WORLD_AREA; idx++)
|
|
||||||
{
|
|
||||||
if(loadedChunks[idx]) {
|
|
||||||
//UnloadModel(renderingT[idx]);
|
|
||||||
//UnloadModel(rendering[idx]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
memset(loadedChunks, 0, sizeof(loadedChunks));
|
memset(loadedChunks, 0, sizeof(loadedChunks));
|
||||||
memset(dirtyChunks, 0, sizeof(dirtyChunks));
|
memset(dirtyChunks, 0, sizeof(dirtyChunks));
|
||||||
entities.clear();
|
entities.clear();
|
||||||
@@ -1439,9 +1551,15 @@ extern void InitMenu();
|
|||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
SetTraceLogLevel(LOG_WARNING);
|
SetTraceLogLevel(LOG_WARNING);
|
||||||
NetworkingStart();
|
|
||||||
SetConfigFlags(FLAG_WINDOW_RESIZABLE);
|
SetConfigFlags(FLAG_WINDOW_RESIZABLE);
|
||||||
InitWindow(WIDTH, HEIGHT, GAME_NAME);
|
InitWindow(WIDTH, HEIGHT, GAME_NAME);
|
||||||
|
|
||||||
|
if(!DirectoryExists(PathifyUser(""))) {
|
||||||
|
MakeDirectory(PathifyUser(""));
|
||||||
|
}
|
||||||
|
if(!DirectoryExists(PathifyUser("worlds"))) {
|
||||||
|
MakeDirectory(PathifyUser("worlds"));
|
||||||
|
}
|
||||||
InitWorldgen(0);
|
InitWorldgen(0);
|
||||||
InitAudioDevice();
|
InitAudioDevice();
|
||||||
InitMenu();
|
InitMenu();
|
||||||
@@ -1459,6 +1577,9 @@ int main(void)
|
|||||||
|
|
||||||
fnt = LoadFontEx(Pathify("font.ttf"), 32, NULL, 1024*8);
|
fnt = LoadFontEx(Pathify("font.ttf"), 32, NULL, 1024*8);
|
||||||
terrain = LoadTexture(Pathify("terrain.png"));
|
terrain = LoadTexture(Pathify("terrain.png"));
|
||||||
|
sun = LoadTexture(Pathify("sun.png"));
|
||||||
|
moon = LoadTexture(Pathify("moon.png"));
|
||||||
|
stars = LoadTexture(Pathify("stars.png"));
|
||||||
GenTextureMipmaps(&terrain);
|
GenTextureMipmaps(&terrain);
|
||||||
Image temp = GenImageColor(1, 1, WHITE);
|
Image temp = GenImageColor(1, 1, WHITE);
|
||||||
white_pixel = LoadTextureFromImage(temp);
|
white_pixel = LoadTextureFromImage(temp);
|
||||||
@@ -1474,14 +1595,32 @@ int main(void)
|
|||||||
ImageCrop(&copied, src0);
|
ImageCrop(&copied, src0);
|
||||||
|
|
||||||
water = LoadTextureFromImage(copied);
|
water = LoadTextureFromImage(copied);
|
||||||
|
SetTextureWrap(terrain, TEXTURE_WRAP_REPEAT);
|
||||||
SetTextureWrap(water, TEXTURE_WRAP_REPEAT);
|
SetTextureWrap(water, TEXTURE_WRAP_REPEAT);
|
||||||
SetTargetFPS(-1);
|
SetTargetFPS(-1);
|
||||||
float time;
|
float time;
|
||||||
|
|
||||||
|
LoadNewShader("terrain");
|
||||||
|
LoadNewShader("water");
|
||||||
|
|
||||||
SetExitKey(KEY_NULL);
|
SetExitKey(KEY_NULL);
|
||||||
|
|
||||||
while (!WindowShouldClose())
|
while (!WindowShouldClose())
|
||||||
{
|
{
|
||||||
|
for (const auto& [key, shader] : loadedShaders) {
|
||||||
|
Vector4 sunlight = ColorNormalize(GetSunlightColor());
|
||||||
|
SetShaderValue(shader, GetShaderLocation(shader, "sunlightColor"), &sunlight, SHADER_UNIFORM_VEC4);
|
||||||
|
|
||||||
|
Vector4 skyColor = ColorNormalize(GetSkyColor());
|
||||||
|
SetShaderValue(shader, GetShaderLocation(shader, "skyColor"), &skyColor, SHADER_UNIFORM_VEC4);
|
||||||
|
|
||||||
|
Vector3 sunlightDir = Vector3Negate(GetSunDirection());
|
||||||
|
SetShaderValue(shader, GetShaderLocation(shader, "lightDir"), &sunlightDir, SHADER_UNIFORM_VEC3);
|
||||||
|
|
||||||
|
float time = (float)GetTime();
|
||||||
|
SetShaderValue(shader, GetShaderLocation(shader, "time"), &time, SHADER_UNIFORM_FLOAT);
|
||||||
|
}
|
||||||
|
|
||||||
NetworkUpdate();
|
NetworkUpdate();
|
||||||
InputUpdate();
|
InputUpdate();
|
||||||
|
|
||||||
@@ -1496,7 +1635,6 @@ int main(void)
|
|||||||
GetXZFromIndex(idx, &x, &z);
|
GetXZFromIndex(idx, &x, &z);
|
||||||
c.x = (uint8_t)x;
|
c.x = (uint8_t)x;
|
||||||
c.z = (uint8_t)z;
|
c.z = (uint8_t)z;
|
||||||
std::cout << data.size() << std::endl;
|
|
||||||
for (int i = 2; i < CHUNK_DATA_SIZE+2; i++)
|
for (int i = 2; i < CHUNK_DATA_SIZE+2; i++)
|
||||||
{
|
{
|
||||||
c.blocks[i-2] = data[i];
|
c.blocks[i-2] = data[i];
|
||||||
@@ -1505,7 +1643,7 @@ int main(void)
|
|||||||
{
|
{
|
||||||
c.highestBlock[i-CHUNK_DATA_SIZE-2] = data[i];
|
c.highestBlock[i-CHUNK_DATA_SIZE-2] = data[i];
|
||||||
}
|
}
|
||||||
world[idx] = c;
|
world.chunks[idx] = c;
|
||||||
dirtyChunks[idx] = true;
|
dirtyChunks[idx] = true;
|
||||||
worldPacketStack.pop();
|
worldPacketStack.pop();
|
||||||
fetchedChunks++;
|
fetchedChunks++;
|
||||||
@@ -1552,7 +1690,7 @@ int main(void)
|
|||||||
int idx = x + y * MAX_WORLD_SIZE;
|
int idx = x + y * MAX_WORLD_SIZE;
|
||||||
if(worldCreationStep == 0 && !online) {
|
if(worldCreationStep == 0 && !online) {
|
||||||
Chunk chunk = GenerateChunk(x, y);
|
Chunk chunk = GenerateChunk(x, y);
|
||||||
world[idx] = chunk;
|
world.chunks[idx] = chunk;
|
||||||
}
|
}
|
||||||
if(worldCreationStep == 1 && !online) {
|
if(worldCreationStep == 1 && !online) {
|
||||||
if(worldCreationProgress > 0) {
|
if(worldCreationProgress > 0) {
|
||||||
@@ -1564,12 +1702,14 @@ int main(void)
|
|||||||
}
|
}
|
||||||
if (worldCreationStep == 2)
|
if (worldCreationStep == 2)
|
||||||
{
|
{
|
||||||
//RebuildOpaqueMask(&world[idx]);
|
RebuildOpaqueMask(world.chunks[idx]);
|
||||||
}
|
}
|
||||||
if (worldCreationStep == 3) {
|
if (worldCreationStep == 3) {
|
||||||
dirtyChunks[idx] = true;
|
dirtyChunks[idx] = true;
|
||||||
}
|
}
|
||||||
if(online)
|
if(!(worldCreationStep == 0 && online))
|
||||||
|
worldCreationProgress++;
|
||||||
|
else
|
||||||
worldCreationProgress = fetchedChunks+1;
|
worldCreationProgress = fetchedChunks+1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1603,7 +1743,7 @@ int main(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enet_deinitialize();
|
|
||||||
GameModeCleanupFull();
|
GameModeCleanupFull();
|
||||||
|
|
||||||
UnloadTexture(terrain);
|
UnloadTexture(terrain);
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
set(CMAKE_SYSTEM_NAME Windows)
|
||||||
|
set(CMAKE_SYSTEM_VERSION 1)
|
||||||
|
|
||||||
|
set(CMAKE_C_COMPILER gcc)
|
||||||
|
set(CMAKE_CXX_COMPILER g++)
|
||||||
|
set(CMAKE_RC_COMPILER windres)
|
||||||
|
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
||||||
|
|
||||||
|
set(CMAKE_C_FLAGS "-static-libgcc -static-libstdc++ ${CMAKE_C_FLAGS}")
|
||||||
|
set(CMAKE_CXX_FLAGS "-static-libgcc -static-libstdc++ ${CMAKE_CXX_FLAGS}")
|
||||||
Reference in New Issue
Block a user