This commit is contained in:
Dennis Eichhorn 2024-07-21 21:25:39 +02:00
parent 2b8a31ff7c
commit acde815291
95 changed files with 2740 additions and 757 deletions

6
.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
build/*
data/*
bin/*
*.obj
*.log
*.res

119
camera/Camera.h Normal file
View File

@ -0,0 +1,119 @@
/**
* Jingga
*
* @copyright Jingga
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
#ifndef TOS_CAMERA_H
#define TOS_CAMERA_H
#include "../stdlib/Types.h"
#include "../stdlib/Mathtypes.h"
#include "../math/matrix/QuaternionFloat32.h"
#include "CameraMovement.h"
struct Camera {
// left handed cartesian coordinates
v3_f32 location;
v4_f32 orientation;
float speed;
float zoom;
};
// you can have up to 4 camera movement inputs at the same time
void camera_movement(Camera* camera, CameraMovement* movement, float dt)
{
f32 velocity = camera->speed * dt;
bool has_pos = false;
v4_f32 pos;
bool has_view = false;
v3_f32 view;
v4_f32 quaternion;
for (int i = 0; i < 4; i++) {
switch(movement[i]) {
case CAMERA_MOVEMENT_FORWARD: {
pos.z = velocity;
has_pos = true;
} break;
case CAMERA_MOVEMENT_BACK: {
pos.z = velocity;
has_pos = true;
} break;
case CAMERA_MOVEMENT_LEFT: {
pos.x = velocity;
has_pos = true;
} break;
case CAMERA_MOVEMENT_RIGHT: {
pos.x = velocity;
has_pos = true;
} break;
case CAMERA_MOVEMENT_UP: {
pos.y = velocity;
has_pos = true;
} break;
case CAMERA_MOVEMENT_DOWN: {
pos.y = velocity;
has_pos = true;
} break;
case CAMERA_MOVEMENT_PITCH_UP: {
view.pitch += velocity;
has_view = true;
} break;
case CAMERA_MOVEMENT_PITCH_DOWN: {
view.pitch -= velocity;
has_view = true;
} break;
case CAMERA_MOVEMENT_ROLL_LEFT: {
view.roll += velocity;
has_view = true;
} break;
case CAMERA_MOVEMENT_ROLL_RIGHT: {
view.roll -= velocity;
has_view = true;
} break;
case CAMERA_MOVEMENT_YAW_LEFT: {
view.yaw += velocity;
has_view = true;
} break;
case CAMERA_MOVEMENT_YAW_RIGHT: {
view.yaw -= velocity;
has_view = true;
} break;
case CAMERA_MOVEMENT_ZOOM_IN: {
camera->zoom += velocity;
} break;
case CAMERA_MOVEMENT_ZOOM_OUT: {
camera->zoom -= velocity;
} break;
default: {}
}
}
// A position change updates the position AND the quaternion
if (has_pos) {
// @question this might be wrong/bad since pos is not a normalized vector
v4_f32 quat_temp = camera->orientation;
quaternion_rotate_euler(&camera->orientation, &quat_temp, &pos);
camera->location.x += pos.x;
camera->location.y += pos.y;
camera->location.z += pos.z;
}
// A view change only updates the quaternion
if (has_view) {
v4_f32 quat_temp = camera->orientation;
quaternion_from_euler(&quaternion, &view);
quaternion_multiply(&camera->orientation, &quat_temp, &quaternion);
}
}
#endif

35
camera/CameraMovement.h Normal file
View File

@ -0,0 +1,35 @@
/**
* Jingga
*
* @copyright Jingga
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
#ifndef TOS_CAMERA_MOVEMENT_H
#define TOS_CAMERA_MOVEMENT_H
enum CameraMovement {
CAMERA_MOVEMENT_FORWARD,
CAMERA_MOVEMENT_BACK,
CAMERA_MOVEMENT_LEFT,
CAMERA_MOVEMENT_RIGHT,
CAMERA_MOVEMENT_UP,
CAMERA_MOVEMENT_DOWN,
CAMERA_MOVEMENT_PITCH_UP,
CAMERA_MOVEMENT_PITCH_DOWN,
CAMERA_MOVEMENT_ROLL_LEFT,
CAMERA_MOVEMENT_ROLL_RIGHT,
CAMERA_MOVEMENT_YAW_LEFT,
CAMERA_MOVEMENT_YAW_RIGHT,
CAMERA_MOVEMENT_ZOOM_IN,
CAMERA_MOVEMENT_ZOOM_OUT
};
#endif

213
gpuapi/RenderUtils.h Normal file
View File

@ -0,0 +1,213 @@
/**
* Jingga
*
* @copyright Jingga
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
#ifndef TOS_GPUAPI_RENDER_UTILS_H
#define TOS_GPUAPI_RENDER_UTILS_H
#include <stdio.h>
#include <string.h>
#include "../stdlib/Mathtypes.h"
#include "../math/matrix/MatrixFloat32.h"
void make_character(
float *data,
float x, float y, float n, float m, char c)
{
float *d = data;
// Texture atlas is 16 characters
// 1 / 16 = 0.0625
float a = 0.0625;
float b = 0.0625 * 2;
// ascii offset
int w = c - 32;
float du = (w % 16) * a;
float dv = 1 - (w / 16) * b - b;
// Quad data (2 triangles)
*(d++) = x - n; *(d++) = y - m;
*(d++) = du + 0; *(d++) = dv;
*(d++) = x + n; *(d++) = y - m;
*(d++) = du + a; *(d++) = dv;
*(d++) = x + n; *(d++) = y + m;
*(d++) = du + a; *(d++) = dv + b;
*(d++) = x - n; *(d++) = y - m;
*(d++) = du + 0; *(d++) = dv;
*(d++) = x + n; *(d++) = y + m;
*(d++) = du + a; *(d++) = dv + b;
*(d++) = x - n; *(d++) = y + m;
*(d++) = du + 0; *(d++) = dv + b;
}
void font_string_dimension(const char *str, v2_int32* dim, const int* width_lookup)
{
size_t length = strlen(str);
int width = 0;
for (int i = 0; i < length; ++i) {
if (str[i] == '\n') {
if (width > dim->x) {
dim->x = width;
}
width = 0;
++dim->y;
}
width += width_lookup[str[i]];
}
if (width > dim->x) {
dim->x = width;
}
if (width > 0) {
++dim->y;
}
}
inline
void entity_world_space(float* world_space, const float* local_space, const float* model_mat)
{
mat4vec4_mult(model_mat, local_space, world_space);
}
inline
void entity_view_space(float* view_space, const float* world_space, const float* view_mat)
{
mat4vec4_mult(view_mat, world_space, view_space);
}
inline
void entity_clip_space(float* clip_space, const float* view_space, const float* projection_mat)
{
mat4vec4_mult(projection_mat, view_space, clip_space);
}
inline
void entity_clip_space_mat(float* result_mat, const float* model_mat, const float* view_mat, const float* projection_mat)
{
float temp[16];
mat4mat4_mult(projection_mat, view_mat, temp);
mat4mat4_mult(temp, model_mat, result_mat);
}
/**
* Create the matrix used to transform from local space to clip space
*
* This allows us to transform multiple objects with the same matrix
*
* Vclip = Mprojection * Mview * Mmodel * Vlocal
*/
void entity_clip_space_mat_sse(float* result_mat, const float* model_mat, const float* view_mat, const float* projection_mat)
{
__m128 temp[4];
__m128 a[4];
__m128 b[4];
a[0] = _mm_loadu_ps(projection_mat);
a[1] = _mm_loadu_ps(&projection_mat[4]);
a[2] = _mm_loadu_ps(&projection_mat[8]);
a[3] = _mm_loadu_ps(&projection_mat[12]);
b[0] = _mm_loadu_ps(view_mat);
b[1] = _mm_loadu_ps(&view_mat[4]);
b[2] = _mm_loadu_ps(&view_mat[8]);
b[3] = _mm_loadu_ps(&view_mat[12]);
_MM_TRANSPOSE4_PS(b[0], b[1], b[2], b[3]);
mat4mat4_mult_sse(a, b, temp);
a[0] = temp[0];
a[1] = temp[1];
a[2] = temp[2];
a[3] = temp[3];
b[0] = _mm_loadu_ps(model_mat);
b[1] = _mm_loadu_ps(&model_mat[4]);
b[2] = _mm_loadu_ps(&model_mat[8]);
b[3] = _mm_loadu_ps(&model_mat[12]);
_MM_TRANSPOSE4_PS(b[0], b[1], b[2], b[3]);
mat4mat4_mult_sse(a, b, temp);
_mm_store_ps(&result_mat[0], temp[0]);
_mm_store_ps(&result_mat[4], temp[1]);
_mm_store_ps(&result_mat[8], temp[2]);
_mm_store_ps(&result_mat[12], temp[3]);
}
inline
void entity_clip_space_from_local(float* clip_space, const float* local_space, const float* mat)
{
mat4vec4_mult(mat, local_space, clip_space);
}
inline
void entity_clip_space_from_local_sse(float* clip_space, const float* local_space, const float* mat)
{
mat4vec4_mult_sse(mat, local_space, clip_space);
}
inline
void entity_screen_space(float* screen_space, const float* clip_space, const float* viewport_mat)
{
// @todo implement
}
inline
void entity_world_space_sse(float* world_space, const float* local_space, const float* model_mat)
{
mat4vec4_mult_sse(model_mat, local_space, world_space);
}
inline
void entity_view_space_sse(float* view_space, const float* world_space, const float* view_mat)
{
mat4vec4_mult_sse(view_mat, world_space, view_space);
}
inline
void entity_clip_space_sse(float* clip_space, const float* view_space, const float* projection_mat)
{
mat4vec4_mult_sse(projection_mat, view_space, clip_space);
}
inline
void entity_screen_space_sse(float* screen_space, const float* clip_space, const float* viewport_mat)
{
// @todo implement
}
inline
void entity_world_space_sse(__m128* world_space, const __m128* local_space, const __m128* model_mat)
{
mat4vec4_mult_sse(model_mat, local_space, world_space);
}
inline
void entity_view_space_sse(__m128* view_space, const __m128* world_space, const __m128* view_mat)
{
mat4vec4_mult_sse(view_mat, world_space, view_space);
}
inline
void entity_clip_space_sse(__m128* clip_space, const __m128* view_space, const __m128* projection_mat)
{
mat4vec4_mult_sse(projection_mat, view_space, clip_space);
}
inline
void entity_screen_space_sse(__m128* screen_space, const __m128* clip_space, const __m128* viewport_mat)
{
// @todo implement
}
#endif

View File

@ -0,0 +1,91 @@
/**
* Jingga
*
* @copyright Jingga
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
#ifndef TOS_GPUAPI_OPENGL_SHADER_UTILS_H
#define TOS_GPUAPI_OPENGL_SHADER_UTILS_H
#include "../../../EngineDependencies/opengl/glew/include/GL/glew.h"
#include "../../../EngineDependencies/opengl/glfw/include/glfw3.h"
#include "../../stdlib/Types.h"
inline
void shader_set_value(uint32 id, const char* name, bool value)
{
glUniform1i(glGetUniformLocation(id, name), (int) value);
}
inline
void shader_set_value(uint32 id, const char* name, int value)
{
glUniform1i(glGetUniformLocation(id, name), value);
}
inline
void shader_set_value(uint32 id, const char* name, float value)
{
glUniform1f(glGetUniformLocation(id, name), value);
}
inline
void shader_set_v2(uint32 id, const char* name, float* value)
{
glUniform2fv(glGetUniformLocation(id, name), 1, value);
}
inline
void shader_set_v3(uint32 id, const char* name, float* value)
{
glUniform3fv(glGetUniformLocation(id, name), 1, value);
}
inline
void shader_set_v4(uint32 id, const char* name, float* value)
{
glUniform4fv(glGetUniformLocation(id, name), 1, value);
}
inline
void shader_set_m2(uint32 id, const char* name, float* value)
{
glUniformMatrix2fv(glGetUniformLocation(id, name), 1, GL_FALSE, value);
}
inline
void shader_set_m3(uint32 id, const char* name, float* value)
{
glUniformMatrix3fv(glGetUniformLocation(id, name), 1, GL_FALSE, value);
}
inline
void shader_set_m4(uint32 id, const char* name, float* value)
{
glUniformMatrix4fv(glGetUniformLocation(id, name), 1, GL_FALSE, value);
}
inline
void shader_check_link_errors(uint32 id, char* log)
{
GLint success;
glGetProgramiv(id, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(id, 1024, NULL, log);
}
}
inline
void shader_check_compile_errors(uint32 id, char* log)
{
GLint success;
glGetShaderiv(id, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(id, 1024, NULL, log);
}
}
#endif

View File

@ -14,6 +14,7 @@
#include "../../models/Attrib.h" #include "../../models/Attrib.h"
#include "../../models/Texture.h" #include "../../models/Texture.h"
#include "../RenderUtils.h"
#include "../../../EngineDependencies/opengl/glew/include/GL/glew.h" #include "../../../EngineDependencies/opengl/glew/include/GL/glew.h"
#include "../../../EngineDependencies/opengl/glfw/include/glfw3.h" #include "../../../EngineDependencies/opengl/glfw/include/glfw3.h"
@ -54,7 +55,7 @@ void window_create(Window* window, void*)
NULL NULL
); );
glfwSetInputMode(window->hwnd_lib, GLFW_CURSOR, GLFW_CURSOR_DISABLED); //glfwSetInputMode(window->hwnd_lib, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
glfwMakeContextCurrent(window->hwnd_lib); glfwMakeContextCurrent(window->hwnd_lib);
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
@ -109,13 +110,14 @@ uint32 get_texture_data_type(uint32 texture_data_type)
} }
} }
// 1. prepare_texture
// 2. define wrap
// 3. define filter
// 4. load_texture_to_gpu
inline inline
void prepare_texture(TextureFile* texture, uint32 texture_unit) void prepare_texture(TextureFile* texture, uint32 texture_unit)
{ {
if (texture->id) {
return;
}
uint32 texture_data_type = get_texture_data_type(texture->texture_data_type); uint32 texture_data_type = get_texture_data_type(texture->texture_data_type);
glGenTextures(1, (GLuint *) &texture->id); glGenTextures(1, (GLuint *) &texture->id);
@ -133,6 +135,15 @@ void load_texture_to_gpu(const TextureFile* texture)
0, GL_RGBA, GL_UNSIGNED_BYTE, 0, GL_RGBA, GL_UNSIGNED_BYTE,
texture->image.pixels texture->image.pixels
); );
// @question use mipmap?
}
inline
void texture_use(const TextureFile* texture, uint32 texture_unit)
{
glActiveTexture(GL_TEXTURE0 + texture_unit);
glBindTexture(GL_TEXTURE_2D, texture->id);
} }
GLuint make_shader(GLenum type, const char *source, RingMemory* ring) GLuint make_shader(GLenum type, const char *source, RingMemory* ring)
@ -152,8 +163,7 @@ GLuint make_shader(GLenum type, const char *source, RingMemory* ring)
glGetShaderInfoLog(shader, length, NULL, info); glGetShaderInfoLog(shader, length, NULL, info);
// @todo use global logger // @todo log
fprintf(stderr, "glCompileShader failed:\n%s\n", info);
} }
return shader; return shader;
@ -166,6 +176,7 @@ GLuint load_shader(GLenum type, const char *path, RingMemory* ring) {
file_body file; file_body file;
file.content = ring_get_memory(ring, MEGABYTE * 4); file.content = ring_get_memory(ring, MEGABYTE * 4);
// @todo consider to accept file as parameter and load file before
file_read(path, &file); file_read(path, &file);
GLuint result = make_shader(type, (const char *) file.content, ring); GLuint result = make_shader(type, (const char *) file.content, ring);
@ -198,8 +209,11 @@ GLuint make_program(GLuint shader1, GLuint shader2, RingMemory* ring) {
fprintf(stderr, "glLinkProgram failed: %s\n", info); fprintf(stderr, "glLinkProgram failed: %s\n", info);
} }
// @question really?
glDetachShader(program, shader1); glDetachShader(program, shader1);
glDetachShader(program, shader2); glDetachShader(program, shader2);
// @question really?
glDeleteShader(shader1); glDeleteShader(shader1);
glDeleteShader(shader2); glDeleteShader(shader2);
@ -215,8 +229,9 @@ GLuint load_program(const char *path1, const char *path2, RingMemory* ring) {
} }
inline inline
void activate_texture(TextureFile* texture, uint32 texture_unit) void shader_use(uint32 id)
{ {
glUseProgram(id);
} }
void draw_triangles_3d(Attrib *attrib, GLuint buffer, int count) { void draw_triangles_3d(Attrib *attrib, GLuint buffer, int count) {
@ -296,16 +311,44 @@ int calculate_face_size(int components, int faces)
// generates faces // generates faces
// data is no longer needed after this // data is no longer needed after this
inline inline
GLuint gpuapi_buffer_generate(int size, GLfloat *data) uint32 gpuapi_buffer_generate(int size, f32 *data)
{ {
GLuint buffer; uint32 vbo;
glGenBuffers(1, &buffer); glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, buffer); glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
return buffer; return vbo;
}
inline
uint32 gpuapi_buffer_element_generate(int size, uint32 *data)
{
uint32 ebo;
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
return ebo;
}
inline
uint32 gpuapi_vertex_array_generate()
{
uint32 vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
return vao;
}
inline
void gpuapi_unbind_all()
{
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
} }
inline inline
@ -314,6 +357,4 @@ void gpuapi_buffer_delete(GLuint buffer)
glDeleteBuffers(1, &buffer); glDeleteBuffers(1, &buffer);
} }
#endif #endif

View File

@ -9,7 +9,7 @@
#ifndef TOS_INPUT_H #ifndef TOS_INPUT_H
#define TOS_INPUT_H #define TOS_INPUT_H
#define MAX_KEY_PRESSES 4 #define MAX_KEY_PRESSES 5
#define MIN_INPUT_DEVICES 2 #define MIN_INPUT_DEVICES 2
#define INPUT_TYPE_MOUSE 0x01 #define INPUT_TYPE_MOUSE 0x01
@ -38,16 +38,12 @@ struct InputState {
HANDLE handle_mouse; HANDLE handle_mouse;
#endif #endif
// Keyboard
bool key_down = false;
bool key_up = false;
uint16 key = 0;
// After handling the keyboard state change the game loop should set this to false // After handling the keyboard state change the game loop should set this to false
bool state_change_keyboard = false; bool state_change_keyboard = false;
// We only consider up to 4 pressed keys // We only consider up to 4 pressed keys
// Depending on the keyboard you may only be able to detect a limited amount of key presses anyway // Depending on the keyboard you may only be able to detect a limited amount of key presses anyway
uint16 keys_down_old[MAX_KEY_PRESSES];
uint16 keys_down[MAX_KEY_PRESSES]; uint16 keys_down[MAX_KEY_PRESSES];
// Mouse // Mouse
@ -60,20 +56,10 @@ struct InputState {
uint32 x_last; uint32 x_last;
uint32 y_last; uint32 y_last;
bool mouse1_down = false; // https://usb.org/sites/default/files/hid1_11.pdf Page 71 or 61
bool mouse1_up = false; // @question consider to use bit field (one int32 would be sufficient)
bool mouse_down_old[18];
bool mouse2_down = false; bool mouse1_down[18];
bool mouse2_up = false;
bool mouse3_down = false;
bool mouse3_up = false;
bool mouse4_down = false;
bool mouse4_up = false;
bool mouse5_down = false;
bool mouse5_up = false;
int16 wheel_delta = 0; int16 wheel_delta = 0;
uint32 raw_button = 0; uint32 raw_button = 0;
@ -86,23 +72,18 @@ struct ControllerState {
// After handling the state change the game loop should set this to false // After handling the state change the game loop should set this to false
bool state_change = false; bool state_change = false;
// @question maybe make part of button
bool up = false; bool up = false;
bool down = false; bool down = false;
bool left = false; bool left = false;
bool right = false; bool right = false;
bool start = false;
bool back = false;
bool shoulder_left = false; byte trigger_old[4];
bool shoulder_right = false; byte trigger[4];
byte trigger_left = 0; // @question consider to use bit field (one int32 would be sufficient)
byte trigger_right = 0; bool button_old[10];
bool button[10];
bool button_a = false;
bool button_b = false;
bool button_x = false;
bool button_y = false;
int16 stickl_x = 0; int16 stickl_x = 0;
int16 stickl_y = 0; int16 stickl_y = 0;

View File

@ -10,6 +10,7 @@
#define TOS_MATH_MATRIX_FLOAT32_H #define TOS_MATH_MATRIX_FLOAT32_H
#include "../../stdlib/Intrinsics.h" #include "../../stdlib/Intrinsics.h"
#include "../../stdlib/Mathtypes.h"
#include "../../utils/MathUtils.h" #include "../../utils/MathUtils.h"
void mat3_identity_f32(float* matrix) void mat3_identity_f32(float* matrix)
@ -105,6 +106,7 @@ void mat3vec3_mult(const float* matrix, const float* vector, float* result)
*/ */
} }
// @question could simple mul add sse be faster?
void mat3vec3_mult_sse(const float* matrix, const float* vector, float* result) void mat3vec3_mult_sse(const float* matrix, const float* vector, float* result)
{ {
__m128 vec = _mm_loadu_ps(vector); __m128 vec = _mm_loadu_ps(vector);
@ -120,6 +122,7 @@ void mat3vec3_mult_sse(const float* matrix, const float* vector, float* result)
} }
} }
// @question could simple mul add sse be faster?
void mat3vec3_mult_sse(const __m128* matrix, const __m128* vector, float* result) void mat3vec3_mult_sse(const __m128* matrix, const __m128* vector, float* result)
{ {
for (int i = 0; i < 3; ++i) { for (int i = 0; i < 3; ++i) {
@ -129,6 +132,7 @@ void mat3vec3_mult_sse(const __m128* matrix, const __m128* vector, float* result
} }
} }
// @question could simple mul add sse be faster?
void mat3vec3_mult_sse(const __m128* matrix, const __m128* vector, __m128* result) void mat3vec3_mult_sse(const __m128* matrix, const __m128* vector, __m128* result)
{ {
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i) {
@ -142,17 +146,9 @@ void mat4vec4_mult(const float* matrix, const float* vector, float* result)
result[1] = matrix[4] * vector[0] + matrix[5] * vector[1] + matrix[6] * vector[2] + matrix[7] * vector[3]; result[1] = matrix[4] * vector[0] + matrix[5] * vector[1] + matrix[6] * vector[2] + matrix[7] * vector[3];
result[2] = matrix[8] * vector[0] + matrix[9] * vector[1] + matrix[10] * vector[2] + matrix[11] * vector[3]; result[2] = matrix[8] * vector[0] + matrix[9] * vector[1] + matrix[10] * vector[2] + matrix[11] * vector[3];
result[3] = matrix[12] * vector[0] + matrix[13] * vector[1] + matrix[14] * vector[2] + matrix[15] * vector[3]; result[3] = matrix[12] * vector[0] + matrix[13] * vector[1] + matrix[14] * vector[2] + matrix[15] * vector[3];
/*
for (int i = 0; i < 4; ++i) {
result[i] = matrix[i * 4 + 0] * vector[0]
+ matrix[i * 4 + 1] * vector[1]
+ matrix[i * 4 + 2] * vector[2]
+ matrix[i * 4 + 3] * vector[3];
}
*/
} }
// @question could simple mul add sse be faster?
void mat4vec4_mult_sse(const float* matrix, const float* vector, float* result) void mat4vec4_mult_sse(const float* matrix, const float* vector, float* result)
{ {
__m128 vec = _mm_loadu_ps(vector); __m128 vec = _mm_loadu_ps(vector);
@ -165,6 +161,7 @@ void mat4vec4_mult_sse(const float* matrix, const float* vector, float* result)
} }
} }
// @question could simple mul add sse be faster?
void mat4vec4_mult_sse(const __m128* matrix, const __m128* vector, float* result) void mat4vec4_mult_sse(const __m128* matrix, const __m128* vector, float* result)
{ {
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i) {
@ -174,6 +171,7 @@ void mat4vec4_mult_sse(const __m128* matrix, const __m128* vector, float* result
} }
} }
// @question could simple mul add sse be faster?
void mat4vec4_mult_sse(const __m128* matrix, const __m128* vector, __m128* result) void mat4vec4_mult_sse(const __m128* matrix, const __m128* vector, __m128* result)
{ {
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i) {
@ -181,6 +179,172 @@ void mat4vec4_mult_sse(const __m128* matrix, const __m128* vector, __m128* resul
} }
} }
void mat4mat4_mult(const float* a, const float* b, float* result)
{
// Row 0
result[0] = a[0] * b[0] + a[1] * b[4] + a[2] * b[8] + a[3] * b[12];
result[1] = a[0] * b[1] + a[1] * b[5] + a[2] * b[9] + a[3] * b[13];
result[2] = a[0] * b[2] + a[1] * b[6] + a[2] * b[10] + a[3] * b[14];
result[3] = a[0] * b[3] + a[1] * b[7] + a[2] * b[11] + a[3] * b[15];
// Row 1
result[4] = a[4] * b[0] + a[5] * b[4] + a[6] * b[8] + a[7] * b[12];
result[5] = a[4] * b[1] + a[5] * b[5] + a[6] * b[9] + a[7] * b[13];
result[6] = a[4] * b[2] + a[5] * b[6] + a[6] * b[10] + a[7] * b[14];
result[7] = a[4] * b[3] + a[5] * b[7] + a[6] * b[11] + a[7] * b[15];
// Row 2
result[8] = a[8] * b[0] + a[9] * b[4] + a[10] * b[8] + a[11] * b[12];
result[9] = a[8] * b[1] + a[9] * b[5] + a[10] * b[9] + a[11] * b[13];
result[10] = a[8] * b[2] + a[9] * b[6] + a[10] * b[10] + a[11] * b[14];
result[11] = a[8] * b[3] + a[9] * b[7] + a[10] * b[11] + a[11] * b[15];
// Row 3
result[12] = a[12] * b[0] + a[13] * b[4] + a[14] * b[8] + a[15] * b[12];
result[13] = a[12] * b[1] + a[13] * b[5] + a[14] * b[9] + a[15] * b[13];
result[14] = a[12] * b[2] + a[13] * b[6] + a[14] * b[10] + a[15] * b[14];
result[15] = a[12] * b[3] + a[13] * b[7] + a[14] * b[11] + a[15] * b[15];
}
void mat4mat4_mult_sse(const float* a, const float* b, float* result)
{
// @todo check http://fhtr.blogspot.com/2010/02/4x4-float-matrix-multiplication-using.html
// @question could simple mul add sse be faster?
__m128 a_1 = _mm_loadu_ps(a);
__m128 a_2 = _mm_loadu_ps(&a[4]);
__m128 a_3 = _mm_loadu_ps(&a[8]);
__m128 a_4 = _mm_loadu_ps(&a[12]);
__m128 b_1 = _mm_loadu_ps(b);
__m128 b_2 = _mm_loadu_ps(&b[4]);
__m128 b_3 = _mm_loadu_ps(&b[8]);
__m128 b_4 = _mm_loadu_ps(&b[12]);
_MM_TRANSPOSE4_PS(b_1, b_2, b_3, b_4);
__m128 dot;
// b1
dot = _mm_dp_ps(a_1, b_1, 0xF1);
result[0] = _mm_cvtss_f32(dot);
dot = _mm_dp_ps(a_2, b_1, 0xF1);
result[1] = _mm_cvtss_f32(dot);
dot = _mm_dp_ps(a_3, b_1, 0xF1);
result[2] = _mm_cvtss_f32(dot);
dot = _mm_dp_ps(a_4, b_1, 0xF1);
result[3] = _mm_cvtss_f32(dot);
// b2
dot = _mm_dp_ps(a_1, b_2, 0xF1);
result[4] = _mm_cvtss_f32(dot);
dot = _mm_dp_ps(a_2, b_2, 0xF1);
result[5] = _mm_cvtss_f32(dot);
dot = _mm_dp_ps(a_3, b_2, 0xF1);
result[6] = _mm_cvtss_f32(dot);
dot = _mm_dp_ps(a_4, b_2, 0xF1);
result[7] = _mm_cvtss_f32(dot);
// b3
dot = _mm_dp_ps(a_1, b_3, 0xF1);
result[8] = _mm_cvtss_f32(dot);
dot = _mm_dp_ps(a_2, b_3, 0xF1);
result[9] = _mm_cvtss_f32(dot);
dot = _mm_dp_ps(a_3, b_3, 0xF1);
result[10] = _mm_cvtss_f32(dot);
dot = _mm_dp_ps(a_4, b_3, 0xF1);
result[11] = _mm_cvtss_f32(dot);
// b4
dot = _mm_dp_ps(a_1, b_4, 0xF1);
result[12] = _mm_cvtss_f32(dot);
dot = _mm_dp_ps(a_2, b_4, 0xF1);
result[13] = _mm_cvtss_f32(dot);
dot = _mm_dp_ps(a_3, b_4, 0xF1);
result[14] = _mm_cvtss_f32(dot);
dot = _mm_dp_ps(a_4, b_4, 0xF1);
result[15] = _mm_cvtss_f32(dot);
}
void mat4mat4_mult_sse(const __m128* a, const __m128* b_transposed, float* result)
{
__m128 dot;
// @question could simple mul add sse be faster?
// b1
dot = _mm_dp_ps(a[0], b_transposed[0], 0xF1);
result[0] = _mm_cvtss_f32(dot);
dot = _mm_dp_ps(a[1], b_transposed[0], 0xF1);
result[1] = _mm_cvtss_f32(dot);
dot = _mm_dp_ps(a[2], b_transposed[0], 0xF1);
result[2] = _mm_cvtss_f32(dot);
dot = _mm_dp_ps(a[3], b_transposed[0], 0xF1);
result[3] = _mm_cvtss_f32(dot);
// b2
dot = _mm_dp_ps(a[0], b_transposed[1], 0xF1);
result[4] = _mm_cvtss_f32(dot);
dot = _mm_dp_ps(a[1], b_transposed[1], 0xF1);
result[5] = _mm_cvtss_f32(dot);
dot = _mm_dp_ps(a[2], b_transposed[1], 0xF1);
result[6] = _mm_cvtss_f32(dot);
dot = _mm_dp_ps(a[3], b_transposed[1], 0xF1);
result[7] = _mm_cvtss_f32(dot);
// b3
dot = _mm_dp_ps(a[0], b_transposed[2], 0xF1);
result[8] = _mm_cvtss_f32(dot);
dot = _mm_dp_ps(a[1], b_transposed[2], 0xF1);
result[9] = _mm_cvtss_f32(dot);
dot = _mm_dp_ps(a[2], b_transposed[2], 0xF1);
result[10] = _mm_cvtss_f32(dot);
dot = _mm_dp_ps(a[3], b_transposed[2], 0xF1);
result[11] = _mm_cvtss_f32(dot);
// b4
dot = _mm_dp_ps(a[0], b_transposed[3], 0xF1);
result[12] = _mm_cvtss_f32(dot);
dot = _mm_dp_ps(a[1], b_transposed[3], 0xF1);
result[13] = _mm_cvtss_f32(dot);
dot = _mm_dp_ps(a[2], b_transposed[3], 0xF1);
result[14] = _mm_cvtss_f32(dot);
dot = _mm_dp_ps(a[3], b_transposed[3], 0xF1);
result[15] = _mm_cvtss_f32(dot);
}
void mat4mat4_mult_sse(const __m128* a, const __m128* b_transpose, __m128* result)
{
for (int i = 0; i < 4; ++i) {
result[i] = _mm_mul_ps(a[0], b_transpose[i]);
for (int j = 1; j < 4; ++j) {
result[i] = _mm_add_ps(_mm_mul_ps(a[j], b_transpose[4 * j + i]), result[i]);
}
}
}
// @question Consider to replace with 1d array // @question Consider to replace with 1d array
void frustum_planes(float planes[6][4], int radius, float *matrix) { void frustum_planes(float planes[6][4], int radius, float *matrix) {
// @todo make this a setting // @todo make this a setting

View File

@ -0,0 +1,117 @@
/**
* Jingga
*
* @copyright Jingga
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
#ifndef TOS_MATH_MATRIX_QUATERNION_FLOAT32_H
#define TOS_MATH_MATRIX_QUATERNION_FLOAT32_H
#include "../../stdlib/Intrinsics.h"
#include "../../stdlib/Mathtypes.h"
#include "../../utils/MathUtils.h"
void quaternion_from_euler(v4_f32* quat, float pitch, float yaw, float roll)
{
float y = OMS_RAD2DEG(yaw * 0.5f);
float cy = cosf_approx(y);
float sy = sinf_approx(y);
float p = OMS_RAD2DEG(pitch * 0.5f);
float cp = cosf_approx(p);
float sp = sinf_approx(p);
float r = OMS_RAD2DEG(roll * 0.5f);
float cr = cosf_approx(r);
float sr = sinf_approx(r);
quat->w = cr * cp * cy + sr * sp * sy;
quat->x = sr * cp * cy - cr * sp * sy;
quat->y = cr * sp * cy + sr * cp * sy;
quat->z = cr * cp * sy - sr * sp * cy;
}
void quaternion_from_euler(v4_f32* quat, const v3_f32* v)
{
float y = OMS_RAD2DEG(v->y * 0.5f);
float cy = cosf_approx(y);
float sy = sinf_approx(y);
float p = OMS_RAD2DEG(v->x * 0.5f);
float cp = cosf_approx(p);
float sp = sinf_approx(p);
float r = OMS_RAD2DEG(v->z * 0.5f);
float cr = cosf_approx(r);
float sr = sinf_approx(r);
quat->w = cr * cp * cy + sr * sp * sy;
quat->x = sr * cp * cy - cr * sp * sy;
quat->y = cr * sp * cy + sr * cp * sy;
quat->z = cr * cp * sy - sr * sp * cy;
}
void euler_from_quaternion(const v4_f32* quat, v3_f32* v) {
// Pitch
float sinp = 2.0f * (quat->w * quat->x + quat->y * quat->z);
float cosp = 1.0f - 2.0f * (quat->x * quat->x + quat->y * quat->y);
v->pitch = atan2f_approx(sinp, cosp);
// Yaw
float siny = 2.0f * (quat->w * quat->y - quat->z * quat->x);
if (siny >= 1.0f) {
v->yaw = OMS_PI_OVER_TWO;
} else if (siny <= -1.0f ) {
v->yaw = -OMS_PI_OVER_TWO;
} else {
v->yaw = asinf_approx(siny);
}
// Roll
float sinr = 2.0f * (quat->w * quat->z + quat->x * quat->y);
float cosr = 1.0f - 2.0f * (quat->y * quat->y + quat->z * quat->z);
v->roll = atan2f_approx(sinr, cosr);
}
void quaternion_multiply(v4_f32* quat, const v4_f32* quat1, const v4_f32* quat2)
{
quat->w = quat1->w * quat2->w - quat1->x * quat2->x - quat1->y * quat2->y - quat1->z * quat2->z;
quat->x = quat1->w * quat2->x + quat1->x * quat2->w + quat1->y * quat2->z - quat1->z * quat2->y;
quat->y = quat1->w * quat2->y - quat1->x * quat2->z + quat1->y * quat2->w + quat1->z * quat2->x;
quat->z = quat1->w * quat2->z + quat1->x * quat2->y - quat1->y * quat2->x + quat1->z * quat2->w;
}
void quaternion_inverse(v4_f32* quat, const v4_f32* quat_origin) {
float norm = quat_origin->w * quat_origin->w
+ quat_origin->x * quat_origin->x
+ quat_origin->y * quat_origin->y
+ quat_origin->z * quat_origin->z;
quat->w = quat_origin->w / norm;
quat->x = -quat_origin->x / norm;
quat->y = -quat_origin->y / norm;
quat->z = -quat_origin->z / norm;
}
inline
void quaternion_rotate_euler(v4_f32* quat, const v4_f32* quat_origin, const v4_f32* euler)
{
quaternion_multiply(quat, quat_origin, euler);
}
inline
void quaternion_rotate_quaternion(v4_f32* quat, const v4_f32* quat_origin, const v4_f32* quat_rot)
{
v4_f32 quat_tmp;
quaternion_multiply(&quat_tmp, quat_rot, quat_origin);
v4_f32 rot_;
quaternion_inverse(&rot_, quat_rot);
quaternion_multiply(quat, &quat_tmp, &rot_);
}
#endif

19
math/random/BlueNoise.h Normal file
View File

@ -0,0 +1,19 @@
/**
* Jingga
*
* @package Utils
* @copyright Jingga
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
#ifndef TOS_MATH_RANDOM_BLUE_NOISE
#define TOS_MATH_RANDOM_BLUE_NOISE
#include "../../stdlib/Types.h"
// @todo Implement poisson disc sampling for 2d and sphere
// https://observablehq.com/@jrus/bridson-fork/2
// https://observablehq.com/@jrus/spheredisksample
#endif

View File

@ -12,6 +12,22 @@
#include "../stdlib/Types.h" #include "../stdlib/Types.h"
struct ObjFile { struct ObjFile {
// Amount of references to this object
int references;
bool facing; // front or back
void* buffer;
void* facingness;
void* normals;
void* uvs;
void* parallaxs;
void* animations;
void* textures; // could be texture maps
void* mipmaps;
void* samplers;
void* materials;
}; };
#endif #endif

67
models/account/Account.h Normal file
View File

@ -0,0 +1,67 @@
/**
* Jingga
*
* @copyright Jingga
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
#ifndef TOS_MODELS_ACCOUNT_H
#define TOS_MODELS_ACCOUNT_H
#include "../../stdlib/Types.h"
#ifndef MAX_CHAR_NAME_LENGTH
#define MAX_CHAR_NAME_LENGTH 32
#endif
struct Account {
uint64 id;
char name[MAX_CHAR_NAME_LENGTH];
// relative memory position
int64 index;
// @question Maybe add pointers to Player, PacketCache?
};
/**
* Whenever a user connects to the game server we immediately need to allocate a fixed amount of data.
* Instead of putting this data willy-nilly into memory we can put all the user/account data always at the
* same offset respective to the memory area of that data type.
*
* e.g. this means that if the account with the id X is found at position 12 in memory (not in the hashmap)
* the player and packet cache are also all located at position 12 in memory in their respective buffers
* this means we only have to find the memory position ONCE and we know where all the other data is of that account
* this also means we don't have to chase too many pointers
*
* @performance It might be faster to make Player and PacketCache part of the Account?
* It really depends on how we perform the game loop
* Are we handling account by account OR (probably should be inside account for L1 cache)
* Are we handling one data type by data type (then this is correct)
*/
void account_init_game_connect(Account* accounts, Player* players, PacketCache* packet_cache)
{
int64 index = -1;
if (index < 0) {
return;
}
// init account
Account* temp_acc = accounts[index];
temp_acc->index = index;
// init player
Player* temp_player = players[index];
// init packet cache
PacketCache* temp_packets = packet_cache[index];
}
void account_free_game_disconnect()
{
}
#endif

67
models/bracket/Bracket.h Normal file
View File

@ -0,0 +1,67 @@
/**
* Jingga
*
* @copyright Jingga
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
#ifndef TOS_MODELS_BRACKET_SIMPLE_BRACKET_H
#define TOS_MODELS_BRACKET_SIMPLE_BRACKET_H
#include "BracketTeam.h"
#include "BracketSeeding.h"
#include "BracketMatch.h"
struct SimpleBracket {
int size;
BracketMatch* matches;
BracketSeeding seeding;
};
struct DoubleEliminationBracket {
SimpleBracket winners_bracket;
SimpleBracket losers_bracket;
};
void bracket_single_elim_create(SimpleBracket* bracket)
{
for (int i = 0; i < bracket->size / 2; ++i) {
bracket->matches[i].teams[0] = &bracket->seeding.teams[bracket->seeding.team_seedings[i]];
bracket->matches[i].teams[1] = &bracket->seeding.teams[bracket->seeding.team_seedings[bracket->size - i - 1]];
}
int j = 0;
for (int i = bracket->size / 2; bracket->size - 1; ++i) {
bracket->matches[i].teams[0] = bracket->matches[j].winner;
bracket->matches[i].teams[0] = bracket->matches[++j].winner;
++j;
}
}
void bracket_double_elim_create(DoubleEliminationBracket* bracket)
{
bracket_single_elim_create(&bracket->winners_bracket);
int match_index = 0;
for (int i = 0; i < bracket->winners_bracket.size - 1; ++i) {
if (i % 2 == 0) {
bracket->losers_bracket.matches[match_index].teams[0] = bracket->winners_bracket.matches[i].loser;
bracket->losers_bracket.matches[match_index].teams[1] = bracket->winners_bracket.matches[i + 1].loser;
++match_index;
} else {
bracket->losers_bracket.matches[match_index].teams[0] = bracket->losers_bracket.matches[match_index - 1].winner;
bracket->losers_bracket.matches[match_index].teams[1] = bracket->winners_bracket.matches[i + 1].loser;
++match_index;
}
}
int j = 0;
for (int i = match_index; i < bracket->losers_bracket.size - 1; ++i) {
bracket->losers_bracket.matches[i].teams[0] = bracket->losers_bracket.matches[j].winner;
bracket->losers_bracket.matches[i].teams[1] = bracket->losers_bracket.matches[++j].winner;
++j;
}
}
#endif

View File

@ -0,0 +1,20 @@
/**
* Jingga
*
* @copyright Jingga
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
#ifndef TOS_MODELS_BRACKET_MATCH_H
#define TOS_MODELS_BRACKET_MATCH_H
#include "BracketTeam.h"
struct BracketMatch {
BracketTeam* teams[2];
BracketTeam* winner;
BracketTeam* loser;
};
#endif

View File

@ -0,0 +1,20 @@
/**
* Jingga
*
* @copyright Jingga
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
#ifndef TOS_MODELS_BRACKET_SEEDING_H
#define TOS_MODELS_BRACKET_SEEDING_H
#include "../../stdlib/Types.h"
#include "BracketTeam.h"
struct BracketSeeding {
BracketTeam* teams;
uint32* team_seedings; // stores the index of the respective seed, index + 1 = seed
};
#endif

View File

@ -0,0 +1,20 @@
/**
* Jingga
*
* @copyright Jingga
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
#ifndef TOS_MODELS_BRACKET_TEAM_H
#define TOS_MODELS_BRACKET_TEAM_H
#include "../../stdlib/Types.h"
struct BracketTeam {
int size;
uint64* player_ids;
uint32 rating;
};
#endif

View File

@ -11,9 +11,23 @@
#include "../../stdlib/Types.h" #include "../../stdlib/Types.h"
#include "../../mob/MobStats.h"
#include "../../mob/skill/StatsTarget.h"
struct Equipment { struct Equipment {
byte type; byte type;
char* name; char* name;
// @tood how to handle multiplicative stats?
// you can have 2 stats for 2 target types (e.g. you could create a buff and debuff in one skill)
SMobStats stats1;
StatsTarget stats1_target;
SMobStats stats2;
StatsTarget stats2_target;
// @todo probably add more of the Skill attributes here
// @question what should be part of skills and what should be part of items?!?!?!?
}; };
#endif #endif

View File

@ -24,7 +24,10 @@ struct MobState {
// last 3 bytes = animation to use // last 3 bytes = animation to use
uint32 action = (MOB_ACTION_INACTIVE << 24); uint32 action = (MOB_ACTION_INACTIVE << 24);
bool in_battle;
int chunk_id; int chunk_id;
byte environment; // dungeon/raid, pvp-openworld, pvp, pvp-tournament, open-world, instance-private, instance-invite, housing,
}; };
#endif #endif

View File

@ -1,6 +1,547 @@
/**
* Jingga
*
* @copyright Jingga
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
#ifndef TOS_MODELS_MOB_STATS_H #ifndef TOS_MODELS_MOB_STATS_H
#define TOS_MODELS_MOB_STATS_H #define TOS_MODELS_MOB_STATS_H
#include "../../../stdlib/Types.h" #include "../../stdlib/Types.h"
struct SMobStatsTotal {
byte stat_str; // strength : effects health + base damage
byte stat_int; // inteligence : effects resource + base demage
byte stat_acc; // accuracy : effects critical chance + base damage + miss chance
byte stat_agi; // agility : effects resource + base damage + dodge change
byte stat_def; // defense : effects resource + base defense + dodge change
byte stat_sta; // stamina : effects health regen + resource regen
// Naming conventions
// : total
// _base : character stats (see stat_ above)
// _equip : character equipment
// _item : other item effects (consumables, e.g. potions)
// _effect : external aoe/skill effect
// _skill : own skill
// Damage types
uint32 dmg;
uint32 dmg_base;
uint32 dmg_equip;
uint32 dmg_item;
uint32 dmg_effect;
uint32 dmg_skill;
uint32 dmg_pircing;
uint32 dmg_pircing_base;
uint32 dmg_pircing_equip;
uint32 dmg_pircing_item;
uint32 dmg_pircing_effect;
uint32 dmg_pircing_skill;
uint32 dmg_slashing;
uint32 dmg_slashing_base;
uint32 dmg_slashing_equip;
uint32 dmg_slashing_item;
uint32 dmg_slashing_effect;
uint32 dmg_slashing_skill;
uint32 dmg_bludgeoning;
uint32 dmg_bludgeoning_base;
uint32 dmg_bludgeoning_equip;
uint32 dmg_bludgeoning_item;
uint32 dmg_bludgeoning_effect;
uint32 dmg_bludgeoning_skill;
uint32 dmg_stabbing;
uint32 dmg_stabbing_base;
uint32 dmg_stabbing_equip;
uint32 dmg_stabbing_item;
uint32 dmg_stabbing_effect;
uint32 dmg_stabbing_skill;
uint32 dmg_fire;
uint32 dmg_fire_base;
uint32 dmg_fire_equip;
uint32 dmg_fire_item;
uint32 dmg_fire_effect;
uint32 dmg_fire_skill;
uint32 dmg_water;
uint32 dmg_water_base;
uint32 dmg_water_equip;
uint32 dmg_water_item;
uint32 dmg_water_effect;
uint32 dmg_water_skill;
uint32 dmg_ice;
uint32 dmg_ice_base;
uint32 dmg_ice_equip;
uint32 dmg_ice_item;
uint32 dmg_ice_effect;
uint32 dmg_ice_skill;
uint32 dmg_earth;
uint32 dmg_earth_base;
uint32 dmg_earth_equip;
uint32 dmg_earth_item;
uint32 dmg_earth_effect;
uint32 dmg_earth_skill;
uint32 dmg_wind;
uint32 dmg_wind_base;
uint32 dmg_wind_equip;
uint32 dmg_wind_item;
uint32 dmg_wind_effect;
uint32 dmg_wind_skill;
uint32 dmg_poison;
uint32 dmg_poison_base;
uint32 dmg_poison_equip;
uint32 dmg_poison_item;
uint32 dmg_poison_effect;
uint32 dmg_poison_skill;
uint32 dmg_lightning;
uint32 dmg_lightning_base;
uint32 dmg_lightning_equip;
uint32 dmg_lightning_item;
uint32 dmg_lightning_effect;
uint32 dmg_lightning_skill;
uint32 dmg_holy;
uint32 dmg_holy_base;
uint32 dmg_holy_equip;
uint32 dmg_holy_item;
uint32 dmg_holy_effect;
uint32 dmg_holy_skill;
uint32 dmg_arcane;
uint32 dmg_arcane_base;
uint32 dmg_arcane_equip;
uint32 dmg_arcane_item;
uint32 dmg_arcane_effect;
uint32 dmg_arcane_skill;
uint32 dmg_corrupted;
uint32 dmg_corrupted_base;
uint32 dmg_corrupted_equip;
uint32 dmg_corrupted_item;
uint32 dmg_corrupted_effect;
uint32 dmg_corrupted_skill;
uint32 dmg_crit;
uint32 dmg_crit_base;
uint32 dmg_crit_equip;
uint32 dmg_crit_item;
uint32 dmg_crit_effect;
uint32 dmg_crit_skill;
f32 dmg_crit_chance;
f32 dmg_crit_chance_base;
f32 dmg_crit_chance_equip;
f32 dmg_crit_chance_item;
f32 dmg_crit_chance_effect;
f32 dmg_crit_chance_skill;
uint32 dmg_reflection;
uint32 dmg_reflection_base;
uint32 dmg_reflection_equip;
uint32 dmg_reflection_item;
uint32 dmg_reflection_effect;
uint32 dmg_reflection_skill;
// Health & Resource
uint32 health;
uint32 health_base;
uint32 health_equip;
uint32 health_item;
uint32 health_effect;
uint32 health_skill;
uint32 health_on_dmg_dealt;
uint32 health_on_dmg_dealt_base;
uint32 health_on_dmg_dealt_equip;
uint32 health_on_dmg_dealt_item;
uint32 health_on_dmg_dealt_effect;
uint32 health_on_dmg_dealt_skill;
uint32 health_on_dmg_taken;
uint32 health_on_dmg_taken_base;
uint32 health_on_dmg_taken_equip;
uint32 health_on_dmg_taken_item;
uint32 health_on_dmg_taken_effect;
uint32 health_on_dmg_taken_skill;
uint32 health_regen;
uint32 health_regen_base;
uint32 health_regen_equip;
uint32 health_regen_item;
uint32 health_regen_effect;
uint32 health_regen_skill;
uint32 health_regen_on_dmg_dealt;
uint32 health_regen_on_dmg_dealt_base;
uint32 health_regen_on_dmg_dealt_equip;
uint32 health_regen_on_dmg_dealt_item;
uint32 health_regen_on_dmg_dealt_effect;
uint32 health_regen_on_dmg_dealt_skill;
uint32 health_regen_on_dmg_taken;
uint32 health_regen_on_dmg_taken_base;
uint32 health_regen_on_dmg_taken_equip;
uint32 health_regen_on_dmg_taken_item;
uint32 health_regen_on_dmg_taken_effect;
uint32 health_regen_on_dmg_taken_skill;
uint32 resource;
uint32 resource_base;
uint32 resource_equip;
uint32 resource_item;
uint32 resource_effect;
uint32 resource_skill;
uint32 resource_on_dmg_dealt;
uint32 resource_on_dmg_dealt_base;
uint32 resource_on_dmg_dealt_equip;
uint32 resource_on_dmg_dealt_item;
uint32 resource_on_dmg_dealt_effect;
uint32 resource_on_dmg_dealt_skill;
uint32 resource_on_dmg_taken;
uint32 resource_on_dmg_taken_base;
uint32 resource_on_dmg_taken_equip;
uint32 resource_on_dmg_taken_item;
uint32 resource_on_dmg_taken_effect;
uint32 resource_on_dmg_taken_skill;
uint32 resource_regen;
uint32 resource_regen_base;
uint32 resource_regen_equip;
uint32 resource_regen_item;
uint32 resource_regen_effect;
uint32 resource_regen_skill;
uint32 resource_regen_on_dmg_dealt;
uint32 resource_regen_on_dmg_dealt_base;
uint32 resource_regen_on_dmg_dealt_equip;
uint32 resource_regen_on_dmg_dealt_item;
uint32 resource_regen_on_dmg_dealt_effect;
uint32 resource_regen_on_dmg_dealt_skill;
uint32 resource_regen_on_dmg_taken;
uint32 resource_regen_on_dmg_taken_base;
uint32 resource_regen_on_dmg_taken_equip;
uint32 resource_regen_on_dmg_taken_item;
uint32 resource_regen_on_dmg_taken_effect;
uint32 resource_regen_on_dmg_taken_skill;
uint32 resource_loss;
uint32 resource_loss_base;
uint32 resource_loss_equip;
uint32 resource_loss_item;
uint32 resource_loss_effect;
uint32 resource_loss_skill;
uint32 resource_loss_on_dmg_dealt;
uint32 resource_loss_on_dmg_dealt_base;
uint32 resource_loss_on_dmg_dealt_equip;
uint32 resource_loss_on_dmg_dealt_item;
uint32 resource_loss_on_dmg_dealt_effect;
uint32 resource_loss_on_dmg_dealt_skill;
uint32 resource_loss_on_dmg_taken;
uint32 resource_loss_on_dmg_taken_base;
uint32 resource_loss_on_dmg_taken_equip;
uint32 resource_loss_on_dmg_taken_item;
uint32 resource_loss_on_dmg_taken_effect;
uint32 resource_loss_on_dmg_taken_skill;
// Defense types
// think about it as armor and/or resistence if it helps
uint32 defense;
uint32 defense_base;
uint32 defense_equip;
uint32 defense_item;
uint32 defense_effect;
uint32 defense_skill;
uint32 defense_pircing;
uint32 defense_pircing_base;
uint32 defense_pircing_equip;
uint32 defense_pircing_item;
uint32 defense_pircing_effect;
uint32 defense_pircing_skill;
uint32 defense_slashing;
uint32 defense_slashing_base;
uint32 defense_slashing_equip;
uint32 defense_slashing_item;
uint32 defense_slashing_effect;
uint32 defense_slashing_skill;
uint32 defense_bludgeoning;
uint32 defense_bludgeoning_base;
uint32 defense_bludgeoning_equip;
uint32 defense_bludgeoning_item;
uint32 defense_bludgeoning_effect;
uint32 defense_bludgeoning_skill;
uint32 defense_stabbing;
uint32 defense_stabbing_base;
uint32 defense_stabbing_equip;
uint32 defense_stabbing_item;
uint32 defense_stabbing_effect;
uint32 defense_stabbing_skill;
uint32 defense_fire;
uint32 defense_fire_base;
uint32 defense_fire_equip;
uint32 defense_fire_item;
uint32 defense_fire_effect;
uint32 defense_fire_skill;
uint32 defense_water;
uint32 defense_water_base;
uint32 defense_water_equip;
uint32 defense_water_item;
uint32 defense_water_effect;
uint32 defense_water_skill;
uint32 defense_ice;
uint32 defense_ice_base;
uint32 defense_ice_equip;
uint32 defense_ice_item;
uint32 defense_ice_effect;
uint32 defense_ice_skill;
uint32 defense_earth;
uint32 defense_earth_base;
uint32 defense_earth_equip;
uint32 defense_earth_item;
uint32 defense_earth_effect;
uint32 defense_earth_skill;
uint32 defense_wind;
uint32 defense_wind_base;
uint32 defense_wind_equip;
uint32 defense_wind_item;
uint32 defense_wind_effect;
uint32 defense_wind_skill;
uint32 defense_poison;
uint32 defense_poison_base;
uint32 defense_poison_equip;
uint32 defense_poison_item;
uint32 defense_poison_effect;
uint32 defense_poison_skill;
uint32 defense_lightning;
uint32 defense_lightning_base;
uint32 defense_lightning_equip;
uint32 defense_lightning_item;
uint32 defense_lightning_effect;
uint32 defense_lightning_skill;
uint32 defense_holy;
uint32 defense_holy_base;
uint32 defense_holy_equip;
uint32 defense_holy_item;
uint32 defense_holy_effect;
uint32 defense_holy_skill;
uint32 defense_arcane;
uint32 defense_arcane_base;
uint32 defense_arcane_equip;
uint32 defense_arcane_item;
uint32 defense_arcane_effect;
uint32 defense_arcane_skill;
uint32 defense_corrupted;
uint32 defense_corrupted_base;
uint32 defense_corrupted_equip;
uint32 defense_corrupted_item;
uint32 defense_corrupted_effect;
uint32 defense_corrupted_skill;
uint32 shield_type;
bool shield_dispellable;
uint32 shield;
uint32 shield_base;
uint32 shield_equip;
uint32 shield_item;
uint32 shield_effect;
uint32 shield_skill;
// Accuracy
f32 dodge_chance;
f32 dodge_chance_base;
f32 dodge_chance_equip;
f32 dodge_chance_item;
f32 dodge_chance_effect;
f32 dodge_chance_skill;
f32 root_protection;
f32 root_protection_base;
f32 root_protection_equip;
f32 root_protection_item;
f32 root_protection_effect;
f32 root_protection_skill;
f32 miss_chance;
f32 miss_chance_base;
f32 miss_chance_equip;
f32 miss_chance_item;
f32 miss_chance_effect;
f32 miss_chance_skill;
// Movement
// Additional speeds may be defined for Mobs
f32 speed_walk1; // normal/fast
f32 speed_walk1_base;
f32 speed_walk1_equip;
f32 speed_walk1_item;
f32 speed_walk1_effect;
f32 speed_walk1_skill;
f32 speed_walk2; // casual/slow
f32 speed_swim1; // normal/fast
f32 speed_swim1_base;
f32 speed_swim1_equip;
f32 speed_swim1_item;
f32 speed_swim1_effect;
f32 speed_swim1_skill;
f32 speed_swim2; // casual/slow
f32 speed_fly1; // normal/fast
f32 speed_fly1_base;
f32 speed_fly1_equip;
f32 speed_fly1_item;
f32 speed_fly1_effect;
f32 speed_fly1_skill;
f32 speed_fly2; // casual/slow
f32 speed_jump;
f32 speed_dodge;
f32 speed_turn;
// Fighting speed
f32 speed_cast;
f32 speed_cast_base;
f32 speed_cast_equip;
f32 speed_cast_item;
f32 speed_cast_effect;
f32 speed_cast_skill;
f32 speed_attack;
f32 speed_attack_base;
f32 speed_attack_equip;
f32 speed_attack_item;
f32 speed_attack_effect;
f32 speed_attack_skill;
};
struct SMobStats {
byte stat_str; // strength : effects health + base damage
byte stat_int; // inteligence : effects resource + base demage
byte stat_acc; // accuracy : effects critical chance + base damage + miss chance
byte stat_agi; // agility : effects resource + base damage + dodge change
byte stat_def; // defense : effects resource + base defense + dodge change
byte stat_sta; // stamina : effects health regen + resource regen
// Damage types
uint32 dmg;
uint32 dmg_pircing;
uint32 dmg_slashing;
uint32 dmg_bludgeoning;
uint32 dmg_stabbing;
uint32 dmg_fire;
uint32 dmg_water;
uint32 dmg_ice;
uint32 dmg_arcane;
uint32 dmg_corrupted;
uint32 dmg_reflection;
uint32 dmg_crit;
f32 dmg_crit_chance;
// Health & Resource
uint32 health;
uint32 health_on_dmg_dealt;
uint32 health_on_dmg_taken;
uint32 health_regen;
uint32 health_regen_on_dmg_dealt;
uint32 health_regen_on_dmg_taken;
uint32 resource;
uint32 resource_on_dmg_dealt;
uint32 resource_on_dmg_taken;
uint32 resource_regen;
uint32 resource_regen_on_dmg_dealt;
uint32 resource_regen_on_dmg_taken;
uint32 resource_loss;
uint32 resource_loss_on_dmg_dealt;
uint32 resource_loss_on_dmg_taken;
// Defense types
// think about it as armor and/or resistence if it helps
uint32 defense;
uint32 defense_pircing;
uint32 defense_slashing;
uint32 defense_bludgeoning;
uint32 defense_stabbing;
uint32 defense_fire;
uint32 defense_water;
uint32 defense_ice;
uint32 defense_earth;
uint32 defense_wind;
uint32 defense_poison;
uint32 defense_lightning;
uint32 defense_holy;
uint32 defense_arcane;
uint32 defense_corrupted;
uint32 shield_type;
bool shield_dispellable;
uint32 shield;
// Accuracy
f32 dodge_chance;
f32 root_protection;
f32 miss_chance;
// Movement
// Additional speeds may be defined for Mobs
f32 speed_walk1; // normal/fast
f32 speed_walk2; // casual/slow
f32 speed_swim1; // normal/fast
f32 speed_swim2; // casual/slow
f32 speed_fly1; // normal/fast
f32 speed_fly2; // casual/slow
f32 speed_jump;
f32 speed_dodge;
f32 speed_turn;
// Fighting speed
f32 speed_cast;
f32 speed_attack;
};
struct CMobStats {
};
#endif #endif

View File

View File

@ -16,7 +16,7 @@
#include "../MobState.h" #include "../MobState.h"
#include "../monster/LootTable.h" #include "../monster/LootTable.h"
#include "Backpack.h" #include "Backpack.h"
#include "PlayerStats.h" #include "../MobStats.h"
#ifndef MAX_CHAR_NAME_LENGTH #ifndef MAX_CHAR_NAME_LENGTH
#define MAX_CHAR_NAME_LENGTH 32 #define MAX_CHAR_NAME_LENGTH 32
@ -29,7 +29,7 @@
#if SERVER #if SERVER
struct SPlayer { struct SPlayer {
Mob mob; Mob mob;
SPlayerStats player_stats; SMobStats player_stats;
char name[MAX_CHAR_NAME_LENGTH]; char name[MAX_CHAR_NAME_LENGTH];
char title[MAX_CHAR_TITLE_LENGTH]; char title[MAX_CHAR_TITLE_LENGTH];
@ -89,7 +89,7 @@
struct CPlayer { struct CPlayer {
Mob mob; Mob mob;
CPlayerStats player_stats; CMobStats player_stats;
char name[MAX_CHAR_NAME_LENGTH]; char name[MAX_CHAR_NAME_LENGTH];
char title[MAX_CHAR_TITLE_LENGTH]; char title[MAX_CHAR_TITLE_LENGTH];

View File

@ -1,349 +0,0 @@
/**
* Jingga
*
* @copyright Jingga
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
#ifndef TOS_MODELS_MOB_PLAYER_STATS_H
#define TOS_MODELS_MOB_PLAYER_STATS_H
#include "../../../stdlib/Types.h"
#if SERVER
struct SPlayerStats {
byte stat_str; // strength : effects health + base damage
byte stat_int; // inteligence : effects resource + base demage
byte stat_acc; // accuracy : effects critical chance + base damage + miss chance
byte stat_agi; // agility : effects resource + base damage + dodge change
byte stat_def; // defense : effects resource + base defense + dodge change
byte stat_sta; // stamina : effects health regen + resource regen
// Naming conventions
// : total
// _base : character stats (see stat_ above)
// _equip : character equipment
// _item : other item effects (consumables, e.g. potions)
// _effect : external aoe/skill effect
// _skill : own skill
// Damage types
unsigned int dmg;
unsigned int dmg_base;
unsigned int dmg_equip;
unsigned int dmg_item;
unsigned int dmg_effect;
unsigned int dmg_skill;
unsigned int dmg_pircing;
unsigned int dmg_pircing_base;
unsigned int dmg_pircing_equip;
unsigned int dmg_pircing_item;
unsigned int dmg_pircing_effect;
unsigned int dmg_pircing_skill;
unsigned int dmg_slashing;
unsigned int dmg_slashing_base;
unsigned int dmg_slashing_equip;
unsigned int dmg_slashing_item;
unsigned int dmg_slashing_effect;
unsigned int dmg_slashing_skill;
unsigned int dmg_bludgeoning;
unsigned int dmg_bludgeoning_base;
unsigned int dmg_bludgeoning_equip;
unsigned int dmg_bludgeoning_item;
unsigned int dmg_bludgeoning_effect;
unsigned int dmg_bludgeoning_skill;
unsigned int dmg_fire;
unsigned int dmg_fire_base;
unsigned int dmg_fire_equip;
unsigned int dmg_fire_item;
unsigned int dmg_fire_effect;
unsigned int dmg_fire_skill;
unsigned int dmg_water;
unsigned int dmg_water_base;
unsigned int dmg_water_equip;
unsigned int dmg_water_item;
unsigned int dmg_water_effect;
unsigned int dmg_water_skill;
unsigned int dmg_ice;
unsigned int dmg_ice_base;
unsigned int dmg_ice_equip;
unsigned int dmg_ice_item;
unsigned int dmg_ice_effect;
unsigned int dmg_ice_skill;
unsigned int dmg_earth;
unsigned int dmg_earth_base;
unsigned int dmg_earth_equip;
unsigned int dmg_earth_item;
unsigned int dmg_earth_effect;
unsigned int dmg_earth_skill;
unsigned int dmg_wind;
unsigned int dmg_wind_base;
unsigned int dmg_wind_equip;
unsigned int dmg_wind_item;
unsigned int dmg_wind_effect;
unsigned int dmg_wind_skill;
unsigned int dmg_poison;
unsigned int dmg_poison_base;
unsigned int dmg_poison_equip;
unsigned int dmg_poison_item;
unsigned int dmg_poison_effect;
unsigned int dmg_poison_skill;
unsigned int dmg_lightning;
unsigned int dmg_lightning_base;
unsigned int dmg_lightning_equip;
unsigned int dmg_lightning_item;
unsigned int dmg_lightning_effect;
unsigned int dmg_lightning_skill;
unsigned int dmg_holy;
unsigned int dmg_holy_base;
unsigned int dmg_holy_equip;
unsigned int dmg_holy_item;
unsigned int dmg_holy_effect;
unsigned int dmg_holy_skill;
unsigned int dmg_arcane;
unsigned int dmg_arcane_base;
unsigned int dmg_arcane_equip;
unsigned int dmg_arcane_item;
unsigned int dmg_arcane_effect;
unsigned int dmg_arcane_skill;
unsigned int dmg_corrupted;
unsigned int dmg_corrupted_base;
unsigned int dmg_corrupted_equip;
unsigned int dmg_corrupted_item;
unsigned int dmg_corrupted_effect;
unsigned int dmg_corrupted_skill;
unsigned int dmg_crit;
unsigned int dmg_crit_base;
unsigned int dmg_crit_equip;
unsigned int dmg_crit_item;
unsigned int dmg_crit_effect;
unsigned int dmg_crit_skill;
float dmg_crit_chance;
float dmg_crit_chance_base;
float dmg_crit_chance_equip;
float dmg_crit_chance_item;
float dmg_crit_chance_effect;
float dmg_crit_chance_skill;
// Health & Resource
unsigned int health;
unsigned int health_base;
unsigned int health_equip;
unsigned int health_item;
unsigned int health_effect;
unsigned int health_skill;
unsigned int health_regen;
unsigned int health_regen_base;
unsigned int health_regen_equip;
unsigned int health_regen_item;
unsigned int health_regen_effect;
unsigned int health_regen_skill;
unsigned int resource;
unsigned int resource_base;
unsigned int resource_equip;
unsigned int resource_item;
unsigned int resource_effect;
unsigned int resource_skill;
unsigned int resource_regen;
unsigned int resource_regen_base;
unsigned int resource_regen_equip;
unsigned int resource_regen_item;
unsigned int resource_regen_effect;
unsigned int resource_regen_skill;
// Defense types
// think about it as armor and/or resistence if it helps
unsigned int defense;
unsigned int defense_base;
unsigned int defense_equip;
unsigned int defense_item;
unsigned int defense_effect;
unsigned int defense_skill;
unsigned int defense_pircing;
unsigned int defense_pircing_base;
unsigned int defense_pircing_equip;
unsigned int defense_pircing_item;
unsigned int defense_pircing_effect;
unsigned int defense_pircing_skill;
unsigned int defense_slashing;
unsigned int defense_slashing_base;
unsigned int defense_slashing_equip;
unsigned int defense_slashing_item;
unsigned int defense_slashing_effect;
unsigned int defense_slashing_skill;
unsigned int defense_bludgeoning;
unsigned int defense_bludgeoning_base;
unsigned int defense_bludgeoning_equip;
unsigned int defense_bludgeoning_item;
unsigned int defense_bludgeoning_effect;
unsigned int defense_bludgeoning_skill;
unsigned int defense_fire;
unsigned int defense_fire_base;
unsigned int defense_fire_equip;
unsigned int defense_fire_item;
unsigned int defense_fire_effect;
unsigned int defense_fire_skill;
unsigned int defense_water;
unsigned int defense_water_base;
unsigned int defense_water_equip;
unsigned int defense_water_item;
unsigned int defense_water_effect;
unsigned int defense_water_skill;
unsigned int defense_ice;
unsigned int defense_ice_base;
unsigned int defense_ice_equip;
unsigned int defense_ice_item;
unsigned int defense_ice_effect;
unsigned int defense_ice_skill;
unsigned int defense_earth;
unsigned int defense_earth_base;
unsigned int defense_earth_equip;
unsigned int defense_earth_item;
unsigned int defense_earth_effect;
unsigned int defense_earth_skill;
unsigned int defense_wind;
unsigned int defense_wind_base;
unsigned int defense_wind_equip;
unsigned int defense_wind_item;
unsigned int defense_wind_effect;
unsigned int defense_wind_skill;
unsigned int defense_poison;
unsigned int defense_poison_base;
unsigned int defense_poison_equip;
unsigned int defense_poison_item;
unsigned int defense_poison_effect;
unsigned int defense_poison_skill;
unsigned int defense_lightning;
unsigned int defense_lightning_base;
unsigned int defense_lightning_equip;
unsigned int defense_lightning_item;
unsigned int defense_lightning_effect;
unsigned int defense_lightning_skill;
unsigned int defense_holy;
unsigned int defense_holy_base;
unsigned int defense_holy_equip;
unsigned int defense_holy_item;
unsigned int defense_holy_effect;
unsigned int defense_holy_skill;
unsigned int defense_arcane;
unsigned int defense_arcane_base;
unsigned int defense_arcane_equip;
unsigned int defense_arcane_item;
unsigned int defense_arcane_effect;
unsigned int defense_arcane_skill;
unsigned int defense_corrupted;
unsigned int defense_corrupted_base;
unsigned int defense_corrupted_equip;
unsigned int defense_corrupted_item;
unsigned int defense_corrupted_effect;
unsigned int defense_corrupted_skill;
// Accuracy
float dodge_chance;
float dodge_chance_base;
float dodge_chance_equip;
float dodge_chance_item;
float dodge_chance_effect;
float dodge_chance_skill;
float root_protection;
float root_protection_base;
float root_protection_equip;
float root_protection_item;
float root_protection_effect;
float root_protection_skill;
float miss_chance;
float miss_chance_base;
float miss_chance_equip;
float miss_chance_item;
float miss_chance_effect;
float miss_chance_skill;
// Movement
// Additional speeds may be defined for players
float speed_walk1; // normal/fast
float speed_walk1_base;
float speed_walk1_equip;
float speed_walk1_item;
float speed_walk1_effect;
float speed_walk1_skill;
float speed_walk2; // casual/slow
float speed_swim1; // normal/fast
float speed_swim1_base;
float speed_swim1_equip;
float speed_swim1_item;
float speed_swim1_effect;
float speed_swim1_skill;
float speed_swim2; // casual/slow
float speed_fly1; // normal/fast
float speed_fly1_base;
float speed_fly1_equip;
float speed_fly1_item;
float speed_fly1_effect;
float speed_fly1_skill;
float speed_fly2; // casual/slow
float speed_jump;
float speed_dodge;
float speed_turn;
// Fighting speed
float speed_cast;
float speed_cast_base;
float speed_cast_equip;
float speed_cast_item;
float speed_cast_effect;
float speed_cast_skill;
float speed_attack;
float speed_attack_base;
float speed_attack_equip;
float speed_attack_item;
float speed_attack_effect;
float speed_attack_skill;
};
#endif
struct CPlayerStats {
};
#endif

View File

@ -0,0 +1,9 @@
#ifndef TOS_MODELS_SKILL_AOE_DISTRIBUTIOM_H
#define TOS_MODELS_SKILL_AOE_DISTRIBUTIOM_H
enum AoeDistribution {
AOE_DISTRIBUTION_FILL,
AOE_DISTRIBUTION_SPOTTY
};
#endif

View File

@ -0,0 +1,12 @@
#ifndef TOS_MODELS_SKILL_AOE_SHAPE_H
#define TOS_MODELS_SKILL_AOE_SHAPE_H
enum AoeShape {
AOE_SHAPE_RECTANGLE,
AOE_SHAPE_CIRCLE,
AOE_SHAPE_SPHEAR,
AOE_SHAPE_BOX,
AOE_SHAPE_FUNNEL
};
#endif

View File

@ -0,0 +1,11 @@
#ifndef TOS_MODELS_SKILL_PROJECTILE_DISTRIBUTION_H
#define TOS_MODELS_SKILL_PROJECTILE_DISTRIBUTION_H
enum ProjectileDistribution
{
PROJECTILE_DISTRIBUTION_HORIZONTAL,
PROJECTILE_DISTRIBUTION_LINE,
PROJECTILE_DISTRIBUTION_CIRCLE
};
#endif

160
models/mob/skill/Skill.h Normal file
View File

@ -0,0 +1,160 @@
#ifndef TOS_MODELS_SKILL_H
#define TOS_MODELS_SKILL_H
#include "../../../stdlib/Types.h"
#include "ProjectileDistribution.h"
#include "SkillLocation.h"
#include "AoeDistribution.h"
#include "StatsTarget.h"
#include "../MobStats.h"
#define MAX_SKILL_NAME 32
#define MAX_SKILL_DESCRIPTION 128
struct Skill
{
// not required for server
// const char name[MAX_SKILL_NAME];
// const char description[MAX_SKILL_DESCRIPTION];
int id;
// animations
void* animation_casting;
void* animation_channeling;
bool projectile_animation_uses_item; // Use the equiped item for the projectile
byte target; // what is targatable (self, enemies, allies, ground, none?) Has to be bitset 2^n to define multiple
byte default_target;
f32 visual_scale; // make visual larger/smaller
// @tood how to handle multiplicative stats?
// you can have 2 stats for 2 target types (e.g. you could create a buff and debuff in one skill)
SMobStats stats1;
StatsTarget stats1_target;
SMobStats stats2;
StatsTarget stats2_target;
byte skill_movement; // none, follows target, random moevement, random movement in aoe
byte count; // how often is the skill executed @question can this also be used as tick count for heals? or is this in the MobStats?
byte count_delay; // delay between executions
byte count_manual; // you can manually perform the skill count * times
// @todo how to implement random distribution e.g. place n totems in random distribution close to selected spot
// General
int resource_cost;
int health_cost;
bool is_range;
f32 attack_range;
void* attack_anim;
bool is_melee;
f32 melee_range;
// Projectile data
bool is_projectile;
f32 projectile_speed;
int projectile_count;
int projectile_shape; // 3d Model
int projectile_distribution;
bool projectile_angle; // Projectiles fan out from start point
// Either creates new sub-projectiles on shatter OR
// shatter is basically a second hit
bool shatter;
int shatter_projectiles;
int shatter_count; // How often can it shatter at most
f32 shatter_probability;
f32 shatter_range;
f32 shatter_duration;
uint32 shatter_damage;
bool is_retargatable; // If multiple you may be able to switch targets in between
bool is_boomerang;
// Casting happens before the skill
f32 cast_duration;
bool is_cast_cancalable;
bool is_cast_disruptable;
bool is_cast_movable;
// Channeling happens during the skill.
// even a normal punch attack is a channelled skill
f32 channeling_duration; // -1.0 = infinite (e.g. aura), 0 = no duration = instant
bool is_channeling; // duration = skill_duration + it shows the channeling timeline
bool is_channeling_cancalable;
bool is_channeling_disruptable;
bool is_channeling_movable;
byte channeling_distribution; // beginning, on hit, end, intervals, smooth -> also effects dmg if channeling is cancled
byte channeling_ticks; // how often is dmg dealt
f32 passthrough_damage; // How much of your damage in % is passing through to the next mob.
int passtrhough_count;
// AOE
bool is_aoe;
f32 aoe_distance;
int aoe_shape; // circle, square, donut
AoeDistribution aoe_fill_pattern;
f32 aoe_dim1;
f32 aoe_dim2;
f32 aoe_dim3;
int aoe_shatter;
SkillLocation aoe_location;
byte aoe_apply; // Applies while in aoe, applies even after moving out of aoe
// DOT
f32 dot_duration;
int dot_count;
byte dot_state; // only when moving, standing still, always
byte dot_effective; // always; on move; on stand still
byte dot_buff_effective; // buff modifier (e.g. increase by/decrease by)
float dot_buff; // buff dot when on move or on standstill
int bleeding_dot;
int poison_dot;
int burn_dot;
int ice_dot;
int resource_drain;
int dot_shatter;
// Minion (and totems)
int minion_type;
int minon_count; // Max minion count
int minion_duration;
int minion_summon_count; // How many summons per summon cast @question still required with general skill count? I don't think so.
// Effects
bool is_effect_spreading;
f32 effect_spreading_probability;
f32 effect_spreading_radius; // What is the maximum distance for spreading
f32 effect_spreading_max_count; // How many mobs can be effected at maximum
f32 effect_duration;
// Aura
f32 aura_range;
// Push/pull
byte push_pull_distance;
byte push_pull_direction; // circle, pov = fan like; > 0 = push, < 0 = pull
byte player_visibility; // = e.g. sneak skill
// @todo skill jumps over to close by enemies = chain lightning
// @todo illusion skill that multiplies the targeted mob and also shuffels the position
// move_distances (e.g. launch attack propells attacker forward x distance)
byte movement_distances;
};
#endif

View File

@ -0,0 +1,7 @@
enum SkillLocation {
SKILL_LOCATION_NONE,
SKILL_LOCATION_CAST_POINT,
SKILL_LOCATION_TARGET_POINT,
SKILL_LOCATION_BETWEEN_CAST_TARGET
};

View File

@ -0,0 +1,18 @@
#ifndef TOS_MODELS_SKILL_STATS_TARGET_H
#define TOS_MODELS_SKILL_STATS_TARGET_H
enum StatsTarget {
STATS_TARGET_NONE,
STATS_TARGET_SELF,
STATS_TARGET_ENEMY,
STATS_TARGET_ENEMY_AOE,
STATS_TARGET_ENEMY_AURA,
STATS_TARGET_ALLY,
STATS_TARGET_ALLY_AOE,
STATS_TARGET_ALLY_AURA
};
#endif

View File

@ -0,0 +1,4 @@
# Revive slain enemies
# Requires sub skill to re-summon if they die
# Requires sub option to pick who to revive
# Requires sub option to pick who should be released if already full

View File

View File

@ -0,0 +1,2 @@
# Chain enemy to the ground using actual chains
# @todo Consider multiple chains = chained in places OR one chain to player = some movement around center allowed

View File

@ -0,0 +1 @@
# Lightning attack that jumps from target to target

View File

@ -0,0 +1,3 @@
# Cyclone with random movement
# Can be split into multiple cyclones that move randomely
# Can be modified to different elemental types

View File

View File

@ -0,0 +1 @@
# Turns person invisible while walking/running

View File

View File

View File

@ -0,0 +1,2 @@
# Drops a meteor to the ground
# Can have different elemental attributes (fire = burning meteor, default = earth)

View File

@ -0,0 +1 @@
# creates illusions

View File

@ -0,0 +1,2 @@
# Holds person in place
# Can have elemental damage = burning net etc.

View File

View File

View File

View File

@ -0,0 +1,2 @@
# Reflects damage
# either one attack, attack during short window, attack long window

View File

@ -0,0 +1 @@
# Revive player

View File

View File

@ -0,0 +1 @@
# Elemental shield

View File

@ -0,0 +1,2 @@
# Spikes coming from the ground
# different elements change looks of spikes

View File

View File

View File

@ -0,0 +1,2 @@
# Summon monster
# Requires sub option for selecting mob

View File

View File

@ -0,0 +1 @@
# turns a single attack into a split shot

View File

@ -10,47 +10,87 @@
#define TOS_MODELS_SETTINGS_H #define TOS_MODELS_SETTINGS_H
#include "../../stdlib/Types.h" #include "../../stdlib/Types.h"
#include "../chat/ChatStatus.h" #include "../chat/ChatStatus.h"
#include "setting_types.h" #include "setting_types.h"
#if SERVER #if __linux__
struct SSettings { #include <linux/limits.h>
byte distance_terrain = RENDER_CHUNK_RADIUS; #define MAX_PATH PATH_MAX
byte distance_terrain_secondary = RENDER_BLOCK_OBJECT_CHUNK_RADIUS;
byte distance_terrain_tertiary = RENDER_INTERACTIVE_CHUNK_RADIUS;
byte distance_models = RENDER_OBJECT_CHUNK_RADIUS;
byte distance_monster = RENDER_MONSTER_CHUNK_RADIUS;
byte distance_npc = RENDER_NPC_CHUNK_RADIUS;
byte distance_player = RENDER_PAYER_CHUNK_RADIUS;
uint32 player_cache = 8192; // = max active players on a server
uint32 monster_cache = 8192;
uint32 npc_cache = 8192;
uint32 guild_cache = 128;
uint32 message_cache = 1024;
uint32 interpolation_buffer;
byte simd_version;
};
// Player settings that the server needs to know about
struct PSettings {
byte render_distance_models = RENDER_OBJECT_CHUNK_RADIUS;
byte render_distance_monster = RENDER_MONSTER_CHUNK_RADIUS;
byte render_distance_npc = RENDER_NPC_CHUNK_RADIUS;
byte render_distance_player = RENDER_PAYER_CHUNK_RADIUS;
byte chat_status = CHAT_STATUS_OFFLINE;
bool allow_invites = true;
};
#endif #endif
#ifndef RENDER_CHUNK_RADIUS
#define RENDER_CHUNK_RADIUS 10
#endif
#ifndef RENDER_BLOCK_OBJECT_CHUNK_RADIUS
#define RENDER_BLOCK_OBJECT_CHUNK_RADIUS 10
#endif
#ifndef RENDER_INTERACTIVE_CHUNK_RADIUS
#define RENDER_INTERACTIVE_CHUNK_RADIUS 1
#endif
#ifndef RENDER_OBJECT_CHUNK_RADIUS
#define RENDER_OBJECT_CHUNK_RADIUS 1
#endif
#ifndef RENDER_MONSTER_CHUNK_RADIUS
#define RENDER_MONSTER_CHUNK_RADIUS 3
#endif
#ifndef RENDER_NPC_CHUNK_RADIUS
#define RENDER_NPC_CHUNK_RADIUS 3
#endif
#ifndef RENDER_PAYER_CHUNK_RADIUS
#define RENDER_PAYER_CHUNK_RADIUS 3
#endif
// @todo remove default values because we will load them during startup
struct SSettings {
char path[MAX_PATH];
bool is_changed = false;
byte simd_version;
char network_hostname[64];
uint16 network_port;
byte distance_terrain = RENDER_CHUNK_RADIUS;
byte distance_terrain_secondary = RENDER_BLOCK_OBJECT_CHUNK_RADIUS;
byte distance_terrain_tertiary = RENDER_INTERACTIVE_CHUNK_RADIUS;
byte distance_models = RENDER_OBJECT_CHUNK_RADIUS;
byte distance_monster = RENDER_MONSTER_CHUNK_RADIUS;
byte distance_npc = RENDER_NPC_CHUNK_RADIUS;
byte distance_player = RENDER_PAYER_CHUNK_RADIUS;
uint32 player_cache = 8192; // = max active players on a server
uint32 monster_cache = 8192;
uint32 npc_cache = 8192;
uint32 guild_cache = 128;
uint32 message_cache = 1024;
uint32 interpolation_buffer;
};
// Player settings that the server needs to know about
struct PSettings {
byte render_distance_models = RENDER_OBJECT_CHUNK_RADIUS;
byte render_distance_monster = RENDER_MONSTER_CHUNK_RADIUS;
byte render_distance_npc = RENDER_NPC_CHUNK_RADIUS;
byte render_distance_player = RENDER_PAYER_CHUNK_RADIUS;
byte chat_status = CHAT_STATUS_OFFLINE;
bool allow_invites = true;
};
struct CSettings { struct CSettings {
char path[MAX_PATH]; char path[MAX_PATH];
bool is_changed = false; bool is_changed = false;
byte simd_version; byte simd_version;
char network_hostname[64];
uint16 network_port;
byte gpu_api = SETTING_TYPE_GPU_API_NONE; byte gpu_api = SETTING_TYPE_GPU_API_NONE;
byte gpu_type = SETTING_TYPE_GPU_MEDIUM; byte gpu_type = SETTING_TYPE_GPU_MEDIUM;
byte gpu_fps = SETTING_TYPE_UNLIMITED; byte gpu_fps = SETTING_TYPE_UNLIMITED;
@ -63,9 +103,6 @@ struct CSettings {
byte gpu_fov; byte gpu_fov;
byte gpu_sync = SETTING_TYPE_DISABLED; byte gpu_sync = SETTING_TYPE_DISABLED;
char editor_hostname[64];
uint16 editor_port;
uint32 gpu_number_of_npc_characters = 128; uint32 gpu_number_of_npc_characters = 128;
uint32 gpu_number_of_player_characters = 512; uint32 gpu_number_of_player_characters = 512;
uint32 gpu_number_of_monster_characters = 128; uint32 gpu_number_of_monster_characters = 128;
@ -113,6 +150,10 @@ struct CSettings {
bool gpu_particles_skills = true; bool gpu_particles_skills = true;
bool gpu_particles_weapons = true; bool gpu_particles_weapons = true;
byte gpu_shadow_type = SETTING_TYPE_DISABLED; // none, baked, shadow mapping, point shadow, ray tracing
byte gpu_light_ssao = SETTING_TYPE_DISABLED;
byte gpu_light_bloom = SETTING_TYPE_DISABLED;
byte gpu_reflection_blur = SETTING_TYPE_DISABLED; byte gpu_reflection_blur = SETTING_TYPE_DISABLED;
byte gpu_motion_blur = SETTING_TYPE_DISABLED; byte gpu_motion_blur = SETTING_TYPE_DISABLED;
byte gpu_blur = SETTING_TYPE_DISABLED; byte gpu_blur = SETTING_TYPE_DISABLED;
@ -120,6 +161,10 @@ struct CSettings {
byte gpu_sharpening = SETTING_TYPE_DISABLED; byte gpu_sharpening = SETTING_TYPE_DISABLED;
byte gpu_ambient_occlusion = SETTING_TYPE_DISABLED; byte gpu_ambient_occlusion = SETTING_TYPE_DISABLED;
bool gpu_gamma_correction = true;
bool gpu_normal_mapping = true;
bool gpu_parallax_mapping = true;
bool gpu_depth_of_field = true; bool gpu_depth_of_field = true;
bool gpu_chromatic_aberration = true; bool gpu_chromatic_aberration = true;
bool gpu_vignetting = true; bool gpu_vignetting = true;
@ -299,6 +344,7 @@ struct CSettings {
bool input_click_to_move = true; bool input_click_to_move = true;
// Hotkey settings // Hotkey settings
// @todo hotkey combination e.g. alt+1
byte hotkeys_movement_up = 0x57; // W byte hotkeys_movement_up = 0x57; // W
byte hotkeys_movement_down = 0x53; // S byte hotkeys_movement_down = 0x53; // S
byte hotkeys_movement_left = 0x41; // A byte hotkeys_movement_left = 0x41; // A
@ -354,6 +400,12 @@ struct CSettings {
byte hotkeys_menu = 0x1B; // ESC byte hotkeys_menu = 0x1B; // ESC
byte hotkeys_window_close = 0x1B; // ESC byte hotkeys_window_close = 0x1B; // ESC
byte hotkeys_marker_1 = 0x31; // 1
byte hotkeys_marker_2 = 0x32; // 2
byte hotkeys_marker_3 = 0x33; // 3
byte hotkeys_marker_4 = 0x34; // 4
byte hotkeys_marker_5 = 0x35; // 5
}; };
#endif #endif

View File

@ -20,19 +20,19 @@
#if _WIN32 #if _WIN32
#include <winsock2.h> #include <winsock2.h>
#include <windows.h> #include <windows.h>
#define close closesocket
#define sleep Sleep
#else #else
#include <netdb.h> #include <netdb.h>
#include <unistd.h> #include <unistd.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#endif #endif
#include "NetworkOSWrapper.h"
#ifndef MAX_STATIC_NETWORK_PACKET_SIZE #ifndef MAX_STATIC_NETWORK_PACKET_SIZE
#define MAX_STATIC_NETWORK_PACKET_SIZE 8192 #define MAX_STATIC_NETWORK_PACKET_SIZE 8192
#endif #endif
SOCKET socket_client_udb_connect(const char *hostname, int port, sockaddr_in6 *server_addr) { void socket_client_udb_connect(const char *hostname, SocketConnection* con) {
addrinfo hints, *res, *p; addrinfo hints, *res, *p;
memset(&hints, 0, sizeof(hints)); memset(&hints, 0, sizeof(hints));
@ -40,29 +40,22 @@ SOCKET socket_client_udb_connect(const char *hostname, int port, sockaddr_in6 *s
hints.ai_socktype = SOCK_DGRAM; hints.ai_socktype = SOCK_DGRAM;
char port_str[6]; char port_str[6];
snprintf(port_str, sizeof(port_str), "%d", port); snprintf(port_str, sizeof(port_str), "%d", con->port);
if (getaddrinfo(hostname, port_str, &hints, &res) != 0) { if (getaddrinfo(hostname, port_str, &hints, &res) != 0) {
return NULL; return;
} }
SOCKET sd = NULL;
for (p = res; p != NULL; p = p->ai_next) { for (p = res; p != NULL; p = p->ai_next) {
if ((sd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { if ((con->sd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
continue; continue;
} }
memcpy(server_addr, p->ai_addr, p->ai_addrlen); memcpy((void *) &con->server_addr, p->ai_addr, p->ai_addrlen);
break; break;
} }
freeaddrinfo(res); freeaddrinfo(res);
if (p == NULL) {
return NULL;
}
return sd;
} }
int socket_client_send(SOCKET sd, char *data, size_t length, sockaddr_in6 *server_addr, socklen_t addr_len) { int socket_client_send(SOCKET sd, char *data, size_t length, sockaddr_in6 *server_addr, socklen_t addr_len) {

View File

@ -0,0 +1,19 @@
/**
* Jingga
*
* @copyright Jingga
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
#ifndef TOS_NETWORK_OS_WRAPPER_H
#define TOS_NETWORK_OS_WRAPPER_H
#if _WIN32
#include <winsock2.h>
#include <windows.h>
#define close closesocket
#define sleep Sleep
#endif
#endif

View File

@ -6,3 +6,51 @@
* @version 1.0.0 * @version 1.0.0
* @link https://jingga.app * @link https://jingga.app
*/ */
#ifndef TOS_NETWORK_SERVER_H
#define TOS_NETWORK_SERVER_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if _WIN32
#include <winsock2.h>
#include <windows.h>
#else
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <errno.h>
#endif
#include "NetworkOSWrapper.h"
#include "SocketConnection.h"
void socket_server_udb_create(const char *hostname, SocketConnection* con) {
con->sd = socket(AF_INET6, SOCK_DGRAM, 0);
int flags;
if ((flags = fcntl(con->sd, F_GETFL, 0)) < 0) {
close(con->sd);
con->sd = 0;
}
if (fcntl(con->sd, F_SETFL, flags | O_NONBLOCK) < 0) {
close(con->sd);
con->sd = 0;
}
con->server_addr.sin6_family = AF_INET6;
con->server_addr.sin6_addr = in6addr_any;
con->server_addr.sin6_port = htons(con->port);
if (bind(con->sd, (sockaddr *) &con->server_addr, sizeof(sockaddr_in6)) < 0) {
close(con->sd);
con->sd = 0;
}
}
#endif

View File

@ -9,6 +9,8 @@
#ifndef TOS_NETWORK_SOCKET_CONNECTION_H #ifndef TOS_NETWORK_SOCKET_CONNECTION_H
#define TOS_NETWORK_SOCKET_CONNECTION_H #define TOS_NETWORK_SOCKET_CONNECTION_H
#include "../stdlib/Types.h"
#if _WIN32 #if _WIN32
#include <winsock2.h> #include <winsock2.h>
#include <ws2tcpip.h> #include <ws2tcpip.h>
@ -19,9 +21,15 @@
#endif #endif
struct SocketConnection { struct SocketConnection {
SOCKET sd; #if _WIN32
SOCKET sd;
#else
int sd;
#endif
sockaddr_in6 server_addr; sockaddr_in6 server_addr;
socklen_t addr_len; socklen_t addr_len;
uint16 port;
}; };
#endif #endif

View File

@ -0,0 +1,136 @@
/**
* Jingga
*
* @copyright Jingga
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
#ifndef TOS_NETWORK_PACKET_CACHE_H
#define TOS_NETWORK_PACKET_CACHE_H
#include "../../utils/RingMemory.h"
#include "../../utils/BufferMemory.h"
#if _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#endif
struct PacketCache {
sockaddr_in6 addr;
int last_received;
int last_sent;
RingMemory packets_received;
RingMemory packets_sent;
int packets_received_ack[64];
int packets_sent_ack[64];
};
struct PacketCacheHashEntry {
in6_addr* key;
PacketCache* value;
PacketCacheHashEntry* next;
};
struct PacketCacheHashTable {
uint32 size;
PacketCacheHashEntry** entries;
// BufferMemory for PacketCacheHashEntry NOT PacketCache
BufferMemory buf;
};
uint32 hash_ipv6_address(uint32 hashmap_size, sockaddr_in6 *addr) {
uint32 hash_val = addr->sin6_addr;
hash_val = ((hash_val >> 16) ^ hash_val) * 0x45d9f3b;
hash_val = ((hash_val >> 16) ^ hash_val) * 0x45d9f3b;
hash_val = (hash_val >> 16) ^ hash_val;
return hash_val % hashmap_size;
}
PacketCache* hash_packet_cache_get(PacketCacheHashTable* ht, sockaddr_in6* addr) {
uint32 index = hash_ipv6_address(ht->size, addr);
PacketCacheHashEntry* entry;
if (!(entry = ht->entries[index])) {
return NULL;
}
bool no_match;
while ((no_match = (memcmp(&addr->sin6_addr, entry->key, sizeof(in6_addr)) != 0))
&& entry->next != NULL
) {
entry = entry->next;
}
if (no_match) {
return NULL;
}
return entry->value;
}
PacketCacheHashEntry* hash_packet_cache_insert(PacketCacheHashTable* ht, sockaddr_in6* addr, PacketCache* value) {
uint32 index = hash_ipv6_address(ht->size, addr);
PacketCacheHashEntry* element = (PacketCacheHashEntry *) buffer_find_free(&ht->buf);
element->key = &value->addr.sin6_addr;
element->value = value;
element->next = NULL;
PacketCacheHashEntry* entry = ht->entries[index];
if (entry == NULL) {
ht->entries[index] = element;
return element;
}
while (entry->next != NULL) {
entry = entry->next;
}
entry->next = element;
return element;
}
void hash_packet_cache_remove(PacketCacheHashTable* ht, sockaddr_in6* addr) {
uint32 index = hash_ipv6_address(ht->size, addr);
PacketCacheHashEntry* entry;
if (!(entry = ht->entries[index])) {
return;
}
PacketCacheHashEntry* prev = NULL;
bool no_match = false;
while (entry && (no_match = (memcmp(&addr->sin6_addr, entry->key, sizeof(in6_addr)) != 0))) {
prev = entry;
entry = entry->next;
}
if (no_match) {
return;
}
if (!prev) {
ht->entries[index] = NULL;
return;
}
prev->next = NULL;
}
#endif

View File

@ -12,23 +12,36 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <time.h> #include <time.h>
#include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include <linux/limits.h>
#include "../../stdlib/Types.h" #include "../../stdlib/Types.h"
#include "../../utils/Utils.h" #include "../../utils/Utils.h"
#include "../../utils/TestUtils.h" #include "../../utils/TestUtils.h"
inline uint64 last_modification(const char* filename) inline
uint64 file_size(const char* filename) {
struct stat st;
if (stat(filename, &st) != 0) {
return 0;
}
return st.st_size;
}
inline
uint64 last_modified(const char* filename)
{ {
struct stat buffer; struct stat buffer;
stat(filename, &buffer); stat(filename, &buffer);
return (uint64) buffer.st_mtime.tv_sec; return (uint64) buffer.st_mtime;
} }
inline void inline
file_read(const char* filename, file_body* file) void file_read(const char* filename, file_body* file)
{ {
FILE *fp = fopen(filename, "rb"); FILE *fp = fopen(filename, "rb");
fseek(fp, 0, SEEK_END); fseek(fp, 0, SEEK_END);
@ -41,6 +54,131 @@ file_read(const char* filename, file_body* file)
fclose(fp); fclose(fp);
} }
inline
uint64_t file_read_struct(const char* filename, void* file, uint32 size) {
FILE *fp = fopen(filename, "rb");
if (!fp) {
return 0;
}
fseek(fp, 0, SEEK_END);
long fsize = ftell(fp);
fseek(fp, 0, SEEK_SET);
ASSERT_SIMPLE(fsize > size);
size_t read_bytes = fread(file, 1, size, fp);
fclose(fp);
return read_bytes;
}
inline
bool file_write(const char* filename, const file_body* file) {
FILE *fp = fopen(filename, "wb");
if (!fp) {
return false;
}
size_t written = fwrite(file->content, 1, file->size, fp);
fclose(fp);
return written == file->size;
}
inline
bool file_write_struct(const char* filename, const void* file, uint32_t size) {
FILE *fp = fopen(filename, "wb");
if (!fp) {
return false;
}
size_t written = fwrite(file, 1, size, fp);
fclose(fp);
return written == size;
}
inline
void file_copy(const char* src, const char* dst) {
FILE *src_fp = fopen(src, "rb");
FILE *dst_fp = fopen(dst, "wb");
if (!src_fp || !dst_fp) {
if (src_fp) fclose(src_fp);
if (dst_fp) fclose(dst_fp);
return;
}
char buffer[4096];
size_t bytes;
while ((bytes = fread(buffer, 1, sizeof(buffer), src_fp)) > 0) {
fwrite(buffer, 1, bytes, dst_fp);
}
fclose(src_fp);
fclose(dst_fp);
}
inline
FILE* get_append_handle(const char* filename) {
FILE *fp = fopen(filename, "ab");
if (!fp) {
return NULL;
}
return fp;
}
inline bool file_append(const char* filename, const char* file) {
FILE *fp = get_append_handle(filename);
if (!fp) {
return false;
}
size_t length = strlen(file);
ASSERT_SIMPLE(length < INT32_MAX);
size_t written = fwrite(file, 1, length, fp);
fclose(fp);
return written == length;
}
inline bool file_append(FILE* fp, const char* file) {
if (!fp) {
return false;
}
size_t length = strlen(file);
ASSERT_SIMPLE(length < INT32_MAX);
size_t written = fwrite(file, 1, length, fp);
fclose(fp);
return written == length;
}
inline bool file_append(const char* filename, const file_body* file) {
FILE *fp = get_append_handle(filename);
if (!fp) {
return false;
}
size_t length = file->size;
ASSERT_SIMPLE(length < INT32_MAX);
size_t written = fwrite(file->content, 1, length, fp);
fclose(fp);
return written == length;
}
inline
void self_path(char* path) {
size_t len = readlink("/proc/self/exe", path, PATH_MAX);
if (len > 0) {
path[len] = '\0';
} else {
path[0] = '\0';
}
}
inline inline
void strncpy_s(char *dest, size_t destsz, const char *src, size_t count) { void strncpy_s(char *dest, size_t destsz, const char *src, size_t count) {
size_t i; size_t i;

View File

@ -271,7 +271,8 @@ file_append(const char* filename, const file_body* file)
return true; return true;
} }
inline uint64 last_modified(const char* filename) inline
uint64 last_modified(const char* filename)
{ {
FILETIME modified = {}; FILETIME modified = {};

View File

@ -108,7 +108,7 @@ void audio_play(AudioSetting* setting, DirectSoundSetting* api_setting)
} }
inline inline
void audio_free(AudioSetting* setting, DirectSoundSetting* api_setting) void audio_free(AudioSetting*, DirectSoundSetting* api_setting)
{ {
if (api_setting->direct_sound) { if (api_setting->direct_sound) {
api_setting->direct_sound->Release(); api_setting->direct_sound->Release();

View File

@ -13,7 +13,7 @@
#include <inttypes.h> #include <inttypes.h>
#include <xmmintrin.h> #include <xmmintrin.h>
#ifdef _LINUX #if __linux__
#include <x86intrin.h> #include <x86intrin.h>
#endif #endif

View File

@ -118,14 +118,17 @@ struct v3_f32 {
union { union {
f32 x; f32 x;
f32 r; f32 r;
f32 pitch;
}; };
union { union {
f32 y; f32 y;
f32 g; f32 g;
f32 yaw;
}; };
union { union {
f32 z; f32 z;
f32 b; f32 b;
f32 roll;
}; };
}; };

View File

@ -80,8 +80,6 @@ uint16 float_to_f16(float f) {
} }
float f16_to_float(f16 f) { float f16_to_float(f16 f) {
uint32_t f_bits = 0;
uint32_t sign = (f & HALF_FLOAT_SIGN_MASK) << 16; uint32_t sign = (f & HALF_FLOAT_SIGN_MASK) << 16;
int32_t exponent = (f & HALF_FLOAT_EXP_MASK) >> HALF_FLOAT_EXP_SHIFT; int32_t exponent = (f & HALF_FLOAT_EXP_MASK) >> HALF_FLOAT_EXP_SHIFT;
uint32_t fraction = (f & HALF_FLOAT_FRAC_MASK) << (FLOAT32_EXP_SHIFT - HALF_FLOAT_EXP_SHIFT); uint32_t fraction = (f & HALF_FLOAT_FRAC_MASK) << (FLOAT32_EXP_SHIFT - HALF_FLOAT_EXP_SHIFT);
@ -101,9 +99,9 @@ float f16_to_float(f16 f) {
exponent += FLOAT32_EXP_BIAS - HALF_FLOAT_EXP_BIAS; exponent += FLOAT32_EXP_BIAS - HALF_FLOAT_EXP_BIAS;
} }
f_bits = sign | (exponent << FLOAT32_EXP_SHIFT) | fraction; uint32_t f_bits = sign | (exponent << FLOAT32_EXP_SHIFT) | fraction;
return *((float*)&f_bits); return *((float *) &f_bits);
} }
#endif #endif

View File

@ -43,168 +43,4 @@ void thread_stop(Worker* worker)
} }
} }
ThreadJob *thread_pool_work_poll(ThreadPool *pool)
{
if (pool == NULL) {
return NULL;
}
ThreadJob *work = pool->work_first;
if (work == NULL) {
return NULL;
}
if (work->next == NULL) {
pool->work_first = NULL;
pool->work_last = NULL;
} else {
pool->work_first = work->next;
}
return work;
}
#ifdef _WIN32
static DWORD WINAPI thread_pool_worker(void* arg)
#else
static void* thread_pool_worker(void *arg)
#endif
{
ThreadPool *pool = (ThreadPool *) arg;
ThreadJob *work;
while (true) {
pthread_mutex_lock(&pool->work_mutex);
while (pool->work_first == NULL && !pool->stop) {
pthread_cond_wait(&pool->work_cond, &pool->work_mutex);
}
if (pool->stop) {
break;
}
work = thread_pool_work_poll(pool);
++(pool->working_cnt);
pthread_mutex_unlock(&pool->work_mutex);
if (work != NULL) {
work->func(work);
}
pthread_mutex_lock(&pool->work_mutex);
--(pool->working_cnt);
if (!pool->stop && pool->working_cnt == 0 && pool->work_first == NULL) {
pthread_cond_signal(&pool->working_cond);
}
pthread_mutex_unlock(&pool->work_mutex);
}
--(pool->thread_cnt);
pthread_cond_signal(&pool->working_cond);
pthread_mutex_unlock(&pool->work_mutex);
return NULL;
}
ThreadPool *thread_pool_create(size_t num, ThreadPool* pool)
{
pthread_t thread;
size_t i;
if (num == 0) {
num = 2;
}
pool->thread_cnt = num;
// @todo switch from pool mutex and pool cond to threadjob mutex/cond
// thread_pool_wait etc. should just itereate over all mutexes
pthread_mutex_init(&pool->work_mutex, NULL);
pthread_cond_init(&pool->work_cond, NULL);
pthread_cond_init(&pool->working_cond, NULL);
pool->work_first = NULL;
pool->work_last = NULL;
for (i = 0; i < num; i++) {
pthread_create(&thread, NULL, thread_pool_worker, pool);
++(pool->size);
pthread_detach(thread);
}
return pool;
}
void thread_pool_wait(ThreadPool *pool)
{
if (pool == NULL) {
return;
}
pthread_mutex_lock(&pool->work_mutex);
while (true) {
if ((!pool->stop && pool->working_cnt != 0) || (pool->stop && pool->thread_cnt != 0)) {
pthread_cond_wait(&pool->working_cond, &pool->work_mutex);
} else {
break;
}
}
pthread_mutex_unlock(&pool->work_mutex);
}
void thread_pool_destroy(ThreadPool *pool)
{
if (pool == NULL) {
return;
}
pthread_mutex_lock(&pool->work_mutex);
ThreadJob *work = pool->work_first;
while (work != NULL) {
work = work->next;
}
pool->stop = true;
pthread_cond_broadcast(&pool->work_cond);
pthread_mutex_unlock(&pool->work_mutex);
thread_pool_wait(pool);
pthread_mutex_destroy(&pool->work_mutex);
pthread_cond_destroy(&pool->work_cond);
pthread_cond_destroy(&pool->working_cond);
}
ThreadJob* thread_pool_add_work(ThreadPool *pool, ThreadJob* job)
{
if (pool == NULL) {
return NULL;
}
if (job == NULL) {
return NULL;
}
pthread_mutex_lock(&pool->work_mutex);
if (pool->work_first == NULL) {
pool->work_first = job;
pool->work_last = pool->work_first;
} else {
pool->work_last->next = job;
pool->work_last = job;
}
pthread_cond_broadcast(&pool->work_cond);
pthread_mutex_unlock(&pool->work_mutex);
return job;
}
#endif #endif

View File

@ -12,15 +12,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#ifdef _WIN32 #include "ThreadOSDefines.h"
#include <windows.h>
typedef DWORD (WINAPI *ThreadJobFunc)(void*);
#else
typedef void (*ThreadJobFunc)(void*);
#endif
#include "ThreadOSWrapper.h"
struct job_t { struct job_t {
ThreadJobFunc func; ThreadJobFunc func;

33
thread/ThreadOSDefines.h Normal file
View File

@ -0,0 +1,33 @@
/**
* Jingga
*
* @copyright Jingga
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
#ifndef TOS_THREADS_OS_DEFINES_H
#define TOS_THREADS_OS_DEFINES_H
#if _WIN32
#include <windows.h>
typedef DWORD (WINAPI *ThreadJobFunc)(void*);
typedef CRITICAL_SECTION pthread_mutex_t;
typedef void pthread_mutexattr_t;
typedef void pthread_condattr_t;
typedef void pthread_rwlockattr_t;
typedef HANDLE pthread_t;
typedef CONDITION_VARIABLE pthread_cond_t;
struct pthread_rwlock_t {
SRWLOCK lock;
bool exclusive;
};
#else
#include <pthread.h>
#include <unistd.h>
typedef void * (*ThreadJobFunc)(void*);
#endif
#endif

View File

@ -9,12 +9,13 @@
#ifndef TOS_THREADS_OS_WRAPPER_H #ifndef TOS_THREADS_OS_WRAPPER_H
#define TOS_THREADS_OS_WRAPPER_H #define TOS_THREADS_OS_WRAPPER_H
#include <time.h>
#include "../stdlib/Types.h" #include "../stdlib/Types.h"
#include "ThreadOSDefines.h"
#ifdef _WIN32 #ifdef _WIN32
#include <stdbool.h>
#include <windows.h> #include <windows.h>
#include <time.h>
#else #else
#include <pthread.h> #include <pthread.h>
#include <unistd.h> #include <unistd.h>
@ -33,18 +34,6 @@ void ms_to_timespec(timespec *ts, uint32 ms)
} }
#ifdef _WIN32 #ifdef _WIN32
typedef CRITICAL_SECTION pthread_mutex_t;
typedef void pthread_mutexattr_t;
typedef void pthread_condattr_t;
typedef void pthread_rwlockattr_t;
typedef HANDLE pthread_t;
typedef CONDITION_VARIABLE pthread_cond_t;
struct pthread_rwlock_t {
SRWLOCK lock;
bool exclusive;
};
int pthread_create(pthread_t* thread, void*, ThreadJobFunc start_routine, void* arg) int pthread_create(pthread_t* thread, void*, ThreadJobFunc start_routine, void* arg)
{ {
if (thread == NULL || start_routine == NULL) { if (thread == NULL || start_routine == NULL) {
@ -59,7 +48,7 @@ void ms_to_timespec(timespec *ts, uint32 ms)
return 0; return 0;
} }
int pthread_join(pthread_t thread, void** value_ptr) int pthread_join(pthread_t thread, void**)
{ {
WaitForSingleObject(thread, INFINITE); WaitForSingleObject(thread, INFINITE);
CloseHandle(thread); CloseHandle(thread);
@ -202,7 +191,7 @@ void ms_to_timespec(timespec *ts, uint32 ms)
return 0; return 0;
} }
int pthread_rwlock_destroy(pthread_rwlock_t* rwlock) int pthread_rwlock_destroy(pthread_rwlock_t*)
{ {
return 0; return 0;
} }

View File

@ -23,7 +23,7 @@
#include "ThreadJob.h" #include "ThreadJob.h"
#include "ThreadOSWrapper.h" #include "ThreadOSWrapper.h"
typedef struct { struct ThreadPool {
ThreadJob *work_first; ThreadJob *work_first;
ThreadJob *work_last; ThreadJob *work_last;
@ -36,6 +36,170 @@ typedef struct {
int32 size; int32 size;
bool stop; bool stop;
} ThreadPool; };
ThreadJob *thread_pool_work_poll(ThreadPool *pool)
{
if (pool == NULL) {
return NULL;
}
ThreadJob *work = pool->work_first;
if (work == NULL) {
return NULL;
}
if (work->next == NULL) {
pool->work_first = NULL;
pool->work_last = NULL;
} else {
pool->work_first = work->next;
}
return work;
}
#ifdef _WIN32
static DWORD WINAPI thread_pool_worker(void* arg)
#else
static void* thread_pool_worker(void *arg)
#endif
{
ThreadPool *pool = (ThreadPool *) arg;
ThreadJob *work;
while (true) {
pthread_mutex_lock(&pool->work_mutex);
while (pool->work_first == NULL && !pool->stop) {
pthread_cond_wait(&pool->work_cond, &pool->work_mutex);
}
if (pool->stop) {
break;
}
work = thread_pool_work_poll(pool);
++(pool->working_cnt);
pthread_mutex_unlock(&pool->work_mutex);
if (work != NULL) {
work->func(work);
}
pthread_mutex_lock(&pool->work_mutex);
--(pool->working_cnt);
if (!pool->stop && pool->working_cnt == 0 && pool->work_first == NULL) {
pthread_cond_signal(&pool->working_cond);
}
pthread_mutex_unlock(&pool->work_mutex);
}
--(pool->thread_cnt);
pthread_cond_signal(&pool->working_cond);
pthread_mutex_unlock(&pool->work_mutex);
return NULL;
}
ThreadPool *thread_pool_create(size_t num, ThreadPool* pool)
{
pthread_t thread;
size_t i;
if (num == 0) {
num = 2;
}
pool->thread_cnt = num;
// @todo switch from pool mutex and pool cond to threadjob mutex/cond
// thread_pool_wait etc. should just itereate over all mutexes
pthread_mutex_init(&pool->work_mutex, NULL);
pthread_cond_init(&pool->work_cond, NULL);
pthread_cond_init(&pool->working_cond, NULL);
pool->work_first = NULL;
pool->work_last = NULL;
for (i = 0; i < num; i++) {
pthread_create(&thread, NULL, thread_pool_worker, pool);
++(pool->size);
pthread_detach(thread);
}
return pool;
}
void thread_pool_wait(ThreadPool *pool)
{
if (pool == NULL) {
return;
}
pthread_mutex_lock(&pool->work_mutex);
while (true) {
if ((!pool->stop && pool->working_cnt != 0) || (pool->stop && pool->thread_cnt != 0)) {
pthread_cond_wait(&pool->working_cond, &pool->work_mutex);
} else {
break;
}
}
pthread_mutex_unlock(&pool->work_mutex);
}
void thread_pool_destroy(ThreadPool *pool)
{
if (pool == NULL) {
return;
}
pthread_mutex_lock(&pool->work_mutex);
ThreadJob *work = pool->work_first;
while (work != NULL) {
work = work->next;
}
pool->stop = true;
pthread_cond_broadcast(&pool->work_cond);
pthread_mutex_unlock(&pool->work_mutex);
thread_pool_wait(pool);
pthread_mutex_destroy(&pool->work_mutex);
pthread_cond_destroy(&pool->work_cond);
pthread_cond_destroy(&pool->working_cond);
}
ThreadJob* thread_pool_add_work(ThreadPool *pool, ThreadJob* job)
{
if (pool == NULL) {
return NULL;
}
if (job == NULL) {
return NULL;
}
pthread_mutex_lock(&pool->work_mutex);
if (pool->work_first == NULL) {
pool->work_first = job;
pool->work_last = pool->work_first;
} else {
pool->work_last->next = job;
pool->work_last = job;
}
pthread_cond_broadcast(&pool->work_cond);
pthread_mutex_unlock(&pool->work_mutex);
return job;
}
#endif #endif

View File

@ -11,6 +11,7 @@
#include "../stdlib/Types.h" #include "../stdlib/Types.h"
inline
uint32 bytes_merge(byte b0, byte b1, byte b2, byte b3) { uint32 bytes_merge(byte b0, byte b1, byte b2, byte b3) {
uint32 result = 0; uint32 result = 0;
@ -22,6 +23,7 @@ uint32 bytes_merge(byte b0, byte b1, byte b2, byte b3) {
return result; return result;
} }
inline
uint64 bytes_merge( uint64 bytes_merge(
byte b0, byte b1, byte b2, byte b3, byte b0, byte b1, byte b2, byte b3,
byte b4, byte b5, byte b6, byte b7 byte b4, byte b5, byte b6, byte b7

125
utils/BufferMemory.h Normal file
View File

@ -0,0 +1,125 @@
/**
* Jingga
*
* @copyright Jingga
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
#ifndef TOS_UTILS_BUFFER_MEMORY_H
#define TOS_UTILS_BUFFER_MEMORY_H
#include "../stdlib/Types.h"
#include "MathUtils.h"
struct BufferMemory {
byte* memory;
uint64 count;
uint64 element_size;
uint64 last_pos = -1;
// length = count
// free describes which locations are used and which are free
// @performance using uint32 or even uint64 might be faster
// since we can check for free elements faster if the memory is almost filled
// at the moment we can only check 8 elements at a time
byte* free;
};
inline
byte* buffer_element_get(BufferMemory* buf, uint64 element)
{
return buf->memory + element * buf->element_size;
}
int64 buffer_reserve(BufferMemory* buf)
{
int byte_index = (buf->last_pos + 1) / 8;
int bit_index;
int64 free_element = -1;
byte mask;
int i = 0;
int max_loop = buf->count * buf->element_size;
while (free_element < 0 && i < max_loop) {
if (buf->free[byte_index] == 0xFF) {
++i;
++byte_index;
continue;
}
// This always breaks!
// @performance on the first iteration through the buffer we could optimize this by starting at a different bit_index
// because we know that the bit_index is based on last_pos
for (bit_index = 0; bit_index < 8; ++bit_index) {
mask = 1 << bit_index;
if ((buf->free[byte_index] & mask) == 0) {
free_element = byte_index * 8 + bit_index;
break;
}
}
}
if (free_element < 0) {
return -1;
}
buf->free[byte_index] |= (1 << bit_index);
return byte_index * 8 + bit_index;
}
byte* buffer_find_free(BufferMemory* buf, bool zeroed = false)
{
int byte_index = (buf->last_pos + 1) / 8;
int bit_index;
int64 free_element = -1;
byte mask;
int i = 0;
int max_loop = buf->count * buf->element_size;
while (free_element < 0 && i < max_loop) {
if (buf->free[byte_index] == 0xFF) {
++i;
++byte_index;
continue;
}
// This always breaks!
// @performance on the first iteration through the buffer we could optimize this by starting at a different bit_index
// because we know that the bit_index is based on last_pos
for (bit_index = 0; bit_index < 8; ++bit_index) {
mask = 1 << bit_index;
if ((buf->free[byte_index] & mask) == 0) {
free_element = byte_index * 8 + bit_index;
break;
}
}
}
if (free_element < 0) {
return NULL;
}
buf->free[byte_index] |= (1 << bit_index);
return buf->memory + free_element * buf->element_size;
}
inline
void buffer_element_free(BufferMemory* buf, uint64 element)
{
int byte_index = element / 8;
int bit_index = element % 8;
buf->free[byte_index] &= ~(1 << bit_index);
}
#endif

View File

@ -14,6 +14,7 @@
#define OMS_PI 3.14159265358979323846f #define OMS_PI 3.14159265358979323846f
#define OMS_PI_OVER_TWO OMS_PI / 2.0f #define OMS_PI_OVER_TWO OMS_PI / 2.0f
#define OMS_PI_OVER_FOUR OMS_PI / 4.0f
#define OMS_TWO_PI 2 * OMS_PI #define OMS_TWO_PI 2 * OMS_PI
#define OMS_MAX(a, b) ((a) > (b) ? (a) : (b)) #define OMS_MAX(a, b) ((a) > (b) ? (a) : (b))
@ -24,6 +25,10 @@
#define OMS_RAD2DEG(angle) ((angle) * 180.0f / OMS_PI) #define OMS_RAD2DEG(angle) ((angle) * 180.0f / OMS_PI)
#define ROUND_TO_NEAREST(a, b) (((a) + ((b) - 1)) & ~((b) - 1)) #define ROUND_TO_NEAREST(a, b) (((a) + ((b) - 1)) & ~((b) - 1))
#ifndef FLT_MIN
#define FLT_MIN 1.175494e-038
#endif
// @question Consider to implement table based sine wave + approximation if necessary // @question Consider to implement table based sine wave + approximation if necessary
// [-PI/2, PI/2] // [-PI/2, PI/2]
inline inline
@ -35,7 +40,6 @@ float sin_approx_pih_pih(float x)
inline inline
float sinf_approx(float x) float sinf_approx(float x)
{ {
x = OMS_RAD2DEG(x);
return 4 * x * (180 - x) / (40500 - x * (180 - x)); return 4 * x * (180 - x) / (40500 - x * (180 - x));
} }
@ -58,4 +62,55 @@ float tanf_approx(float x)
return sin_x / cos_x; return sin_x / cos_x;
} }
inline
float atanf_approx(float x)
{
float abs_x = OMS_ABS(x);
float result;
if (abs_x > 1.0f) {
result = OMS_PI_OVER_TWO - (1.0f / abs_x);
} else {
result = abs_x - (abs_x * abs_x * abs_x / 3.0f);
}
return (x < 0.0f) ? -result : result;
}
inline
float atan2f_approx(float y, float x)
{
float abs_y = OMS_ABS(y) + FLT_MIN; // prevent division by zero
float angle;
if (x >= 0.0f) {
float r = (x - abs_y) / (x + abs_y);
angle = OMS_PI_OVER_FOUR - OMS_PI_OVER_FOUR * r;
} else {
float r = (x + abs_y) / (abs_y - x);
angle = (3.0f * OMS_PI / 4.0f) - OMS_PI_OVER_FOUR * r;
}
return (y < 0.0f) ? -angle : angle;
}
inline
float asinf_approx(float x)
{
float negate = (x < 0) ? 1.0f : 0.0f;
x = OMS_ABS(x);
float result = -0.0187293f;
result *= x;
result += 0.0742610f;
result *= x;
result -= 0.2121144f;
result *= x;
result += 1.5707288f;
result *= sqrt(1.0f - x);
result -= 2 * negate * result;
return negate * OMS_PI + result;
}
#endif #endif

View File

@ -54,7 +54,7 @@ byte* ring_get_memory(RingMemory* ring, uint64 size, byte aligned = 1, bool zero
ring->pos = 0; ring->pos = 0;
} }
byte* offset = (byte *) ring->memory[ring->pos]; byte* offset = (byte *) (ring->memory + ring->pos);
if (zeroed) { if (zeroed) {
memset((void *) offset, 0, size); memset((void *) offset, 0, size);
} }
@ -64,6 +64,17 @@ byte* ring_get_memory(RingMemory* ring, uint64 size, byte aligned = 1, bool zero
return offset; return offset;
} }
// Used if the ring only contains elements of a certain size
// This way you can get a certain element
inline
byte *ring_get_element(const RingMemory* ring, uint64 element_count, uint64 element, uint64 size)
{
uint64 index = (element % element_count) - 1;
index = index < 0 ? element_count : index;
return ring->memory + index * size;
}
inline inline
void ring_reset(RingMemory* ring) void ring_reset(RingMemory* ring)
{ {
@ -78,6 +89,10 @@ bool ring_commit_safe(const RingMemory* ring, uint64 size, byte aligned = 1)
{ {
uint64 pos = ring_calculate_position(ring, ring->pos, size, aligned); uint64 pos = ring_calculate_position(ring, ring->pos, size, aligned);
if (ring->start == ring->end && ring->pos == 0) {
return true;
}
return ring->start < ring->pos return ring->start < ring->pos
? ring->start < pos ? ring->start < pos
: pos < ring->start; : pos < ring->start;

View File

@ -14,7 +14,6 @@
#include <ctype.h> #include <ctype.h>
#include "../stdlib/Types.h" #include "../stdlib/Types.h"
#include "../stdlib/Mathtypes.h"
inline size_t str_count(const char *str, const char *substr) inline size_t str_count(const char *str, const char *substr)
{ {
@ -59,15 +58,13 @@ str_concat(
const char* src2, size_t src2_length, const char* src2, size_t src2_length,
char* dst char* dst
) { ) {
for (size_t i = 0; i < src1_length; ++i) { memcpy(dst, src1, src1_length);
*dst++ = *src1++; dst += src1_length;
}
for (size_t i = 0; i < src2_length; ++i) { memcpy(dst, src2, src2_length);
*dst++ = *src2++; dst += src2_length;
}
*dst++ = '\0'; *dst = '\0';
} }
char *strtok(char *str, const char *delim, char **saveptr) char *strtok(char *str, const char *delim, char **saveptr)
@ -144,33 +141,6 @@ void create_const_name(const unsigned char *name, unsigned char* modified_name)
} }
} }
void font_string_dimension(const char *str, v2_int32* dim, const int* width_lookup)
{
size_t length = strlen(str);
int width = 0;
for (int i = 0; i < length; ++i) {
if (str[i] == '\n') {
if (width > dim->x) {
dim->x = width;
}
width = 0;
++dim->y;
}
width += width_lookup[str[i]];
}
if (width > dim->x) {
dim->x = width;
}
if (width > 0) {
++dim->y;
}
}
/** /**
* Custom implementation of strtok_r/strtok_s * Custom implementation of strtok_r/strtok_s
*/ */

View File

@ -12,6 +12,12 @@
#include <time.h> #include <time.h>
#include "../stdlib/Types.h" #include "../stdlib/Types.h"
#if _WIN32
#include <intrin.h>
#else
#include <x86intrin.h>
#endif
#define MAX_LOG_LENGTH 128 #define MAX_LOG_LENGTH 128
global_persist uint64 performance_count_frequency; global_persist uint64 performance_count_frequency;
@ -31,36 +37,21 @@ struct LogPool {
// uint32 size = count * MAX_LOG_LENGTH // uint32 size = count * MAX_LOG_LENGTH
}; };
#if _WIN32 // IMPORTANT: This function should only be called when you actually use this data
inline // e.g. log to display or file
void update_timing_stat(TimingStat *stat) inline
{ void update_timing_stat(TimingStat *stat)
LARGE_INTEGER counter; {
QueryPerformanceCounter(&counter); stat->new_tick_count = __rdtsc();
stat->new_tick_count = counter.QuadPart; stat->delta_tick = stat->new_tick_count - stat->old_tick_count;
stat->delta_time = (double) stat->delta_tick / (double) performance_count_frequency;
// @performance Consider to only do the following two calculations when outputting the tick/time stat->old_tick_count = stat->new_tick_count;
stat->delta_tick = stat->new_tick_count - stat->old_tick_count; }
stat->delta_time = (double) stat->delta_tick / (double) performance_count_frequency;
stat->old_tick_count = stat->new_tick_count;
}
#else
void update_timing_stat(TimingStat *stat)
{
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
stat->new_tick_count = now.tv_sec + now.tv_nsec;
// @performance Consider to only do the following two calculations when outputting the tick/time
stat->delta_tick = stat->new_tick_count - stat->old_tick_count;
stat->delta_time = (double) stat->delta_tick / (double) performance_count_frequency;
stat->old_tick_count = stat->new_tick_count;
}
#endif
// Sometimes we want to only do logging in debug mode.
// In such cases use the following macro.
#if DEBUG #if DEBUG
#define UPDATE_TIMING_STAT(stat) update_timing_stat(stat) #define UPDATE_TIMING_STAT(stat) update_timing_stat(stat)
#else #else

View File

@ -37,36 +37,4 @@ bool is_bit_set(byte data, byte bit)
return (data & (1 << bit)) == 0; return (data & (1 << bit)) == 0;
} }
void make_character(
float *data,
float x, float y, float n, float m, char c)
{
float *d = data;
// Texture atlas is 16 characters
// 1 / 16 = 0.0625
float a = 0.0625;
float b = 0.0625 * 2;
// ascii offset
int w = c - 32;
float du = (w % 16) * a;
float dv = 1 - (w / 16) * b - b;
// Quad data (2 triangles)
*(d++) = x - n; *(d++) = y - m;
*(d++) = du + 0; *(d++) = dv;
*(d++) = x + n; *(d++) = y - m;
*(d++) = du + a; *(d++) = dv;
*(d++) = x + n; *(d++) = y + m;
*(d++) = du + a; *(d++) = dv + b;
*(d++) = x - n; *(d++) = y - m;
*(d++) = du + 0; *(d++) = dv;
*(d++) = x + n; *(d++) = y + m;
*(d++) = du + a; *(d++) = dv + b;
*(d++) = x - n; *(d++) = y + m;
*(d++) = du + 0; *(d++) = dv + b;
}
#endif #endif