3 #include "client/camera.h"
4 #include "client/client.h"
5 #include "client/client_inventory.h"
6 #include "client/client_player.h"
7 #include "client/client_terrain.h"
8 #include "client/cube.h"
9 #include "client/debug_menu.h"
10 #include "client/texture.h"
11 #include "environment.h"
14 struct ClientPlayer client_player;
16 static ClientEntity *player_entity;
17 static pthread_rwlock_t lock_player_entity;
19 static Model *player_model;
21 // updat epos/rot box/eye functions
23 static void update_camera()
25 vec4 dst, src = {0.0f, 0.0f, 0.0f, 1.0f};
27 ClientPlayerData *data = player_entity->extra;
30 mat4x4_mul_vec4(dst, data->bones.eyes->abs, src);
34 camera_set_position((v3f32) {dst[0], dst[1], dst[2]});
37 static void update_pos()
39 debug_menu_changed(ENTRY_POS);
40 debug_menu_changed(ENTRY_HUMIDITY);
41 debug_menu_changed(ENTRY_TEMPERATURE);
44 static void update_rot()
46 camera_set_angle(M_PI / 2 - player_entity->data.rot.y, -player_entity->data.rot.x);
47 debug_menu_changed(ENTRY_YAW);
48 debug_menu_changed(ENTRY_PITCH);
51 static void update_transform()
53 client_entity_transform(player_entity);
57 static void send_pos_rot()
61 dragonnet_peer_send_ToServerPosRot(client, &(ToServerPosRot) {
62 .pos = player_entity->data.pos,
63 .rot = player_entity->data.rot,
67 static void recv_pos_rot()
77 static void on_add(ClientEntity *entity)
79 entity->model = model_clone(player_model);
80 entity->model->extra = refcount_grb(&entity->rc);
82 ClientPlayerData *data = entity->extra = malloc(sizeof *data);
83 data->bones = (struct ClientPlayerBones) {NULL};
85 model_get_bones(entity->model, (ModelBoneMapping[9]) {
86 {"nametag", &data->bones.nametag },
87 {"neck", &data->bones.neck },
88 {"neck.head.eyes", &data->bones.eyes },
89 {"arm_left", &data->bones.arm_left },
90 {"arm_right", &data->bones.arm_right },
91 {"arm_left.hand", &data->bones.hand_left },
92 {"arm_right.hand", &data->bones.hand_right},
93 {"leg_left", &data->bones.leg_left },
94 {"leg_right", &data->bones.leg_right },
97 entity->nametag_offset = data->bones.nametag ? &data->bones.nametag->abs : NULL;
98 entity->box_collision = (aabb3f32) {{-0.45f, 0.0f, -0.45f}, {0.45f, 1.8f, 0.45f}};
100 client_inventory_init_player(entity);
102 model_scene_add(entity->model);
103 client_entity_transform(entity);
106 static void on_remove(ClientEntity *entity)
108 entity->model->flags.delete = 1;
109 entity->model = NULL;
112 static void on_free(ClientEntity *entity)
114 client_inventory_init_player(entity);
118 static void on_transform(ClientEntity *entity)
120 ClientPlayerData *data = entity->extra;
122 entity->model->root->rot.x = entity->model->root->rot.z = 0.0f;
124 if (data->bones.neck) {
125 data->bones.neck->rot.x = entity->data.rot.x;
126 model_node_transform(data->bones.neck);
130 static void local_on_add(ClientEntity *entity)
132 pthread_rwlock_wrlock(&lock_player_entity);
135 fprintf(stderr, "[error] attempt to re-add localplayer entity\n");
141 player_entity = refcount_grb(&entity->rc);
144 entity->type->update_nametag(entity);
146 pthread_rwlock_unlock(&lock_player_entity);
149 static void local_on_remove(ClientEntity *entity)
151 pthread_rwlock_wrlock(&lock_player_entity);
152 refcount_drp(&entity->rc);
153 player_entity = NULL;
154 pthread_rwlock_unlock(&lock_player_entity);
159 static void local_on_update_pos_rot(__attribute__((unused)) ClientEntity *entity)
164 static void local_on_update_nametag(ClientEntity *entity)
166 if (entity->data.nametag) {
167 free(entity->data.nametag);
168 entity->data.nametag = NULL;
172 static void __attribute__((unused)) on_model_step(Model *model, __attribute__((unused)) f64 dtime)
174 ClientPlayerData *data = ((ClientEntity *) model->extra)->extra;
175 (void) data; // ToDo: animations
178 static void on_model_delete(Model *model)
181 refcount_drp(&((ClientEntity *) model->extra)->rc);
185 void client_player_init()
187 client_player.movement = (ToClientMovement) {
195 client_entity_types[ENTITY_PLAYER] = (ClientEntityType) {
197 .remove = &on_remove,
199 .update_pos_rot = NULL,
200 .update_nametag = NULL,
201 .transform = &on_transform,
204 client_entity_types[ENTITY_LOCALPLAYER] = (ClientEntityType) {
205 .add = &local_on_add,
206 .remove = &local_on_remove,
208 .update_pos_rot = &local_on_update_pos_rot,
209 .update_nametag = &local_on_update_nametag,
210 .transform = &on_transform,
213 pthread_rwlock_init(&client_player.lock_movement, NULL);
215 player_entity = NULL;
216 pthread_rwlock_init(&lock_player_entity, NULL);
219 // called on shutdown
220 void client_player_deinit()
222 pthread_rwlock_destroy(&client_player.lock_movement);
223 pthread_rwlock_destroy(&lock_player_entity);
226 void client_player_gfx_init()
228 player_model = model_load(
229 RESSOURCE_PATH "models/player.txt", RESSOURCE_PATH "textures/models/player",
230 &client_entity_cube, &client_entity_shader);
232 player_model->callbacks.step = &on_model_step;
233 player_model->callbacks.delete = &on_model_delete;
236 void client_player_gfx_deinit()
238 model_delete(player_model);
241 ClientEntity *client_player_entity(u64 id)
243 ClientEntity *entity = client_entity_grab(id);
245 if (entity->type == &client_entity_types[ENTITY_LOCALPLAYER]
246 || entity->type == &client_entity_types[ENTITY_PLAYER])
249 refcount_drp(&entity->rc);
253 ClientEntity *client_player_entity_local()
255 ClientEntity *entity = NULL;
257 pthread_rwlock_rdlock(&lock_player_entity);
259 entity = refcount_grb(&player_entity->rc);
260 pthread_rwlock_unlock(&lock_player_entity);
265 void client_player_update_pos(ClientEntity *entity)
267 pthread_rwlock_rdlock(&lock_player_entity);
269 if (entity == player_entity) {
274 pthread_rwlock_unlock(&lock_player_entity);
277 void client_player_update_rot(ClientEntity *entity)
279 pthread_rwlock_rdlock(&lock_player_entity);
281 if (entity == player_entity) {
286 pthread_rwlock_unlock(&lock_player_entity);
290 void client_player_jump()
292 ClientEntity *entity = client_player_entity_local();
296 pthread_rwlock_rdlock(&entity->lock_pos_rot);
297 pthread_rwlock_rdlock(&entity->lock_box_off);
301 client_player.movement.collision,
302 entity->box_collision,
304 &client_player.velocity
306 client_player.velocity.y += client_player.movement.jump;
308 pthread_rwlock_unlock(&entity->lock_box_off);
309 pthread_rwlock_unlock(&entity->lock_pos_rot);
311 refcount_drp(&entity->rc);
314 // to be called every frame
315 void client_player_tick(f64 dtime)
317 ClientEntity *entity = client_player_entity_local();
321 pthread_rwlock_rdlock(&client_player.lock_movement);
322 pthread_rwlock_wrlock(&entity->lock_pos_rot);
323 pthread_rwlock_rdlock(&entity->lock_box_off);
327 client_player.movement.collision,
328 entity->box_collision,
330 &client_player.velocity,
333 client_player.movement.flight ? 0.0 : -client_player.movement.gravity,
338 client_player_update_pos(entity);
340 pthread_rwlock_unlock(&entity->lock_box_off);
341 pthread_rwlock_unlock(&entity->lock_pos_rot);
342 pthread_rwlock_unlock(&client_player.lock_movement);
344 refcount_drp(&entity->rc);