First commit (very unfinished)

This commit is contained in:
milkwx3
2026-06-13 22:02:49 +03:00
commit c60f598661
47 changed files with 9309 additions and 0 deletions
+9
View File
@@ -0,0 +1,9 @@
OUTPUT/*
OLD STUFF
build
makeheaders
libraries/*
.vscode
android
__UTILS__
snapshots
+4
View File
@@ -0,0 +1,4 @@
cmake_minimum_required(VERSION 3.23)
project(RCRAFT)
add_subdirectory(src)
+21
View File
@@ -0,0 +1,21 @@
#/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 > src/helpers/common.hpp
#rm -r build
echo Building Linux...
cmake -B build -DUNIX=ON -DUNIX=true
cd build
make -j12
cd ..
cp build/src/RCRAFT* OUTPUT
#cp build/src/dedicated_server/RDS* OUTPUT
#rm -r build
#echo Building Windows...
#cmake -DCMAKE_TOOLCHAIN_FILE=toolchains/mingw-w64.cmake -DWIN32=ON -DWIN32=true -B build
#cd build
#make -j12
#cd ..
#cp build/src/RCRAFT.exe OUTPUT
#cp build/src/dedicated_server/RDS.exe OUTPUT
+35
View File
@@ -0,0 +1,35 @@
cmake_minimum_required(VERSION 3.23)
project(RCRAFT)
add_subdirectory(helpers)
#add_subdirectory(dedicated_server)
set(YAML_BUILD_SHARED_LIBS OFF)
set(YAML_MSVC_SHARED_RT OFF)
set(OPENGL_VERSION 4.3)
add_subdirectory(libraries/raylib)
add_subdirectory(libraries/enet)
add_subdirectory(libraries/yaml-cpp)
add_subdirectory(libraries/Lua)
if (WIN32)
add_compile_definitions(WIN32)
add_compile_options(-DWIN32)
link_libraries(ws2_32)
endif()
execute_process(COMMAND date +v.%yw%W OUTPUT_VARIABLE BUILD_DATE OUTPUT_STRIP_TRAILING_WHITESPACE)
add_compile_definitions(GAME_VERSION="${BUILD_DATE}")
add_executable(RCRAFT rcraft.cpp)
target_include_directories(RCRAFT PRIVATE
libraries/enet/include/.
libraries/yaml-cpp/include/.
libraries/raylib/src/.
libraries/Lua/lua-5.4.7/src/
)
target_link_libraries(RCRAFT PRIVATE
raylib
enet
helpers
yaml-cpp
lua_static
)
+659
View File
@@ -0,0 +1,659 @@
//----------------------------------------------------------------------------------------
//
// 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_
+20
View File
@@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 3.23)
project(RDS)
add_compile_definitions(SERVER)
if (WIN32)
add_compile_definitions(WIN32 SERVER)
endif()
add_executable(RDS ds.cpp)
add_subdirectory(Lua)
target_include_directories(RDS PRIVATE
../libraries/enet/include/.
)
target_link_libraries(RDS PRIVATE
raylib
enet
helpers
lua_static
)
+382
View File
@@ -0,0 +1,382 @@
#include "common.hpp"
#include <iostream>
#include <cstring>
#include <list>
#include <unordered_set>
#include <vector>
#include <string>
#include <memory>
#include <filesystem> // C++17 for plugin folder iteration
#include <lua.hpp> // Lua header (adjust include if needed)
namespace fs = std::filesystem;
// Globals
std::list<NetPlayer> players;
Chunk world[MAX_WORLD_AREA];
ENetHost* server;
// Lua plugin system types
struct LuaPlugin {
std::string name;
lua_State* L;
// presence flags for callbacks
bool has_on_connect = false;
bool has_on_disconnect = false;
bool has_on_packet = false;
};
std::vector<std::unique_ptr<LuaPlugin>> plugins;
// Helper: push peer id (int) and send/broadcast wrappers
static int l_server_send(lua_State* L) {
// args: peer_id (number), string data
int peer_id = (int)luaL_checkinteger(L, 1);
size_t len;
const char* data = luaL_checklstring(L, 2, &len);
// find peer addr/port from players list
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;
}
// Register C functions available to plugins
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");
// assign this table to global "server"
lua_setglobal(L, "server");
}
// Load one plugin file
bool LoadPluginFile(const fs::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);
// Provide limited API: global 'server' table
RegisterLuaAPI(plugin->L);
// Load file
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;
}
// Check for callbacks: on_connect, on_disconnect, on_packet
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;
}
void LoadPluginsFromFolder(const std::string& folder) {
try {
if (!fs::exists(folder)) {
std::cout << "Plugins folder does not exist; skipping: " << folder << std::endl;
return;
}
for (auto& p : fs::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;
}
}
// Helper to call plugin callbacks
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);
}
}
}
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);
}
}
}
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);
}
}
}
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;
}
// Modified ParseData to call Lua plugin packet handlers
void ParseData(ENetPacket* packet, ENetPeer* peer) {
int len = packet->dataLength;
unsigned char data[len];
memcpy(&data, packet->data, len);
// Call Lua packet handlers first (they can inspect/log; they cannot modify server internals directly)
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(plr.addr == peer->address.host && plr.port == peer->address.port) {
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(plr.addr == peer->address.host && plr.port == peer->address.port) {
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(plr.addr != peer->address.host || plr.port != peer->address.port) {
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(plr.addr == peer->address.host || plr.port == peer->address.port) {
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;
}
}
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;
}
int main(int argc, char** argv) {
int worldType = 0;
InitWorldgen(worldType);
std::cout << "Building chunks..." << std::endl;
for (int x = 0; x < MAX_WORLD_SIZE; x++)
{
for (int y = 0; y < MAX_WORLD_SIZE; y++)
{
Chunk chunk = GenerateChunk(x, y);
world[x + y * MAX_WORLD_SIZE] = chunk;
}
}
// Load Lua plugins
LoadPluginsFromFolder("plugins");
std::cout << "Starting server..." << std::endl;
server = StartServer();
ENetEvent event;
std::cout << "Serving on port: " << PORT << std::endl;
while(true)
{
ENetEvent event;
while (enet_host_service (server, & event, 1000) > 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 = 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));
}
// notify plugins
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 (it->addr == event.peer->address.host && it->port == event.peer->address.port) {
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;
}
}
}
// cleanup plugins
for (auto &pl : plugins) {
lua_close(pl->L);
}
enet_host_destroy(server);
return 0;
}
@@ -0,0 +1,16 @@
# CMAKE generated file: DO NOT EDIT!
# Generated by "Unix Makefiles" Generator, CMake Version 3.31
# Relative path conversion top directories.
set(CMAKE_RELATIVE_PATH_TOP_SOURCE "/home/milkwx3/workspace/RCRAFT-MINEVOX")
set(CMAKE_RELATIVE_PATH_TOP_BINARY "/home/milkwx3/workspace/RCRAFT-MINEVOX")
# Force unix paths in dependencies.
set(CMAKE_FORCE_UNIX_PATHS 1)
# The C and CXX include file regular expressions for this directory.
set(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$")
set(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$")
set(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN})
set(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN})
@@ -0,0 +1,30 @@
# Consider dependencies only in project.
set(CMAKE_DEPENDS_IN_PROJECT_ONLY OFF)
# The set of languages for which implicit dependencies are needed:
set(CMAKE_DEPENDS_LANGUAGES
)
# The set of dependency files which are needed:
set(CMAKE_DEPENDS_DEPENDENCY_FILES
"/home/milkwx3/workspace/RCRAFT-MINEVOX/helpers/chunks.cpp" "helpers/CMakeFiles/helpers.dir/chunks.cpp.o" "gcc" "helpers/CMakeFiles/helpers.dir/chunks.cpp.o.d"
"/home/milkwx3/workspace/RCRAFT-MINEVOX/helpers/debug.cpp" "helpers/CMakeFiles/helpers.dir/debug.cpp.o" "gcc" "helpers/CMakeFiles/helpers.dir/debug.cpp.o.d"
"/home/milkwx3/workspace/RCRAFT-MINEVOX/helpers/entities.cpp" "helpers/CMakeFiles/helpers.dir/entities.cpp.o" "gcc" "helpers/CMakeFiles/helpers.dir/entities.cpp.o.d"
"/home/milkwx3/workspace/RCRAFT-MINEVOX/helpers/input.cpp" "helpers/CMakeFiles/helpers.dir/input.cpp.o" "gcc" "helpers/CMakeFiles/helpers.dir/input.cpp.o.d"
"/home/milkwx3/workspace/RCRAFT-MINEVOX/helpers/menu.cpp" "helpers/CMakeFiles/helpers.dir/menu.cpp.o" "gcc" "helpers/CMakeFiles/helpers.dir/menu.cpp.o.d"
"/home/milkwx3/workspace/RCRAFT-MINEVOX/helpers/mesher.cpp" "helpers/CMakeFiles/helpers.dir/mesher.cpp.o" "gcc" "helpers/CMakeFiles/helpers.dir/mesher.cpp.o.d"
"/home/milkwx3/workspace/RCRAFT-MINEVOX/helpers/networking.cpp" "helpers/CMakeFiles/helpers.dir/networking.cpp.o" "gcc" "helpers/CMakeFiles/helpers.dir/networking.cpp.o.d"
"/home/milkwx3/workspace/RCRAFT-MINEVOX/helpers/utils.cpp" "helpers/CMakeFiles/helpers.dir/utils.cpp.o" "gcc" "helpers/CMakeFiles/helpers.dir/utils.cpp.o.d"
)
# Targets to which this target links which contain Fortran sources.
set(CMAKE_Fortran_TARGET_LINKED_INFO_FILES
)
# Targets to which this target links which contain Fortran sources.
set(CMAKE_Fortran_TARGET_FORWARD_LINKED_INFO_FILES
)
# Fortran module output directory.
set(CMAKE_Fortran_TARGET_MODULE_DIR "")
@@ -0,0 +1,226 @@
# CMAKE generated file: DO NOT EDIT!
# Generated by "Unix Makefiles" Generator, CMake Version 3.31
# Delete rule output on recipe failure.
.DELETE_ON_ERROR:
#=============================================================================
# Special targets provided by cmake.
# Disable implicit rules so canonical targets will work.
.SUFFIXES:
# Disable VCS-based implicit rules.
% : %,v
# Disable VCS-based implicit rules.
% : RCS/%
# Disable VCS-based implicit rules.
% : RCS/%,v
# Disable VCS-based implicit rules.
% : SCCS/s.%
# Disable VCS-based implicit rules.
% : s.%
.SUFFIXES: .hpux_make_needs_suffix_list
# Command-line flag to silence nested $(MAKE).
$(VERBOSE)MAKESILENT = -s
#Suppress display of executed commands.
$(VERBOSE).SILENT:
# A target that is always out of date.
cmake_force:
.PHONY : cmake_force
#=============================================================================
# Set environment variables for the build.
# The shell in which to execute make rules.
SHELL = /bin/sh
# The CMake executable.
CMAKE_COMMAND = /usr/bin/cmake
# The command to remove a file.
RM = /usr/bin/cmake -E rm -f
# Escaping for special characters.
EQUALS = =
# The top-level source directory on which CMake was run.
CMAKE_SOURCE_DIR = /home/milkwx3/workspace/RCRAFT-MINEVOX
# The top-level build directory on which CMake was run.
CMAKE_BINARY_DIR = /home/milkwx3/workspace/RCRAFT-MINEVOX
# Include any dependencies generated for this target.
include helpers/CMakeFiles/helpers.dir/depend.make
# Include any dependencies generated by the compiler for this target.
include helpers/CMakeFiles/helpers.dir/compiler_depend.make
# Include the progress variables for this target.
include helpers/CMakeFiles/helpers.dir/progress.make
# Include the compile flags for this target's objects.
include helpers/CMakeFiles/helpers.dir/flags.make
helpers/CMakeFiles/helpers.dir/codegen:
.PHONY : helpers/CMakeFiles/helpers.dir/codegen
helpers/CMakeFiles/helpers.dir/chunks.cpp.o: helpers/CMakeFiles/helpers.dir/flags.make
helpers/CMakeFiles/helpers.dir/chunks.cpp.o: helpers/chunks.cpp
helpers/CMakeFiles/helpers.dir/chunks.cpp.o: helpers/CMakeFiles/helpers.dir/compiler_depend.ts
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --green --progress-dir=/home/milkwx3/workspace/RCRAFT-MINEVOX/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building CXX object helpers/CMakeFiles/helpers.dir/chunks.cpp.o"
cd /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -MD -MT helpers/CMakeFiles/helpers.dir/chunks.cpp.o -MF CMakeFiles/helpers.dir/chunks.cpp.o.d -o CMakeFiles/helpers.dir/chunks.cpp.o -c /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers/chunks.cpp
helpers/CMakeFiles/helpers.dir/chunks.cpp.i: cmake_force
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --green "Preprocessing CXX source to CMakeFiles/helpers.dir/chunks.cpp.i"
cd /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers/chunks.cpp > CMakeFiles/helpers.dir/chunks.cpp.i
helpers/CMakeFiles/helpers.dir/chunks.cpp.s: cmake_force
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --green "Compiling CXX source to assembly CMakeFiles/helpers.dir/chunks.cpp.s"
cd /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers/chunks.cpp -o CMakeFiles/helpers.dir/chunks.cpp.s
helpers/CMakeFiles/helpers.dir/debug.cpp.o: helpers/CMakeFiles/helpers.dir/flags.make
helpers/CMakeFiles/helpers.dir/debug.cpp.o: helpers/debug.cpp
helpers/CMakeFiles/helpers.dir/debug.cpp.o: helpers/CMakeFiles/helpers.dir/compiler_depend.ts
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --green --progress-dir=/home/milkwx3/workspace/RCRAFT-MINEVOX/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Building CXX object helpers/CMakeFiles/helpers.dir/debug.cpp.o"
cd /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -MD -MT helpers/CMakeFiles/helpers.dir/debug.cpp.o -MF CMakeFiles/helpers.dir/debug.cpp.o.d -o CMakeFiles/helpers.dir/debug.cpp.o -c /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers/debug.cpp
helpers/CMakeFiles/helpers.dir/debug.cpp.i: cmake_force
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --green "Preprocessing CXX source to CMakeFiles/helpers.dir/debug.cpp.i"
cd /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers/debug.cpp > CMakeFiles/helpers.dir/debug.cpp.i
helpers/CMakeFiles/helpers.dir/debug.cpp.s: cmake_force
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --green "Compiling CXX source to assembly CMakeFiles/helpers.dir/debug.cpp.s"
cd /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers/debug.cpp -o CMakeFiles/helpers.dir/debug.cpp.s
helpers/CMakeFiles/helpers.dir/entities.cpp.o: helpers/CMakeFiles/helpers.dir/flags.make
helpers/CMakeFiles/helpers.dir/entities.cpp.o: helpers/entities.cpp
helpers/CMakeFiles/helpers.dir/entities.cpp.o: helpers/CMakeFiles/helpers.dir/compiler_depend.ts
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --green --progress-dir=/home/milkwx3/workspace/RCRAFT-MINEVOX/CMakeFiles --progress-num=$(CMAKE_PROGRESS_3) "Building CXX object helpers/CMakeFiles/helpers.dir/entities.cpp.o"
cd /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -MD -MT helpers/CMakeFiles/helpers.dir/entities.cpp.o -MF CMakeFiles/helpers.dir/entities.cpp.o.d -o CMakeFiles/helpers.dir/entities.cpp.o -c /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers/entities.cpp
helpers/CMakeFiles/helpers.dir/entities.cpp.i: cmake_force
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --green "Preprocessing CXX source to CMakeFiles/helpers.dir/entities.cpp.i"
cd /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers/entities.cpp > CMakeFiles/helpers.dir/entities.cpp.i
helpers/CMakeFiles/helpers.dir/entities.cpp.s: cmake_force
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --green "Compiling CXX source to assembly CMakeFiles/helpers.dir/entities.cpp.s"
cd /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers/entities.cpp -o CMakeFiles/helpers.dir/entities.cpp.s
helpers/CMakeFiles/helpers.dir/input.cpp.o: helpers/CMakeFiles/helpers.dir/flags.make
helpers/CMakeFiles/helpers.dir/input.cpp.o: helpers/input.cpp
helpers/CMakeFiles/helpers.dir/input.cpp.o: helpers/CMakeFiles/helpers.dir/compiler_depend.ts
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --green --progress-dir=/home/milkwx3/workspace/RCRAFT-MINEVOX/CMakeFiles --progress-num=$(CMAKE_PROGRESS_4) "Building CXX object helpers/CMakeFiles/helpers.dir/input.cpp.o"
cd /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -MD -MT helpers/CMakeFiles/helpers.dir/input.cpp.o -MF CMakeFiles/helpers.dir/input.cpp.o.d -o CMakeFiles/helpers.dir/input.cpp.o -c /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers/input.cpp
helpers/CMakeFiles/helpers.dir/input.cpp.i: cmake_force
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --green "Preprocessing CXX source to CMakeFiles/helpers.dir/input.cpp.i"
cd /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers/input.cpp > CMakeFiles/helpers.dir/input.cpp.i
helpers/CMakeFiles/helpers.dir/input.cpp.s: cmake_force
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --green "Compiling CXX source to assembly CMakeFiles/helpers.dir/input.cpp.s"
cd /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers/input.cpp -o CMakeFiles/helpers.dir/input.cpp.s
helpers/CMakeFiles/helpers.dir/menu.cpp.o: helpers/CMakeFiles/helpers.dir/flags.make
helpers/CMakeFiles/helpers.dir/menu.cpp.o: helpers/menu.cpp
helpers/CMakeFiles/helpers.dir/menu.cpp.o: helpers/CMakeFiles/helpers.dir/compiler_depend.ts
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --green --progress-dir=/home/milkwx3/workspace/RCRAFT-MINEVOX/CMakeFiles --progress-num=$(CMAKE_PROGRESS_5) "Building CXX object helpers/CMakeFiles/helpers.dir/menu.cpp.o"
cd /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -MD -MT helpers/CMakeFiles/helpers.dir/menu.cpp.o -MF CMakeFiles/helpers.dir/menu.cpp.o.d -o CMakeFiles/helpers.dir/menu.cpp.o -c /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers/menu.cpp
helpers/CMakeFiles/helpers.dir/menu.cpp.i: cmake_force
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --green "Preprocessing CXX source to CMakeFiles/helpers.dir/menu.cpp.i"
cd /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers/menu.cpp > CMakeFiles/helpers.dir/menu.cpp.i
helpers/CMakeFiles/helpers.dir/menu.cpp.s: cmake_force
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --green "Compiling CXX source to assembly CMakeFiles/helpers.dir/menu.cpp.s"
cd /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers/menu.cpp -o CMakeFiles/helpers.dir/menu.cpp.s
helpers/CMakeFiles/helpers.dir/mesher.cpp.o: helpers/CMakeFiles/helpers.dir/flags.make
helpers/CMakeFiles/helpers.dir/mesher.cpp.o: helpers/mesher.cpp
helpers/CMakeFiles/helpers.dir/mesher.cpp.o: helpers/CMakeFiles/helpers.dir/compiler_depend.ts
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --green --progress-dir=/home/milkwx3/workspace/RCRAFT-MINEVOX/CMakeFiles --progress-num=$(CMAKE_PROGRESS_6) "Building CXX object helpers/CMakeFiles/helpers.dir/mesher.cpp.o"
cd /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -MD -MT helpers/CMakeFiles/helpers.dir/mesher.cpp.o -MF CMakeFiles/helpers.dir/mesher.cpp.o.d -o CMakeFiles/helpers.dir/mesher.cpp.o -c /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers/mesher.cpp
helpers/CMakeFiles/helpers.dir/mesher.cpp.i: cmake_force
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --green "Preprocessing CXX source to CMakeFiles/helpers.dir/mesher.cpp.i"
cd /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers/mesher.cpp > CMakeFiles/helpers.dir/mesher.cpp.i
helpers/CMakeFiles/helpers.dir/mesher.cpp.s: cmake_force
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --green "Compiling CXX source to assembly CMakeFiles/helpers.dir/mesher.cpp.s"
cd /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers/mesher.cpp -o CMakeFiles/helpers.dir/mesher.cpp.s
helpers/CMakeFiles/helpers.dir/networking.cpp.o: helpers/CMakeFiles/helpers.dir/flags.make
helpers/CMakeFiles/helpers.dir/networking.cpp.o: helpers/networking.cpp
helpers/CMakeFiles/helpers.dir/networking.cpp.o: helpers/CMakeFiles/helpers.dir/compiler_depend.ts
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --green --progress-dir=/home/milkwx3/workspace/RCRAFT-MINEVOX/CMakeFiles --progress-num=$(CMAKE_PROGRESS_7) "Building CXX object helpers/CMakeFiles/helpers.dir/networking.cpp.o"
cd /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -MD -MT helpers/CMakeFiles/helpers.dir/networking.cpp.o -MF CMakeFiles/helpers.dir/networking.cpp.o.d -o CMakeFiles/helpers.dir/networking.cpp.o -c /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers/networking.cpp
helpers/CMakeFiles/helpers.dir/networking.cpp.i: cmake_force
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --green "Preprocessing CXX source to CMakeFiles/helpers.dir/networking.cpp.i"
cd /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers/networking.cpp > CMakeFiles/helpers.dir/networking.cpp.i
helpers/CMakeFiles/helpers.dir/networking.cpp.s: cmake_force
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --green "Compiling CXX source to assembly CMakeFiles/helpers.dir/networking.cpp.s"
cd /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers/networking.cpp -o CMakeFiles/helpers.dir/networking.cpp.s
helpers/CMakeFiles/helpers.dir/utils.cpp.o: helpers/CMakeFiles/helpers.dir/flags.make
helpers/CMakeFiles/helpers.dir/utils.cpp.o: helpers/utils.cpp
helpers/CMakeFiles/helpers.dir/utils.cpp.o: helpers/CMakeFiles/helpers.dir/compiler_depend.ts
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --green --progress-dir=/home/milkwx3/workspace/RCRAFT-MINEVOX/CMakeFiles --progress-num=$(CMAKE_PROGRESS_8) "Building CXX object helpers/CMakeFiles/helpers.dir/utils.cpp.o"
cd /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -MD -MT helpers/CMakeFiles/helpers.dir/utils.cpp.o -MF CMakeFiles/helpers.dir/utils.cpp.o.d -o CMakeFiles/helpers.dir/utils.cpp.o -c /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers/utils.cpp
helpers/CMakeFiles/helpers.dir/utils.cpp.i: cmake_force
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --green "Preprocessing CXX source to CMakeFiles/helpers.dir/utils.cpp.i"
cd /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -E /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers/utils.cpp > CMakeFiles/helpers.dir/utils.cpp.i
helpers/CMakeFiles/helpers.dir/utils.cpp.s: cmake_force
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --green "Compiling CXX source to assembly CMakeFiles/helpers.dir/utils.cpp.s"
cd /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers && /usr/bin/c++ $(CXX_DEFINES) $(CXX_INCLUDES) $(CXX_FLAGS) -S /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers/utils.cpp -o CMakeFiles/helpers.dir/utils.cpp.s
# Object files for target helpers
helpers_OBJECTS = \
"CMakeFiles/helpers.dir/chunks.cpp.o" \
"CMakeFiles/helpers.dir/debug.cpp.o" \
"CMakeFiles/helpers.dir/entities.cpp.o" \
"CMakeFiles/helpers.dir/input.cpp.o" \
"CMakeFiles/helpers.dir/menu.cpp.o" \
"CMakeFiles/helpers.dir/mesher.cpp.o" \
"CMakeFiles/helpers.dir/networking.cpp.o" \
"CMakeFiles/helpers.dir/utils.cpp.o"
# External object files for target helpers
helpers_EXTERNAL_OBJECTS =
helpers/libhelpers.a: helpers/CMakeFiles/helpers.dir/chunks.cpp.o
helpers/libhelpers.a: helpers/CMakeFiles/helpers.dir/debug.cpp.o
helpers/libhelpers.a: helpers/CMakeFiles/helpers.dir/entities.cpp.o
helpers/libhelpers.a: helpers/CMakeFiles/helpers.dir/input.cpp.o
helpers/libhelpers.a: helpers/CMakeFiles/helpers.dir/menu.cpp.o
helpers/libhelpers.a: helpers/CMakeFiles/helpers.dir/mesher.cpp.o
helpers/libhelpers.a: helpers/CMakeFiles/helpers.dir/networking.cpp.o
helpers/libhelpers.a: helpers/CMakeFiles/helpers.dir/utils.cpp.o
helpers/libhelpers.a: helpers/CMakeFiles/helpers.dir/build.make
helpers/libhelpers.a: helpers/CMakeFiles/helpers.dir/link.txt
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --green --bold --progress-dir=/home/milkwx3/workspace/RCRAFT-MINEVOX/CMakeFiles --progress-num=$(CMAKE_PROGRESS_9) "Linking CXX static library libhelpers.a"
cd /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers && $(CMAKE_COMMAND) -P CMakeFiles/helpers.dir/cmake_clean_target.cmake
cd /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers && $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/helpers.dir/link.txt --verbose=$(VERBOSE)
# Rule to build all files generated by this target.
helpers/CMakeFiles/helpers.dir/build: helpers/libhelpers.a
.PHONY : helpers/CMakeFiles/helpers.dir/build
helpers/CMakeFiles/helpers.dir/clean:
cd /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers && $(CMAKE_COMMAND) -P CMakeFiles/helpers.dir/cmake_clean.cmake
.PHONY : helpers/CMakeFiles/helpers.dir/clean
helpers/CMakeFiles/helpers.dir/depend:
cd /home/milkwx3/workspace/RCRAFT-MINEVOX && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /home/milkwx3/workspace/RCRAFT-MINEVOX /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers /home/milkwx3/workspace/RCRAFT-MINEVOX /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers/CMakeFiles/helpers.dir/DependInfo.cmake "--color=$(COLOR)"
.PHONY : helpers/CMakeFiles/helpers.dir/depend
@@ -0,0 +1,25 @@
file(REMOVE_RECURSE
"CMakeFiles/helpers.dir/chunks.cpp.o"
"CMakeFiles/helpers.dir/chunks.cpp.o.d"
"CMakeFiles/helpers.dir/debug.cpp.o"
"CMakeFiles/helpers.dir/debug.cpp.o.d"
"CMakeFiles/helpers.dir/entities.cpp.o"
"CMakeFiles/helpers.dir/entities.cpp.o.d"
"CMakeFiles/helpers.dir/input.cpp.o"
"CMakeFiles/helpers.dir/input.cpp.o.d"
"CMakeFiles/helpers.dir/menu.cpp.o"
"CMakeFiles/helpers.dir/menu.cpp.o.d"
"CMakeFiles/helpers.dir/mesher.cpp.o"
"CMakeFiles/helpers.dir/mesher.cpp.o.d"
"CMakeFiles/helpers.dir/networking.cpp.o"
"CMakeFiles/helpers.dir/networking.cpp.o.d"
"CMakeFiles/helpers.dir/utils.cpp.o"
"CMakeFiles/helpers.dir/utils.cpp.o.d"
"libhelpers.a"
"libhelpers.pdb"
)
# Per-language clean rules from dependency scanning.
foreach(lang CXX)
include(CMakeFiles/helpers.dir/cmake_clean_${lang}.cmake OPTIONAL)
endforeach()
@@ -0,0 +1,3 @@
file(REMOVE_RECURSE
"libhelpers.a"
)
@@ -0,0 +1,2 @@
# Empty compiler generated dependencies file for helpers.
# This may be replaced when dependencies are built.
@@ -0,0 +1,2 @@
# CMAKE generated file: DO NOT EDIT!
# Timestamp file for compiler generated dependencies management for helpers.
@@ -0,0 +1,2 @@
# Empty dependencies file for helpers.
# This may be replaced when dependencies are built.
@@ -0,0 +1,10 @@
# CMAKE generated file: DO NOT EDIT!
# Generated by "Unix Makefiles" Generator, CMake Version 3.31
# compile CXX with /usr/bin/c++
CXX_DEFINES = -DGRAPHICS_API_OPENGL_33 -DPLATFORM_DESKTOP
CXX_INCLUDES = -I/home/milkwx3/workspace/RCRAFT-MINEVOX/helpers -I/home/milkwx3/workspace/RCRAFT-MINEVOX/libraries/raylib/src
CXX_FLAGS =
@@ -0,0 +1,2 @@
/usr/bin/ar qc libhelpers.a CMakeFiles/helpers.dir/chunks.cpp.o CMakeFiles/helpers.dir/debug.cpp.o CMakeFiles/helpers.dir/entities.cpp.o CMakeFiles/helpers.dir/input.cpp.o CMakeFiles/helpers.dir/menu.cpp.o CMakeFiles/helpers.dir/mesher.cpp.o CMakeFiles/helpers.dir/networking.cpp.o CMakeFiles/helpers.dir/utils.cpp.o
/usr/bin/ranlib libhelpers.a
@@ -0,0 +1,10 @@
CMAKE_PROGRESS_1 = 36
CMAKE_PROGRESS_2 = 37
CMAKE_PROGRESS_3 = 38
CMAKE_PROGRESS_4 = 39
CMAKE_PROGRESS_5 = 40
CMAKE_PROGRESS_6 = 41
CMAKE_PROGRESS_7 = 42
CMAKE_PROGRESS_8 = 43
CMAKE_PROGRESS_9 = 44
+1
View File
@@ -0,0 +1 @@
39
+39
View File
@@ -0,0 +1,39 @@
cmake_minimum_required(VERSION 3.14)
add_library(helpers STATIC
chunks.cpp
debug.cpp
entities.cpp
input.cpp
menu.cpp
mesher.cpp
networking.cpp
utils.cpp
locale.cpp
inventory.cpp
recipes.cpp
particles.cpp
player.cpp
multisound.cpp
svlib.cpp
)
execute_process(COMMAND date +v.%yw%W OUTPUT_VARIABLE BUILD_DATE OUTPUT_STRIP_TRAILING_WHITESPACE)
add_compile_definitions(GAME_VERSION="${BUILD_DATE}")
target_include_directories(helpers
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:include>
)
target_include_directories(helpers PRIVATE
../libraries/enet/include/.
../libraries/yaml-cpp/include/.
../libraries/Lua/lua-5.4.7/src/
)
target_sources(helpers
PUBLIC
FILE_SET headers TYPE HEADERS BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} FILES common.hpp
)
target_link_libraries(helpers PRIVATE raylib yaml-cpp lua_static)
+442
View File
@@ -0,0 +1,442 @@
# CMAKE generated file: DO NOT EDIT!
# Generated by "Unix Makefiles" Generator, CMake Version 3.31
# Default target executed when no arguments are given to make.
default_target: all
.PHONY : default_target
# Allow only one "make -f Makefile2" at a time, but pass parallelism.
.NOTPARALLEL:
#=============================================================================
# Special targets provided by cmake.
# Disable implicit rules so canonical targets will work.
.SUFFIXES:
# Disable VCS-based implicit rules.
% : %,v
# Disable VCS-based implicit rules.
% : RCS/%
# Disable VCS-based implicit rules.
% : RCS/%,v
# Disable VCS-based implicit rules.
% : SCCS/s.%
# Disable VCS-based implicit rules.
% : s.%
.SUFFIXES: .hpux_make_needs_suffix_list
# Command-line flag to silence nested $(MAKE).
$(VERBOSE)MAKESILENT = -s
#Suppress display of executed commands.
$(VERBOSE).SILENT:
# A target that is always out of date.
cmake_force:
.PHONY : cmake_force
#=============================================================================
# Set environment variables for the build.
# The shell in which to execute make rules.
SHELL = /bin/sh
# The CMake executable.
CMAKE_COMMAND = /usr/bin/cmake
# The command to remove a file.
RM = /usr/bin/cmake -E rm -f
# Escaping for special characters.
EQUALS = =
# The top-level source directory on which CMake was run.
CMAKE_SOURCE_DIR = /home/milkwx3/workspace/RCRAFT-MINEVOX
# The top-level build directory on which CMake was run.
CMAKE_BINARY_DIR = /home/milkwx3/workspace/RCRAFT-MINEVOX
#=============================================================================
# Targets provided globally by CMake.
# Special rule for the target package
package: preinstall
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Run CPack packaging tool..."
cd /home/milkwx3/workspace/RCRAFT-MINEVOX && /usr/bin/cpack --config ./CPackConfig.cmake
.PHONY : package
# Special rule for the target package
package/fast: package
.PHONY : package/fast
# Special rule for the target package_source
package_source:
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Run CPack packaging tool for source..."
cd /home/milkwx3/workspace/RCRAFT-MINEVOX && /usr/bin/cpack --config ./CPackSourceConfig.cmake /home/milkwx3/workspace/RCRAFT-MINEVOX/CPackSourceConfig.cmake
.PHONY : package_source
# Special rule for the target package_source
package_source/fast: package_source
.PHONY : package_source/fast
# Special rule for the target edit_cache
edit_cache:
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "No interactive CMake dialog available..."
/usr/bin/cmake -E echo No\ interactive\ CMake\ dialog\ available.
.PHONY : edit_cache
# Special rule for the target edit_cache
edit_cache/fast: edit_cache
.PHONY : edit_cache/fast
# Special rule for the target rebuild_cache
rebuild_cache:
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Running CMake to regenerate build system..."
/usr/bin/cmake --regenerate-during-build -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
.PHONY : rebuild_cache
# Special rule for the target rebuild_cache
rebuild_cache/fast: rebuild_cache
.PHONY : rebuild_cache/fast
# Special rule for the target list_install_components
list_install_components:
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Available install components are: \"Unspecified\""
.PHONY : list_install_components
# Special rule for the target list_install_components
list_install_components/fast: list_install_components
.PHONY : list_install_components/fast
# Special rule for the target install
install: preinstall
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Install the project..."
/usr/bin/cmake -P cmake_install.cmake
.PHONY : install
# Special rule for the target install
install/fast: preinstall/fast
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Install the project..."
/usr/bin/cmake -P cmake_install.cmake
.PHONY : install/fast
# Special rule for the target install/local
install/local: preinstall
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Installing only the local directory..."
/usr/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake
.PHONY : install/local
# Special rule for the target install/local
install/local/fast: preinstall/fast
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Installing only the local directory..."
/usr/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake
.PHONY : install/local/fast
# Special rule for the target install/strip
install/strip: preinstall
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Installing the project stripped..."
/usr/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake
.PHONY : install/strip
# Special rule for the target install/strip
install/strip/fast: preinstall/fast
@$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Installing the project stripped..."
/usr/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake
.PHONY : install/strip/fast
# The main all target
all: cmake_check_build_system
cd /home/milkwx3/workspace/RCRAFT-MINEVOX && $(CMAKE_COMMAND) -E cmake_progress_start /home/milkwx3/workspace/RCRAFT-MINEVOX/CMakeFiles /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers//CMakeFiles/progress.marks
cd /home/milkwx3/workspace/RCRAFT-MINEVOX && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 helpers/all
$(CMAKE_COMMAND) -E cmake_progress_start /home/milkwx3/workspace/RCRAFT-MINEVOX/CMakeFiles 0
.PHONY : all
# The main clean target
clean:
cd /home/milkwx3/workspace/RCRAFT-MINEVOX && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 helpers/clean
.PHONY : clean
# The main clean target
clean/fast: clean
.PHONY : clean/fast
# Prepare targets for installation.
preinstall: all
cd /home/milkwx3/workspace/RCRAFT-MINEVOX && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 helpers/preinstall
.PHONY : preinstall
# Prepare targets for installation.
preinstall/fast:
cd /home/milkwx3/workspace/RCRAFT-MINEVOX && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 helpers/preinstall
.PHONY : preinstall/fast
# clear depends
depend:
cd /home/milkwx3/workspace/RCRAFT-MINEVOX && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1
.PHONY : depend
# Convenience name for target.
helpers/CMakeFiles/helpers.dir/rule:
cd /home/milkwx3/workspace/RCRAFT-MINEVOX && $(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 helpers/CMakeFiles/helpers.dir/rule
.PHONY : helpers/CMakeFiles/helpers.dir/rule
# Convenience name for target.
helpers: helpers/CMakeFiles/helpers.dir/rule
.PHONY : helpers
# fast build rule for target.
helpers/fast:
cd /home/milkwx3/workspace/RCRAFT-MINEVOX && $(MAKE) $(MAKESILENT) -f helpers/CMakeFiles/helpers.dir/build.make helpers/CMakeFiles/helpers.dir/build
.PHONY : helpers/fast
chunks.o: chunks.cpp.o
.PHONY : chunks.o
# target to build an object file
chunks.cpp.o:
cd /home/milkwx3/workspace/RCRAFT-MINEVOX && $(MAKE) $(MAKESILENT) -f helpers/CMakeFiles/helpers.dir/build.make helpers/CMakeFiles/helpers.dir/chunks.cpp.o
.PHONY : chunks.cpp.o
chunks.i: chunks.cpp.i
.PHONY : chunks.i
# target to preprocess a source file
chunks.cpp.i:
cd /home/milkwx3/workspace/RCRAFT-MINEVOX && $(MAKE) $(MAKESILENT) -f helpers/CMakeFiles/helpers.dir/build.make helpers/CMakeFiles/helpers.dir/chunks.cpp.i
.PHONY : chunks.cpp.i
chunks.s: chunks.cpp.s
.PHONY : chunks.s
# target to generate assembly for a file
chunks.cpp.s:
cd /home/milkwx3/workspace/RCRAFT-MINEVOX && $(MAKE) $(MAKESILENT) -f helpers/CMakeFiles/helpers.dir/build.make helpers/CMakeFiles/helpers.dir/chunks.cpp.s
.PHONY : chunks.cpp.s
debug.o: debug.cpp.o
.PHONY : debug.o
# target to build an object file
debug.cpp.o:
cd /home/milkwx3/workspace/RCRAFT-MINEVOX && $(MAKE) $(MAKESILENT) -f helpers/CMakeFiles/helpers.dir/build.make helpers/CMakeFiles/helpers.dir/debug.cpp.o
.PHONY : debug.cpp.o
debug.i: debug.cpp.i
.PHONY : debug.i
# target to preprocess a source file
debug.cpp.i:
cd /home/milkwx3/workspace/RCRAFT-MINEVOX && $(MAKE) $(MAKESILENT) -f helpers/CMakeFiles/helpers.dir/build.make helpers/CMakeFiles/helpers.dir/debug.cpp.i
.PHONY : debug.cpp.i
debug.s: debug.cpp.s
.PHONY : debug.s
# target to generate assembly for a file
debug.cpp.s:
cd /home/milkwx3/workspace/RCRAFT-MINEVOX && $(MAKE) $(MAKESILENT) -f helpers/CMakeFiles/helpers.dir/build.make helpers/CMakeFiles/helpers.dir/debug.cpp.s
.PHONY : debug.cpp.s
entities.o: entities.cpp.o
.PHONY : entities.o
# target to build an object file
entities.cpp.o:
cd /home/milkwx3/workspace/RCRAFT-MINEVOX && $(MAKE) $(MAKESILENT) -f helpers/CMakeFiles/helpers.dir/build.make helpers/CMakeFiles/helpers.dir/entities.cpp.o
.PHONY : entities.cpp.o
entities.i: entities.cpp.i
.PHONY : entities.i
# target to preprocess a source file
entities.cpp.i:
cd /home/milkwx3/workspace/RCRAFT-MINEVOX && $(MAKE) $(MAKESILENT) -f helpers/CMakeFiles/helpers.dir/build.make helpers/CMakeFiles/helpers.dir/entities.cpp.i
.PHONY : entities.cpp.i
entities.s: entities.cpp.s
.PHONY : entities.s
# target to generate assembly for a file
entities.cpp.s:
cd /home/milkwx3/workspace/RCRAFT-MINEVOX && $(MAKE) $(MAKESILENT) -f helpers/CMakeFiles/helpers.dir/build.make helpers/CMakeFiles/helpers.dir/entities.cpp.s
.PHONY : entities.cpp.s
input.o: input.cpp.o
.PHONY : input.o
# target to build an object file
input.cpp.o:
cd /home/milkwx3/workspace/RCRAFT-MINEVOX && $(MAKE) $(MAKESILENT) -f helpers/CMakeFiles/helpers.dir/build.make helpers/CMakeFiles/helpers.dir/input.cpp.o
.PHONY : input.cpp.o
input.i: input.cpp.i
.PHONY : input.i
# target to preprocess a source file
input.cpp.i:
cd /home/milkwx3/workspace/RCRAFT-MINEVOX && $(MAKE) $(MAKESILENT) -f helpers/CMakeFiles/helpers.dir/build.make helpers/CMakeFiles/helpers.dir/input.cpp.i
.PHONY : input.cpp.i
input.s: input.cpp.s
.PHONY : input.s
# target to generate assembly for a file
input.cpp.s:
cd /home/milkwx3/workspace/RCRAFT-MINEVOX && $(MAKE) $(MAKESILENT) -f helpers/CMakeFiles/helpers.dir/build.make helpers/CMakeFiles/helpers.dir/input.cpp.s
.PHONY : input.cpp.s
menu.o: menu.cpp.o
.PHONY : menu.o
# target to build an object file
menu.cpp.o:
cd /home/milkwx3/workspace/RCRAFT-MINEVOX && $(MAKE) $(MAKESILENT) -f helpers/CMakeFiles/helpers.dir/build.make helpers/CMakeFiles/helpers.dir/menu.cpp.o
.PHONY : menu.cpp.o
menu.i: menu.cpp.i
.PHONY : menu.i
# target to preprocess a source file
menu.cpp.i:
cd /home/milkwx3/workspace/RCRAFT-MINEVOX && $(MAKE) $(MAKESILENT) -f helpers/CMakeFiles/helpers.dir/build.make helpers/CMakeFiles/helpers.dir/menu.cpp.i
.PHONY : menu.cpp.i
menu.s: menu.cpp.s
.PHONY : menu.s
# target to generate assembly for a file
menu.cpp.s:
cd /home/milkwx3/workspace/RCRAFT-MINEVOX && $(MAKE) $(MAKESILENT) -f helpers/CMakeFiles/helpers.dir/build.make helpers/CMakeFiles/helpers.dir/menu.cpp.s
.PHONY : menu.cpp.s
mesher.o: mesher.cpp.o
.PHONY : mesher.o
# target to build an object file
mesher.cpp.o:
cd /home/milkwx3/workspace/RCRAFT-MINEVOX && $(MAKE) $(MAKESILENT) -f helpers/CMakeFiles/helpers.dir/build.make helpers/CMakeFiles/helpers.dir/mesher.cpp.o
.PHONY : mesher.cpp.o
mesher.i: mesher.cpp.i
.PHONY : mesher.i
# target to preprocess a source file
mesher.cpp.i:
cd /home/milkwx3/workspace/RCRAFT-MINEVOX && $(MAKE) $(MAKESILENT) -f helpers/CMakeFiles/helpers.dir/build.make helpers/CMakeFiles/helpers.dir/mesher.cpp.i
.PHONY : mesher.cpp.i
mesher.s: mesher.cpp.s
.PHONY : mesher.s
# target to generate assembly for a file
mesher.cpp.s:
cd /home/milkwx3/workspace/RCRAFT-MINEVOX && $(MAKE) $(MAKESILENT) -f helpers/CMakeFiles/helpers.dir/build.make helpers/CMakeFiles/helpers.dir/mesher.cpp.s
.PHONY : mesher.cpp.s
networking.o: networking.cpp.o
.PHONY : networking.o
# target to build an object file
networking.cpp.o:
cd /home/milkwx3/workspace/RCRAFT-MINEVOX && $(MAKE) $(MAKESILENT) -f helpers/CMakeFiles/helpers.dir/build.make helpers/CMakeFiles/helpers.dir/networking.cpp.o
.PHONY : networking.cpp.o
networking.i: networking.cpp.i
.PHONY : networking.i
# target to preprocess a source file
networking.cpp.i:
cd /home/milkwx3/workspace/RCRAFT-MINEVOX && $(MAKE) $(MAKESILENT) -f helpers/CMakeFiles/helpers.dir/build.make helpers/CMakeFiles/helpers.dir/networking.cpp.i
.PHONY : networking.cpp.i
networking.s: networking.cpp.s
.PHONY : networking.s
# target to generate assembly for a file
networking.cpp.s:
cd /home/milkwx3/workspace/RCRAFT-MINEVOX && $(MAKE) $(MAKESILENT) -f helpers/CMakeFiles/helpers.dir/build.make helpers/CMakeFiles/helpers.dir/networking.cpp.s
.PHONY : networking.cpp.s
utils.o: utils.cpp.o
.PHONY : utils.o
# target to build an object file
utils.cpp.o:
cd /home/milkwx3/workspace/RCRAFT-MINEVOX && $(MAKE) $(MAKESILENT) -f helpers/CMakeFiles/helpers.dir/build.make helpers/CMakeFiles/helpers.dir/utils.cpp.o
.PHONY : utils.cpp.o
utils.i: utils.cpp.i
.PHONY : utils.i
# target to preprocess a source file
utils.cpp.i:
cd /home/milkwx3/workspace/RCRAFT-MINEVOX && $(MAKE) $(MAKESILENT) -f helpers/CMakeFiles/helpers.dir/build.make helpers/CMakeFiles/helpers.dir/utils.cpp.i
.PHONY : utils.cpp.i
utils.s: utils.cpp.s
.PHONY : utils.s
# target to generate assembly for a file
utils.cpp.s:
cd /home/milkwx3/workspace/RCRAFT-MINEVOX && $(MAKE) $(MAKESILENT) -f helpers/CMakeFiles/helpers.dir/build.make helpers/CMakeFiles/helpers.dir/utils.cpp.s
.PHONY : utils.cpp.s
# Help Target
help:
@echo "The following are some of the valid targets for this Makefile:"
@echo "... all (the default if no target is provided)"
@echo "... clean"
@echo "... depend"
@echo "... edit_cache"
@echo "... install"
@echo "... install/local"
@echo "... install/strip"
@echo "... list_install_components"
@echo "... package"
@echo "... package_source"
@echo "... rebuild_cache"
@echo "... helpers"
@echo "... chunks.o"
@echo "... chunks.i"
@echo "... chunks.s"
@echo "... debug.o"
@echo "... debug.i"
@echo "... debug.s"
@echo "... entities.o"
@echo "... entities.i"
@echo "... entities.s"
@echo "... input.o"
@echo "... input.i"
@echo "... input.s"
@echo "... menu.o"
@echo "... menu.i"
@echo "... menu.s"
@echo "... mesher.o"
@echo "... mesher.i"
@echo "... mesher.s"
@echo "... networking.o"
@echo "... networking.i"
@echo "... networking.s"
@echo "... utils.o"
@echo "... utils.i"
@echo "... utils.s"
.PHONY : help
#=============================================================================
# Special targets to cleanup operation of make.
# Special rule to run CMake to check the build system integrity.
# No rule that depends on this can have commands that come from listfiles
# because they might be regenerated.
cmake_check_build_system:
cd /home/milkwx3/workspace/RCRAFT-MINEVOX && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0
.PHONY : cmake_check_build_system
+687
View File
@@ -0,0 +1,687 @@
#include <stdint.h>
#include <stdbool.h>
#include "common.hpp"
#include <cstring>
#include <list>
#include <fstream>
#include <vector>
#include <iostream>
#define HUMIDITY_OFFSET 12.3f
#define CAVE_OFFSET 45.6f
#define SCALE 0.01f
#define CAVE_COEFF 0.06
#define EDGES_FADE 64
#define CLOUD_SCALE 0.25f
#define BIOME_FOREST 0
#define BIOME_TAIGA 1
static const siv::PerlinNoise perlin;
static int world_type = 0;
const BlockDef BLOCKS[] = {
BlockDef{ "air", R_Translucent, B_Stone, 0, 0, 0},
BlockDef{ "stone", R_Normal, B_Stone, 7, 0, 3},
BlockDef{ "grass", R_TriSide, B_Grass, 1, 0, 0, 1, 2},
BlockDef{ "dirt", R_Normal, B_Dirt, 2, 0, 2},
BlockDef{ "sand", R_Normal, B_Dirt, 2, 0, 4},
BlockDef{ "water", R_Translucent, B_Stone, 0, 0, 14},
BlockDef{ "planks", R_Normal, B_Wood, 3, 0, 11},
BlockDef{ "gray_bricks", R_Normal, B_Stone, 5, 1, 16},
BlockDef{ "red_bricks", R_Normal, B_Stone, 5, 1, 17},
BlockDef{ "blue_bricks", R_Normal, B_Stone, 5, 1, 18},
BlockDef{ "green_bricks", R_Normal, B_Stone, 5, 1, 19},
BlockDef{ "glass", R_Translucent, B_Stone, 3, 1, 12},
BlockDef{ "log", R_TriSide, B_Wood, 5, 0, 10, 9, 10},
BlockDef{ "spruce_planks", R_Normal, B_Wood, 3, 0, 13},
BlockDef{ "spruce_log", R_TriSide, B_Wood, 5, 0, 21, 20, 21},
BlockDef{ "workbench", R_TranslucentAllSides, B_Stone, 3, 0, 23, 22, 23},
BlockDef{ "blue_block", R_Normal, B_Stone, 5, 0, 22},
BlockDef{ "yellow_block", R_Normal, B_Stone, 5, 0, 23},
BlockDef{ "cyan_block", R_Normal, B_Stone, 5, 0, 24},
BlockDef{ "magenta_block", R_Normal, B_Stone, 5, 0, 25},
BlockDef{ "white_block", R_Normal, B_Stone, 5, 0, 26},
BlockDef{ "black_block", R_Normal, B_Stone, 5, 0, 27},
BlockDef{ "leaves", R_TranslucentAllSides, B_Grass, 1, 0, 28},
BlockDef{ "copper_ore", R_Normal, B_Stone, 7, 1, 5},
BlockDef{ "silver_ore", R_Normal, B_Stone, 7, 2, 6},
BlockDef{ "gold_ore", R_Normal, B_Stone, 7, 3, 7},
BlockDef{ "coal_ore", R_Normal, B_Stone, 7, 0, 8},
BlockDef{ "unobtainium", R_Normal, B_Stone, 7, 999, 3}, // Bedrock?
};
int GetNumericIDFromString(std::string s) {
int count = sizeof(BLOCKS) / sizeof(BLOCKS[0]);
for (int i = 0; i < count; ++i) {
if (BLOCKS[i].name == s) return i;
}
return -1;
}
static std::bitset<256> marked;
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;
float fade_z = (fmax(EDGES_FADE - z, 0) + fmax(EDGES_FADE - WORLD_SIZE_BLOCKS + z, 0)) / (float)EDGES_FADE;
float fade = 1 - (fade_x + fade_z);
const int SEA_HEIGHT = 32; // sea surface y
const int BEACH_DEPTH = 3; // how many blocks below surface become sand
float height0 = (perlin.noise2D((double)x * 1.5f * SCALE, (double)z * 1.5f * SCALE) + 1.0f ) / 2.0f * 16.0f;
float mountains = pow((perlin.noise2D((double)x * 0.5f, (double)z * 0.5f * SCALE) + 1.0f ) / 2.0f, 16);
float height1 = (perlin.noise2D((double)x * 4.5f * SCALE, (double)z * 4.5f * SCALE) + 1.0f ) / 2.0f * 24.0f * mountains;
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 (height <= SEA_HEIGHT) {
return BLOCK_SAND;
}
return BLOCK_GRASS;
}
if (y > height - BEACH_DEPTH && height <= SEA_HEIGHT + 2) {
return BLOCK_SAND;
}
if(caveNoise < 0.2f || y < 4) return BLOCK_STONE;
return BLOCK_DIRT;
}
if (y <= SEA_HEIGHT && height < SEA_HEIGHT) {
return BLOCK_WATERS;
}
return BLOCK_AIR;
}
bool CanTick(int blockType) { // TODO: make smarter in case other blocks can tick too!
return blockType == BLOCK_SAND;
}
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;
}
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;
if(caveNoise > 0.5f) {
return BLOCK_STONE;
}
return BLOCK_AIR;
}
static int has_block(int x, int y, int z)
{
switch (world_type)
{
case 0:
return GetBlockRegularWorld(x, y, z);
break;
case 1:
return GetBlockCaveWorld(x, y, z);
break;
case 254:
if(y == 0 + x / 16) {
return BLOCK_STONE;
}
break;
case 255:
if((y >= 63 || y == 61) && (x < 4 && z < 4)) {
return BLOCK_STONE;
}
break;
default:
const int baseHeight = 32;
if(y <= baseHeight / 3) {
return BLOCK_STONE;
}
if (y > baseHeight / 3 && y < baseHeight)
{
return BLOCK_DIRT;
}
if (y == baseHeight)
{
return BLOCK_GRASS;
}
break;
}
return BLOCK_AIR;
}
bool IsTranslucent(int blockType) {
return marked.test(blockType);
}
void SetBlockChunk(Chunk *c, int x, int y, int z, int t) {
c->blocks[GetIndexChunk(x,y,z)] = t;
if(y >= c->highestBlock[GetIndexChunk2D(x, z)]) {
if(t != 0) {
c->highestBlock[GetIndexChunk2D(x, z)] = y;
}
else {
for (int _y = y-1; _y >= 0; _y--)
{
/*if(!IsTranslucent(c->blocks[GetIndexChunk(x,_y,z)])) {
c->highestBlock[GetIndexChunk2D(x, z)] = _y;
break;
}*/
if(c->blocks[GetIndexChunk(x,_y,z)] != 0) {
c->highestBlock[GetIndexChunk2D(x, z)] = _y;
break;
}
}
}
}
}
void RebuildHeightmap(Chunk *c) {
for (int x = 0; x < CHUNK_SIZE; x++)
{
for (int z = 0; z < CHUNK_SIZE; z++)
{
for (int y = WORLD_HEIGHT-1; y >= 0; y--)
{
if(c->blocks[GetIndexChunk(x,y,z)] != 0) {
c->highestBlock[GetIndexChunk2D(x, z)] = y;
break;
}
}
}
}
}
int GetBiome(int sx, int sy) {
return BIOME_TAIGA;
}
void SetBlockChunkFast(Chunk *c, int i, int t) {
c->blocks[i] = t;
}
void SetBlock(Chunk world[], int x, int y, int z, int t) {
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;
SetBlockChunk(&world[GetIndexWorld(cx, cz)], locX, y, locZ, t);
}
void InitWorldgen(int worldType) {
const siv::PerlinNoise::seed_type seed = 123456u;
const siv::PerlinNoise perlin{ seed };
constexpr size_t MAX = 128; // allowed range: 0..MAX-1
for (int i = 0; i < sizeof(BLOCKS) / sizeof(BlockDef); i++)
{
BlockDef def = BLOCKS[i];
if(def.render == R_Translucent || def.render == R_TranslucentAllSides || def.render == R_TranslucentTriSide) {
marked.set(i);
}
}
world_type = worldType;
}
Vector3 WorldPosition(int cx, int cz, int localX, int y, int localZ) {
return { (float)cx * CHUNK_SIZE + localX, (float)y, (float)cz * CHUNK_SIZE + localZ };
}
Chunk GenerateChunk(int _x, int _y) {
Chunk new_chunk = { 0 };
new_chunk.x = _x;
new_chunk.z = _y;
for (int x = 0; x < CHUNK_SIZE; x++)
{
for (int y = 0; y < WORLD_HEIGHT; y++)
{
for (int z = 0; z < CHUNK_SIZE; z++)
{
int id = has_block(_x * CHUNK_SIZE + x,y,_y * CHUNK_SIZE + z);
SetBlockChunk(&new_chunk, x, y, z, id);
}
}
}
return new_chunk;
}
void GenerateWorldAdditional(Chunk world[]) {
int biome = GetBiome(0, 0);
SetRandomSeed(0);
switch (world_type)
{
case 0:
for (int x = 0; x < WORLD_SIZE_BLOCKS; x++)
{
for (int z = 0; z < WORLD_SIZE_BLOCKS; z++) {
Chunk c = world[GetIndexWorld(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);
for (int _ = 0; _ < GetRandomValue(0, 6); _++)
{
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); _++)
{
if(GetRandomValue(0, 100) == 0) {
Vector3 pos = {x, GetRandomValue(2, WORLD_HEIGHT-24), z};
int type = 23;
if(pos.y < 24)
type = 24;
if(pos.y < 12)
type = 25;
int radius = 2;
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) && GetBlock(world, pos.x + x, pos.y + y, pos.z + z) == BLOCK_STONE) {
SetBlock(world, pos.x + x, pos.y + y, pos.z + z, type);
}
}
}
}
}
}
}
}
}
break;
}
switch (world_type)
{
case 0:
for (int x = 0; x < WORLD_SIZE_BLOCKS; x++)
{
for (int z = 0; z < WORLD_SIZE_BLOCKS; z++) {
Chunk c = world[GetIndexWorld(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);
if(b == BLOCK_GRASS && GetRandomValue(0, 100) < 4 && biome == BIOME_FOREST) { // Regular trees
SetBlock(world, x, highestY, z, BLOCK_DIRT);
int maxY = GetRandomValue(5, 7);
for (int y = 1; y < maxY; y++)
{
int wy = highestY + y;
if(y > 2) { //leaves
SetBlock(world, x-1, wy, z, 22);
SetBlock(world, x+1, wy, z, 22);
SetBlock(world, x, wy, z-1, 22);
SetBlock(world, x, wy, z+1, 22);
SetBlock(world, x, wy+1, z, 22);
}
SetBlock(world, x, wy, z, 12); // log
}
}
if(b == BLOCK_GRASS && GetRandomValue(0, 100) < 2 && biome == BIOME_TAIGA) { // Spruce
SetBlock(world, x, highestY, z, BLOCK_DIRT);
int maxY = 8;
for (int y = 1; y < maxY; y++)
{
int wy = highestY + y;
const int lower_size = 3;
const int upper_size = 2;
if(y > 2) { //leaves
if(y == 3) {
for (int _x = -lower_size; _x <= lower_size; _x++)
{
for (int _z = -lower_size; _z <= lower_size; _z++)
{
if(
!(fabs(_z) == lower_size && fabs(_x) == lower_size)
) SetBlock(world, x+_x, wy, z+_z, 22);
}
}
}
else {
if(y == maxY-1) {
SetBlock(world, x-1, wy+1, z, 22);
SetBlock(world, x+1, wy+1, z, 22);
SetBlock(world, x, wy+1, z-1, 22);
SetBlock(world, x, wy+1, z+1, 22);
SetBlock(world, x, wy+1, z, 22);
}
if(y == 4) {
for (int _x = -upper_size; _x <= upper_size; _x++)
{
for (int _z = -upper_size; _z <= upper_size; _z++)
{
if(
!(fabs(_z) == upper_size && fabs(_x) == upper_size)
) SetBlock(world, x+_x, wy, z+_z, 22);
}
}
}
if(y > 4 && y%2 == 0) {
SetBlock(world, x-1, wy, z, 22);
SetBlock(world, x+1, wy, z, 22);
SetBlock(world, x, wy, z-1, 22);
SetBlock(world, x, wy, z+1, 22);
SetBlock(world, x, wy, z, 22);
}
}
}
SetBlock(world, x, wy, z, 14); // log
}
}
if(!marked.test(b) && GetRandomValue(0, 800) == 0) {
int maxY = GetRandomValue(5, 7);
for (int _x = -1; _x <= 1; _x++)
for (int _z = -1; _z <= 1; _z++) {
int t = BLOCK_STONE;
if(GetRandomValue(0, 50) == 0) t = 23;
SetBlock(world, x+_x-1, highestY+1, z+_z-1, t);
}
for (int _x = -1; _x <= 1; _x++)
for (int _z = -1; _z <= 1; _z++)
if(_x != _z) {
int t = BLOCK_STONE;
if(GetRandomValue(0, 80) == 0) t = 23;
SetBlock(world, x+_x-1, highestY+2, z+_z-1, t);
}
SetBlock(world, x-1, highestY+2, z-1, BLOCK_STONE);
SetBlock(world, x-1, highestY+3, z-1, BLOCK_STONE);
}
}
}
break;
}
switch (world_type)
{
case 0:
for (int x = 0; x < WORLD_SIZE_BLOCKS; x++)
{
for (int z = 0; z < WORLD_SIZE_BLOCKS; z++) {
SetBlock(world, x, 1, z, 27);
}
}
break;
}
}
void TickBlock(Chunk world[], int wx, int wy, int wz) {
if(CheckOOBWorld(wx, wy, wz)) return;
int tile = GetBlock(world, wx, wy, wz);
if(tile == BLOCK_SAND) {
if(GetBlock(world, wx, wy-1, wz) == 0) {
SetBlockNetwork(world, wx, wy, wz, 0);
Entity temp = NewEntity();
temp.type = 4;
temp.position = (Vector3){wx, wy, wz};
temp.velocity = {0, 0, 0};
temp.data[1] = BLOCK_SAND;
AddEntity(temp);
}
}
}
void TickChunk(Chunk *chunk, Chunk *world, int wx, int wz) {
for (int y = WORLD_HEIGHT-1; y > 1; y--) {
for (int x = 0; x < CHUNK_SIZE; x++)
{
for (int z = 0; z < CHUNK_SIZE; z++)
{
int tile = fetch_block_ptr(chunk, x, y, z);
if(tile == BLOCK_SAND) {
if(fetch_block_ptr(chunk, x, y-1, z) == 0) {
SetBlockChunk(chunk, x, y, z, 0);
Entity temp = NewEntity();
temp.type = 4;
temp.position = (Vector3){((int)wx * CHUNK_SIZE + x), y, ((int)wz * CHUNK_SIZE + z)};
temp.velocity = {0, 0, 0};
temp.data[1] = BLOCK_SAND;
AddEntity(temp);
chunk->isDirty = true;
}
}
if(false) { // tile == BLOCK_WATERS
int rx = GetRandomValue(-1, 1);
int rz = GetRandomValue(-1, 1);
for (int _y = 0; _y >= -1; _y--)
{
if(GetBlock(world, wx+x+rx, y+_y, wz+z+rz) == 0) {
SetBlockChunk(chunk, x, y+_y, z, 0);
SetBlock(world, wx+x+rx, y+_y, wz+z+rz, BLOCK_WATERS);
chunk->isDirty = true;
continue;
}
}
}
}
}
}
}
void RebuildOpaqueMask(Chunk *chunk) {
const int GROUP = 16;
const int GROUPS = CHUNK_DATA_SIZE / GROUP;
uint16_t oMask[GROUPS] = { 0 };
uint16_t aMask[GROUPS] = { 0 };
uint8_t blocks[CHUNK_DATA_SIZE];
memcpy(blocks, chunk->blocks, sizeof(blocks));
for (int i = 0; i < CHUNK_DATA_SIZE; ++i) {
int g = i / GROUP;
int bit = i % GROUP;
if (chunk->blocks[i] == 0) {
aMask[g] |= 1 << bit;
}
if (!IsTranslucent(chunk->blocks[i])) {
oMask[g] |= 1 << bit;
}
}
memcpy(chunk->opaqueMask, oMask, sizeof(oMask));
memcpy(chunk->airMask, aMask, sizeof(aMask));
}
#ifndef SERVER
//Generates an opaque CRD (ChunkRenderData). Outputs the CRD.
ChunkRenderData GenerateCRDOpaque(const Chunk &chunk, Chunk world[]) {
struct ChunkRenderData new_chunk = { 0 };
uint16_t mask[CHUNK_DATA_SIZE/16];
memcpy(mask, chunk.opaqueMask, sizeof(chunk.opaqueMask));
const int cxw = chunk.x * CHUNK_SIZE;
const int cxz = chunk.z * CHUNK_SIZE;
const int chunkMaskSize = CHUNK_DATA_SIZE/16;
for (int step = 0; step < chunkMaskSize; ++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;
//int _x, y, _z;
//GetXYZFromIndex(i2, &_x, &y, &_z);
if (!TestMask(mask, i2)) continue; // Skip if this is translucent
int x = _x + cxw;
int z = _z + cxz;
bool l = (_x > 0) ? TestMask(mask, i2-1) : TestOpaqueMaskWorld(world, x - 1, y, z);
bool r = (_x < CHUNK_SIZE-1) ? TestMask(mask, i2+1) : TestOpaqueMaskWorld(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) ? TestOpaqueMaskWorld(world, x, y, z - 1) : TestMask(mask, i2-CHUNK_SIZE);
bool f = (_z==CHUNK_SIZE-1) ? TestOpaqueMaskWorld(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 translucent CRD (ChunkRenderData). Outputs the CRD.
ChunkRenderData GenerateCRDTranslucent(Chunk chunk, Chunk 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)].render == R_TranslucentAllSides) {
new_chunk.sides[i2] = 0xFF;
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;
}
#endif
#define SAVE_FORMAT 0
void SaveWorld(Chunk world[], const char* path) {
std::ofstream data(path, std::ios::binary);
if (!data) return;
data.write("WFF", 3);
char fmt = static_cast<char>(SAVE_FORMAT);
data.write(&fmt, 1);
for (int i = 0; i < MAX_WORLD_AREA; ++i) {
const Chunk &c = world[i];
std::vector<uint8_t> temp;
int last_type = -1;
uint8_t count = 0;
for (int j = 0; j < CHUNK_DATA_SIZE; ++j) {
uint8_t b = c.blocks[j];
if (last_type == -1) {
last_type = b;
count = 1;
} else if (b == last_type && count < 255) {
++count;
} else {
temp.push_back(count);
temp.push_back(static_cast<uint8_t>(last_type));
last_type = b;
count = 1;
}
}
if (last_type != -1) {
temp.push_back(count);
temp.push_back(static_cast<uint8_t>(last_type));
}
uint16_t size = static_cast<uint16_t>(temp.size());
data.write(reinterpret_cast<const char*>(&size), sizeof(size));
if (!temp.empty()) {
data.write(reinterpret_cast<const char*>(temp.data()), temp.size());
}
}
data.close();
}
void Debug_Write(const std::string &stuff);
bool LoadWorld(Chunk world[], const char* path) {
std::ifstream data(path, std::ios::binary);
if (!data) return false;
char header[3];
if (!data.read(header, 3)) return false;
if (std::memcmp(header, "WFF", 3) != 0) return false;
char fmt;
if (!data.read(&fmt, 1)) return false;
uint8_t* temp = (uint8_t*)malloc(65535);
for (int i = 0; i < MAX_WORLD_AREA; ++i) {
printf("[PRINTF] Chunk %d\n", i);
uint16_t size = 0;
Debug_Write("Trying to read size");
if (!data.read(reinterpret_cast<char*>(&size), sizeof(size))) {
free(temp);
return false;
};
printf("[PRINTF] Size %d\n", size);
if (size > 0) {
if (!data.read(reinterpret_cast<char*>(temp), size)) {
free(temp);
return false;
}
}
Chunk *c = &world[i];
int outIndex = 0;
for (size_t p = 0; p + 1 < size; p += 2) {
uint8_t count = temp[p];
uint8_t value = temp[p + 1];
for (uint8_t k = 0; k < count; ++k) {
SetBlockChunkFast(c, outIndex++, value);
}
}
while (outIndex < CHUNK_DATA_SIZE) {
SetBlockChunkFast(c, outIndex++, 0);
}
RebuildHeightmap(c);
}
free(temp);
return true;
}
+50
View File
@@ -0,0 +1,50 @@
# Install script for directory: /home/milkwx3/workspace/RCRAFT-MINEVOX/helpers
# Set the install prefix
if(NOT DEFINED CMAKE_INSTALL_PREFIX)
set(CMAKE_INSTALL_PREFIX "/usr/local")
endif()
string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
# Set the install configuration name.
if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
if(BUILD_TYPE)
string(REGEX REPLACE "^[^A-Za-z0-9_]+" ""
CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}")
else()
set(CMAKE_INSTALL_CONFIG_NAME "")
endif()
message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"")
endif()
# Set the component getting installed.
if(NOT CMAKE_INSTALL_COMPONENT)
if(COMPONENT)
message(STATUS "Install component: \"${COMPONENT}\"")
set(CMAKE_INSTALL_COMPONENT "${COMPONENT}")
else()
set(CMAKE_INSTALL_COMPONENT)
endif()
endif()
# Install shared libraries without execute permission?
if(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE)
set(CMAKE_INSTALL_SO_NO_EXE "1")
endif()
# Is this installation the result of a crosscompile?
if(NOT DEFINED CMAKE_CROSSCOMPILING)
set(CMAKE_CROSSCOMPILING "FALSE")
endif()
# Set path to fallback-tool for dependency-resolution.
if(NOT DEFINED CMAKE_OBJDUMP)
set(CMAKE_OBJDUMP "/usr/bin/objdump")
endif()
string(REPLACE ";" "\n" CMAKE_INSTALL_MANIFEST_CONTENT
"${CMAKE_INSTALL_MANIFEST_FILES}")
if(CMAKE_INSTALL_LOCAL_ONLY)
file(WRITE "/home/milkwx3/workspace/RCRAFT-MINEVOX/helpers/install_local_manifest.txt"
"${CMAKE_INSTALL_MANIFEST_CONTENT}")
endif()
+623
View File
@@ -0,0 +1,623 @@
#if defined(WIN32)
#include "external/fix_win32_compatibility.h"
#endif
#include "glfw_keycodes_to_string.h"
#include "../PerlinNoise.hpp"
#include <enet/enet.h>
#include "raylib.h"
#include "raymath.h"
#include <stdint.h>
#include <bitset>
#include <cstdint>
#include <list>
#define FOV 90
#define WIDTH 1024.0
#define HEIGHT 600.0
#define ASPECT WIDTH / HEIGHT
#define CHUNK_SIZE 16 // W & H
#define WORLD_HEIGHT 128
#define CHUNK_DATA_SIZE CHUNK_SIZE*CHUNK_SIZE*WORLD_HEIGHT
#define CHUNK_SIZE_SQR CHUNK_SIZE*CHUNK_SIZE
#define MAX_WORLD_SIZE 16
#define MAX_WORLD_AREA MAX_WORLD_SIZE*MAX_WORLD_SIZE
#define WORLD_SIZE_BLOCKS MAX_WORLD_SIZE * CHUNK_SIZE
#define ATLAS_SIZE_W 16
#define ATLAS_SIZE_H 16
#define ITEM_ATLAS_SIZE 16
#define ITEM_SIZE 16
#define PLAYER_HEIGHT 1.75f
#define PLAYER_RADIUS 0.25f
#define GRAVITY 20.0f
#define MOVE_SPEED 6.0f
#define JUMP_SPEED 8.0f
#define DELTA_SMOOTH 0.016f
#define MOUSE_SENS 0.0025f
#define PITCH_MIN -1.47f // ~-83 degrees
#define PITCH_MAX 1.47f // ~ 83 degrees
#define SMOOTH_FACTOR 12.0f // larger = snappier
#define BLOCK_AIR 0
#define BLOCK_STONE 1
#define BLOCK_GRASS 2
#define BLOCK_DIRT 3
#define BLOCK_SAND 4
#define BLOCK_WATERS 5
#define MAX_BLOCK_ID 28
#define CLOUD_FADE_BLOCKS CHUNK_SIZE*8
#define PORT 25565
#define MAX_MESSAGE_LENGTH 64
#define NET_ARG_NONE 0x00 // Invalid
#define NET_ARG_CHUNKF 0x01 // Byte 1 - chunk ID, uint8_t blocks[16*64*16], uint8_t highestBlock[16*16]
#define NET_ARG_BLOCK 0x02 // Player ID, block X, block Y, block Z, block type
#define NET_ARG_PLRCON 0x03 // Byte 1 - ID
#define NET_ARG_PLRDCN 0x04 // Byte 1 - ID
#define NET_ARG_PLRID 0x05 // Byte 1 - Server-assigned ID to the player
#define NET_ARG_ECHOMOVE 0x06 // Byte 1 - player ID, bytes 2-3 - echoed player X, bytes 4-5 - echoed player Y, bytes 6-7 - echoed player Z, byte 8 - player yaw
#define NET_ARG_PLRREG 0x07 // Same as ECHOMOVE, used as an answer to REQPLAYERS
#define NET_ARG_ECHOYAW 0x08 // Byte 1 - ID, byte 2 - yaw
#define NET_ARG_MESSAGEE 0x09 // Byte 1 - sender ID, byte 2 - length, rest is message (128b max)
#define NET_ARG_PLAYERMOVE 0x80 // Byte 1-2 - player X, byte 3-4 - player Y, byte 5-6 - player Z, byte 7 - player yaw
#define NET_ARG_BLOCKDELTA 0x81 // Block X, block Y, block Z, block type
#define NET_ARG_REQWORLD 0x82 // No additional data
#define NET_ARG_REQPLAYERS 0x83 // No additional data
#define NET_ARG_PLAYERYAW 0x84 // Byte 1 - yaw
#define NET_ARG_MESSAGEC 0x85 // All is message (64b max)
#define NET_ERROR_DSCN 0x00
#define NET_ERROR_NOTFOUND 0x01
#define NET_ERROR_FAILED 0x02
#define NET_ERROR_INTERNAL 0x03
#define GAME_NAME "CubeGame"
#define GAME_VERSION_INT 0
#define DEFAULT_FONT_SIZE 16
#define TPS 30.0
#define TPS_DIV 1.0 / TPS
#define RENDER_DISTANCE 16
#define RENDER_DISTANCE_SQUARED RENDER_DISTANCE*RENDER_DISTANCE
#define MAX_HP 100
#define PATH_APPEND "resources/"
#define PATH_APPEND_USER "user/"
#define ITEMS 9
#define INVENTORY_WIDTH 8
#define INVENTORY_HEIGHT 6
#define INVENTORY_SIZE INVENTORY_WIDTH*INVENTORY_HEIGHT
enum BlockType {
B_Wood,
B_Stone,
B_Grass,
B_Dirt
};
typedef enum BlockType BlockType;
typedef struct BlockDef BlockDef;
enum BlockRendering {
R_None,
R_Normal,
R_TriSide,
R_Translucent,
R_TranslucentTriSide,
R_TranslucentAllSides
};
typedef enum BlockRendering BlockRendering;
struct BlockDef {
const std::string name;
BlockRendering render;
uint8_t textureTop;
uint8_t textureSide;
uint8_t textureBottom;
int hardness;
int min_tier;
BlockType type;
// Constructor with initializer list; textureSide/textureBottom default to textureTop if not provided.
BlockDef(
std::string _name,
BlockRendering render_ = R_None,
BlockType btype = B_Stone,
int _hardness = 1,
int _min_tier = 0,
uint8_t textureTop_ = 255,
uint8_t textureSide_ = 255,
uint8_t textureBottom_ = 255)
: name(_name),
render(render_),
hardness(_hardness),
min_tier(_min_tier),
textureTop(textureTop_),
textureSide(textureSide_ == 255 ? textureTop_ : textureSide_),
textureBottom(textureBottom_ == 255 ? textureTop_ : textureBottom_),
type(btype)
{}
};
enum GameState {
GAME_STATE_LOADING,
GAME_STATE_GAME,
GAME_STATE_MAINMENU,
GAME_STATE_WORLDSELECT,
GAME_STATE_MULTIPLAYERSELECT,
GAME_STATE_TRANSITION,
GAME_STATE_WORLD_CREATE,
GAME_STATE_OPTIONS
};
typedef enum GameState GameState;
typedef struct Chunk Chunk;
struct Chunk {
uint8_t x;
uint8_t z;
bool isDirty;
uint8_t blocks[CHUNK_DATA_SIZE];
uint16_t opaqueMask[CHUNK_DATA_SIZE/16];
uint16_t airMask[CHUNK_DATA_SIZE/16];
uint8_t highestBlock[CHUNK_SIZE*CHUNK_SIZE];
};
#if !defined(SERVER)
typedef struct ChunkRenderData ChunkRenderData;
struct ChunkRenderData {
uint8_t sides[CHUNK_DATA_SIZE];
};
typedef struct MeshData MeshData;
struct MeshData {
float *positions; // xyz xyz ...
float *normals; // xyz ...
float *uvs; // uv uv ...
unsigned char *colors; // rgba rgba ...
unsigned short *indices; // triangles
unsigned short vertexCount;
unsigned short indexCount;
};
typedef struct ChunkMeshData ChunkMeshData;
struct ChunkMeshData {
uint8_t *positions; // xyz xyz ...
uint8_t *luminosity; // l l ...
float *uvs; // uv uv ...
unsigned short *indices; // triangles
unsigned short vertexCount;
unsigned short indexCount;
};
typedef struct UVCorners UVCorners;
struct UVCorners {
Vector2 corner0;
Vector2 corner1;
Vector2 corner2;
Vector2 corner3;
};
typedef struct Quad2D Quad2D;
struct Quad2D {
int x;
int y;
int w;
int h;
};
#endif
typedef struct Vector3I Vector3I;
struct Vector3I {
int x;
int y;
int z;
};
typedef struct Entity Entity;
struct Entity {
uint8_t type;
uint8_t id;
uint8_t damage_flash;
uint8_t data[16];
float smoothing;
float health;
float lifetime;
Vector3 position;
Vector3 velocity;
unsigned short yaw;
bool free;
};
typedef struct NetPlayer NetPlayer;
struct NetPlayer {
ENetPeer* peer;
int addr;
int port;
int id;
int yaw;
float x;
float y;
float z;
};
typedef struct MemInfo MemInfo;
struct MemInfo {
uint64_t resident;
uint64_t virtualSize;
uint64_t privateBytes;
};
enum ItemType {
IType_Generic,
IType_Block,
IType_Edible,
IType_Mining,
IType_Weapon,
IType_Special_Tag
};
typedef enum ItemType ItemType;
enum EntityPhysics {
Phys_Falling,
Phys_Floating
};
typedef enum EntityPhysics EntityPhysics;
typedef struct Item Item;
struct Item {
std::string id;
ItemType type;
int texture;
int tier;
Item(
std::string _id,
ItemType _type,
int _texture,
int _tier = 0)
: id(_id),
type(_type),
texture(_texture),
tier(_tier)
{}
};
typedef struct InventoryItem InventoryItem;
struct InventoryItem {
Item* item = nullptr;
int damage = -1;
int amount = 0;
};
typedef struct RecipeItem RecipeItem;
struct RecipeItem {
ItemType type;
std::string id;
int quantity = 1;
};
typedef struct Recipe Recipe;
struct Recipe {
std::string requiredStation;
std::list<RecipeItem> inputs;
std::list<RecipeItem> outputs;
};
typedef struct Particle Particle;
struct Particle {
Vector3 position;
Vector3 velocity;
EntityPhysics physicsType;
Texture2D texture;
int lifetime;
int data[8];
};
extern const BlockDef BLOCKS[];
bool CanTick(int blockType);
bool GetCloud(int x,int z);
bool IsTranslucent(int blockType);
void SetBlockChunk(Chunk *c,int x,int y,int z,int t);
void RebuildHeightmap(Chunk *c);
int GetBiome(int sx,int sy);
void SetBlockChunkFast(Chunk *c,int i,int t);
void SetBlock(Chunk world[],int x,int y,int z,int t);
void InitWorldgen(int worldType);
Vector3 WorldPosition(int cx,int cz,int localX,int y,int localZ);
Chunk GenerateChunk(int _x,int _y);
void GenerateWorldAdditional(Chunk world[]);
void TickBlock(Chunk world[],int wx,int wy,int wz);
void TickChunk(Chunk *chunk,Chunk *world,int wx,int wz);
void RebuildOpaqueMask(Chunk *chunk);
#if !defined(SERVER)
ChunkRenderData GenerateCRDOpaque(const Chunk&chunk,Chunk world[]);
ChunkRenderData GenerateCRDTranslucent(Chunk chunk,Chunk world[]);
#endif
void SaveWorld(Chunk world[],const char *path);
bool LoadWorld(Chunk world[],const char *path);
extern long nsTotal;
void Debug_StartMeasure();
#if defined(WIN32)
bool Debug_GetProcessMemory(MemInfo&out);
#endif
#if defined(PLAYSTATION2)
bool Debug_GetProcessMemory(MemInfo&out);
#endif
#if !defined(WIN32)
bool Debug_GetProcessMemory(MemInfo&out);
#endif
#if !defined(SERVER)
extern Camera camera;
#endif
extern Camera3D camera;
#if !defined(SERVER)
extern Camera camera;
extern Font fnt;
extern Font fnt;
extern Texture2D terrain;
#endif
extern Texture2D terrain;
#if !defined(SERVER)
extern Texture2D terrain;
extern Texture2D terrain;
extern Texture2D playerTex;
extern Texture2D playerTex;
extern Texture2D bomb;
extern Sound nekit_idle;
void EntitiesInit();
extern bool online;
extern bool online;
#endif
#if !(!defined(SERVER))
extern bool online;
#endif
#if !defined(SERVER)
extern Vector3 player_position;
#endif
extern Vector3 player_position;
#if !defined(SERVER)
extern Vector3 player_velocity;
#endif
extern Vector3 player_velocity;
#if !defined(SERVER)
void TakeDamage(float amount);
void SetBlockNetwork(Chunk world[],int bx,int by,int bz,int t);
#endif
Entity NewEntity();
void AddEntity(Entity ent);
void UpdateEntities(Chunk world[],float dt);
extern float globalCounter;
#if !defined(SERVER)
void DrawEntities(float dt);
extern bool swap_mouse;
bool InputGetLMB();
bool InputGetLMBDown();
bool InputGetRMB();
Vector2 InputGetWalkAxis();
Vector2 InputGetLookAxis();
Vector2 InputGetDPAD();
void InputWriteControls();
void InputInit();
void InputUpdate();
extern int currentlySelected;
extern GameState state;
extern Texture2D cubemap;
int TryConnect(const char *hostname);
void InitSingleplayer();
void GameModeCleanup();
void DrawBackground();
void InitMenu();
void DrawTextB(const char *text,int posX,int posY,int fontSize,Color color);
bool Button(const char *text,int x,int y,int width,int id);
bool ButtonInventory(int x,int y,int width,int height);
extern char buffer[64];
bool TextField(int id,char *buffer,int bufferSize,int x,int y,int width);
extern const char *error;
void UIBegin();
void UIResetMousePos();
void UIHandleControls();
void DrawControls();
void DrawMainMenu();
void _LoadWorld(const char *path);
void DrawWorldSelect();
void DrawMultiplayer();
void DrawPauseMenu();
extern char bufferChat[MAX_MESSAGE_LENGTH];
char *DrawChat();
void DrawLogoCenter();
#endif
#if !defined(LEGACY_GL) && !defined(SERVER)
MeshData GenerateChunkMesh(ChunkRenderData chunkRenderData,Chunk chunk,int chunkWorldX,int chunkWorldY,uint8_t sideMask);
MeshData MergeMeshData(const MeshData&a,const MeshData&b);
MeshData CreateCubeMeshData(const BlockDef&def,float cx,float cy,float cz);
Mesh GenChunkMesh(MeshData meshData);
#endif
int NetworkingStart();
ENetHost *StartServer();
ENetHost *StartClient();
void SendPacket(ENetPeer *peer,void *data,int len);
void SendPacketR(ENetPeer *peer,void *data,int len);
void BroadcastPacketR(ENetHost *server,void *data,int len);
void SerializeFloat2Data(float v,void *target,int offset);
float DeserializeFloat(int b0,int b1);
const char *Pathify(const char *src);
const char *PathifyUser(const char *src);
#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 DrawCubeBlock(Texture2D texture,Vector3 position,float width,float height,float length,BlockDef def);
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);
#endif
inline uint8_t pack6(bool b0,bool b1,bool b2,bool b3,bool b4,bool b5){
return (uint8_t)(
((uint8_t)(b0 ? 1 : 0) << 0) |
((uint8_t)(b1 ? 1 : 0) << 1) |
((uint8_t)(b2 ? 1 : 0) << 2) |
((uint8_t)(b3 ? 1 : 0) << 3) |
((uint8_t)(b4 ? 1 : 0) << 4) |
((uint8_t)(b5 ? 1 : 0) << 5)
);
};
inline void unpack6(uint8_t v,bool *b0,bool *b1,bool *b2,bool *b3,bool *b4,bool *b5){
*b0 = (v >> 0) & 1;
*b1 = (v >> 1) & 1;
*b2 = (v >> 2) & 1;
*b3 = (v >> 3) & 1;
*b4 = (v >> 4) & 1;
*b5 = (v >> 5) & 1;
};
inline void GetXYZFromIndex(int index,int *x,int *y,int *z){
*x = index & 15;
int tmp = index << 4;
*z = tmp & 15;
*y = tmp << 4;
};
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;
return x + CHUNK_SIZE * (z + CHUNK_SIZE* y);
};
inline int GetIndexChunk2D(int x,int z){
if(x < 0 || z < 0 || x >= CHUNK_SIZE || z >= CHUNK_SIZE) return 0;
return x + CHUNK_SIZE * z;
};
inline int GetIndexWorld(int x,int z){
return x + MAX_WORLD_SIZE * z;
};
inline void GetXZFromIndex(int index,int *x,int *z){
*z = index / MAX_WORLD_SIZE;
*x = index % MAX_WORLD_SIZE;
};
inline bool TestMask(uint16_t *maskArray,int position){
int index = position >> 4;
int bit = position & 15;
int maskArrayLen = CHUNK_DATA_SIZE << 4;
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){
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){
if(CheckOOBWorld(x, y, z)) return true;
Chunk* c = &world[GetIndexWorld(x >> 4, z >> 4)];
int localIndex = GetIndexChunk((uint8_t)x & 15, y, (uint8_t)z & 15);
return TestMask(c->opaqueMask, localIndex);
};
inline bool TestAirMaskWorld(Chunk world[],int x,int y,int z){
if(CheckOOBWorld(x, y, z)) return true;
Chunk* c = &world[GetIndexWorld(x >> 4, z >> 4)];
int localIndex = GetIndexChunk((uint8_t)x & 15, y, (uint8_t)z & 15);
return TestMask(c->airMask, localIndex);
};
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;
return chunk.blocks[GetIndexChunk(x, y, z)];
};
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;
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){
if (!ptr) return malloc(newBytes);
return realloc(ptr, newBytes);
};
inline void pushFloats(float *&buf,int&count,const float *vals,int n){
for (int i=0;i<n;i++) buf[count+i] = vals[i];
count += n;
};
inline void pushU8(unsigned char *&buf,int&count,const unsigned char *vals,int n){
for (int i=0;i<n;i++) buf[count+i] = vals[i];
count += n;
};
inline void pushU32(uint32_t *&buf,int&count,const uint32_t *vals,int n){
for (int i=0;i<n;i++) buf[count+i] = vals[i];
count += n;
};
inline void pushU16(unsigned short *&buf,int&count,const unsigned short *vals,int n){
for (int i=0;i<n;i++) buf[count+i] = vals[i];
count += n;
};
#if !defined(SERVER)
inline UVCorners GetUVTex(int texture){
const float uv_mod_x = 1.0f / static_cast<float>(ATLAS_SIZE_W);
const float uv_mod_y = 1.0f / static_cast<float>(ATLAS_SIZE_H);
const float uv_x = (texture % ATLAS_SIZE_W) * uv_mod_x;
const float uv_y = (texture / ATLAS_SIZE_W) * uv_mod_y;
UVCorners corners = { 0 };
corners.corner2 = Vector2{uv_x,uv_y};
corners.corner3 = Vector2{uv_x+uv_mod_x,uv_y};
corners.corner0 = Vector2{uv_x+uv_mod_x,uv_y+uv_mod_y};
corners.corner1 = Vector2{uv_x,uv_y+uv_mod_y};
return corners;
};
inline UVCorners GetUVTex(int w,int h,int offsetX,int offsetY,int sizeX,int sizeY){
const float uv_mod_x = 1.0f / static_cast<float>(w);
const float uv_mod_y = 1.0f / static_cast<float>(h);
const float uv_x = offsetX * uv_mod_x;
const float uv_y = offsetY * uv_mod_y;
const float uvsx = sizeX * uv_mod_x;
const float uvsy = sizeY * uv_mod_y;
UVCorners corners = { 0 };
corners.corner2 = Vector2{uv_x,uv_y};
corners.corner3 = Vector2{uv_x+uvsx,uv_y};
corners.corner0 = Vector2{uv_x+uvsx,uv_y+uvsy};
corners.corner1 = Vector2{uv_x,uv_y+uvsy};
return corners;
};
inline UVCorners GetUVTex(int texture,float offsetX,float offsetY,float sizeModX,float sizeModY){
const float uv_mod_x = 1.0f / static_cast<float>(ATLAS_SIZE_W);
const float uv_mod_y = 1.0f / static_cast<float>(ATLAS_SIZE_H);
const float uv_mod1_x = sizeModX / static_cast<float>(ATLAS_SIZE_W);
const float uv_mod1_y = sizeModY / static_cast<float>(ATLAS_SIZE_H);
const float uv_off_x = offsetX / static_cast<float>(ATLAS_SIZE_W);
const float uv_off_y = offsetY / static_cast<float>(ATLAS_SIZE_H);
const float uv_x = (texture % ATLAS_SIZE_W) * uv_mod_x;
const float uv_y = (texture / ATLAS_SIZE_W) * uv_mod_y;
UVCorners corners = { 0 };
corners.corner2 = Vector2{uv_x+uv_off_x,uv_y+uv_off_y};
corners.corner3 = Vector2{uv_x+uv_off_x+uv_mod1_x,uv_y+uv_off_y};
corners.corner0 = Vector2{uv_x+uv_off_x+uv_mod1_x,uv_y+uv_off_y+uv_mod1_y};
corners.corner1 = Vector2{uv_x+uv_off_x,uv_y+uv_off_y+uv_mod1_y};
return corners;
};
inline UVCorners GetUVTexFlipX(int w,int h,int offsetX,int offsetY,int sizeX,int sizeY){
const float uv_mod_x = 1.0f / static_cast<float>(w);
const float uv_mod_y = 1.0f / static_cast<float>(h);
const float uv_x = offsetX * uv_mod_x;
const float uv_y = offsetY * uv_mod_y;
const float uvsx = sizeX * uv_mod_x;
const float uvsy = sizeY * uv_mod_y;
UVCorners corners = { 0 };
corners.corner2 = Vector2{uv_x+uvsx,uv_y};
corners.corner3 = Vector2{uv_x,uv_y};
corners.corner0 = Vector2{uv_x,uv_y+uvsy};
corners.corner1 = Vector2{uv_x+uvsx,uv_y+uvsy};
return corners;
};
extern InventoryItem hotbar[ITEMS];
#endif
extern InventoryItem hotbar[ITEMS];
#if !defined(SERVER)
extern InventoryItem inventory[INVENTORY_SIZE];
#endif
extern InventoryItem inventory[INVENTORY_SIZE];
#if !defined(SERVER)
extern bool inventoryOpen;
extern InventoryItem *movingItem;
void DrawItem(InventoryItem item,int x,int y);
void InventoryRemoveItem(int slot);
void HotbarRemoveItem(int slot);
void HotbarRemoveSelected();
void HotbarAddItem(Item *registry,int damage);
void HotbarAddItemLots(Item *registry,int damage,int amount);
void InitHotbar();
void DrawHotbar();
InventoryItem HotbarGetSelected();
void DrawSelectedItem();
void CloseInventory();
void UpdateHotbar();
void LocaleUpdate();
void LoadRecipes();
#endif
void ParticlesUpdate(float dt,Chunk world[]);
void ParticlesDraw();
void AddParticle(Particle part);
Particle NewParticle(Vector3 position);
extern bool creative_mode;
extern float player_health;
extern float player_attack_time;
extern float player_place_time;
extern float player_break_parts_time;
void SavePlayerData();
bool LoadPlayerData();
void MS_PlaySound(Sound src,float pitch,float volume,Vector3 position);
void MS_Update(float dt,Camera camera);
void StartInternalServer(bool&started);
void ServerNetworkUpdate();
void StopInternalServer();
#define INTERFACE 0
#define EXPORT_INTERFACE 0
#define LOCAL_INTERFACE 0
#define EXPORT
#define LOCAL static
#define PUBLIC
#define PRIVATE
#define PROTECTED
+78
View File
@@ -0,0 +1,78 @@
#include <iostream>
#include <chrono>
#include <string>
#include "common.hpp"
#define __DEBUG__
std::chrono::_V2::system_clock::time_point start;
std::chrono::_V2::system_clock::time_point end;
long nsTotal;
void Debug_StartMeasure() {
start = std::chrono::high_resolution_clock::now();
}
void Debug_EndMeasure(const std::string &stuff) {
end = std::chrono::high_resolution_clock::now();
int ns = std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count();
#ifdef __DEBUG__
std::cout << "[DEBUG] " << stuff << " took " << (float)(ns)/1000000.0f << " ms"<< std::endl;
#endif
nsTotal += ns;
}
void Debug_EndMeasureLoops(const std::string &stuff, int loops) {
std::cout << "[DEBUG] " << stuff << " took " << (float)(nsTotal)/1000000000.0f << " seconds across " << loops << " loops (" << (float)(nsTotal)/1000000.0f / (float)loops << " ms per cycle)" << std::endl;
nsTotal = 0;
}
void Debug_Write(const std::string &stuff) {
#ifdef __DEBUG__
std::cout << "[DEBUG] " << stuff << std::endl;
#endif
}
#if defined(WIN32)
#include <windows.h>
#include <psapi.h>
bool Debug_GetProcessMemory(MemInfo &out) {
PROCESS_MEMORY_COUNTERS pmc{};
if (!GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) return false;
out.resident = pmc.WorkingSetSize;
out.virtualSize = pmc.PagefileUsage + pmc.WorkingSetSize;
out.privateBytes = 0;
return true;
}
#endif
#if !defined(WIN32)
#include <fstream>
#include <string>
#include <unistd.h>
bool Debug_GetProcessMemory(MemInfo &out) {
out.resident = out.virtualSize = out.privateBytes = 0;
std::ifstream f("/proc/self/statm");
if (f) {
long rss_pages=0, size_pages=0;
if (f >> size_pages >> rss_pages) {
long page = sysconf(_SC_PAGESIZE);
out.resident = (uint64_t)rss_pages * page;
out.virtualSize = (uint64_t)size_pages * page;
}
} else {
std::ifstream s("/proc/self/status");
std::string line;
while (std::getline(s, line)) {
if (line.rfind("VmRSS:",0)==0) { sscanf(line.c_str(),"VmRSS: %llu kB",&out.resident); out.resident *= 1024; }
if (line.rfind("VmSize:",0)==0) { sscanf(line.c_str(),"VmSize: %llu kB",&out.virtualSize); out.virtualSize *= 1024; }
}
}
return true;
}
#endif
#if defined(PLAYSTATION2)
bool Debug_GetProcessMemory(MemInfo &out) {
out.resident = 0;
out.virtualSize = 32*1024*1024;
out.privateBytes = 0;
return true;
}
#endif
+370
View File
@@ -0,0 +1,370 @@
#include <stdint.h>
#include <stdbool.h>
#include "common.hpp"
#include <cstring>
#include <list>
#include <raymath.h>
#include <iostream>
#include <rlgl.h>
#include <vector>
#include <algorithm>
#define PIXUNIT 1.0f / 16.0f
#ifndef SERVER
extern Camera camera;
extern Font fnt;
extern Texture2D terrain;
Texture2D playerTex;
Texture2D bomb;
Sound nekit_idle;
void EntitiesInit() {
playerTex = LoadTexture(Pathify("player.png"));
bomb = LoadTexture(Pathify("bomb.png"));
nekit_idle = LoadSound(Pathify("sound/nekit/idle.ogg"));
}
extern bool online;
extern Vector3 player_position;
extern Vector3 player_velocity;
void TakeDamage(float amount);
void SetBlockNetwork(Chunk world[], int bx, int by, int bz, int t);
#else
bool online = true;
#endif
std::list<Entity> entities;
Entity NewEntity() {
Entity ent;
ent.id = entities.size();
ent.type = 0;
ent.yaw = 0;
ent.free = false;
return ent;
}
void AddEntity(Entity ent) {
entities.push_back(ent);
}
static void UpdateEntityPhysics(Chunk world[], Entity& ent, float dt) {
Vector3 velocityTgt = Vector3Add(ent.velocity, {0, -dt * 20.0f, 0});
Vector3 tgt = Vector3Add(ent.position, Vector3Scale(velocityTgt, dt));
Vector3 final = ent.position;
if(!GetBlock(world, (int)tgt.x, (int)final.y, (int)final.z)) {
final.x = tgt.x;
}
if(!GetBlock(world, (int)final.x, (int)tgt.y, (int)final.z)) {
final.y = tgt.y;
}
else {
velocityTgt.y = 0;
}
if(!GetBlock(world, (int)final.x, (int)final.y, (int)tgt.z)) {
final.z = tgt.z;
}
ent.velocity = velocityTgt;
ent.position = final;
}
void UpdateEntities(Chunk world[], float dt) {
if(entities.size() > 0) {
int idx = 0;
for(Entity& ent : entities) {
ent.smoothing = 0;
if(ent.type != 1) {
ent.lifetime += dt;
}
else {
ent.lifetime += dt * ent.data[1] / 255.0f;
if(ent.data[1]-4 >= 0) {
ent.data[1]-=4;
}
}
if(ent.damage_flash != 0) {
ent.damage_flash--;
}
if(ent.type == 2) {
Vector3 target = Vector3Zero();
#ifndef SERVER
target = player_position;
#endif
Vector3 direction = Vector3Normalize(Vector3Subtract(target, ent.position));
float degYaw = -atan2f(direction.z, direction.x) * RAD2DEG + 90;
if(GetRandomValue(0, 2000) == 0) {
MS_PlaySound(nekit_idle, GetRandomValue(75,125)/100.0f, 1.0f, ent.position);
}
ent.velocity = Vector3Add(ent.velocity, (Vector3){direction.x * 20.0f, 0, direction.z * 20.0f}*dt);
if(GetBlock(world, (int)ent.position.x, (int)ent.position.y-1, (int)ent.position.z) && GetRandomValue(0, 100) == 0) {
ent.velocity.y += 10.0f;
}
UpdateEntityPhysics(world, ent, dt);
if(Vector3Distance(target, ent.position) < 1.5f && ent.data[2] > 80) {
player_velocity += (Vector3){direction.x, 0, direction.z} * 30.0f;
player_velocity += {0, 2, 0};
ent.data[2] = 0;
TakeDamage(10.0f);
}
if(ent.health < 0.1f) {
ent.free = true;
}
if(ent.data[2] < 90)
ent.data[2]++;
ent.yaw = (unsigned short)(degYaw/360.0f*65535);
}
/*if(ent.type == 3) {
Vector3 velocityTgt = Vector3Clamp(Vector3Add(ent.velocity, {0, -dt * 20.0f, 0}), {-30.0f, -30.0f, -30.0f}, {30.0f, 30.0f, 30.0f});
Vector3 tgt = Vector3Add(ent.position, Vector3Scale(velocityTgt, dt));
Vector3 final = ent.position;
if(!GetBlock(world, (int)tgt.x, (int)final.y, (int)final.z)) {
final.x = tgt.x;
}
if(!GetBlock(world, (int)final.x, (int)tgt.y, (int)final.z)) {
final.y = tgt.y;
}
else {
velocityTgt.y = -velocityTgt.y / 2.0f;
velocityTgt = Vector3Scale(velocityTgt, 0.9f);
}
if(!GetBlock(world, (int)final.x, (int)final.y, (int)tgt.z)) {
final.z = tgt.z;
}
Entity* entp = &ent;
entp->yaw = 0;
entp->position = final;
entp->velocity = velocityTgt;
if(ent.lifetime > 5.0f) {
int radius = 3;
for (int x = -radius; x < radius; x++)
{
for (int y = -radius; y < radius; y++)
{
for (int z = -radius; z < radius; z++)
{
if(Vector3Distance({final.x + x, final.y + y, final.z + z}, final) <= radius) {
if(!CheckOOBWorld(final.x + x, final.y + y, final.z + z)) {
#ifndef SERVER
SetBlockNetwork(world, final.x + x, final.y + y, final.z + z, 0);
#endif
}
}
}
}
}
entp->free = true;
}
idx++;
}*/
if(ent.type == 4) {
Vector3 velocityTgt = Vector3Clamp(Vector3Add(ent.velocity, {0, -dt * 20.0f, 0}), {-30.0f, -30.0f, -30.0f}, {30.0f, 30.0f, 30.0f});
Vector3 tgt = Vector3Add(ent.position, Vector3Scale(velocityTgt, dt));
Vector3 final = ent.position;
bool hit = false;
if(!GetBlock(world, (int)tgt.x, (int)final.y, (int)final.z)) {
final.x = tgt.x;
}
else {
hit = true;
}
if(!GetBlock(world, (int)final.x, (int)tgt.y, (int)final.z)) {
final.y = tgt.y;
}
else {
hit = true;
}
if(!GetBlock(world, (int)final.x, (int)final.y, (int)tgt.z)) {
final.z = tgt.z;
}
else {
hit = true;
}
Entity* entp = &ent;
if(hit) {
SetBlockNetwork(world, (int)ent.position.x, (int)ent.position.y, (int)ent.position.z, ent.data[1]);
entp->free = true;
}
entp->yaw = 0;
entp->position = final;
entp->velocity = velocityTgt;
idx++;
}
}
auto match = [&](const Entity ent){
return ent.free;
};
auto it = std::find_if(entities.begin(), entities.end(), match);
if (it != entities.end()) {
entities.erase(it);
}
}
}
float globalCounter = 0;
#ifndef SERVER
void DrawEntities(float dt) {
globalCounter += dt;
for(Entity& ent : entities) {
ent.smoothing += dt;
if(ent.smoothing > TPS_DIV) {
ent.smoothing = 0;
}
Vector3 pos_lerped = Vector3Lerp(ent.position, Vector3Add(ent.position, ent.velocity*TPS_DIV), ent.smoothing * TPS);
if(ent.type == 0 || ent.type == 2) {
Color color = ColorLerp(WHITE, RED, ent.damage_flash / 50.0f);
Vector3 posLerp = Vector3Add(pos_lerped, {-0.5f, -0.1f, -0.5f});
float time = (ent.lifetime + ent.smoothing) * 4.0f;
float armWave0 = sinf(time * PI);
float armWave1 = -abs(cosf(time * PI));
float headWave = cosf(time * PI);
posLerp = Vector3Add(posLerp, {0, abs(sinf(time * PI)) * 0.1f, 0});
Vector3 headPivot = Vector3Add(posLerp, (Vector3){0, 16*PIXUNIT, 0});
float yaw = ent.yaw / 65535.0f * 360.0f;
rlColor4f(color.r, color.g, color.b, color.a);
rlPushMatrix();
rlTranslatef(posLerp.x, posLerp.y, posLerp.z); // move to model origin
rlRotatef(yaw, 0, 1, 0); // rotate around Y
rlTranslatef(-posLerp.x, -posLerp.y, -posLerp.z); // move back (optional depending on your pivots)
//
rlPushMatrix();
rlTranslatef(headPivot.x, headPivot.y, headPivot.z);
rlRotatef(25.0f * armWave0, 1, 0, 0);
rlRotatef(25.0f * headWave, 0, 0, 1);
// Head
DrawCubeTexture(playerTex, {0, 4*PIXUNIT, 0}, 8*PIXUNIT, 8*PIXUNIT, 8*PIXUNIT, WHITE, 8, 8, 8, 8);
rlPopMatrix();
Vector3 leftPivot = Vector3Add(posLerp, (Vector3){-6*PIXUNIT, 1.25f - 5*PIXUNIT, 0});
Vector3 rightPivot = Vector3Add(posLerp, (Vector3){6*PIXUNIT, 1.25f - 5*PIXUNIT, 0});
rlPushMatrix();
rlTranslatef(leftPivot.x, leftPivot.y, leftPivot.z);
rlRotatef(45.0f * armWave0, 1, 0, 0);
rlRotatef(45.0f * armWave1, 0, 0, 1);
DrawCubeTexture(playerTex, (Vector3){0, -6*PIXUNIT, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 44,20,4,4);
rlPopMatrix();
rlPushMatrix();
rlTranslatef(rightPivot.x, rightPivot.y, rightPivot.z);
rlRotatef(-45.0f * armWave0, 1, 0, 0);
rlRotatef(-45.0f * armWave1, 0, 0, 1);
DrawCubeTexture(playerTex, (Vector3){0, -6*PIXUNIT, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 44,20,4,4);
rlPopMatrix();
Vector3 body = Vector3Add(posLerp, {0, 1.25f - 10*PIXUNIT, 0});
rlPushMatrix();
rlTranslatef(body.x, body.y, body.z);
DrawCubeTexture(playerTex, Vector3Zero(), 8*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 20, 20, 8, 4);
rlPopMatrix();
leftPivot = Vector3Add(posLerp, (Vector3){-2*PIXUNIT, 1.25f - 14*PIXUNIT, 0});
rightPivot = Vector3Add(posLerp, (Vector3){2*PIXUNIT, 1.25f - 14*PIXUNIT, 0});
rlPushMatrix();
rlTranslatef(leftPivot.x, leftPivot.y, leftPivot.z);
rlRotatef(-45.0f * armWave0, 1, 0, 0);
DrawCubeTexture(playerTex, {0*PIXUNIT, -8*PIXUNIT, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 4, 20, 4, 4);
rlPopMatrix();
rlPushMatrix();
rlTranslatef(rightPivot.x, rightPivot.y, rightPivot.z);
rlRotatef(45.0f * armWave0, 1, 0, 0);
DrawCubeTexture(playerTex, {0*PIXUNIT, -8*PIXUNIT, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 4, 20, 4, 4);
rlPopMatrix();
rlPopMatrix();
}
if(ent.type == 1) {
Color color = WHITE;
Vector3 posLerp = Vector3Add(ent.position, {-0.5f, -0.1f, -0.5f});
float time = ent.lifetime * 4.0f;
float armWave0 = sinf(time * PI);
float armWave1 = -abs(cosf(time * PI));
float headWave = cosf(time * PI);
posLerp = Vector3Add(posLerp, {0, abs(sinf(time * PI)) * 0.1f, 0});
Vector3 headPivot = Vector3Add(posLerp, (Vector3){0, 16*PIXUNIT, 0});
float yaw = -ent.yaw / 65535.0f * 360.0f - 90;
rlPushMatrix();
rlTranslatef(posLerp.x, posLerp.y, posLerp.z);
rlRotatef(yaw, 0, 1, 0);
rlTranslatef(-posLerp.x, -posLerp.y, -posLerp.z);
//
rlPushMatrix();
rlTranslatef(headPivot.x, headPivot.y, headPivot.z);
rlRotatef(25.0f * armWave0, 1, 0, 0);
rlRotatef(25.0f * headWave, 0, 0, 1);
// Head
DrawCubeTexture(playerTex, {0, 4*PIXUNIT, 0}, 8*PIXUNIT, 8*PIXUNIT, 8*PIXUNIT, WHITE, 8, 8, 8, 8);
rlPopMatrix();
Vector3 leftPivot = Vector3Add(posLerp, (Vector3){-6*PIXUNIT, 1.25f - 5*PIXUNIT, 0});
Vector3 rightPivot = Vector3Add(posLerp, (Vector3){6*PIXUNIT, 1.25f - 5*PIXUNIT, 0});
rlPushMatrix();
rlTranslatef(leftPivot.x, leftPivot.y, leftPivot.z);
rlRotatef(45.0f * armWave0, 1, 0, 0);
rlRotatef(45.0f * armWave1, 0, 0, 1);
DrawCubeTexture(playerTex, (Vector3){0, -6*PIXUNIT, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 44,20,4,4);
rlPopMatrix();
rlPushMatrix();
rlTranslatef(rightPivot.x, rightPivot.y, rightPivot.z);
rlRotatef(-45.0f * armWave0, 1, 0, 0);
rlRotatef(-45.0f * armWave1, 0, 0, 1);
DrawCubeTexture(playerTex, (Vector3){0, -6*PIXUNIT, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 44,20,4,4);
rlPopMatrix();
Vector3 body = Vector3Add(posLerp, {0, 1.25f - 10*PIXUNIT, 0});
rlPushMatrix();
rlTranslatef(body.x, body.y, body.z);
DrawCubeTexture(playerTex, Vector3Zero(), 8*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 20, 20, 8, 4);
rlPopMatrix();
leftPivot = Vector3Add(posLerp, (Vector3){-2*PIXUNIT, 1.25f - 14*PIXUNIT, 0});
rightPivot = Vector3Add(posLerp, (Vector3){2*PIXUNIT, 1.25f - 14*PIXUNIT, 0});
rlPushMatrix();
rlTranslatef(leftPivot.x, leftPivot.y, leftPivot.z);
rlRotatef(-45.0f * armWave0, 1, 0, 0);
DrawCubeTexture(playerTex, {0*PIXUNIT, -8*PIXUNIT, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 4, 20, 4, 4);
rlPopMatrix();
rlPushMatrix();
rlTranslatef(rightPivot.x, rightPivot.y, rightPivot.z);
rlRotatef(45.0f * armWave0, 1, 0, 0);
DrawCubeTexture(playerTex, {0*PIXUNIT, -8*PIXUNIT, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 4, 20, 4, 4);
rlPopMatrix();
rlPopMatrix();
Vector3 dir = Vector3Subtract(camera.position, ent.position);
rlPushMatrix();
rlTranslatef(ent.position.x, ent.position.y + 1.5f, ent.position.z);
rlRotatef(atan2f(dir.x, dir.z) * RAD2DEG, 0.0f, 1.0f, 0.0f);
rlRotatef(90.0f, 1.0f, 0.0f, 0.0f);
char name[12];
sprintf(name, "Player %d", (int)ent.data[0]);
DrawText3D(fnt, name, {-MeasureTextEx(fnt, name, PIXUNIT * 4, 0).x * 1.5f, 0, 0}, PIXUNIT * 4, PIXUNIT, 1, true, WHITE);
rlPopMatrix();
}
if(ent.type == 3) {
DrawCube(pos_lerped, 1, 1, 1, RED);
}
if(ent.type == 4) {
DrawCubeBlock(terrain, pos_lerped, 1,1,1, BLOCKS[ent.data[1]]);
}
}
}
#endif
+424
View File
@@ -0,0 +1,424 @@
// https://gist.github.com/0xD34DC0DE/910855d41786b962127ae401da2a3441
#include <cstdint>
// Key code from the USB HID Usage Tables v1.12(p. 53-60) but re-arranged to map to 7-bit ASCII for printable keys
enum KeyCode : int32_t
{
Unknown = -1,
Space = 32,
Apostrophe = 39,
Comma = 44,
Minus = 45,
Period = 46,
Slash = 47,
Num0 = 48,
Num1 = 49,
Num2 = 50,
Num3 = 51,
Num4 = 52,
Num5 = 53,
Num6 = 54,
Num7 = 55,
Num8 = 56,
Num9 = 57,
Semicolon = 59,
Equal = 61,
A = 65,
B = 66,
C = 67,
D = 68,
E = 69,
F = 70,
G = 71,
H = 72,
I = 73,
J = 74,
K = 75,
L = 76,
M = 77,
N = 78,
O = 79,
P = 80,
Q = 81,
R = 82,
S = 83,
T = 84,
U = 85,
V = 86,
W = 87,
X = 88,
Y = 89,
Z = 90,
LeftBracket = 91,
Backslash = 92,
RightBracket = 93,
GraveAccent = 96,
World1 = 161,
World2 = 162,
K_Escape = 256,
Enter = 257,
Tab = 258,
Backspace = 259,
Insert = 260,
Delete = 261,
Right = 262,
Left = 263,
Down = 264,
Up = 265,
PageUp = 266,
PageDown = 267,
Home = 268,
End = 269,
CapsLock = 280,
ScrollLock = 281,
NumLock = 282,
PrintScreen = 283,
Pause = 284,
F1 = 290,
F2 = 291,
F3 = 292,
F4 = 293,
F5 = 294,
F6 = 295,
F7 = 296,
F8 = 297,
F9 = 298,
F10 = 299,
F11 = 300,
F12 = 301,
F13 = 302,
F14 = 303,
F15 = 304,
F16 = 305,
F17 = 306,
F18 = 307,
F19 = 308,
F20 = 309,
F21 = 310,
F22 = 311,
F23 = 312,
F24 = 313,
F25 = 314,
Keypad0 = 320,
Keypad1 = 321,
Keypad2 = 322,
Keypad3 = 323,
Keypad4 = 324,
Keypad5 = 325,
Keypad6 = 326,
Keypad7 = 327,
Keypad8 = 328,
Keypad9 = 329,
KeypadDecimal = 330,
KeypadDivide = 331,
KeypadMultiply = 332,
KeypadSubtract = 333,
KeypadAdd = 334,
KeypadEnter = 335,
KeypadEqual = 336,
LeftShift = 340,
LeftControl = 341,
LeftAlt = 342,
LeftSuper = 343,
RightShift = 344,
RightControl = 345,
RightAlt = 346,
RightSuper = 347,
Menu = 348
};
constexpr const char* const LUT44To96[] { "Comma",
"Minus",
"Period",
"Slash",
"Num0",
"Num1",
"Num2",
"Num3",
"Num4",
"Num5",
"Num6",
"Num7",
"Num8",
"Num9",
"Invalid",
"Semicolon",
"Invalid",
"Equal",
"Invalid",
"Invalid",
"Invalid",
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
"Y",
"Z",
"LeftBracket",
"Backslash",
"RightBracket",
"Invalid",
"Invalid",
"GraveAccent" };
constexpr const char* const LUT256To348[] { "Escape",
"Enter",
"Tab",
"Backspace",
"Insert",
"Delete",
"Right",
"Left",
"Down",
"Up",
"PageUp",
"PageDown",
"Home",
"End",
"Invalid",
"Invalid",
"Invalid",
"Invalid",
"Invalid",
"Invalid",
"Invalid",
"Invalid",
"Invalid",
"Invalid",
"CapsLock",
"ScrollLock",
"NumLock",
"PrintScreen",
"Pause",
"Invalid",
"Invalid",
"Invalid",
"Invalid",
"Invalid",
"F1",
"F2",
"F3",
"F4",
"F5",
"F6",
"F7",
"F8",
"F9",
"F10",
"F11",
"F12",
"F13",
"F14",
"F15",
"F16",
"F17",
"F18",
"F19",
"F20",
"F21",
"F22",
"F23",
"F24",
"F25",
"Invalid",
"Invalid",
"Invalid",
"Invalid",
"Invalid",
"Keypad0",
"Keypad1",
"Keypad2",
"Keypad3",
"Keypad4",
"Keypad5",
"Keypad6",
"Keypad7",
"Keypad8",
"Keypad9",
"KeypadDecimal",
"KeypadDivide",
"KeypadMultiply",
"KeypadSubtract",
"KeypadAdd",
"KeypadEnter",
"KeypadEqual",
"Invalid",
"Invalid",
"Invalid",
"LeftShift",
"LeftControl",
"LeftAlt",
"LeftSuper",
"RightShift",
"RightControl",
"RightAlt",
"RightSuper",
"Menu" };
constexpr const char* KeyCodeToString(KeyCode keycode) noexcept
{
if (keycode == 32) { return "Space"; } // Common key, don't treat as an unlikely scenario
if (keycode >= 44 && keycode <= 96) [[likely]] { return LUT44To96[keycode - 44]; }
if (keycode >= 256 && keycode <= 348) [[likely]] { return LUT256To348[keycode - 256]; }
// Unlikely scenario where the keycode didn't fall inside one of the two lookup tables
switch (keycode)
{
case 39: return "Apostrophe";
case 161: return "World1";
case 162: return "Wordl2";
default: return "Unknown";
}
}
constexpr const char* KeyCodeToStringSwitch(KeyCode keycode) noexcept
{
switch (keycode)
{
case -1: return "Unknown";
case 32: return "Space";
case 39: return "Apostrophe";
case 44: return "Comma";
case 45: return "Minus";
case 46: return "Period";
case 47: return "Slash";
case 48: return "Num0";
case 49: return "Num1";
case 50: return "Num2";
case 51: return "Num3";
case 52: return "Num4";
case 53: return "Num5";
case 54: return "Num6";
case 55: return "Num7";
case 56: return "Num8";
case 57: return "Num9";
case 59: return "Semicolon";
case 61: return "Equal";
case 65: return "A";
case 66: return "B";
case 67: return "C";
case 68: return "D";
case 69: return "E";
case 70: return "F";
case 71: return "G";
case 72: return "H";
case 73: return "I";
case 74: return "J";
case 75: return "K";
case 76: return "L";
case 77: return "M";
case 78: return "N";
case 79: return "O";
case 80: return "P";
case 81: return "Q";
case 82: return "R";
case 83: return "S";
case 84: return "T";
case 85: return "U";
case 86: return "V";
case 87: return "W";
case 88: return "X";
case 89: return "Y";
case 90: return "Z";
case 91: return "Left Bracket";
case 92: return "Backslash";
case 93: return "Right Bracket";
case 96: return "Grave Accent";
case 161: return "World1";
case 162: return "World2";
case 256: return "Escape";
case 257: return "Enter";
case 258: return "Tab";
case 259: return "Backspace";
case 260: return "Insert";
case 261: return "Delete";
case 262: return "Right";
case 263: return "Left";
case 264: return "Down";
case 265: return "Up";
case 266: return "Page Up";
case 267: return "Page Down";
case 268: return "Home";
case 269: return "End";
case 280: return "Caps Lock";
case 281: return "Scroll Lock";
case 282: return "Num Lock";
case 283: return "Print Screen";
case 284: return "Pause";
case 290: return "F1";
case 291: return "F2";
case 292: return "F3";
case 293: return "F4";
case 294: return "F5";
case 295: return "F6";
case 296: return "F7";
case 297: return "F8";
case 298: return "F9";
case 299: return "F10";
case 300: return "F11";
case 301: return "F12";
case 302: return "F13";
case 303: return "F14";
case 304: return "F15";
case 305: return "F16";
case 306: return "F17";
case 307: return "F18";
case 308: return "F19";
case 309: return "F20";
case 310: return "F21";
case 311: return "F22";
case 312: return "F23";
case 313: return "F24";
case 314: return "F25";
case 320: return "Keypad 0";
case 321: return "Keypad 1";
case 322: return "Keypad 2";
case 323: return "Keypad 3";
case 324: return "Keypad 4";
case 325: return "Keypad 5";
case 326: return "Keypad 6";
case 327: return "Keypad 7";
case 328: return "Keypad 8";
case 329: return "Keypad 9";
case 330: return "Keypad Decimal";
case 331: return "Keypad Divide";
case 332: return "Keypad Multiply";
case 333: return "Keypad Subtract";
case 334: return "Keypad Add";
case 335: return "Keypad Enter";
case 336: return "Keypad Equal";
case 340: return "Left Shift";
case 341: return "Left Control";
case 342: return "Left Alt";
case 343: return "Left Super";
case 344: return "Right Shift";
case 345: return "Right Control";
case 346: return "Right Alt";
case 347: return "Right Super";
case 348: return "Menu";
default: return "Unknown";
};
}
+177
View File
@@ -0,0 +1,177 @@
// For use within makeheaders!
inline uint8_t pack6(bool b0, bool b1, bool b2, bool b3, bool b4, bool b5) {
return (uint8_t)(
((uint8_t)(b0 ? 1 : 0) << 0) |
((uint8_t)(b1 ? 1 : 0) << 1) |
((uint8_t)(b2 ? 1 : 0) << 2) |
((uint8_t)(b3 ? 1 : 0) << 3) |
((uint8_t)(b4 ? 1 : 0) << 4) |
((uint8_t)(b5 ? 1 : 0) << 5)
);
}
inline void unpack6(uint8_t v, bool *b0, bool *b1, bool *b2, bool *b3, bool *b4, bool *b5) {
*b0 = (v >> 0) & 1;
*b1 = (v >> 1) & 1;
*b2 = (v >> 2) & 1;
*b3 = (v >> 3) & 1;
*b4 = (v >> 4) & 1;
*b5 = (v >> 5) & 1;
}
inline void GetXYZFromIndex(int index, int *x, int *y, int *z) {
*x = index & 15;
int tmp = index << 4;
*z = tmp & 15;
*y = tmp << 4;
}
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;
return x + CHUNK_SIZE * (z + CHUNK_SIZE* y);
}
inline int GetIndexChunk2D(int x, int z) {
if(x < 0 || z < 0 || x >= CHUNK_SIZE || z >= CHUNK_SIZE) return 0;
return x + CHUNK_SIZE * z;
}
inline int GetIndexWorld(int x, int z) {
return x + MAX_WORLD_SIZE * z;
}
inline void GetXZFromIndex(int index, int *x, int *z) {
*z = index / MAX_WORLD_SIZE;
*x = index % MAX_WORLD_SIZE;
}
inline bool TestMask(uint16_t *maskArray, int position)
{
int index = position >> 4;
int bit = position & 15;
int maskArrayLen = CHUNK_DATA_SIZE << 4;
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) {
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) {
if(CheckOOBWorld(x, y, z)) return true;
Chunk* c = &world[GetIndexWorld(x >> 4, z >> 4)];
int localIndex = GetIndexChunk((uint8_t)x & 15, y, (uint8_t)z & 15);
return TestMask(c->opaqueMask, localIndex);
}
inline bool TestAirMaskWorld(Chunk world[], int x, int y, int z) {
if(CheckOOBWorld(x, y, z)) return true;
Chunk* c = &world[GetIndexWorld(x >> 4, z >> 4)];
int localIndex = GetIndexChunk((uint8_t)x & 15, y, (uint8_t)z & 15);
return TestMask(c->airMask, localIndex);
}
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;
return chunk.blocks[GetIndexChunk(x, y, z)];
}
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;
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) {
if (!ptr) return malloc(newBytes);
return realloc(ptr, newBytes);
}
inline void pushFloats(float *&buf, int &count, const float *vals, int n) {
for (int i=0;i<n;i++) buf[count+i] = vals[i];
count += n;
}
inline void pushU8(unsigned char *&buf, int &count, const unsigned char *vals, int n) {
for (int i=0;i<n;i++) buf[count+i] = vals[i];
count += n;
}
inline void pushU32(uint32_t *&buf, int &count, const uint32_t *vals, int n) {
for (int i=0;i<n;i++) buf[count+i] = vals[i];
count += n;
}
inline void pushU16(unsigned short *&buf, int &count, const unsigned short *vals, int n) {
for (int i=0;i<n;i++) buf[count+i] = vals[i];
count += n;
}
#ifndef SERVER
inline UVCorners GetUVTex(int texture) {
const float uv_mod_x = 1.0f / static_cast<float>(ATLAS_SIZE_W);
const float uv_mod_y = 1.0f / static_cast<float>(ATLAS_SIZE_H);
const float uv_x = (texture % ATLAS_SIZE_W) * uv_mod_x;
const float uv_y = (texture / ATLAS_SIZE_W) * uv_mod_y;
UVCorners corners = { 0 };
corners.corner2 = Vector2{uv_x,uv_y};
corners.corner3 = Vector2{uv_x+uv_mod_x,uv_y};
corners.corner0 = Vector2{uv_x+uv_mod_x,uv_y+uv_mod_y};
corners.corner1 = Vector2{uv_x,uv_y+uv_mod_y};
return corners;
}
inline UVCorners GetUVTex(int texture, float offsetX, float offsetY, float sizeModX, float sizeModY) {
const float uv_mod_x = 1.0f / static_cast<float>(ATLAS_SIZE_W);
const float uv_mod_y = 1.0f / static_cast<float>(ATLAS_SIZE_H);
const float uv_mod1_x = sizeModX / static_cast<float>(ATLAS_SIZE_W);
const float uv_mod1_y = sizeModY / static_cast<float>(ATLAS_SIZE_H);
const float uv_off_x = offsetX / static_cast<float>(ATLAS_SIZE_W);
const float uv_off_y = offsetY / static_cast<float>(ATLAS_SIZE_H);
const float uv_x = (texture % ATLAS_SIZE_W) * uv_mod_x;
const float uv_y = (texture / ATLAS_SIZE_W) * uv_mod_y;
UVCorners corners = { 0 };
corners.corner2 = Vector2{uv_x+uv_off_x,uv_y+uv_off_y};
corners.corner3 = Vector2{uv_x+uv_off_x+uv_mod1_x,uv_y+uv_off_y};
corners.corner0 = Vector2{uv_x+uv_off_x+uv_mod1_x,uv_y+uv_off_y+uv_mod1_y};
corners.corner1 = Vector2{uv_x+uv_off_x,uv_y+uv_off_y+uv_mod1_y};
return corners;
}
inline UVCorners GetUVTex(int w, int h, int offsetX, int offsetY, int sizeX, int sizeY) {
const float uv_mod_x = 1.0f / static_cast<float>(w);
const float uv_mod_y = 1.0f / static_cast<float>(h);
const float uv_x = offsetX * uv_mod_x;
const float uv_y = offsetY * uv_mod_y;
const float uvsx = sizeX * uv_mod_x;
const float uvsy = sizeY * uv_mod_y;
UVCorners corners = { 0 };
corners.corner2 = Vector2{uv_x,uv_y};
corners.corner3 = Vector2{uv_x+uvsx,uv_y};
corners.corner0 = Vector2{uv_x+uvsx,uv_y+uvsy};
corners.corner1 = Vector2{uv_x,uv_y+uvsy};
return corners;
}
inline UVCorners GetUVTexFlipX(int w, int h, int offsetX, int offsetY, int sizeX, int sizeY) {
const float uv_mod_x = 1.0f / static_cast<float>(w);
const float uv_mod_y = 1.0f / static_cast<float>(h);
const float uv_x = offsetX * uv_mod_x;
const float uv_y = offsetY * uv_mod_y;
const float uvsx = sizeX * uv_mod_x;
const float uvsy = sizeY * uv_mod_y;
UVCorners corners = { 0 };
corners.corner2 = Vector2{uv_x+uvsx,uv_y};
corners.corner3 = Vector2{uv_x,uv_y};
corners.corner0 = Vector2{uv_x,uv_y+uvsy};
corners.corner1 = Vector2{uv_x+uvsx,uv_y+uvsy};
return corners;
}
#endif
+147
View File
@@ -0,0 +1,147 @@
#ifndef SERVER
#include "common.hpp"
#include <cstring>
#include <raymath.h>
#include <iostream>
#include <filesystem>
#include "yaml-cpp/yaml.h"
#define CONFIG_LOC "config.yaml"
static bool IsMouseMoving() {
return GetMouseDelta().x > 0.01f || GetMouseDelta().y > 0.01f;
}
// Config
std::map <std::string, int> controls = {
{"forward", KEY_W},
{"left", KEY_A},
{"back", KEY_S},
{"right", KEY_D},
{"jump", KEY_SPACE},
{"shift", KEY_LEFT_SHIFT},
{"speed_up", KEY_LEFT_CONTROL},
{"fly", KEY_V},
{"inventory", KEY_E},
{"chat", KEY_APOSTROPHE}
};
bool swap_mouse = false; // H1N1 mode (wink)
bool InputGetKeyDown(const std::string name) {
return IsKeyDown(controls.at(name));
}
bool InputGetKeyPressed(const std::string name) {
return IsKeyPressed(controls.at(name));
}
bool InputGetLMB() {
if(swap_mouse) {
return IsMouseButtonPressed(MOUSE_RIGHT_BUTTON);
}
else {
return IsMouseButtonPressed(MOUSE_LEFT_BUTTON);
}
}
bool InputGetLMBDown() {
if(swap_mouse) {
return IsMouseButtonDown(MOUSE_RIGHT_BUTTON);
}
else {
return IsMouseButtonDown(MOUSE_LEFT_BUTTON);
}
}
bool InputGetRMB() {
if(swap_mouse) {
return IsMouseButtonPressed(MOUSE_LEFT_BUTTON);
}
else {
return IsMouseButtonPressed(MOUSE_RIGHT_BUTTON);
}
}
Vector2 InputGetWalkAxis() {
bool isJoystick = IsGamepadAvailable(0);
float x = 0;
float y = 0;
if(isJoystick) {
x = GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X);
y = GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y);
if(abs(x) < 0.5f) {
x = 0;
}
if(abs(y) < 0.5f) {
y = 0;
}
}
if (InputGetKeyDown("forward")) { y = 1; }
if (InputGetKeyDown("back")) { y = -1; }
if (InputGetKeyDown("right")) { x = 1; }
if (InputGetKeyDown("left")) { x = -1; }
return {x, y};
}
Vector2 InputGetLookAxis() {
bool isJoystick = IsGamepadAvailable(0);
float x = 0;
float y = 0;
if(isJoystick) {
x = GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_X);
y = GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_Y);
if(abs(x) < 0.1f) {
x = 0;
}
if(abs(y) < 0.1f) {
y = 0;
}
return {x, y};
}
else {
return GetMouseDelta();
}
}
Vector2 InputGetDPAD() {
bool isJoystick = IsGamepadAvailable(0);
float x = 0.0f;
float y = 0.0f;
if(isJoystick) {
if (IsGamepadButtonPressed(0, GAMEPAD_BUTTON_LEFT_FACE_UP)) { y = 1; }
if (IsGamepadButtonPressed(0, GAMEPAD_BUTTON_LEFT_FACE_DOWN)) { y = -1; }
if (IsGamepadButtonPressed(0, GAMEPAD_BUTTON_LEFT_FACE_RIGHT)) { x = 1; }
if (IsGamepadButtonPressed(0, GAMEPAD_BUTTON_LEFT_FACE_LEFT)) { x = -1; }
}
return {x, y};
}
void InputWriteControls() {
YAML::Emitter out;
out << YAML::BeginMap;
out << YAML::Key << "Mapped controls";
out << YAML::Value << controls;
out << YAML::Key << "Swap mouse buttons";
out << YAML::Value << swap_mouse;
out << YAML::EndMap;
FILE* file = fopen(CONFIG_LOC, "w" );
fprintf( file, out.c_str());
fclose( file );
}
void InputInit() {
if(!FileExists(CONFIG_LOC)) {
InputWriteControls();
}
else {
YAML::Node config = YAML::LoadFile(CONFIG_LOC);
const std::map<std::string, int> _controls = config["Mapped controls"].as<std::map<std::string, int>>();
for (auto const& [key, val] : _controls)
{
controls[key] = val;
}
swap_mouse = config["Swap mouse buttons"].as<bool>();
}
}
void InputUpdate() {
}
#endif
+554
View File
@@ -0,0 +1,554 @@
#ifndef SERVER
#include <stdint.h>
#include <stdbool.h>
#include "common.hpp"
#include <cstring>
#include <iostream>
#include <map>
#include <rlgl.h>
#define PIXUNIT 1.0f / 16.0f
InventoryItem hotbar[ITEMS];
InventoryItem inventory[INVENTORY_SIZE];
static uint8_t selected = 0;
static Texture2D item_atlas;
extern Texture2D terrain;
extern Texture2D playerTex;
const std::string LocaleGet(std::string loc);
std::vector<Item> registry = {
Item{ "block", IType_Block, 0},
Item{ "apple", IType_Edible, 0},
Item{ "stick", IType_Generic, 1},
Item{ "stone_pickaxe", IType_Mining, 2, 1},
Item{ "copper_pickaxe", IType_Mining, 4, 2},
Item{ "silver_pickaxe", IType_Mining, 3, 3},
Item{ "gold_pickaxe", IType_Mining, 5, 4},
Item{ "copper_ingot", IType_Generic, 6},
Item{ "silver_ingot", IType_Generic, 7},
Item{ "gold_ingot", IType_Generic, 8},
};
bool inventoryOpen = false;
InventoryItem* movingItem = nullptr;
static Image itemAtlasImg;
extern std::list<Recipe> recipes;
int GetNumericIDFromString(std::string s);
void DrawItem(InventoryItem item, int x, int y) {
if(item.item != nullptr) {
int atl_size = ITEM_ATLAS_SIZE;
int tex = item.item->texture;
Texture2D atlas = item_atlas;
if(item.item->type == IType_Block) {
atlas = terrain;
atl_size = ATLAS_SIZE_W;
tex = BLOCKS[item.damage].textureTop;
}
DrawTexturePro(atlas,
{
(float)(tex % atl_size) * ITEM_SIZE,
(float)(tex / atl_size) * ITEM_SIZE,
ITEM_SIZE,
ITEM_SIZE
},
{
(float)x+6, (float)y+6, 44, 44
},
{0, 0},
0,
WHITE);
char text[12] = "???\0";
sprintf(text, "x%d", item.amount);
if(item.amount != 0) DrawText(text, x, y, DEFAULT_FONT_SIZE / 2, WHITE);
}
}
void InventoryRemoveItem(int slot) {
if(inventory[slot].amount-1 > 0) {
inventory[slot].amount--;
}
else {
inventory[slot].item = nullptr;
inventory[slot].damage = 0;
inventory[slot].amount = 0;
}
}
void HotbarRemoveItem(int slot) {
if(hotbar[slot].amount-1 > 0) {
hotbar[slot].amount--;
}
else {
hotbar[slot].item = nullptr;
hotbar[slot].damage = 0;
hotbar[slot].amount = 0;
}
}
void HotbarRemoveSelected() {
HotbarRemoveItem(selected);
}
void HotbarAddItem(Item* registry, int damage) {
for (int i = 0; i < ITEMS; i++)
{
InventoryItem item = hotbar[i];
if((item.item == registry && item.damage == damage)) {
hotbar[i].item = registry;
hotbar[i].damage = damage;
hotbar[i].amount += 1;
return;
}
}
for (int i = 0; i < INVENTORY_SIZE; i++)
{
InventoryItem item = inventory[i];
if((item.item == registry && item.damage == damage)) {
inventory[i].item = registry;
inventory[i].damage = damage;
inventory[i].amount += 1;
return;
}
}
for (int i = 0; i < ITEMS; i++)
{
InventoryItem item = hotbar[i];
if(item.item == nullptr) {
hotbar[i].item = registry;
hotbar[i].damage = damage;
hotbar[i].amount += 1;
return;
}
}
for (int i = 0; i < INVENTORY_SIZE; i++)
{
InventoryItem item = inventory[i];
if(item.item == nullptr) {
inventory[i].item = registry;
inventory[i].damage = damage;
inventory[i].amount += 1;
return;
}
}
}
void HotbarAddItemLots(Item* registry, int damage, int amount) {
for (int i = 0; i < ITEMS; i++)
{
InventoryItem item = hotbar[i];
if((item.item == registry && item.damage == damage)) {
hotbar[i].item = registry;
hotbar[i].damage = damage;
hotbar[i].amount += amount;
return;
}
}
for (int i = 0; i < INVENTORY_SIZE; i++)
{
InventoryItem item = inventory[i];
if((item.item == registry && item.damage == damage)) {
inventory[i].item = registry;
inventory[i].damage = damage;
inventory[i].amount += amount;
return;
}
}
for (int i = 0; i < ITEMS; i++)
{
InventoryItem item = hotbar[i];
if(item.item == nullptr) {
hotbar[i].item = registry;
hotbar[i].damage = damage;
hotbar[i].amount += amount;
return;
}
}
for (int i = 0; i < INVENTORY_SIZE; i++)
{
InventoryItem item = inventory[i];
if(item.item == nullptr) {
inventory[i].item = registry;
inventory[i].damage = damage;
inventory[i].amount += amount;
return;
}
}
}
Item* GetItemByID(std::string s) {
for (Item& i : registry) {
if (i.id == s) return &i;
}
return nullptr;
}
int GetItemNumID(std::string s) {
int o = 0;
for (Item& i : registry) {
if (i.id == s) return o;
o++;
}
return -1;
}
void InitHotbar() {
/*for (int i = 0; i < ITEMS; i++)
{
HotbarRemoveItem(i);
}*/
//HotbarAddItem(&registry[0], GetNumericIDFromString("workbench"));
item_atlas = LoadTexture(Pathify("items.png"));
itemAtlasImg = LoadImageFromTexture(item_atlas);
}
bool IDTagMatch(std::string tag, std::string id);
static bool GetTaggedItem(std::string tag, InventoryItem* item) {
InventoryItem temp;
int id;
bool isBlock;
bool found;
for(int blk = 0; blk < MAX_BLOCK_ID; blk++) {
if(IDTagMatch(tag, BLOCKS[blk].name)) {
isBlock = true;
id = GetNumericIDFromString(BLOCKS[blk].name);
found = true;
break;
};
}
if(!found) {
for(Item item : registry) {
if(IDTagMatch(tag, item.id)) {
isBlock = false;
id = GetItemNumID(item.id);
found = true;
break;
};
}
}
if(!found) {
return false;
}
if(isBlock) {
temp.item = &(registry[0]);
temp.damage = id;
}
else {
temp.item = &(registry[id]);
}
memcpy(item, &temp, sizeof(InventoryItem));
return true;
}
static bool FindTaggedItem(std::string tag, InventoryItem* item) {
for(int blk = 0; blk < INVENTORY_SIZE; blk++) {
InventoryItem itm = inventory[blk];
if(itm.item != nullptr) {
if(GetTaggedItem(tag, &itm)) {
memcpy(item, &itm, sizeof(InventoryItem));
return true;
}
}
}
return false;
}
void DrawHotbar() {
if(inventoryOpen) UIBegin();
const int width = 52 * ITEMS;
DrawRectangle(GetScreenWidth()/2-width/2, GetScreenHeight()-48-2, width, 50, ColorAlpha(BLACK, 0.25f));
for (int i = 0; i < ITEMS; i++)
{
int x = GetScreenWidth()/2-width/2 + i * 52;
int y = GetScreenHeight()-50;
if(inventoryOpen) {
if(ButtonInventory(x, y, 52, 52)) {
if(movingItem != nullptr && hotbar[i].item == nullptr) {
memcpy(&hotbar[i], movingItem, sizeof(InventoryItem));
movingItem->item = nullptr;
movingItem->amount = 0;
movingItem->damage = 0;
}
else {
movingItem = &hotbar[i];
}
};
}
if(i == selected) {
DrawRectangle(x, y, 52, 52, BLACK);
}
if(&hotbar[i] != movingItem) {
DrawItem(hotbar[i], x, y);
}
}
if(inventoryOpen) {
const int width2 = 52 * INVENTORY_WIDTH;
const int inv_height = 52 * INVENTORY_HEIGHT;
DrawRectangle(GetScreenWidth()/2-width2/2, GetScreenHeight()-56-inv_height, width2, inv_height, ColorAlpha(BLACK, 0.25f));
for (int i = 0; i < INVENTORY_SIZE; i++)
{
int x = GetScreenWidth()/2-width2/2 + (i % INVENTORY_WIDTH) * 52;
int y = GetScreenHeight()-56-inv_height + (i / INVENTORY_WIDTH) * 52;
if((i + (i / INVENTORY_WIDTH)) % 2 == 0) {
DrawRectangle(x, y, 52, 52, ColorAlpha(BLACK, 0.1f));
}
if(ButtonInventory(x, y, 52, 52)) {
if(movingItem != nullptr && inventory[i].item == nullptr) {
memcpy(&inventory[i], movingItem, sizeof(InventoryItem));
movingItem->item = nullptr;
movingItem->amount = 0;
movingItem->damage = 0;
}
else {
movingItem = &inventory[i];
}
};
if(&inventory[i] != movingItem) {
DrawItem(inventory[i], x, y);
}
}
std::list<Recipe> validRecipes;
for (Recipe r : recipes)
{
if(r.requiredStation == "hands") {
std::vector<int> items;
for (RecipeItem ingredient : r.inputs) {
for (int i = 0; i < INVENTORY_SIZE; i++)
{
InventoryItem item = inventory[i];
if(item.item != nullptr) {
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 tagBlockCond = item.item->type == IType_Block && ingredient.type == IType_Special_Tag && IDTagMatch(ingredient.id, BLOCKS[item.damage].name);
bool tagItemCond = item.item->type != IType_Block && ingredient.type == IType_Special_Tag && IDTagMatch(ingredient.id, item.item->id);
if(blockCond || genericCond || tagBlockCond || tagItemCond) {
items.push_back(i);
}
}
}
}
if(items.size() == r.inputs.size()) {
validRecipes.push_back(r);
}
}
}
int _y = 0;
for (Recipe r : validRecipes)
{
int x = GetScreenWidth()/2-width2/2 - 300;
int y = GetScreenHeight()-56-inv_height - _y * 52;
DrawRectangle(x, y, 260, 52, Fade(BLACK, 0.25f));
int _x = 0;
for (RecipeItem ingredient : r.inputs) {
InventoryItem temp;
if(ingredient.type == IType_Block) {
temp.item = &(registry[0]);
temp.damage = GetNumericIDFromString(ingredient.id);
}
else if (ingredient.type == IType_Generic) {
temp.item = GetItemByID(ingredient.id);
}
else {
GetTaggedItem(ingredient.id, &temp);
}
temp.amount = ingredient.quantity;
DrawItem(temp, x + _x * 52, y);
_x++;
}
_x = 1;
for (RecipeItem ingredient : r.outputs) {
InventoryItem temp;
if(ingredient.type == IType_Block) {
temp.item = &(registry[0]);
temp.damage = GetNumericIDFromString(ingredient.id);
}
else {
temp.item = GetItemByID(ingredient.id);
}
temp.amount = ingredient.quantity;
DrawItem(temp, x + 300 - 40 - _x * 52, y);
_x++;
}
if(ButtonInventory(x, y, 260, 52)) {
std::map<int, int> items;
for (RecipeItem ingredient : r.inputs) {
for (int i = 0; i < INVENTORY_SIZE; i++)
{
InventoryItem item = inventory[i];
if(item.item != nullptr) {
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 tagBlockCond = item.item->type == IType_Block && ingredient.type == IType_Special_Tag && IDTagMatch(ingredient.id, BLOCKS[item.damage].name);
bool tagItemCond = item.item->type != IType_Block && ingredient.type == IType_Special_Tag && IDTagMatch(ingredient.id, item.item->id);
if(blockCond || genericCond || tagBlockCond || tagItemCond) {
items[i] = ingredient.quantity;
}
}
}
}
if(items.size() == r.inputs.size()) {
for(auto [i, amount] : items) {
for (int _ = 0; _ < amount; _++)
{
InventoryRemoveItem(i);
}
}
for (RecipeItem ingredient : r.outputs) {
if(ingredient.type == IType_Block) {
for (int _ = 0; _ < ingredient.quantity; _++) {
HotbarAddItem(&registry[0], GetNumericIDFromString(ingredient.id));
}
}
else {
for (int _ = 0; _ < ingredient.quantity; _++) {
HotbarAddItem(GetItemByID(ingredient.id), 255);
}
}
}
}
}
_y++;
}
}
if(inventoryOpen) {
const int width2 = 52 * INVENTORY_WIDTH;
const int inv_height = 52 * INVENTORY_HEIGHT;
DrawRectangle(GetScreenWidth()/2-width2/2, 4, width2, inv_height, ColorAlpha(BLACK, 0.25f));
for (int i = 0; i < INVENTORY_SIZE; i++)
{
InventoryItem item;
if(i < MAX_BLOCK_ID) {
item.item = &registry[0];
item.damage = i;
}
else if (i < registry.size()+MAX_BLOCK_ID-1) {
item.item = &registry[i-MAX_BLOCK_ID+1];
}
int x = GetScreenWidth()/2-width2/2 + (i % INVENTORY_WIDTH) * 52;
int y = 4 + (i / INVENTORY_WIDTH) * 52;
if((i + (i / INVENTORY_WIDTH)) % 2 == 0) {
DrawRectangle(x, y, 52, 52, ColorAlpha(BLACK, 0.1f));
}
if(ButtonInventory(x, y, 52, 52)) {
if(movingItem != nullptr) {
movingItem = nullptr;
}
else {
HotbarAddItem(item.item, item.damage);
}
};
DrawItem(item, x, y);
}
}
if(movingItem != nullptr && movingItem->item != nullptr) {
DrawItem(*movingItem, GetMouseX(), GetMouseY());
std::string name = "item."+movingItem->item->id;
if(movingItem->item->type == IType_Block) {
name = "item."+BLOCKS[movingItem->damage].name;
}
DrawTextB(LocaleGet(name).c_str(), GetMouseX()-16, GetMouseY()+56, 16, WHITE);
}
if(inventoryOpen) UIHandleControls();
}
InventoryItem HotbarGetSelected() {
return hotbar[selected];
}
void DrawSelectedItem() {
InventoryItem item = hotbar[selected];
Vector3 center = {-0.75f, -0.45f, 0.5f};
rlPushMatrix();
rlTranslatef(center.x, center.y-0.25f, center.z);
float swing = powf(player_attack_time,1);
float swing3 = sinf(swing * swing * PI);
float swing2 = sinf(sqrt(swing) * PI);
rlRotatef(-swing3 * 50, 1, 0, 0);
rlRotatef(-swing2 * 80, 0, 1, 0);
swing = powf(player_place_time,2);
swing2 = sinf(swing * PI);
rlRotatef(swing2 * 80, 0, 1, 0);
rlRotatef(-45, 1, 0, 0);
rlRotatef(25, 0, 0, 1);
DrawCubeTexture(playerTex, {0, -12*PIXUNIT/2, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 44,20,4,4);
if(item.item != nullptr) {
if(item.item->type == IType_Block) {
DrawCubeBlock(terrain, {0, -12*PIXUNIT - 0.25f, 0}, 0.5f, 0.5f, 0.5f, BLOCKS[item.damage]);
}
else {
UVCorners left = GetUVTex(item.item->texture);
rlSetTexture(item_atlas.id);
rlBegin(RL_QUADS);
rlColor4ub(255, 255, 255, 255);
rlNormal3f(1.0f, 0.0f, 0.0f);
const float size = 0.5f;
rlTexCoord2f(left.corner0.x, left.corner0.y); rlVertex3f(0, -12*PIXUNIT - size, 0.25f - size);
rlTexCoord2f(left.corner1.x, left.corner1.y); rlVertex3f(0, -12*PIXUNIT + size, 0.25f - size);
rlTexCoord2f(left.corner2.x, left.corner2.y); rlVertex3f(0, -12*PIXUNIT + size, 0.25f + size);
rlTexCoord2f(left.corner3.x, left.corner3.y); rlVertex3f(0, -12*PIXUNIT - size, 0.25f + size);
rlEnd();
}
}
rlPopMatrix();
}
bool InputGetKeyDown(const std::string name);
bool InputGetKeyPressed(const std::string name);
void CloseInventory() {
inventoryOpen = false;
movingItem = nullptr;
DisableCursor();
}
void UpdateHotbar() {
if(GetMouseWheelMoveV().y > 0.1f) {
selected++;
if(selected >= ITEMS) {
selected = 0;
}
}
if(GetMouseWheelMoveV().y < -0.1f) {
selected--;
if(selected >= ITEMS) {
selected = ITEMS-1;
}
}
if(IsKeyPressed(KEY_ONE)) {
selected = 0;
}
if(IsKeyPressed(KEY_TWO)) {
selected = 1;
}
if(IsKeyPressed(KEY_THREE)) {
selected = 2;
}
if(IsKeyPressed(KEY_FOUR)) {
selected = 3;
}
if(IsKeyPressed(KEY_FIVE)) {
selected = 4;
}
if(IsKeyPressed(KEY_SIX)) {
selected = 5;
}
if(IsKeyPressed(KEY_SEVEN)) {
selected = 6;
}
if(IsKeyPressed(KEY_EIGHT)) {
selected = 7;
}
if(IsKeyPressed(KEY_NINE)) {
selected = 8;
}
if(IsKeyPressed(KEY_KP_ADD)) {
hotbar[selected].damage++;
}
if(IsKeyPressed(KEY_KP_SUBTRACT)) {
hotbar[selected].damage--;
}
if(InputGetKeyPressed("inventory")) {
inventoryOpen = !inventoryOpen;
if(inventoryOpen) {
EnableCursor();
}
else {
CloseInventory();
}
}
if(IsKeyPressed(KEY_F9)) {
HotbarAddItem(GetItemByID("gold_pickaxe"), 255);
HotbarAddItemLots(GetItemByID("gold_ingot"), 255, INT32_MAX);
HotbarAddItemLots(GetItemByID("copper_ingot"), 255, INT32_MAX);
HotbarAddItemLots(GetItemByID("silver_ingot"), 255, INT32_MAX);
HotbarAddItemLots(GetItemByID("block"), GetNumericIDFromString("stone"), INT32_MAX);
HotbarAddItemLots(GetItemByID("block"), GetNumericIDFromString("planks"), INT32_MAX);
HotbarAddItemLots(GetItemByID("apple"), 255, INT32_MAX);
}
}
#endif
+29
View File
@@ -0,0 +1,29 @@
#ifndef SERVER
#include "common.hpp"
#include "yaml-cpp/yaml.h"
#include <cstring>
#include <iostream>
#define LOCALE_LOC "locale.yaml"
static std::map <std::string, std::string> locale;
void LocaleUpdate() {
YAML::Node _locale = YAML::LoadFile(Pathify(LOCALE_LOC));
for(YAML::const_iterator it=_locale.begin();it!=_locale.end();++it)
{
locale[it->first.as<std::string>()] = it->second.as<std::string>();
}
}
const std::string LocaleGet(const std::string loc) {
if(locale.find(loc) != locale.end()) {
return locale[loc];
}
return loc;
}
const std::string GetKeycodeName(KeyboardKey key) {
const char* name = GetKeyName(key);
if(name == NULL) //fallback
name = KeyCodeToString((KeyCode)key);
return std::string(name);
}
#endif
+587
View File
@@ -0,0 +1,587 @@
#ifndef SERVER
#include <stdint.h>
#include <stdbool.h>
#include "common.hpp"
#include <cstring>
#include <list>
#include <raymath.h>
#include <iostream>
#include <rlgl.h>
#include <unordered_set>
#include <algorithm>
#include <vector>
#include <filesystem>
#include <map>
int currentlySelected = -1;
extern Font fnt;
extern GameState state;
extern bool online;
static Sound snd_click;
static Sound snd_hover;
extern Texture2D terrain;
Texture2D cubemap;
extern Camera camera;
static int MakeUIPOI(int x, int y) {
return x << 16 | y;
}
std::unordered_set<uint32_t> ui_pois;
int TryConnect(const char* hostname);
void InitSingleplayer();
void GameModeCleanup();
static int mouseX = -1;
static int mouseY = -1;
std::vector<std::filesystem::path> worldList;
static void LoadWorlds() {
worldList.clear();
const std::filesystem::path worlds{PathifyUser("worlds")};
for (auto const& dir_entry : std::filesystem::directory_iterator{worlds})
worldList.push_back(dir_entry.path());
}
void DrawBackground()
{
ClearBackground(BLACK);
const float unit = 1;
camera.position = { 0 };
BeginMode3D(camera);
rlSetTexture(cubemap.id);
rlColor4ub(128, 128, 128, 255);
rlRotatef(GetTime(), 0, 1, 0);
rlBegin(RL_QUADS);
rlTexCoord2f(2/6.0f, 0); rlVertex3f(-unit, unit, unit);
rlTexCoord2f(2/6.0f, 1); rlVertex3f(-unit, -unit, unit);
rlTexCoord2f(3/6.0f, 1); rlVertex3f(-unit, -unit, -unit);
rlTexCoord2f(3/6.0f, 0); rlVertex3f(-unit, unit, -unit);
rlTexCoord2f(1/6.0f, 0); rlVertex3f(unit, unit, unit);
rlTexCoord2f(1/6.0f, 1); rlVertex3f(unit, -unit, unit);
rlTexCoord2f(2/6.0f, 1); rlVertex3f(-unit, -unit, unit);
rlTexCoord2f(2/6.0f, 0); rlVertex3f(-unit, unit, unit);
rlTexCoord2f(0/6.0f, 0); rlVertex3f(unit, unit, -unit);
rlTexCoord2f(0/6.0f, 1); rlVertex3f(unit, -unit, -unit);
rlTexCoord2f(1/6.0f, 1); rlVertex3f(unit, -unit, unit);
rlTexCoord2f(1/6.0f, 0); rlVertex3f(unit, unit, unit);
rlTexCoord2f(3/6.0f, 0); rlVertex3f(-unit, unit, -unit);
rlTexCoord2f(3/6.0f, 1); rlVertex3f(-unit, -unit, -unit);
rlTexCoord2f(4/6.0f, 1); rlVertex3f(unit, -unit, -unit);
rlTexCoord2f(4/6.0f, 0); rlVertex3f(unit, unit, -unit);
rlTexCoord2f(4/6.0f, 0); rlVertex3f(unit, unit, -unit);
rlTexCoord2f(4/6.0f, 1); rlVertex3f(unit, unit, unit);
rlTexCoord2f(5/6.0f, 1); rlVertex3f(-unit, unit, unit);
rlTexCoord2f(5/6.0f, 0); rlVertex3f(-unit, unit, -unit);
rlTexCoord2f(6/6.0f, 1); rlVertex3f(-unit, -unit, -unit);
rlTexCoord2f(6/6.0f, 0); rlVertex3f(-unit, -unit, unit);
rlTexCoord2f(5/6.0f, 0); rlVertex3f(unit, -unit, unit);
rlTexCoord2f(5/6.0f, 1); rlVertex3f(unit, -unit, -unit);
rlEnd();
EndMode3D();
}
void InitMenu() {
snd_click = LoadSound(Pathify("sound/select.wav"));
snd_hover = LoadSound(Pathify("sound/hover.wav"));
cubemap = LoadTexture(Pathify("cubemap.png"));
}
void DrawTextB(const char *text, int posX, int posY, int fontSize, Color color)
{
DrawTextEx(fnt, text, (Vector2){ posX+2, posY+2 }, fontSize, 1, BLACK);
DrawTextEx(fnt, text, (Vector2){ posX, posY }, fontSize, 1, color);
}
static int lastHover = 0;
static int lastHover0 = 0;
bool Button(const char* text, int x, int y, int width, int id) {
int screenID = MakeUIPOI(x, y);
ui_pois.insert(screenID);
Color shadow0 = BLACK;
Color shadow1 = WHITE;
Color fill = GRAY;
bool mouseOnButton = mouseX >= x && mouseY >= y && mouseX <= x+width && mouseY <= y+32;
if(mouseOnButton) {
lastHover = MakeUIPOI(x, y);
fill = BLACK;
shadow0 = WHITE;
shadow1 = GRAY;
}
else {
if(lastHover == screenID) {
lastHover = 0;
}
}
DrawRectangle(x-2, y-2, width, 32, shadow1);
DrawRectangle(x+2, y+2, width, 32, shadow0);
DrawRectangle(x, y, width, 32, fill);
DrawRectangleGradientV(x,y, width, 32, fill, ColorLerp(shadow0, fill, 0.5f));
Vector2 measures = MeasureTextEx(fnt, text, DEFAULT_FONT_SIZE, 1);
DrawTextB(text, x + width / 2 - measures.x / 2, y + 32 / 2 - measures.y / 2, DEFAULT_FONT_SIZE, WHITE);
if((IsMouseButtonPressed(0) || IsGamepadButtonPressed(0, GAMEPAD_BUTTON_RIGHT_FACE_UP)) && mouseOnButton) {
PlaySound(snd_click);
return true;
}
return false;
}
bool ButtonInventory(int x, int y, int width, int height) {
int screenID = MakeUIPOI(x, y);
ui_pois.insert(screenID);
Color fill = Fade(WHITE, 0);
bool mouseOnButton = mouseX >= x && mouseY >= y && mouseX <= x+width && mouseY <= y+height;
if(mouseOnButton) {
lastHover = MakeUIPOI(x, y);
fill = Fade(WHITE, 0.25f);
}
else {
if(lastHover == screenID) {
lastHover = 0;
}
}
DrawRectangle(x, y, width, height, fill);
if((IsMouseButtonPressed(0) || IsGamepadButtonPressed(0, GAMEPAD_BUTTON_RIGHT_FACE_UP)) && mouseOnButton) {
PlaySound(snd_click);
return true;
}
return false;
}
bool TextField(int id, char *buffer, int bufferSize, int x, int y, int width) {
Color shadow0 = BLACK;
Color shadow1 = WHITE;
Color fill = DARKGRAY;
static int focusedId = -1; // currently focused field
static int caretBlinkTimer = 0; // frames
static int caretPos = 0; // insertion index within buffer
// Measure mouse-over and focus
bool mouseOnField = mouseX >= x && mouseY >= y && mouseX <= x+width && mouseY <= y+32;
if(mouseOnField) {
fill = BLACK;
shadow0 = WHITE;
shadow1 = GRAY;
}
if(focusedId == id) {
fill = BLACK;
shadow0 = WHITE;
shadow1 = GRAY;
}
// Draw field
DrawRectangle(x-2, y-2, width, 32, shadow1);
DrawRectangle(x+2, y+2, width, 32, shadow0);
DrawRectangle(x, y, width, 32, GRAY);
DrawRectangle(x+2, y+2, width-4, 28, fill);
// Click to focus
if(IsMouseButtonPressed(0) && mouseOnField) {
focusedId = id;
// position caret near mouse x: approximate by measuring characters
int len = (int)strlen(buffer);
caretPos = len;
float relX = mouseX - (x + 6); // 6px padding
// walk characters to determine caret index
float acc = 0;
for(int i = 0; i <= len; ++i) {
char temp = buffer[i];
buffer[i] = '\0';
Vector2 m = MeasureTextEx(fnt, buffer, DEFAULT_FONT_SIZE, 1);
buffer[i] = temp;
if(m.x >= relX) { caretPos = i; break; }
}
caretBlinkTimer = 0;
} else if(IsMouseButtonPressed(0) && !mouseOnField) {
// clicking elsewhere removes focus
// keep focusedId unless clicking outside any field; simplistic: clear focus
if(focusedId == id) focusedId = -1;
}
// Draw text with padding
const int padding = 6;
Vector2 measures = MeasureTextEx(fnt, buffer, DEFAULT_FONT_SIZE, 1);
DrawTextB(buffer, x + padding, y + 32 / 2 - measures.y / 2, DEFAULT_FONT_SIZE, WHITE);
bool edited = false;
// If focused, handle keyboard input
if(focusedId == id) {
// Blink caret
caretBlinkTimer = (caretBlinkTimer + 1) % 60; // 60-frame cycle
if(caretBlinkTimer < 30) {
// compute caret x position by measuring substring
char tmp[256];
int len = (int)strlen(buffer);
int cp = caretPos;
if(cp < 0) cp = 0;
if(cp > len) cp = len;
int copyLen = (cp < (int)sizeof(tmp)-1) ? cp : (int)sizeof(tmp)-1;
memcpy(tmp, buffer, copyLen);
tmp[copyLen] = '\0';
Vector2 subMeas = MeasureTextEx(fnt, tmp, DEFAULT_FONT_SIZE, 1);
int cx = x + padding + (int)subMeas.x;
DrawRectangle(cx, y + 6, 2, 20, WHITE); // caret
}
// Handle control keys: backspace, delete, left/right
int key;
while((key = GetKeyPressed()) != 0) {
std::cout << key << std::endl;
if(key == 259) { // Backspace
int len = (int)strlen(buffer);
if(caretPos > 0 && len > 0) {
// shift left
memmove(buffer + caretPos - 1, buffer + caretPos, len - caretPos + 1);
caretPos--;
edited = true;
}
} else if(key == 127) { // Delete
int len = (int)strlen(buffer);
if(caretPos < len) {
memmove(buffer + caretPos, buffer + caretPos + 1, len - caretPos);
edited = true;
}
} else if(key == 9) { // Tab (remove focus)
focusedId = -1;
} else if(key == 13 || key == 10) {
focusedId = -1;
} else if(key == 27) {
focusedId = -1;
} else if(key == 1270) {
} else {
}
}
// Character input (UTF-8 aware limited)
int c;
while((c = GetCharPressed()) > 0) {
if(c >= 32 && c <= 125) {
int len = (int)strlen(buffer);
if(len + 1 < bufferSize) {
memmove(buffer + caretPos + 1, buffer + caretPos, len - caretPos + 1);
buffer[caretPos] = (char)c;
caretPos++;
edited = true;
}
}
}
int finalLen = (int)strlen(buffer);
if(caretPos < 0) caretPos = 0;
if(caretPos > finalLen) caretPos = finalLen;
}
return edited;
}
const char* error = "";
void UIBegin() {
ui_pois.clear();
}
void UIResetMousePos() {
mouseX = -1;
mouseY = -1;
ui_pois.clear();
}
static int controlsDelay = 0;
void UIHandleControls() {
if(lastHover0 != lastHover) {
lastHover0 = lastHover;
PlaySound(snd_hover);
}
if(mouseX == -1 || mouseY == -1) {
std::vector<std::pair<int, int>> v;
for (int poi : ui_pois) {
int x = (poi >> 16) & 0xFFFF;
int y = poi & 0xFFFF;
v.push_back({y, x});
}
std::sort(v.begin(), v.end(), [](const auto &a, const auto &b){
if (a.first != b.first) return a.first < b.first;
return a.second < b.second;
});
mouseX = v[0].second;
mouseY = v[0].first;
}
Vector2 dpad = InputGetDPAD();
if(controlsDelay == 0) {
if(dpad.y > 0.1f) {
std::vector<std::pair<int, int>> v;
for (int poi : ui_pois) {
int x = (poi >> 16) & 0xFFFF;
int y = poi & 0xFFFF;
v.push_back({y, x});
}
std::sort(v.begin(), v.end(), [](const auto &a, const auto &b){
if (a.first != b.first) return a.first > b.first;
return a.second < b.second;
});
for (const auto &poi : v) {
int x = poi.second;
int y = poi.first;
if(y < mouseY && x == mouseX) {
mouseX = x;
mouseY = y;
controlsDelay = 30;
return;
}
}
}
if(dpad.y < -0.1f) {
std::vector<std::pair<int, int>> v;
for (int poi : ui_pois) {
int x = (poi >> 16) & 0xFFFF;
int y = poi & 0xFFFF;
v.push_back({y, x});
}
std::sort(v.begin(), v.end(), [](const auto &a, const auto &b){
if (a.first != b.first) return a.first < b.first;
return a.second < b.second;
});
for (const auto &poi : v) {
int x = poi.second;
int y = poi.first;
if(y > mouseY && x == mouseX) {
mouseX = x;
mouseY = y;
controlsDelay = 30;
return;
}
}
}
if(dpad.x > 0.1f) {
std::vector<std::pair<int, int>> v;
for (int poi : ui_pois) {
int x = (poi >> 16) & 0xFFFF;
int y = poi & 0xFFFF;
v.push_back({y, x});
}
std::sort(v.begin(), v.end(), [](const auto &a, const auto &b){
if (a.first != b.first) return a.first > b.first;
return a.second < b.second;
});
for (const auto &poi : v) {
int x = poi.second;
int y = poi.first;
if(x > mouseX && y == mouseY) {
mouseX = x;
mouseY = y;
controlsDelay = 30;
return;
}
}
}
if(dpad.x < -0.1f) {
std::vector<std::pair<int, int>> v;
for (int poi : ui_pois) {
int x = (poi >> 16) & 0xFFFF;
int y = poi & 0xFFFF;
v.push_back({y, x});
}
std::sort(v.begin(), v.end(), [](const auto &a, const auto &b){
if (a.first != b.first) return a.first > b.first;
return a.second < b.second;
});
for (const auto &poi : v) {
int x = poi.second;
int y = poi.first;
if(x < mouseX && y == mouseY) {
mouseX = x;
mouseY = y;
controlsDelay = 30;
return;
}
}
}
}
else {
controlsDelay--;
}
if(!IsGamepadAvailable(0)) {
mouseX = GetMouseX();
mouseY = GetMouseY();
}
}
extern std::map <std::string, int> controls;
const std::string LocaleGet(std::string loc);
const std::string GetKeycodeName(KeyboardKey key);
static int currently_selected_control = -1;
void DrawControls() {
UIBegin();
BeginDrawing();
DrawBackground();
const int base_x = GetScreenWidth() / 2 - (160 + 128) / 2;
const int base_y = 64;
int n = 0;
for (const auto& [name, key] : controls) {
const char *text = "...\0";
if(n != currently_selected_control) {
text = GetKeycodeName((KeyboardKey)key).c_str();
}
else {
int _key = GetKeyPressed();
if(_key != 0) {
controls[name] = _key;
currently_selected_control = -1;
}
}
DrawTextB(LocaleGet(name).c_str(), base_x, base_y + n * 36, DEFAULT_FONT_SIZE, WHITE);
if (Button(text, base_x + 160, base_y + n * 36, 128, 0)) {
currently_selected_control = n;
};
n++;
}
const char *text = " ";
if(swap_mouse) {
text = "X";
}
DrawTextB(LocaleGet("swap_mouse").c_str(), base_x, base_y + n * 36, DEFAULT_FONT_SIZE, WHITE);
if (Button(text, base_x + 160, base_y + n * 36, 32, 0)) {
swap_mouse = !swap_mouse;
};
if (Button(LocaleGet("exit").c_str(), GetScreenWidth() / 2 - 64, GetScreenHeight() - 48, 128, 0)) {
InputWriteControls();
state = GAME_STATE_MAINMENU;
};
EndDrawing();
UIHandleControls();
}
void DrawMainMenu() {
UIBegin();
BeginDrawing();
DrawBackground();
DrawText(GAME_NAME, 24, 24, 64, BLACK);
DrawText(GAME_NAME, 16, 16, 64, WHITE);
DrawTextB(GAME_VERSION, 16, 72, DEFAULT_FONT_SIZE, WHITE);
if (Button(LocaleGet("select_level").c_str(), 16, 128, 128, 0)) {
LoadWorlds();
UIResetMousePos();
state = GAME_STATE_WORLDSELECT;
return;
}
if (Button(LocaleGet("multiplayer").c_str(), 16, 128+48, 128, 0)) {
UIResetMousePos();
state = GAME_STATE_MULTIPLAYERSELECT;
error = "";
return;
}
if (Button(LocaleGet("options").c_str(), 16, 128+48+48, 128, 0)) {
UIResetMousePos();
state = GAME_STATE_OPTIONS;
return;
}
if (Button(LocaleGet("exit").c_str(), 16, 128+48+48+48, 128, 0)) {
exit(0);
}
EndDrawing();
UIHandleControls();
}
void _LoadWorld(const char* path);
void DrawWorldSelect() {
UIBegin();
BeginDrawing();
DrawBackground();
int i = 0;
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)) {
online = false;
SetTargetFPS(-1);
_LoadWorld(reinterpret_cast<const char*>(path.u8string().c_str()));
return;
}
i++;
}
if (Button(LocaleGet("exit").c_str(), GetScreenWidth()/2-196, GetScreenHeight()-48, 128, 0)) {
UIResetMousePos();
state = GAME_STATE_MAINMENU;
return;
}
if (Button(LocaleGet("create_world").c_str(), GetScreenWidth()/2+196-128, GetScreenHeight()-48, 128, 0)) {
UIResetMousePos();
InitSingleplayer();
return;
}
if (Button(LocaleGet("create_world").c_str(), GetScreenWidth()/2+196-128, GetScreenHeight()-48-48, 128, 0)) {
UIResetMousePos();
InitWorldgen(2);
state = GAME_STATE_LOADING;
return;
}
EndDrawing();
UIHandleControls();
}
char buffer[64];
void DrawMultiplayer() {
UIBegin();
BeginDrawing();
DrawBackground();
bool changed = TextField(1, buffer, sizeof(buffer), GetScreenWidth()/2-100, 32, 200);
if (Button(LocaleGet("join").c_str(), GetScreenWidth()/2-196, GetScreenHeight()-48, 128, 0)) {
int code = TryConnect(buffer);
if(code != -1) {
switch (code)
{
case NET_ERROR_NOTFOUND:
error = LocaleGet("error_notfound").c_str();
break;
case NET_ERROR_INTERNAL:
error = LocaleGet("error_internal").c_str();
break;
case NET_ERROR_FAILED:
error = LocaleGet("error_unknown").c_str();
break;
default:
break;
}
}
}
if (Button(LocaleGet("exit").c_str(), GetScreenWidth()/2+196-128, GetScreenHeight()-48, 128, 0)) {
state = GAME_STATE_MAINMENU;
UIResetMousePos();
return;
}
DrawTextB(error, GetScreenWidth()/2-100, 128, DEFAULT_FONT_SIZE, WHITE);
EndDrawing();
UIHandleControls();
}
void DrawPauseMenu() {
UIBegin();
DrawRectangle(0,0,GetScreenWidth(),GetScreenHeight(),Fade(GRAY,0.5f));
if (Button(LocaleGet("exit").c_str(), GetScreenWidth()/2-64, 48, 128, 0)) {
GameModeCleanup();
UIResetMousePos();
return;
}
UIHandleControls();
}
char bufferChat[MAX_MESSAGE_LENGTH];
char* DrawChat() {
const int x = 0;
const int y = 0;
const int h = 240;
const int buttonWidth = 120;
UIBegin();
DrawRectangle(x,y,GetScreenWidth(),h,Fade(GRAY,0.5f));
bool changed = TextField(1, bufferChat, sizeof(bufferChat), x, y+h, GetScreenWidth());
bool send = Button(LocaleGet("send").c_str(), x+GetScreenWidth()-buttonWidth, y+h, buttonWidth, 0) || IsKeyPressed(KEY_ENTER);
if(send) {
return bufferChat;
}
UIHandleControls();
return nullptr;
}
void DrawLogoCenter() {
BeginDrawing();
Vector2 m = MeasureTextEx(GetFontDefault(), GAME_NAME, 64, 0);
DrawText(GAME_NAME, GetScreenWidth()/2 - m.x / 2 - 8, GetScreenHeight()/2 - m.y / 2 - 8, 64, BLACK);
DrawText(GAME_NAME, GetScreenWidth()/2 - m.x / 2, GetScreenHeight()/2 - m.y / 2, 64, WHITE);
EndDrawing();
}
#endif
+591
View File
@@ -0,0 +1,591 @@
#include <vector>
#include <cstdint>
#include <cstring>
#include <algorithm>
#include "common.hpp"
#include <vector>
#include <cstdint>
#include <array>
#ifndef SERVER
#ifndef LEGACY_GL
MeshData GenerateChunkMesh(ChunkRenderData chunkRenderData, Chunk chunk, int chunkWorldX, int chunkWorldY, uint8_t sideMask)
{
MeshData out = {0};
out.vertexCount = 0; out.indexCount = 0;
std::vector<Vector3> positions;
std::vector<Vector3> normals;
std::vector<Vector2> uvs;
std::vector<Color> colors;
std::vector<unsigned short> indices;
int face = 0;
for (int x = 0; x < CHUNK_SIZE; ++x)
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];
if (crdata == 0) continue;
int this_block = fetch_block(chunk, x,y,z);
BlockDef definition = BLOCKS[this_block];
UVCorners UVside = GetUVTex(definition.textureSide);
UVCorners UVtop = GetUVTex(definition.textureTop);
UVCorners UVbtm = GetUVTex(definition.textureBottom);
bool left, right, up, down, back, front;
unpack6(crdata & sideMask, &left, &right, &up, &down, &back, &front);
bool shaded = chunk.highestBlock[GetIndexChunk2D(x, z)] != y;
Color color = {255, 255, 255, 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)) {
color = ColorLerp(color, colorShaded, 0.5f);
}*/
if (left) {
Vector3 verts[4] = {
{wx - 0.5f, wy - 0.5f, wz - 0.5f}, // bottom-left
{wx - 0.5f, wy - 0.5f, wz + 0.5f}, // bottom-right
{wx - 0.5f, wy + 0.5f, wz + 0.5f}, // top-right
{wx - 0.5f, wy + 0.5f, wz - 0.5f} // top-left
};
Vector3 normal = {-1.0f, 0.0f, 0.0f};
Vector2 corners[4] = {
UVside.corner0,
UVside.corner1,
UVside.corner2,
UVside.corner3
};
positions.push_back(verts[0]);
positions.push_back(verts[1]);
positions.push_back(verts[2]);
positions.push_back(verts[3]);
normals.push_back(normal);
colors.push_back(colorShaded);
uvs.push_back(corners[0]);
uvs.push_back(corners[1]);
uvs.push_back(corners[2]);
uvs.push_back(corners[3]);
unsigned short indbase = face*4;
unsigned short tri[6] = {
indbase + 0, indbase + 1, indbase + 2,
indbase + 0, indbase + 2, indbase + 3
};
indices.insert(indices.end(), tri, tri + 6);
face++;
}
// Right face (+X)
if (right) {
Vector3 verts[4] = {
{wx + 0.5f, wy - 0.5f, wz + 0.5f}, // bottom-left (from +X side)
{wx + 0.5f, wy - 0.5f, wz - 0.5f}, // bottom-right
{wx + 0.5f, wy + 0.5f, wz - 0.5f}, // top-right
{wx + 0.5f, wy + 0.5f, wz + 0.5f} // top-left
};
Vector3 normal = {1.0f, 0.0f, 0.0f};
Vector2 corners[4] = {
UVside.corner0,
UVside.corner1,
UVside.corner2,
UVside.corner3
};
positions.push_back(verts[0]);
positions.push_back(verts[1]);
positions.push_back(verts[2]);
positions.push_back(verts[3]);
normals.push_back(normal);
colors.push_back(colorShaded);
uvs.push_back(corners[0]);
uvs.push_back(corners[1]);
uvs.push_back(corners[2]);
uvs.push_back(corners[3]);
unsigned short indbase = face*4;
unsigned short tri[6] = {
indbase + 0, indbase + 1, indbase + 2,
indbase + 0, indbase + 2, indbase + 3
};
indices.insert(indices.end(), tri, tri + 6);
face++;
}
// Down (-Y)
if (down) {
Vector3 verts[4] = {
{wx - 0.5f, wy - 0.5f, wz - 0.5f}, // bottom-left
{wx + 0.5f, wy - 0.5f, wz - 0.5f}, // bottom-right
{wx + 0.5f, wy - 0.5f, wz + 0.5f}, // top-right
{wx - 0.5f, wy - 0.5f, wz + 0.5f} // top-left
};
Vector3 normal = {0.0f, -1.0f, 0.0f};
Vector2 corners[4] = {
UVbtm.corner0,
UVbtm.corner1,
UVbtm.corner2,
UVbtm.corner3
};
positions.push_back(verts[0]);
positions.push_back(verts[1]);
positions.push_back(verts[2]);
positions.push_back(verts[3]);
normals.push_back(normal);
colors.push_back(colorShaded);
uvs.push_back(corners[0]);
uvs.push_back(corners[1]);
uvs.push_back(corners[2]);
uvs.push_back(corners[3]);
unsigned short indbase = face*4;
unsigned short tri[6] = {
indbase + 0, indbase + 1, indbase + 2,
indbase + 0, indbase + 2, indbase + 3
};
indices.insert(indices.end(), tri, tri + 6);
face++;
}
// Up (+Y)
if (up) {
Vector3 verts[4] = {
{wx - 0.5f, wy + 0.5f, wz + 0.5f}, // bottom-left (from +Y side)
{wx + 0.5f, wy + 0.5f, wz + 0.5f}, // bottom-right
{wx + 0.5f, wy + 0.5f, wz - 0.5f}, // top-right
{wx - 0.5f, wy + 0.5f, wz - 0.5f} // top-left
};
Vector3 normal = {0.0f, 1.0f, 0.0f};
Vector2 corners[4] = {
UVtop.corner0,
UVtop.corner1,
UVtop.corner2,
UVtop.corner3
};
positions.push_back(verts[0]);
positions.push_back(verts[1]);
positions.push_back(verts[2]);
positions.push_back(verts[3]);
normals.push_back(normal);
if(shaded) {
colors.push_back(colorShaded);
}
else {
colors.push_back(color);
}
uvs.push_back(corners[0]);
uvs.push_back(corners[1]);
uvs.push_back(corners[2]);
uvs.push_back(corners[3]);
unsigned short indbase = face*4;
unsigned short tri[6] = {
indbase + 0, indbase + 1, indbase + 2,
indbase + 0, indbase + 2, indbase + 3
};
indices.insert(indices.end(), tri, tri + 6);
face++;
}
// Front (+Z)
if (front) {
Vector3 verts[4] = {
{wx - 0.5f, wy - 0.5f, wz + 0.5f}, // bottom-left
{wx + 0.5f, wy - 0.5f, wz + 0.5f}, // bottom-right
{wx + 0.5f, wy + 0.5f, wz + 0.5f}, // top-right
{wx - 0.5f, wy + 0.5f, wz + 0.5f} // top-left
};
Vector3 normal = {0.0f, 0.0f, 1.0f};
Vector2 corners[4] = {
UVside.corner0,
UVside.corner1,
UVside.corner2,
UVside.corner3
};
positions.push_back(verts[0]);
positions.push_back(verts[1]);
positions.push_back(verts[2]);
positions.push_back(verts[3]);
normals.push_back(normal);
colors.push_back(colorShaded);
uvs.push_back(corners[0]);
uvs.push_back(corners[1]);
uvs.push_back(corners[2]);
uvs.push_back(corners[3]);
unsigned short indbase = face*4;
unsigned short tri[6] = {
indbase + 0, indbase + 1, indbase + 2,
indbase + 0, indbase + 2, indbase + 3
};
indices.insert(indices.end(), tri, tri + 6);
face++;
}
// Back (-Z)
if (back) {
Vector3 verts[4] = {
{wx + 0.5f, wy - 0.5f, wz - 0.5f}, // bottom-left (from -Z side)
{wx - 0.5f, wy - 0.5f, wz - 0.5f}, // bottom-right
{wx - 0.5f, wy + 0.5f, wz - 0.5f}, // top-right
{wx + 0.5f, wy + 0.5f, wz - 0.5f} // top-left
};
Vector3 normal = {0.0f, 0.0f, -1.0f};
Vector2 corners[4] = {
UVside.corner0,
UVside.corner1,
UVside.corner2,
UVside.corner3
};
positions.push_back(verts[0]);
positions.push_back(verts[1]);
positions.push_back(verts[2]);
positions.push_back(verts[3]);
normals.push_back(normal);
colors.push_back(colorShaded);
uvs.push_back(corners[0]);
uvs.push_back(corners[1]);
uvs.push_back(corners[2]);
uvs.push_back(corners[3]);
unsigned short indbase = face*4;
unsigned short tri[6] = {
indbase + 0, indbase + 1, indbase + 2,
indbase + 0, indbase + 2, indbase + 3
};
indices.insert(indices.end(), tri, tri + 6);
face++;
}
}
out.positions = (float*)malloc(sizeof(float) * 3 * positions.size());
out.uvs = (float*)malloc(sizeof(float) * 2 * uvs.size());
out.indices = (unsigned short*)malloc(sizeof(unsigned short) * indices.size());
out.normals = (float*)malloc(sizeof(float) * 3 * 4 * normals.size());
out.colors = (unsigned char*)malloc(sizeof(unsigned char) * 4 * 4 * colors.size());
int s = 0;
for (Vector3 v : positions)
{
out.positions[s] = v.x;
out.positions[s+1] = v.y;
out.positions[s+2] = v.z;
s += 3;
}
s = 0;
for (Vector3 n : normals)
{
for (size_t _ = 0; _ < 4; _++)
{
out.normals[s] = n.x;
out.normals[s+1] = n.y;
out.normals[s+2] = n.z;
s += 3;
}
}
s = 0;
for (Color c : colors)
{
for (size_t _ = 0; _ < 4; _++)
{
out.colors[s] = c.r;
out.colors[s+1] = c.g;
out.colors[s+2] = c.b;
out.colors[s+3] = c.a;
s += 4;
}
}
s = 0;
for (Vector2 uv : uvs)
{
out.uvs[s] = uv.x;
out.uvs[s+1] = uv.y;
s += 2;
}
s = 0;
for (unsigned short i : indices)
{
out.indices[s] = i;
s += 1;
}
out.vertexCount = positions.size();
out.indexCount = indices.size();
positions.clear();
normals.clear();
uvs.clear();
indices.clear();
return out;
}
MeshData MergeMeshData(const MeshData &a, const MeshData &b)
{
MeshData out = {0};
// initial counts
int aPosCount = a.positions ? (a.vertexCount * 3) : 0;
int aNormCount = a.normals ? (a.vertexCount * 3) : 0;
int aUvCount = a.uvs ? (a.vertexCount * 2) : 0;
int aColCount = a.colors ? (a.vertexCount * 4) : 0;
int aIdxCount = a.indices ? (a.indexCount) : 0;
int bPosCount = b.positions ? (b.vertexCount * 3) : 0;
int bNormCount = b.normals ? (b.vertexCount * 3) : 0;
int bUvCount = b.uvs ? (b.vertexCount * 2) : 0;
int bColCount = b.colors ? (b.vertexCount * 4) : 0;
int bIdxCount = b.indices ? (b.indexCount) : 0;
// allocate combined buffers
int totalVert = a.vertexCount + b.vertexCount;
int totalPos = totalVert * 3;
int totalNorm = totalVert * 3;
int totalUv = totalVert * 2;
int totalCol = totalVert * 4;
int totalIdx = a.indexCount + b.indexCount;
if (totalPos > 0) {
out.positions = (float*)malloc(totalPos * sizeof(float));
memcpy(out.positions, a.positions ? a.positions : nullptr, aPosCount * sizeof(float));
} else out.positions = nullptr;
if (totalNorm > 0) {
out.normals = (float*)malloc(totalNorm * sizeof(float));
memcpy(out.normals, a.normals ? a.normals : nullptr, aNormCount * sizeof(float));
} else out.normals = nullptr;
if (totalUv > 0) {
out.uvs = (float*)malloc(totalUv * sizeof(float));
memcpy(out.uvs, a.uvs ? a.uvs : nullptr, aUvCount * sizeof(float));
} else out.uvs = nullptr;
if (totalCol > 0) {
out.colors = (unsigned char*)malloc(totalCol * sizeof(unsigned char));
memcpy(out.colors, a.colors ? a.colors : nullptr, aColCount * sizeof(unsigned char));
} else out.colors = nullptr;
if (totalIdx > 0) {
out.indices = (unsigned short*)malloc(totalIdx * sizeof(unsigned short));
if (a.indices && aIdxCount > 0)
memcpy(out.indices, a.indices, aIdxCount * sizeof(unsigned short));
} else out.indices = nullptr;
// copy B data appending with index offset
// positions
if (bPosCount > 0) {
memcpy(out.positions + aPosCount, b.positions, bPosCount * sizeof(float));
}
// normals
if (bNormCount > 0) {
memcpy(out.normals + aNormCount, b.normals, bNormCount * sizeof(float));
}
// uvs
if (bUvCount > 0) {
memcpy(out.uvs + aUvCount, b.uvs, bUvCount * sizeof(float));
}
// colors
if (bColCount > 0) {
memcpy(out.colors + aColCount, b.colors, bColCount * sizeof(unsigned char));
}
// indices (need to offset b indices by a.vertexCount)
if (bIdxCount > 0) {
unsigned short idxOffset = (unsigned short)(a.vertexCount);
for (int i = 0; i < bIdxCount; ++i) {
out.indices[aIdxCount + i] = (unsigned short)(b.indices[i] + idxOffset);
}
}
out.vertexCount = totalVert;
out.indexCount = totalIdx;
return out;
}
MeshData CreateCubeMeshData(const BlockDef &def, float cx, float cy, float cz)
{
MeshData out = {0};
// 4 verts * 6 faces = 24 vertices
const int vertsPerFace = 4;
const int faces = 6;
const int totalVerts = vertsPerFace * faces;
const int totalPos = totalVerts * 3;
const int totalNorm = totalVerts * 3;
const int totalUv = totalVerts * 2;
const int totalCol = totalVerts * 4;
const int totalIdx = faces * 6;
out.vertexCount = totalVerts;
out.indexCount = totalIdx;
out.positions = (float*)malloc(totalPos * sizeof(float));
out.normals = (float*)malloc(totalNorm * sizeof(float));
out.uvs = (float*)malloc(totalUv * sizeof(float));
out.colors = (unsigned char*)malloc(totalCol * sizeof(unsigned char));
out.indices = (unsigned short*)malloc(totalIdx * sizeof(unsigned short));
int p = 0, n = 0, u = 0, c = 0, ix = 0;
Color baseColor = {255,255,255,255};
auto pushPos = [&](float x, float y, float z) {
out.positions[p++] = x; out.positions[p++] = y; out.positions[p++] = z;
};
auto pushNorm = [&](float x, float y, float z) {
out.normals[n++] = x; out.normals[n++] = y; out.normals[n++] = z;
};
auto pushUV = [&](float uu, float vv) {
out.uvs[u++] = uu; out.uvs[u++] = vv;
};
auto pushCol = [&](unsigned char r, unsigned char g, unsigned char b, unsigned char a) {
out.colors[c++] = r; out.colors[c++] = g; out.colors[c++] = b; out.colors[c++] = a;
};
auto pushTriIdx = [&](unsigned short a, unsigned short b, unsigned short c2) {
out.indices[ix++] = a; out.indices[ix++] = b; out.indices[ix++] = c2;
};
// get UV corners for faces
UVCorners UVside = GetUVTex(def.textureSide);
UVCorners UVtop = GetUVTex(def.textureTop);
UVCorners UVbtm = GetUVTex(def.textureBottom);
// face builder: verts in CCW for the outside-facing side
auto buildFace = [&](const Vector3 faceVerts[4], const Vector3 &normal, const Vector2 faceUVs[4]) {
unsigned short base = (unsigned short)((p/3)); // current vertex index
Color clr = baseColor;
for (int i=0;i<4;i++) {
pushPos(faceVerts[i].x, faceVerts[i].y, faceVerts[i].z);
pushNorm(normal.x, normal.y, normal.z);
pushUV(faceUVs[i].x, faceUVs[i].y);
pushCol(clr.r, clr.g, clr.b, clr.a);
}
// two tris (0,1,2) (0,2,3)
pushTriIdx(base + 0, base + 1, base + 2);
pushTriIdx(base + 0, base + 2, base + 3);
};
float hx = 0.5f, hy = 0.5f, hz = 0.5f;
// Left (-X)
{
Vector3 verts[4] = {
{cx - hx, cy - hy, cz - hz},
{cx - hx, cy - hy, cz + hz},
{cx - hx, cy + hy, cz + hz},
{cx - hx, cy + hy, cz - hz}
};
Vector2 uvs[4] = { UVside.corner0, UVside.corner1, UVside.corner2, UVside.corner3 };
Vector3 normal = {-1,0,0};
buildFace(verts, normal, uvs);
}
// Right (+X)
{
Vector3 verts[4] = {
{cx + hx, cy - hy, cz + hz},
{cx + hx, cy - hy, cz - hz},
{cx + hx, cy + hy, cz - hz},
{cx + hx, cy + hy, cz + hz}
};
Vector2 uvs[4] = { UVside.corner0, UVside.corner1, UVside.corner2, UVside.corner3 };
Vector3 normal = {1,0,0};
buildFace(verts, normal, uvs);
}
// Down (-Y)
{
Vector3 verts[4] = {
{cx - hx, cy - hy, cz - hz},
{cx + hx, cy - hy, cz - hz},
{cx + hx, cy - hy, cz + hz},
{cx - hx, cy - hy, cz + hz}
};
Vector2 uvs[4] = { UVbtm.corner0, UVbtm.corner1, UVbtm.corner2, UVbtm.corner3 };
Vector3 normal = {0,-1,0};
buildFace(verts, normal, uvs);
}
// Up (+Y)
{
Vector3 verts[4] = {
{cx - hx, cy + hy, cz + hz},
{cx + hx, cy + hy, cz + hz},
{cx + hx, cy + hy, cz - hz},
{cx - hx, cy + hy, cz - hz}
};
Vector2 uvs[4] = { UVtop.corner0, UVtop.corner1, UVtop.corner2, UVtop.corner3 };
Vector3 normal = {0,1,0};
buildFace(verts, normal, uvs);
}
// Front (+Z)
{
Vector3 verts[4] = {
{cx - hx, cy - hy, cz + hz},
{cx + hx, cy - hy, cz + hz},
{cx + hx, cy + hy, cz + hz},
{cx - hx, cy + hy, cz + hz}
};
Vector2 uvs[4] = { UVside.corner0, UVside.corner1, UVside.corner2, UVside.corner3 };
Vector3 normal = {0,0,1};
buildFace(verts, normal, uvs);
}
// Back (-Z)
{
Vector3 verts[4] = {
{cx + hx, cy - hy, cz - hz},
{cx - hx, cy - hy, cz - hz},
{cx - hx, cy + hy, cz - hz},
{cx + hx, cy + hy, cz - hz}
};
Vector2 uvs[4] = { UVside.corner0, UVside.corner1, UVside.corner2, UVside.corner3 };
Vector3 normal = {0,0,-1};
buildFace(verts, normal, uvs);
}
return out;
}
Mesh GenChunkMesh(MeshData meshData)
{
Mesh mesh = { 0 };
mesh.indices = meshData.indices;
mesh.vertexCount = meshData.vertexCount;
mesh.triangleCount = meshData.indexCount / 3;
mesh.vertices = meshData.positions;
mesh.texcoords = meshData.uvs;
mesh.normals = meshData.normals;
mesh.colors = meshData.colors;
UploadMesh(&mesh, false);
return mesh;
}
#endif
#endif
+62
View File
@@ -0,0 +1,62 @@
#include "common.hpp"
struct ThreeDeeSound {
Sound ref;
float pitch;
float volume;
Vector3 position;
float seconds;
};
std::vector<ThreeDeeSound> sounds;
static void SetSoundPosition(Sound sound, Vector3 position, float maxDist, Camera camera)
{
// Calculate direction vector and distance between listener and sound source
Vector3 direction = Vector3Subtract(position, camera.position);
float distance = Vector3Length(direction);
// Apply logarithmic distance attenuation and clamp between 0-1
float attenuation = 1.0f/(1.0f + (distance/maxDist));
attenuation = Clamp(attenuation, 0.0f, 1.0f);
// Calculate normalized vectors for spatial positioning
Vector3 normalizedDirection = Vector3Normalize(direction);
Vector3 forward = Vector3Normalize(camera.target-camera.position);
Vector3 right = Vector3Normalize(Vector3CrossProduct({0, 1, 0}, forward));
// Reduce volume for sounds behind the listener
float dotProduct = Vector3DotProduct(forward, normalizedDirection);
if (dotProduct < 0.0f) attenuation *= (1.0f + dotProduct*0.5f);
// Set stereo panning based on sound position relative to listener
float pan = -Vector3DotProduct(normalizedDirection, right);
if(distance > maxDist) {
attenuation *= 1-Clamp((distance - maxDist) / 10.0f, 0, 1);
}
// Apply final sound properties
SetSoundVolume(sound, attenuation);
SetSoundPan(sound, pan);
}
void MS_PlaySound(Sound src, float pitch, float volume, Vector3 position) {
ThreeDeeSound snd = {};
snd.ref = LoadSoundAlias(src);
snd.pitch = pitch;
snd.volume = volume;
snd.position = position;
SetSoundVolume(snd.ref, 0);
PlaySound(snd.ref);
sounds.push_back(snd);
}
void MS_Update(float dt, Camera camera) {
for (int i = 0; i < sounds.size(); i++)
{
ThreeDeeSound snd = sounds[i];
if(snd.seconds > 3) sounds.erase(sounds.begin() + i); // TODO: make better
SetSoundPosition(snd.ref, snd.position, 40, camera);
SetSoundPitch(snd.ref, snd.pitch);
//SetSoundVolume(snd.ref, snd.volume);
}
}
+109
View File
@@ -0,0 +1,109 @@
#include <cstdio>
#include "common.hpp"
#include <cstring>
int NetworkingStart()
{
if (enet_initialize () < 0)
{
fprintf (stderr, "An error occurred while initializing ENet.\n");
return EXIT_FAILURE;
}
atexit(enet_deinitialize);
}
ENetHost* StartServer() {
ENetAddress address;
ENetHost * server;
/* Bind the server to the default localhost. */
/* A specific host address can be specified by */
/* enet_address_set_host (& address, "x.x.x.x"); */
address.host = ENET_HOST_ANY;
/* Bind the server to port 1234. */
address.port = PORT;
server = enet_host_create(&address, 32, 1, 0, 0);
if (server == NULL)
{
fprintf (stderr,
"An error occurred while trying to create an ENet server host.\n");
exit (EXIT_FAILURE);
}
return server;
}
ENetHost* StartClient() {
ENetHost * client;
client = enet_host_create (NULL /* create a client host */,
1 /* 1 channel*/,
1 /* only allow 1 outgoing connection */,
0 /* assume any amount of incoming bandwidth */,
0);
if (client == NULL)
{
fprintf (stderr,
"An error occurred while trying to create an ENet client host.\n");
exit (EXIT_FAILURE);
}
return client;
}
void SendPacket(ENetPeer* peer, void* data, int len)
{
ENetPacket* packet = enet_packet_create(data, len, ENET_PACKET_FLAG_UNSEQUENCED);
int c = enet_peer_send(peer, 0, packet);
if(c!=0) {
printf("Failed sending packet! ");
printf("%d\n", c);
enet_packet_destroy(packet);
}
}
void SendPacketR(ENetPeer* peer, void* data, int len)
{
ENetPacket* packet = enet_packet_create(data, len, ENET_PACKET_FLAG_RELIABLE);
int c = enet_peer_send(peer, 0, packet);
if(c!=0) {
printf("Failed sending packet! ");
printf("%d\n", c);
enet_packet_destroy(packet);
}
}
void BroadcastPacketR(ENetHost* server, void* data, int len)
{
ENetPacket* packet = enet_packet_create(data, len, ENET_PACKET_FLAG_RELIABLE);
enet_host_broadcast(server, 0, packet);
}
void SerializeFloat2Data(float v, void *target, int offset) {
uint8_t *buf = (uint8_t*)target + offset;
if (!isfinite(v)) { // handle NaN/Inf as zero (choose policy)
buf[0] = 0;
buf[1] = 0;
return;
}
if (v < 0.0f) v = 0.0f;
if (v > 255.0f) v = 255.0f; // clamp to representable range
int intpart = (int)floorf(v);
float frac = v - (float)intpart;
int frac_byte = (int)floorf(frac * 255.0f + 0.5f); // round to nearest
if (frac_byte < 0) frac_byte = 0;
if (frac_byte > 255) frac_byte = 255;
buf[0] = (uint8_t)intpart;
buf[1] = (uint8_t)frac_byte;
}
float DeserializeFloat(int b0, int b1) {
return (float)(uint8_t)b0 + (float)((uint8_t)b1) / 255.0f;
}
+119
View File
@@ -0,0 +1,119 @@
#include "common.hpp"
#include <list>
#include <rlgl.h>
std::list<Particle> particles;
extern Camera3D camera;
extern Texture2D terrain;
static void DrawParticle(Particle particle, Color color)
{
Vector3 position = particle.position;
float x = position.x;
float y = position.y;
float z = position.z;
float width = 0.25f;
float height = width;
float length = height;
UVCorners corners = GetUVTex(particle.data[0], width, width, width, width);
UVCorners front = corners;
UVCorners back = corners;
UVCorners top = corners;
UVCorners bottom = corners;
UVCorners left = corners;
UVCorners right = corners;
// Set desired texture to be enabled while drawing following vertex data
rlSetTexture(terrain.id);
rlBegin(RL_QUADS);
rlColor4ub(color.r, color.g, color.b, color.a);
// Front Face
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.corner1.x, front.corner1.y); rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Right Of The Texture and Quad
rlTexCoord2f(front.corner2.x, front.corner2.y); rlVertex3f(x + width/2, y + height/2, z + length/2); // Top Right Of The Texture and Quad
rlTexCoord2f(front.corner3.x, front.corner3.y); rlVertex3f(x - width/2, y + height/2, z + length/2); // Top Left Of The Texture and Quad
// Back Face
rlNormal3f(0.0f, 0.0f, - 1.0f); // Normal Pointing Away From Viewer
rlTexCoord2f(back.corner1.x, back.corner1.y); rlVertex3f(x - width/2, y - height/2, z - length/2); // Bottom Right Of The Texture and Quad
rlTexCoord2f(back.corner2.x, back.corner2.y); rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Right Of The Texture and Quad
rlTexCoord2f(back.corner3.x, back.corner3.y); rlVertex3f(x + width/2, y + height/2, z - length/2); // Top Left Of The Texture and Quad
rlTexCoord2f(back.corner0.x, back.corner0.y); rlVertex3f(x + width/2, y - height/2, z - length/2); // Bottom Left Of The Texture and Quad
// Top Face
rlNormal3f(0.0f, 1.0f, 0.0f); // Normal Pointing Up
rlTexCoord2f(top.corner3.x, top.corner3.y); rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Left Of The Texture and Quad
rlTexCoord2f(top.corner0.x, top.corner0.y); rlVertex3f(x - width/2, y + height/2, z + length/2); // Bottom Left Of The Texture and Quad
rlTexCoord2f(top.corner1.x, top.corner1.y); rlVertex3f(x + width/2, y + height/2, z + length/2); // Bottom Right Of The Texture and Quad
rlTexCoord2f(top.corner2.x, top.corner2.y); rlVertex3f(x + width/2, y + height/2, z - length/2); // Top Right Of The Texture and Quad
// Bottom Face
rlNormal3f(0.0f, - 1.0f, 0.0f); // Normal Pointing Down
rlTexCoord2f(bottom.corner2.x, bottom.corner2.y); rlVertex3f(x - width/2, y - height/2, z - length/2); // Top Right Of The Texture and Quad
rlTexCoord2f(bottom.corner3.x, bottom.corner3.y); rlVertex3f(x + width/2, y - height/2, z - length/2); // Top Left Of The Texture and Quad
rlTexCoord2f(bottom.corner0.x, bottom.corner0.y); rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Left Of The Texture and Quad
rlTexCoord2f(bottom.corner1.x, bottom.corner1.y); rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom Right Of The Texture and Quad
// Right face
rlNormal3f(1.0f, 0.0f, 0.0f); // Normal Pointing Right
rlTexCoord2f(right.corner1.x, right.corner1.y); rlVertex3f(x + width/2, y - height/2, z - length/2); // Bottom Right Of The Texture and Quad
rlTexCoord2f(right.corner2.x, right.corner2.y); rlVertex3f(x + width/2, y + height/2, z - length/2); // Top Right Of The Texture and Quad
rlTexCoord2f(right.corner3.x, right.corner3.y); rlVertex3f(x + width/2, y + height/2, z + length/2); // Top Left Of The Texture and Quad
rlTexCoord2f(right.corner0.x, right.corner0.y); rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Left Of The Texture and Quad
// Left Face
rlNormal3f( - 1.0f, 0.0f, 0.0f); // Normal Pointing Left
rlTexCoord2f(left.corner0.x, left.corner0.y); rlVertex3f(x - width/2, y - height/2, z - length/2); // Bottom Left Of The Texture and Quad
rlTexCoord2f(left.corner1.x, left.corner1.y); rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom Right Of The Texture and Quad
rlTexCoord2f(left.corner2.x, left.corner2.y); rlVertex3f(x - width/2, y + height/2, z + length/2); // Top Right Of The Texture and Quad
rlTexCoord2f(left.corner3.x, left.corner3.y); rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Left Of The Texture and Quad
rlEnd();
rlSetTexture(0);
}
void ParticlesUpdate(float dt, Chunk world[]) {
particles.remove_if([](Particle x) { return x.lifetime > 200; });
for (Particle &part : particles)
{
part.lifetime++;
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 tgt = Vector3Add(part.position, Vector3Scale(velocityTgt, dt));
Vector3 vis = Vector3Add(tgt, {0.5f, 0.4f, 0.5f});
Vector3 final = part.position;
if(!GetBlock(world, (int)vis.x, (int)final.y, (int)final.z)) {
final.x = tgt.x;
}
if(!GetBlock(world, (int)final.x, (int)vis.y, (int)final.z)) {
final.y = tgt.y;
}
else {
velocityTgt.y = 0;
}
if(!GetBlock(world, (int)final.x, (int)final.y, (int)vis.z)) {
final.z = tgt.z;
}
for (Particle &part2 : particles)
{
if(Vector3DistanceSqr(part.position, part2.position) < 0.25f*0.25f) {
Vector3 force = Vector3Normalize(Vector3Subtract(part.position, part2.position)) * dt * 25;
part.velocity += force;
part2.velocity -= force;
}
}
part.position = final;
part.velocity = velocityTgt;
}
}
}
void ParticlesDraw() {
for (Particle part : particles)
{
DrawParticle(part, WHITE);
}
}
void AddParticle(Particle part) {
particles.push_back(part);
}
Particle NewParticle(Vector3 position) {
Particle part;
part.physicsType = Phys_Falling;
part.position = position;
part.texture = terrain;
return part;
}
+134
View File
@@ -0,0 +1,134 @@
#include <stdint.h>
#include <stdbool.h>
#include "common.hpp"
#include <cstring>
#include <list>
#include <fstream>
#include <vector>
#include <iostream>
#define SAVE_FORMAT 1
bool creative_mode = false;
float player_health = MAX_HP;
float player_attack_time = 0;
float player_place_time = 0;
float player_break_parts_time = 0;
Vector3 player_position;
Vector3 player_velocity;
int GetItemNumID(std::string s);
extern InventoryItem hotbar[ITEMS];
extern InventoryItem inventory[INVENTORY_SIZE];
extern std::vector<Item> registry;
void SavePlayerData() {
std::ofstream data(PathifyUser("player.data"), std::ios::binary);
if (!data) return;
data.write("PLR", 3);
char fmt = static_cast<char>(SAVE_FORMAT);
data.write(&fmt, 1);
char creative = static_cast<char>(creative_mode);
data.write(&creative, 1);
data.write(reinterpret_cast<const char*>(&player_health), sizeof(player_health));
std::cout << "H" << std::endl;
std::vector<uint8_t> temp;
for (int i = 0; i < ITEMS; i++)
{
Item* item = hotbar[i].item;
int id = 0;
if(item != nullptr)
id = GetItemNumID(item->id);
std::cout << inventory[i].amount << std::endl;
temp.push_back((uint8_t)id);
temp.push_back((uint8_t)hotbar[i].damage);
temp.push_back((uint8_t)hotbar[i].amount);
}
for (int i = 0; i < INVENTORY_SIZE; i++)
{
Item* item = inventory[i].item;
int id = 0;
if(item != nullptr)
id = GetItemNumID(item->id);
temp.push_back((uint8_t)id);
temp.push_back((uint8_t)inventory[i].damage);
temp.push_back((uint8_t)inventory[i].amount);
}
uint16_t size = static_cast<uint16_t>(temp.size());
data.write(reinterpret_cast<const char*>(&size), sizeof(size));
if (!temp.empty()) {
data.write(reinterpret_cast<const char*>(temp.data()), temp.size());
}
}
bool LoadPlayerData() {
std::ifstream data(PathifyUser("player.data"), std::ios::binary);
if (!data) return false;
char header[3];
if (!data.read(header, 3)) return false;
if (header[0] != 'P' || header[1] != 'L' || header[2] != 'R') return false;
char fmt;
if (!data.read(&fmt, 1)) return false;
if (static_cast<int>(fmt) != SAVE_FORMAT) {
return false;
}
char creative;
if (!data.read(&creative, 1)) return false;
creative_mode = static_cast<bool>(creative);
if (!data.read(reinterpret_cast<char*>(&player_health), sizeof(player_health))) return false;
uint16_t size = 0;
if (!data.read(reinterpret_cast<char*>(&size), sizeof(size))) return false;
std::vector<uint8_t> temp;
if (size > 0) {
temp.resize(size);
if (!data.read(reinterpret_cast<char*>(temp.data()), size)) return false;
}
// validate expected length: (ITEMS + INVENTORY_SIZE) * 3 bytes
const size_t expected = (static_cast<size_t>(ITEMS) + static_cast<size_t>(INVENTORY_SIZE)) * 3;
if (size != expected) {
// if older/newer formats may differ, handle gracefully; here we reject mismatch
return false;
}
// parse into hotbar and inventory
size_t idx = 0;
for (int i = 0; i < ITEMS; ++i) {
uint8_t numid = temp[idx++];
uint8_t damage = temp[idx++];
uint8_t amount = temp[idx++];
if (amount == 0) {
hotbar[i].item = nullptr;
} else {
Item* itemPtr = &registry[static_cast<int>(numid)];
hotbar[i].item = itemPtr;
}
hotbar[i].damage = damage;
hotbar[i].amount = amount;
}
for (int i = 0; i < INVENTORY_SIZE; ++i) {
uint8_t numid = temp[idx++];
uint8_t damage = temp[idx++];
uint8_t amount = temp[idx++];
if (amount == 0) {
inventory[i].item = nullptr;
} else {
Item* itemPtr = &registry[static_cast<int>(numid)];
inventory[i].item = itemPtr;
}
inventory[i].damage = damage;
inventory[i].amount = amount;
}
return true;
}
+80
View File
@@ -0,0 +1,80 @@
#ifndef SERVER
#include <stdint.h>
#include <stdbool.h>
#include "common.hpp"
#include <cstring>
#include <filesystem>
#include "yaml-cpp/yaml.h"
#include <iostream>
#include <regex>
#include <string>
#include <regex>
#include <iostream>
static std::map<std::string, std::regex> tags = {};
static bool ParseRecipe(const std::string &s, RecipeItem &out) {
static const std::regex re(R"(^([^:]+):([^*]+)(?:\*([0-9]+))?$)");
std::smatch m;
if (!std::regex_match(s, m, re)) return false;
if(m[1].str() == "block")
out.type = IType_Block;
else if(m[1].str() == "tag")
out.type = IType_Special_Tag;
else
out.type = IType_Generic;
out.id = m[2].str();
if (m[3].matched) out.quantity = std::stoi(m[3].str());
else out.quantity = 1;
return true;
}
bool IDTagMatch(std::string tag, std::string id) {
std::smatch m;
std::cout << tag << std::endl;
std::cout << id << std::endl;
return std::regex_match(id, m, tags[tag]);
}
std::list<Recipe> recipes;
void LoadRecipes() {
tags["planks"] = std::regex(".*planks$");
std::vector<std::filesystem::path> recipeList;
recipeList.clear();
std::cout << "A" << std::endl;
std::filesystem::path recipes_path{Pathify("recipes")};
std::cout << "A" << std::endl;
for (auto const& dir_entry : std::filesystem::directory_iterator{recipes_path}) {
try
{
Recipe _recipe;
const std::string path = dir_entry.path().u8string();
YAML::Node recipe = YAML::LoadFile(path);
_recipe.requiredStation = recipe["station"].as<std::string>();
for (auto s : recipe["inputs"]) {
RecipeItem r;
if (ParseRecipe(s.as<std::string>(), r)) {
_recipe.inputs.push_back(r);
} else {
std::cout << "parse failed for: " << s << std::endl;
}
}
for (auto s : recipe["outputs"]) {
RecipeItem r;
if (ParseRecipe(s.as<std::string>(), r)) {
_recipe.outputs.push_back(r);
} else {
std::cout << "parse failed for: " << s << std::endl;
}
}
recipes.push_back(_recipe);
}
catch(const std::exception& e)
{
std::cerr << "Exception while loading recipe " << dir_entry << ": "<< e.what() << '!' << std::endl;
}
}
}
#endif
+358
View File
@@ -0,0 +1,358 @@
#include "common.hpp"
#include <iostream>
#include <cstring>
#include <list>
#include <unordered_set>
#include <vector>
#include <string>
#include <memory>
#include <filesystem>
#include <lua.hpp>
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 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(plr.addr == peer->address.host && plr.port == peer->address.port) {
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(plr.addr == peer->address.host && plr.port == peer->address.port) {
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(plr.addr != peer->address.host || plr.port != peer->address.port) {
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(plr.addr == peer->address.host || plr.port == peer->address.port) {
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(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, 1) > 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 = 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));
}
// notify plugins
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 (it->addr == event.peer->address.host && it->port == event.peer->address.port) {
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);
}
+256
View File
@@ -0,0 +1,256 @@
#include "raylib.h"
#include "math.h"
#include "raymath.h"
#include <stdint.h>
#include <stdbool.h>
#include "common.hpp"
#include <rlgl.h>
#include <iostream>
const char* Pathify(const char* src) {
static std::string s;
s = std::string(PATH_APPEND) + src;
return s.c_str();
}
const char* PathifyUser(const char* src) {
static std::string s;
s = std::string(PATH_APPEND_USER) + src;
return s.c_str();
}
#ifndef SERVER
void DrawCubeTexture(Texture2D texture, Vector3 position, float width, float height, float length, Color color, int offsetX, int offsetY, int sizeX, int sizeY)
{
float x = position.x;
float y = position.y;
float z = position.z;
float sidesModX = length / width;
float topBottomModY = height / width;
UVCorners front = GetUVTexFlipX(texture.width, texture.height, offsetX, offsetY, sizeX, sizeY * topBottomModY);
UVCorners back = GetUVTexFlipX(texture.width, texture.height, offsetX+sizeX+sizeX*sidesModX, offsetY, sizeX, sizeY * topBottomModY);
UVCorners top = GetUVTexFlipX(texture.width, texture.height, offsetX, offsetY-sizeY, sizeX, sizeY);
UVCorners bottom = GetUVTexFlipX(texture.width, texture.height, offsetX+sizeX, offsetY-sizeY, sizeX, sizeY);
UVCorners left = GetUVTexFlipX(texture.width, texture.height, offsetX-sizeX * sidesModX, offsetY, sizeX * sidesModX, sizeY * topBottomModY);
UVCorners right = GetUVTexFlipX(texture.width, texture.height, offsetX+sizeX * sidesModX, offsetY, sizeX * sidesModX, sizeY * topBottomModY);
// Set desired texture to be enabled while drawing following vertex data
rlSetTexture(texture.id);
// Vertex data transformation can be defined with the commented lines,
// but in this example we calculate the transformed vertex data directly when calling rlVertex3f()
//rlPushMatrix();
// NOTE: Transformation is applied in inverse order (scale -> rotate -> translate)
//rlTranslatef(2.0f, 0.0f, 0.0f);
//rlRotatef(45, 0, 1, 0);
//rlScalef(2.0f, 2.0f, 2.0f);
rlBegin(RL_QUADS);
rlColor4ub(color.r, color.g, color.b, color.a);
// Front Face
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.corner1.x, front.corner1.y); rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Right Of The Texture and Quad
rlTexCoord2f(front.corner2.x, front.corner2.y); rlVertex3f(x + width/2, y + height/2, z + length/2); // Top Right Of The Texture and Quad
rlTexCoord2f(front.corner3.x, front.corner3.y); rlVertex3f(x - width/2, y + height/2, z + length/2); // Top Left Of The Texture and Quad
// Back Face
rlNormal3f(0.0f, 0.0f, - 1.0f); // Normal Pointing Away From Viewer
rlTexCoord2f(back.corner1.x, back.corner1.y); rlVertex3f(x - width/2, y - height/2, z - length/2); // Bottom Right Of The Texture and Quad
rlTexCoord2f(back.corner2.x, back.corner2.y); rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Right Of The Texture and Quad
rlTexCoord2f(back.corner3.x, back.corner3.y); rlVertex3f(x + width/2, y + height/2, z - length/2); // Top Left Of The Texture and Quad
rlTexCoord2f(back.corner0.x, back.corner0.y); rlVertex3f(x + width/2, y - height/2, z - length/2); // Bottom Left Of The Texture and Quad
// Top Face
rlNormal3f(0.0f, 1.0f, 0.0f); // Normal Pointing Up
rlTexCoord2f(top.corner3.x, top.corner3.y); rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Left Of The Texture and Quad
rlTexCoord2f(top.corner0.x, top.corner0.y); rlVertex3f(x - width/2, y + height/2, z + length/2); // Bottom Left Of The Texture and Quad
rlTexCoord2f(top.corner1.x, top.corner1.y); rlVertex3f(x + width/2, y + height/2, z + length/2); // Bottom Right Of The Texture and Quad
rlTexCoord2f(top.corner2.x, top.corner2.y); rlVertex3f(x + width/2, y + height/2, z - length/2); // Top Right Of The Texture and Quad
// Bottom Face
rlNormal3f(0.0f, - 1.0f, 0.0f); // Normal Pointing Down
rlTexCoord2f(bottom.corner2.x, bottom.corner2.y); rlVertex3f(x - width/2, y - height/2, z - length/2); // Top Right Of The Texture and Quad
rlTexCoord2f(bottom.corner3.x, bottom.corner3.y); rlVertex3f(x + width/2, y - height/2, z - length/2); // Top Left Of The Texture and Quad
rlTexCoord2f(bottom.corner0.x, bottom.corner0.y); rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Left Of The Texture and Quad
rlTexCoord2f(bottom.corner1.x, bottom.corner1.y); rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom Right Of The Texture and Quad
// Right face
rlNormal3f(1.0f, 0.0f, 0.0f); // Normal Pointing Right
rlTexCoord2f(right.corner1.x, right.corner1.y); rlVertex3f(x + width/2, y - height/2, z - length/2); // Bottom Right Of The Texture and Quad
rlTexCoord2f(right.corner2.x, right.corner2.y); rlVertex3f(x + width/2, y + height/2, z - length/2); // Top Right Of The Texture and Quad
rlTexCoord2f(right.corner3.x, right.corner3.y); rlVertex3f(x + width/2, y + height/2, z + length/2); // Top Left Of The Texture and Quad
rlTexCoord2f(right.corner0.x, right.corner0.y); rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Left Of The Texture and Quad
// Left Face
rlNormal3f( - 1.0f, 0.0f, 0.0f); // Normal Pointing Left
rlTexCoord2f(left.corner0.x, left.corner0.y); rlVertex3f(x - width/2, y - height/2, z - length/2); // Bottom Left Of The Texture and Quad
rlTexCoord2f(left.corner1.x, left.corner1.y); rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom Right Of The Texture and Quad
rlTexCoord2f(left.corner2.x, left.corner2.y); rlVertex3f(x - width/2, y + height/2, z + length/2); // Top Right Of The Texture and Quad
rlTexCoord2f(left.corner3.x, left.corner3.y); rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Left Of The Texture and Quad
rlEnd();
//rlPopMatrix();
rlSetTexture(0);
}
void DrawCubeBlock(Texture2D texture, Vector3 position, float width, float height, float length, BlockDef def)
{
float x = position.x;
float y = position.y;
float z = position.z;
float sidesModX = length / width;
float topBottomModY = height / width;
UVCorners front = GetUVTex(def.textureSide);
UVCorners back = GetUVTex(def.textureSide);
UVCorners top = GetUVTex(def.textureTop);
UVCorners bottom = GetUVTex(def.textureBottom);
UVCorners left = GetUVTex(def.textureSide);
UVCorners right = GetUVTex(def.textureSide);
rlSetTexture(texture.id);
rlBegin(RL_QUADS);
rlColor4ub(255, 255, 255, 255);
// Front Face
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.corner1.x, front.corner1.y); rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Right Of The Texture and Quad
rlTexCoord2f(front.corner2.x, front.corner2.y); rlVertex3f(x + width/2, y + height/2, z + length/2); // Top Right Of The Texture and Quad
rlTexCoord2f(front.corner3.x, front.corner3.y); rlVertex3f(x - width/2, y + height/2, z + length/2); // Top Left Of The Texture and Quad
// Back Face
rlNormal3f(0.0f, 0.0f, - 1.0f); // Normal Pointing Away From Viewer
rlTexCoord2f(back.corner1.x, back.corner1.y); rlVertex3f(x - width/2, y - height/2, z - length/2); // Bottom Right Of The Texture and Quad
rlTexCoord2f(back.corner2.x, back.corner2.y); rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Right Of The Texture and Quad
rlTexCoord2f(back.corner3.x, back.corner3.y); rlVertex3f(x + width/2, y + height/2, z - length/2); // Top Left Of The Texture and Quad
rlTexCoord2f(back.corner0.x, back.corner0.y); rlVertex3f(x + width/2, y - height/2, z - length/2); // Bottom Left Of The Texture and Quad
// Top Face
rlNormal3f(0.0f, 1.0f, 0.0f); // Normal Pointing Up
rlTexCoord2f(top.corner3.x, top.corner3.y); rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Left Of The Texture and Quad
rlTexCoord2f(top.corner0.x, top.corner0.y); rlVertex3f(x - width/2, y + height/2, z + length/2); // Bottom Left Of The Texture and Quad
rlTexCoord2f(top.corner1.x, top.corner1.y); rlVertex3f(x + width/2, y + height/2, z + length/2); // Bottom Right Of The Texture and Quad
rlTexCoord2f(top.corner2.x, top.corner2.y); rlVertex3f(x + width/2, y + height/2, z - length/2); // Top Right Of The Texture and Quad
// Bottom Face
rlNormal3f(0.0f, - 1.0f, 0.0f); // Normal Pointing Down
rlTexCoord2f(bottom.corner2.x, bottom.corner2.y); rlVertex3f(x - width/2, y - height/2, z - length/2); // Top Right Of The Texture and Quad
rlTexCoord2f(bottom.corner3.x, bottom.corner3.y); rlVertex3f(x + width/2, y - height/2, z - length/2); // Top Left Of The Texture and Quad
rlTexCoord2f(bottom.corner0.x, bottom.corner0.y); rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Left Of The Texture and Quad
rlTexCoord2f(bottom.corner1.x, bottom.corner1.y); rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom Right Of The Texture and Quad
// Right face
rlNormal3f(1.0f, 0.0f, 0.0f); // Normal Pointing Right
rlTexCoord2f(right.corner1.x, right.corner1.y); rlVertex3f(x + width/2, y - height/2, z - length/2); // Bottom Right Of The Texture and Quad
rlTexCoord2f(right.corner2.x, right.corner2.y); rlVertex3f(x + width/2, y + height/2, z - length/2); // Top Right Of The Texture and Quad
rlTexCoord2f(right.corner3.x, right.corner3.y); rlVertex3f(x + width/2, y + height/2, z + length/2); // Top Left Of The Texture and Quad
rlTexCoord2f(right.corner0.x, right.corner0.y); rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Left Of The Texture and Quad
// Left Face
rlNormal3f( - 1.0f, 0.0f, 0.0f); // Normal Pointing Left
rlTexCoord2f(left.corner0.x, left.corner0.y); rlVertex3f(x - width/2, y - height/2, z - length/2); // Bottom Left Of The Texture and Quad
rlTexCoord2f(left.corner1.x, left.corner1.y); rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom Right Of The Texture and Quad
rlTexCoord2f(left.corner2.x, left.corner2.y); rlVertex3f(x - width/2, y + height/2, z + length/2); // Top Right Of The Texture and Quad
rlTexCoord2f(left.corner3.x, left.corner3.y); rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Left Of The Texture and Quad
rlEnd();
rlSetTexture(0);
}
#endif
#ifndef SERVER
void DrawTextCodepoint3D(Font font, int codepoint, Vector3 position, float fontSize, bool backface, Color tint)
{
// Character index position in sprite font
// NOTE: In case a codepoint is not available in the font, index returned points to '?'
int index = GetGlyphIndex(font, codepoint);
float scale = fontSize/(float)font.baseSize;
// Character destination rectangle on screen
// NOTE: We consider charsPadding on drawing
position.x += (float)(font.glyphs[index].offsetX - font.glyphPadding)*scale;
position.z += (float)(font.glyphs[index].offsetY - font.glyphPadding)*scale;
// Character source rectangle from font texture atlas
// NOTE: We consider chars padding when drawing, it could be required for outline/glow shader effects
Rectangle srcRec = { font.recs[index].x - (float)font.glyphPadding, font.recs[index].y - (float)font.glyphPadding,
font.recs[index].width + 2.0f*font.glyphPadding, font.recs[index].height + 2.0f*font.glyphPadding };
float width = (float)(font.recs[index].width + 2.0f*font.glyphPadding)*scale;
float height = (float)(font.recs[index].height + 2.0f*font.glyphPadding)*scale;
if (font.texture.id > 0)
{
const float x = 0.0f;
const float y = 0.0f;
const float z = 0.0f;
// normalized texture coordinates of the glyph inside the font texture (0.0f -> 1.0f)
const float tx = srcRec.x/font.texture.width;
const float ty = srcRec.y/font.texture.height;
const float tw = (srcRec.x+srcRec.width)/font.texture.width;
const float th = (srcRec.y+srcRec.height)/font.texture.height;
rlCheckRenderBatchLimit(4 + 4*backface);
rlSetTexture(font.texture.id);
rlPushMatrix();
rlTranslatef(position.x, position.y, position.z);
rlBegin(RL_QUADS);
rlColor4ub(tint.r, tint.g, tint.b, tint.a);
// Front Face
rlNormal3f(0.0f, 1.0f, 0.0f); // Normal Pointing Up
rlTexCoord2f(tx, ty); rlVertex3f(x, y, z); // Top Left Of The Texture and Quad
rlTexCoord2f(tx, th); rlVertex3f(x, y, z + height); // Bottom Left Of The Texture and Quad
rlTexCoord2f(tw, th); rlVertex3f(x + width, y, z + height); // Bottom Right Of The Texture and Quad
rlTexCoord2f(tw, ty); rlVertex3f(x + width, y, z); // Top Right Of The Texture and Quad
if (backface)
{
// Back Face
rlNormal3f(0.0f, -1.0f, 0.0f); // Normal Pointing Down
rlTexCoord2f(tx, ty); rlVertex3f(x, y, z); // Top Right Of The Texture and Quad
rlTexCoord2f(tw, ty); rlVertex3f(x + width, y, z); // Top Left Of The Texture and Quad
rlTexCoord2f(tw, th); rlVertex3f(x + width, y, z + height); // Bottom Left Of The Texture and Quad
rlTexCoord2f(tx, th); rlVertex3f(x, y, z + height); // Bottom Right Of The Texture and Quad
}
rlEnd();
rlPopMatrix();
rlSetTexture(0);
}
}
// Draw a 2D text in 3D space
void DrawText3D(Font font, const char *text, Vector3 position, float fontSize, float fontSpacing, float lineSpacing, bool backface, Color tint)
{
int length = TextLength(text); // Total length in bytes of the text, scanned by codepoints in loop
float textOffsetY = 0.0f; // Offset between lines (on line break '\n')
float textOffsetX = 0.0f; // Offset X to next character to draw
float scale = fontSize/(float)font.baseSize;
for (int i = 0; i < length;)
{
// Get next codepoint from byte string and glyph index in font
int codepointByteCount = 0;
int codepoint = GetCodepoint(&text[i], &codepointByteCount);
int index = GetGlyphIndex(font, codepoint);
// NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
// but we need to draw all of the bad bytes using the '?' symbol moving one byte
if (codepoint == 0x3f) codepointByteCount = 1;
if (codepoint == '\n')
{
// NOTE: Fixed line spacing of 1.5 line-height
// TODO: Support custom line spacing defined by user
textOffsetY += fontSize + lineSpacing;
textOffsetX = 0.0f;
}
else
{
if ((codepoint != ' ') && (codepoint != '\t'))
{
DrawTextCodepoint3D(font, codepoint, (Vector3){ position.x + textOffsetX, position.y, position.z + textOffsetY }, fontSize, backface, tint);
}
if (font.glyphs[index].advanceX == 0) textOffsetX += (float)font.recs[index].width*scale + fontSpacing;
else textOffsetX += (float)font.glyphs[index].advanceX*scale + fontSpacing;
}
i += codepointByteCount; // Move text bytes counter to next codepoint
}
}
#endif
+312
View File
@@ -0,0 +1,312 @@
#if INTERFACE
#ifdef WIN32
#include "external/fix_win32_compatibility.h"
#endif
#ifdef Escape
#undef Escape
#endif
#include "glfw_keycodes_to_string.h"
#include "../PerlinNoise.hpp"
#include <enet/enet.h>
#ifdef PlaySound
#undef PlaySound
#endif
#include "raylib.h"
#include "raymath.h"
#include <stdint.h>
#include <bitset>
#endif
#include <cstdint>
#include <list>
#define FOV 90
#define WIDTH 1024.0
#define HEIGHT 600.0
#define ASPECT WIDTH / HEIGHT
#define CHUNK_SIZE 16 // W & H
#define WORLD_HEIGHT 128
#define CHUNK_DATA_SIZE CHUNK_SIZE*CHUNK_SIZE*WORLD_HEIGHT
#define CHUNK_SIZE_SQR CHUNK_SIZE*CHUNK_SIZE
#define MAX_WORLD_SIZE 16
#define MAX_WORLD_AREA MAX_WORLD_SIZE*MAX_WORLD_SIZE
#define WORLD_SIZE_BLOCKS MAX_WORLD_SIZE * CHUNK_SIZE
#define ATLAS_SIZE_W 16
#define ATLAS_SIZE_H 16
#define ITEM_ATLAS_SIZE 16
#define ITEM_SIZE 16
#define PLAYER_HEIGHT 1.75f
#define PLAYER_RADIUS 0.25f
#define GRAVITY 20.0f
#define MOVE_SPEED 6.0f
#define JUMP_SPEED 8.0f
#define DELTA_SMOOTH 0.016f
#define MOUSE_SENS 0.0025f
#define PITCH_MIN -1.47f // ~-83 degrees
#define PITCH_MAX 1.47f // ~ 83 degrees
#define SMOOTH_FACTOR 12.0f // larger = snappier
#define BLOCK_AIR 0
#define BLOCK_STONE 1
#define BLOCK_GRASS 2
#define BLOCK_DIRT 3
#define BLOCK_SAND 4
#define BLOCK_WATERS 5
#define MAX_BLOCK_ID 28
#define CLOUD_FADE_BLOCKS CHUNK_SIZE*8
//Networking
#define PORT 25565
#define MAX_MESSAGE_LENGTH 64
//Notes:
//The server uses a player ID of 255
//
//Server->Client
// Byte 0
#define NET_ARG_NONE 0x00 // Invalid
#define NET_ARG_CHUNKF 0x01 // Byte 1 - chunk ID, uint8_t blocks[16*64*16], uint8_t highestBlock[16*16]
#define NET_ARG_BLOCK 0x02 // Player ID, block X, block Y, block Z, block type
#define NET_ARG_PLRCON 0x03 // Byte 1 - ID
#define NET_ARG_PLRDCN 0x04 // Byte 1 - ID
#define NET_ARG_PLRID 0x05 // Byte 1 - Server-assigned ID to the player
#define NET_ARG_ECHOMOVE 0x06 // Byte 1 - player ID, bytes 2-3 - echoed player X, bytes 4-5 - echoed player Y, bytes 6-7 - echoed player Z, byte 8 - player yaw
#define NET_ARG_PLRREG 0x07 // Same as ECHOMOVE, used as an answer to REQPLAYERS
#define NET_ARG_ECHOYAW 0x08 // Byte 1 - ID, byte 2 - yaw
#define NET_ARG_MESSAGEE 0x09 // Byte 1 - sender ID, byte 2 - length, rest is message (128b max)
//Client->Server
// Byte 0
#define NET_ARG_PLAYERMOVE 0x80 // Byte 1-2 - player X, byte 3-4 - player Y, byte 5-6 - player Z, byte 7 - player yaw
#define NET_ARG_BLOCKDELTA 0x81 // Block X, block Y, block Z, block type
#define NET_ARG_REQWORLD 0x82 // No additional data
#define NET_ARG_REQPLAYERS 0x83 // No additional data
#define NET_ARG_PLAYERYAW 0x84 // Byte 1 - yaw
#define NET_ARG_MESSAGEC 0x85 // All is message (64b max)
//
//Errors
#define NET_ERROR_DSCN 0x00
#define NET_ERROR_NOTFOUND 0x01
#define NET_ERROR_FAILED 0x02
#define NET_ERROR_INTERNAL 0x03
#define GAME_NAME "CubeGame"
#define GAME_VERSION_INT 0
#define DEFAULT_FONT_SIZE 16
#define TPS 30.0
#define TPS_DIV 1.0 / TPS
//Rendering
#define RENDER_DISTANCE 16
#define RENDER_DISTANCE_SQUARED RENDER_DISTANCE*RENDER_DISTANCE
//Game stuff
#define MAX_HP 100
#define PATH_APPEND "resources/"
#define PATH_APPEND_USER "user/"
#define ITEMS 9
#define INVENTORY_WIDTH 8
#define INVENTORY_HEIGHT 6
#define INVENTORY_SIZE INVENTORY_WIDTH*INVENTORY_HEIGHT
enum BlockType {
B_Wood,
B_Stone,
B_Grass,
B_Dirt
};
struct BlockDef {
const std::string name;
BlockRendering render;
uint8_t textureTop;
uint8_t textureSide;
uint8_t textureBottom;
int hardness;
int min_tier;
BlockType type;
// Constructor with initializer list; textureSide/textureBottom default to textureTop if not provided.
BlockDef(
std::string _name,
BlockRendering render_ = R_None,
BlockType btype = B_Stone,
int _hardness = 1,
int _min_tier = 0,
uint8_t textureTop_ = 255,
uint8_t textureSide_ = 255,
uint8_t textureBottom_ = 255)
: name(_name),
render(render_),
hardness(_hardness),
min_tier(_min_tier),
textureTop(textureTop_),
textureSide(textureSide_ == 255 ? textureTop_ : textureSide_),
textureBottom(textureBottom_ == 255 ? textureTop_ : textureBottom_),
type(btype)
{}
};
enum BlockRendering {
R_None,
R_Normal,
R_TriSide,
R_Translucent,
R_TranslucentTriSide,
R_TranslucentAllSides
};
enum GameState {
GAME_STATE_LOADING,
GAME_STATE_GAME,
GAME_STATE_MAINMENU,
GAME_STATE_WORLDSELECT,
GAME_STATE_MULTIPLAYERSELECT,
GAME_STATE_TRANSITION,
GAME_STATE_WORLD_CREATE,
GAME_STATE_OPTIONS
};
struct Chunk {
uint8_t x;
uint8_t z;
bool isDirty;
uint8_t blocks[CHUNK_DATA_SIZE];
uint16_t opaqueMask[CHUNK_DATA_SIZE/16];
uint16_t airMask[CHUNK_DATA_SIZE/16];
uint8_t highestBlock[CHUNK_SIZE*CHUNK_SIZE];
};
#ifndef SERVER
struct ChunkRenderData {
uint8_t sides[CHUNK_DATA_SIZE];
};
struct MeshData {
float *positions; // xyz xyz ...
float *normals; // xyz ...
float *uvs; // uv uv ...
unsigned char *colors; // rgba rgba ...
unsigned short *indices; // triangles
unsigned short vertexCount;
unsigned short indexCount;
};
struct ChunkMeshData {
uint8_t *positions; // xyz xyz ...
uint8_t *luminosity; // l l ...
float *uvs; // uv uv ...
unsigned short *indices; // triangles
unsigned short vertexCount;
unsigned short indexCount;
};
struct UVCorners {
Vector2 corner0;
Vector2 corner1;
Vector2 corner2;
Vector2 corner3;
};
struct Quad2D {
int x;
int y;
int w;
int h;
};
#endif
struct Vector3I {
int x;
int y;
int z;
};
struct Entity {
uint8_t type;
uint8_t id;
uint8_t damage_flash;
uint8_t data[16];
float smoothing;
float health;
float lifetime;
Vector3 position;
Vector3 velocity;
unsigned short yaw;
bool free;
};
struct NetPlayer
{
ENetPeer* peer;
int addr;
int port;
int id;
int yaw;
float x;
float y;
float z;
};
struct MemInfo {
uint64_t resident;
uint64_t virtualSize;
uint64_t privateBytes;
};
enum ItemType {
IType_Generic,
IType_Block,
IType_Edible,
IType_Mining,
IType_Weapon,
IType_Special_Tag
};
enum EntityPhysics {
Phys_Falling,
Phys_Floating
};
struct Item {
std::string id;
ItemType type;
int texture;
int tier;
Item(
std::string _id,
ItemType _type,
int _texture,
int _tier = 0)
: id(_id),
type(_type),
texture(_texture),
tier(_tier)
{}
};
struct InventoryItem {
Item* item = nullptr;
int damage = -1;
int amount = 0;
};
struct RecipeItem {
ItemType type;
std::string id;
int quantity = 1;
};
struct Recipe {
std::string requiredStation;
std::list<RecipeItem> inputs;
std::list<RecipeItem> outputs;
};
struct Particle {
Vector3 position;
Vector3 velocity;
EntityPhysics physicsType;
Texture2D texture;
int lifetime;
int data[8];
};
+1
Submodule src/libraries/Lua added at 504ef66d50
Submodule src/libraries/enet added at 8be2368a80
Submodule src/libraries/raylib added at cf9f27db54
Submodule src/libraries/yaml-cpp added at 4861d04953
+1604
View File
File diff suppressed because it is too large Load Diff
+14
View File
@@ -0,0 +1,14 @@
set(CMAKE_SYSTEM_NAME Windows)
set(CMAKE_SYSTEM_VERSION 1)
set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc)
set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++)
set(CMAKE_RC_COMPILER x86_64-w64-mingw32-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}")