transfered from codeberg

This commit is contained in:
2026-03-26 14:46:39 -05:00
parent 630f28bb7e
commit 5ed2173793
136 changed files with 14932 additions and 0 deletions

View File

@@ -0,0 +1,301 @@
#include "private_player.h"
#include "chunk.h"
#include "chunk_position_to_vector_3/chunk_position_to_vector_3.h"
#include "player.h"
#include "world.h"
#include "player_input_map.h"
#include "raymath.h"
#include <float.h>
#include <math.h>
#include <stdatomic.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
void _initialize_player(struct player_struct* player)
{
player->position = (Vector3){ 0.0f, 2.0f, 0.0f };
player->velocity = (Vector3){ 0.0f, 0.0f, 0.0f };
player->yaw = 0.0f;
player->pitch = 0.0f;
player->mouse_sensitivity = 0.15f;
player->camera.position = player->position;
player->camera.target = (Vector3){
player->position.x,
player->position.y,
player->position.z + 1.0f
};
player->camera.up = (Vector3){ 0.0f, 1.0f, 0.0f };
player->camera.fovy = 55.0f;
player->camera.projection = CAMERA_PERSPECTIVE;
player->corner_of_watched_block = (Vector3){ 0.0f, 0.0f, 0.0f };
player->block_being_watched = (Vector3){ 0.0f, 0.0f, 0.0f };
player->should_highlight_block = false;
player->reach = 5.0f;
player->movement_speed = 10.0f;
player->is_breaking_block = false;
player->breaking_block_progress = 0.0f;
player->is_making_contact_with.below = false;
player->is_making_contact_with.above = false;
player->is_making_contact_with.left = false;
player->is_making_contact_with.right = false;
player->is_making_contact_with.front = false;
player->is_making_contact_with.back = false;
player->health = 100;
player->fortitude = 0;
player->selected_hotbar_slot = 0;
player->has_entered_new_chunk = true;
player->positive_borders =
offset_chunk_position(player->occupied_chunks_position,
render_distance + 1,
vertical_render_distance + 1,
render_distance + 1 );
player->negative_borders =
offset_chunk_position(player->occupied_chunks_position,
-render_distance - 1,
-vertical_render_distance - 1,
-render_distance - 1 );
create_inventory(&player->inventory);
}
void _free_player(struct player_struct *player)
{
memset(player, 0, sizeof(player_struct));
}
/**
* Refreshes the player's currently highlighted/targeted block based on their
* current position and rotation within the world.
*/
void _update_player_targeted_block(struct player_struct* player)
{
player->should_highlight_block = false;
float closest_hit_distance_squared = FLT_MAX;
// No world mutex lock needed here as we use the local snapshot
for (int x = 0; x < 3; x++)
{
for (int y = 0; y < 3; y++)
{
for (int z = 0; z < 3; z++)
{
struct chunk_struct *current_chunk = player->nearby_chunks[x][y][z];
if (current_chunk == NULL)
{
continue;
}
// Skip chunks that aren't ready yet
if (atomic_load(&current_chunk->build_state) == state_needs_data)
{
continue;
}
bool found_solid_block_from_raycast =
_get_first_solid_block_in_chunk_along_view_ray(player,
current_chunk,
player->reach);
if (found_solid_block_from_raycast)
{
// current_chunk->position is the world space origin of the chunk
Vector3 center_of_watched_block = {
player->corner_of_watched_block.x + (float)current_chunk->position.x + 0.5f,
player->corner_of_watched_block.y + (float)current_chunk->position.y + 0.5f,
player->corner_of_watched_block.z + (float)current_chunk->position.z + 0.5f
};
float current_hit_distance_squared = Vector3DistanceSqr(
player->camera.position,
center_of_watched_block
);
if (current_hit_distance_squared < closest_hit_distance_squared)
{
closest_hit_distance_squared = current_hit_distance_squared;
player->should_highlight_block = true;
player->block_being_watched = center_of_watched_block;
}
}
}
}
}
}
/**
* Iterates through a specific chunk along the player's look vector to find
* the first non-air block.
*/
bool _get_first_solid_block_in_chunk_along_view_ray(struct player_struct *player,
struct chunk_struct *chunk,
float maximum_ray_distance)
{
// Since we are using the player->nearby_chunks snapshot,
// the pointer 'chunk' is guaranteed to be valid for the duration
// of this frame.
Vector3 ray_origin = player->camera.position;
Vector3 ray_direction = Vector3Normalize(
Vector3Subtract(
player->camera.target,
player->camera.position
)
);
/* Smaller step increments result in higher precision block selection */
float ray_traversal_step_increment = 0.1f;
for (float distance_along_ray = 0.0f;
distance_along_ray <= maximum_ray_distance;
distance_along_ray += ray_traversal_step_increment)
{
Vector3 sampled_world_position = Vector3Add(
ray_origin,
Vector3Scale(ray_direction, distance_along_ray)
);
Vector3 sampled_chunk_local_position = Vector3Subtract(
sampled_world_position,
chunk_position_to_vector_3(chunk->position)
);
int32_t block_coordinate_x = (int32_t)floorf(sampled_chunk_local_position.x);
int32_t block_coordinate_y = (int32_t)floorf(sampled_chunk_local_position.y);
int32_t block_coordinate_z = (int32_t)floorf(sampled_chunk_local_position.z);
// Boundary check relative to the chunk being sampled
if (block_coordinate_x < 0 || block_coordinate_y < 0 ||
block_coordinate_z < 0 || block_coordinate_x >= (int32_t)chunk_size ||
block_coordinate_y >= (int32_t)chunk_size ||
block_coordinate_z >= (int32_t)chunk_size)
{
continue;
}
uint32_t block_index = index_chunk((uint8_t)block_coordinate_x,
(uint8_t)block_coordinate_y,
(uint8_t)block_coordinate_z);
// If chunks are modified by other threads, we treat block_data as
// effectively read-only during the raycast phase.
if (chunk->block_data[block_index] != 0)
{
player->corner_of_watched_block = (Vector3){
(float)block_coordinate_x,
(float)block_coordinate_y,
(float)block_coordinate_z
};
return true;
}
}
return false;
}
Vector3 _update_player_movement(struct player_struct* player, float seconds_since_last_frame)
{
Vector3 camera_movement_this_frame = { 0 };
if (player_walk_forward_pressed)
{
camera_movement_this_frame.x +=
player->movement_speed * seconds_since_last_frame;
}
if (player_walk_backward_pressed)
{
camera_movement_this_frame.x -=
player->movement_speed * seconds_since_last_frame;
}
if (player_walk_right_pressed)
{
camera_movement_this_frame.y +=
player->movement_speed * seconds_since_last_frame;
}
if (player_walk_left_pressed)
{
camera_movement_this_frame.y -=
player->movement_speed * seconds_since_last_frame;
}
if (player_fly_up_is_pressed)
{
camera_movement_this_frame.z +=
player->movement_speed * seconds_since_last_frame;
}
if (player_fly_down_is_pressed)
{
camera_movement_this_frame.z -=
player->movement_speed * seconds_since_last_frame;
}
return camera_movement_this_frame;
}
void _update_player_chunk_occupancy_state(struct player_struct *player)
{
if (player == NULL)
{
fprintf(stderr, "_update_player_chunk_occupancy_state,"
"player argument is NULL");
return;
}
int32_t current_chunk_x = (int32_t)floorf(player->camera.position.x / chunk_size);
int32_t current_chunk_y = (int32_t)floorf(player->camera.position.y / chunk_size);
int32_t current_chunk_z = (int32_t)floorf(player->camera.position.z / chunk_size);
int32_t current_chunks_position_x = (current_chunk_x * chunk_size);
int32_t current_chunks_position_y = (current_chunk_y * chunk_size);
int32_t current_chunks_position_z = (current_chunk_z * chunk_size);
bool has_moved_to_different_chunk_x =
(current_chunks_position_x != player->occupied_chunks_position.x);
bool has_moved_to_different_chunk_y =
(current_chunks_position_y != player->occupied_chunks_position.y);
bool has_moved_to_different_chunk_z =
(current_chunks_position_z != player->occupied_chunks_position.z);
if (has_moved_to_different_chunk_x
|| has_moved_to_different_chunk_y
|| has_moved_to_different_chunk_z)
{
player->has_entered_new_chunk = true;
player->occupied_chunks_position.x = current_chunks_position_x;
player->occupied_chunks_position.y = current_chunks_position_y;
player->occupied_chunks_position.z = current_chunks_position_z;
player->positive_borders =
offset_chunk_position(player->occupied_chunks_position,
render_distance + 1,
vertical_render_distance + 1,
render_distance + 1 );
player->negative_borders =
offset_chunk_position(player->occupied_chunks_position,
-render_distance - 1,
-vertical_render_distance - 1,
-render_distance - 1 );
}
else
{
player->has_entered_new_chunk = false;
}
}

View File

@@ -0,0 +1,27 @@
#ifndef private_player_h
#define private_player_h
struct player_struct;
struct world_struct;
struct chunk_struct;
#include "raylib.h"
#include <stdbool.h>
void _initialize_player(struct player_struct* player);
void _free_player(struct player_struct* player);
bool _get_first_solid_block_in_chunk_along_view_ray(struct player_struct *player,
struct chunk_struct *chunk,
float maximum_ray_distance);
void _update_player_targeted_block(struct player_struct* player);
void _update_player_chunk_occupancy_state(struct player_struct *player);
Vector3 _update_player_movement(struct player_struct* player,
float seconds_since_last_frame);
#endif