3 #include "client/camera.h"
4 #include "client/client.h"
5 #include "client/client_player.h"
6 #include "client/client_terrain.h"
7 #include "client/cube.h"
8 #include "client/debug_menu.h"
9 #include "client/texture.h"
10 #include "environment.h"
17 ModelNode *shoulder_left;
18 ModelNode *shoulder_right;
23 struct ClientPlayer client_player;
25 static ClientEntity *player_entity;
26 static pthread_rwlock_t lock_player_entity;
28 static Model *player_model;
30 // updat epos/rot box/eye functions
32 static void update_camera()
34 vec4 dst, src = {0.0f, 0.0f, 0.0f, 1.0f};
36 PlayerModelBones *bones = player_entity->extra;
39 mat4x4_mul_vec4(dst, bones->eyes->abs, src);
43 camera_set_position((v3f32) {dst[0], dst[1], dst[2]});
46 static void update_pos()
48 debug_menu_changed(ENTRY_POS);
49 debug_menu_changed(ENTRY_HUMIDITY);
50 debug_menu_changed(ENTRY_TEMPERATURE);
53 static void update_rot()
55 camera_set_angle(M_PI / 2 - player_entity->data.rot.y, -player_entity->data.rot.x);
56 debug_menu_changed(ENTRY_YAW);
57 debug_menu_changed(ENTRY_PITCH);
60 static void update_transform()
62 client_entity_transform(player_entity);
66 static void send_pos_rot()
70 dragonnet_peer_send_ToServerPosRot(client, &(ToServerPosRot) {
71 .pos = player_entity->data.pos,
72 .rot = player_entity->data.rot,
76 static void recv_pos_rot()
86 static void on_add(ClientEntity *entity)
88 entity->model = model_clone(player_model);
89 entity->model->extra = refcount_grb(&entity->rc);
91 PlayerModelBones *bones = entity->extra = malloc(sizeof *bones);
92 *bones = (PlayerModelBones) {NULL};
93 model_get_bones(entity->model, (ModelBoneMapping[]) {
94 {"player.nametag", &bones->nametag },
95 {"player.neck", &bones->neck },
96 {"player.neck.head.eyes", &bones->eyes },
97 {"player.body.upper.shoulders.left", &bones->shoulder_left },
98 {"player.body.upper.shoulders.right", &bones->shoulder_right},
99 {"player.body.lower.hips.left", &bones->hip_left },
100 {"player.body.lower.hips.right", &bones->hip_right },
103 entity->nametag_offset = bones->nametag ? &bones->nametag->abs : NULL;
104 entity->box_collision = (aabb3f32) {{-0.45f, 0.0f, -0.45f}, {0.45f, 1.8f, 0.45f}};
106 model_scene_add(entity->model);
107 client_entity_transform(entity);
110 static void on_remove(ClientEntity *entity)
112 entity->model->flags.delete = 1;
113 entity->model = NULL;
116 static void on_free(ClientEntity *entity)
121 static void on_transform(ClientEntity *entity)
123 PlayerModelBones *bones = entity->extra;
125 entity->model->root->rot.x = entity->model->root->rot.z = 0.0f;
128 bones->neck->rot.x = entity->data.rot.x;
129 model_node_transform(bones->neck);
133 static void local_on_add(ClientEntity *entity)
135 pthread_rwlock_wrlock(&lock_player_entity);
138 fprintf(stderr, "[error] attempt to re-add localplayer entity\n");
144 player_entity = refcount_grb(&entity->rc);
147 entity->type->update_nametag(entity);
149 pthread_rwlock_unlock(&lock_player_entity);
152 static void local_on_remove(ClientEntity *entity)
154 pthread_rwlock_wrlock(&lock_player_entity);
155 refcount_drp(&entity->rc);
156 player_entity = NULL;
157 pthread_rwlock_unlock(&lock_player_entity);
162 static void local_on_update_pos_rot(__attribute__((unused)) ClientEntity *entity)
167 static void local_on_update_nametag(ClientEntity *entity)
169 if (entity->data.nametag) {
170 free(entity->data.nametag);
171 entity->data.nametag = NULL;
175 static void __attribute__((unused)) on_model_step(Model *model, __attribute__((unused)) f64 dtime)
177 PlayerModelBones *bones = ((ClientEntity *) model->extra)->extra;
181 static void on_model_delete(Model *model)
184 refcount_drp(&((ClientEntity *) model->extra)->rc);
188 void client_player_init()
190 client_player.movement = (ToClientMovement) {
198 client_entity_types[ENTITY_PLAYER] = (ClientEntityType) {
200 .remove = &on_remove,
202 .update_pos_rot = NULL,
203 .update_nametag = NULL,
204 .transform = &on_transform,
207 client_entity_types[ENTITY_LOCALPLAYER] = (ClientEntityType) {
208 .add = &local_on_add,
209 .remove = &local_on_remove,
211 .update_pos_rot = &local_on_update_pos_rot,
212 .update_nametag = &local_on_update_nametag,
213 .transform = &on_transform,
216 pthread_rwlock_init(&client_player.lock_movement, NULL);
218 player_entity = NULL;
219 pthread_rwlock_init(&lock_player_entity, NULL);
222 // called on shutdown
223 void client_player_deinit()
225 pthread_rwlock_destroy(&client_player.lock_movement);
226 pthread_rwlock_destroy(&lock_player_entity);
229 void client_player_gfx_init()
231 player_model = model_load(
232 RESSOURCE_PATH "models/player.txt", RESSOURCE_PATH "textures/models/player",
233 &client_entity_cube, &client_entity_shader);
235 player_model->callbacks.step = &on_model_step;
236 player_model->callbacks.delete = &on_model_delete;
239 void client_player_gfx_deinit()
241 model_delete(player_model);
244 ClientEntity *client_player_entity()
246 ClientEntity *entity = NULL;
248 pthread_rwlock_rdlock(&lock_player_entity);
250 entity = refcount_grb(&player_entity->rc);
251 pthread_rwlock_unlock(&lock_player_entity);
256 void client_player_update_pos(ClientEntity *entity)
258 pthread_rwlock_rdlock(&lock_player_entity);
260 if (entity == player_entity) {
265 pthread_rwlock_unlock(&lock_player_entity);
268 void client_player_update_rot(ClientEntity *entity)
270 pthread_rwlock_rdlock(&lock_player_entity);
272 if (entity == player_entity) {
277 pthread_rwlock_unlock(&lock_player_entity);
281 void client_player_jump()
283 ClientEntity *entity = client_player_entity();
287 pthread_rwlock_rdlock(&entity->lock_pos_rot);
288 pthread_rwlock_rdlock(&entity->lock_box_off);
292 client_player.movement.collision,
293 entity->box_collision,
295 &client_player.velocity
297 client_player.velocity.y += client_player.movement.jump;
299 pthread_rwlock_unlock(&entity->lock_box_off);
300 pthread_rwlock_unlock(&entity->lock_pos_rot);
302 refcount_drp(&entity->rc);
305 // to be called every frame
306 void client_player_tick(f64 dtime)
308 ClientEntity *entity = client_player_entity();
312 pthread_rwlock_rdlock(&client_player.lock_movement);
313 pthread_rwlock_wrlock(&entity->lock_pos_rot);
314 pthread_rwlock_rdlock(&entity->lock_box_off);
318 client_player.movement.collision,
319 entity->box_collision,
321 &client_player.velocity,
324 client_player.movement.flight ? 0.0 : -client_player.movement.gravity,
329 client_player_update_pos(entity);
331 pthread_rwlock_unlock(&entity->lock_box_off);
332 pthread_rwlock_unlock(&entity->lock_pos_rot);
333 pthread_rwlock_unlock(&client_player.lock_movement);
335 refcount_drp(&entity->rc);