First commit (very unfinished)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
39
|
||||
@@ -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)
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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()
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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";
|
||||
};
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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(®istry[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(®istry[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 = ®istry[0];
|
||||
item.damage = i;
|
||||
}
|
||||
else if (i < registry.size()+MAX_BLOCK_ID-1) {
|
||||
item.item = ®istry[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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 = ®istry[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 = ®istry[static_cast<int>(numid)];
|
||||
inventory[i].item = itemPtr;
|
||||
}
|
||||
inventory[i].damage = damage;
|
||||
inventory[i].amount = amount;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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];
|
||||
};
|
||||
Reference in New Issue
Block a user