]> git.lizzy.rs Git - dragonblocks_alpha.git/blob - src/client/client_player.c
refactoring
[dragonblocks_alpha.git] / src / client / client_player.c
1 #include <stdio.h>
2 #include <stdlib.h>
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"
11 #include "physics.h"
12
13 struct ClientPlayer client_player;
14
15 static ClientEntity *player_entity;
16 static pthread_rwlock_t lock_player_entity;
17
18 // updat epos/rot box/eye functions
19
20 static void update_eye_pos_camera()
21 {
22         v3f64 pos = player_entity->data.pos;
23         v3f32 eye = player_entity->data.eye;
24
25         camera_set_position((v3f32) {pos.x + eye.x, pos.y + eye.y, pos.z + eye.z});
26 }
27
28 static void update_pos()
29 {
30         pthread_rwlock_rdlock(&player_entity->lock_box_eye);
31         update_eye_pos_camera();
32         pthread_rwlock_unlock(&player_entity->lock_box_eye);
33
34         debug_menu_changed(ENTRY_POS);
35         debug_menu_changed(ENTRY_HUMIDITY);
36         debug_menu_changed(ENTRY_TEMPERATURE);
37 }
38
39 static void update_rot()
40 {
41         camera_set_angle(player_entity->data.rot.x, player_entity->data.rot.y);
42         debug_menu_changed(ENTRY_YAW);
43         debug_menu_changed(ENTRY_PITCH);
44 }
45
46 static void update_transform()
47 {
48         client_entity_transform(player_entity);
49 }
50
51 static void send_pos_rot()
52 {
53         dragonnet_peer_send_ToServerPosRot(client, &(ToServerPosRot) {
54                 .pos = player_entity->data.pos,
55                 .rot = player_entity->data.rot,
56         });
57
58         update_transform();
59 }
60
61 static void recv_pos_rot()
62 {
63         update_pos();
64         update_rot();
65
66         update_transform();
67 }
68
69 // entity callbacks
70
71 static void on_add(ClientEntity *entity)
72 {
73         pthread_rwlock_wrlock(&lock_player_entity);
74
75         if (player_entity) {
76                 fprintf(stderr, "[error] attempt to re-add localplayer entity\n");
77                 exit(EXIT_FAILURE);
78         } else {
79                 player_entity = refcount_grb(&entity->rc);
80                 recv_pos_rot();
81
82                 entity->type->update_nametag(entity);
83         }
84
85         pthread_rwlock_unlock(&lock_player_entity);
86 }
87
88 static void on_remove(ClientEntity *entity)
89 {
90         pthread_rwlock_wrlock(&lock_player_entity);
91         refcount_drp(&entity->rc);
92         player_entity = NULL;
93         pthread_rwlock_unlock(&lock_player_entity);
94 }
95
96 static void on_update_pos_rot(__attribute__((unused)) ClientEntity *entity)
97 {
98         recv_pos_rot();
99 }
100
101 static void on_update_box_eye(__attribute__((unused)) ClientEntity *entity)
102 {
103         pthread_rwlock_rdlock(&lock_player_entity);
104         update_eye_pos_camera();
105         pthread_rwlock_unlock(&lock_player_entity);
106 }
107
108 static void on_update_nametag(ClientEntity *entity)
109 {
110         if (entity->data.nametag) {
111                 free(entity->data.nametag);
112                 entity->data.nametag = NULL;
113         }
114 }
115
116 static void on_transform(ClientEntity *entity)
117 {
118         entity->model->root->rot.y = entity->model->root->rot.z = 0.0f;
119 }
120
121 // called on startup
122 void client_player_init()
123 {
124         client_player.movement = (ToClientMovement) {
125                 .flight = false,
126                 .collision = true,
127                 .speed = 0.0f,
128                 .jump = 0.0f,
129                 .gravity = 0.0f,
130         };
131
132         client_entity_types[ENTITY_LOCALPLAYER] = (ClientEntityType) {
133                 .add = &on_add,
134                 .remove = &on_remove,
135                 .free = NULL,
136                 .update_pos_rot = &on_update_pos_rot,
137                 .update_box_eye = &on_update_box_eye,
138                 .update_nametag = &on_update_nametag,
139                 .transform = &on_transform,
140         };
141
142         client_entity_types[ENTITY_PLAYER] = (ClientEntityType) {
143                 .add = NULL,
144                 .remove = NULL,
145                 .free = NULL,
146                 .update_pos_rot = NULL,
147                 .update_box_eye = NULL,
148                 .update_nametag = NULL,
149                 .transform = &on_transform,
150         };
151
152         pthread_rwlock_init(&client_player.lock_movement, NULL);
153
154         player_entity = NULL;
155         pthread_rwlock_init(&lock_player_entity, NULL);
156 }
157
158 // called on shutdown
159 void client_player_deinit()
160 {
161         pthread_rwlock_destroy(&client_player.lock_movement);
162         pthread_rwlock_destroy(&lock_player_entity);
163 }
164
165 ClientEntity *client_player_entity()
166 {
167         ClientEntity *entity = NULL;
168
169         pthread_rwlock_rdlock(&lock_player_entity);
170         if (player_entity)
171                 entity = refcount_grb(&player_entity->rc);
172         pthread_rwlock_unlock(&lock_player_entity);
173
174         return entity;
175 }
176
177 void client_player_update_pos(ClientEntity *entity)
178 {
179         pthread_rwlock_rdlock(&lock_player_entity);
180
181         if (entity == player_entity) {
182                 update_pos();
183                 send_pos_rot();
184         }
185
186         pthread_rwlock_unlock(&lock_player_entity);
187 }
188
189 void client_player_update_rot(ClientEntity *entity)
190 {
191         pthread_rwlock_rdlock(&lock_player_entity);
192
193         if (entity == player_entity) {
194                 update_rot();
195                 send_pos_rot();
196         }
197
198         pthread_rwlock_unlock(&lock_player_entity);
199 }
200
201 /*
202 // create mesh object and info hud
203 void client_player_add_to_scene()
204 {
205         client_player.obj = object_create();
206         client_player.obj->scale = (v3f32) {0.6, 1.75, 0.6};
207         client_player.obj->visible = false;
208
209         object_set_texture(client_player.obj, texture_load(RESSOURCE_PATH "textures/player.png", true));
210
211         for (int f = 0; f < 6; f++) {
212                 for (int v = 0; v < 6; v++) {
213                         Vertex3D vertex = cube_vertices[f][v];
214                         vertex.position.y += 0.5;
215                         object_add_vertex(client_player.obj, &vertex);
216                 }
217         }
218
219         pthread_rwlock_rdlock(&client_player.rwlock);
220         update_pos();
221         pthread_rwlock_unlock(&client_player.rwlock);
222
223         debug_menu_update_yaw();
224         debug_menu_update_pitch();
225 }
226 */
227
228 // jump if possible
229 void client_player_jump()
230 {
231         ClientEntity *entity = client_player_entity();
232         if (!entity)
233                 return;
234
235         pthread_rwlock_rdlock(&entity->lock_pos_rot);
236         pthread_rwlock_rdlock(&entity->lock_box_eye);
237
238         if (physics_ground(
239                 client_terrain,
240                 client_player.movement.collision,
241                 entity->data.box,
242                 &entity->data.pos,
243                 &client_player.velocity
244         ))
245                 client_player.velocity.y += client_player.movement.jump;
246
247         pthread_rwlock_unlock(&entity->lock_box_eye);
248         pthread_rwlock_unlock(&entity->lock_pos_rot);
249
250         refcount_drp(&entity->rc);
251 }
252
253 // to be called every frame
254 void client_player_tick(f64 dtime)
255 {
256         ClientEntity *entity = client_player_entity();
257         if (!entity)
258                 return;
259
260         pthread_rwlock_rdlock(&client_player.lock_movement);
261         pthread_rwlock_wrlock(&entity->lock_pos_rot);
262         pthread_rwlock_rdlock(&entity->lock_box_eye);
263
264         if (physics_step(
265                 client_terrain,
266                 client_player.movement.collision,
267                 entity->data.box,
268                 &entity->data.pos,
269                 &client_player.velocity,
270                 &(v3f64) {
271                         0.0,
272                         client_player.movement.flight ? 0.0 : -client_player.movement.gravity,
273                         0.0,
274                 },
275                 dtime
276         ))
277                 client_player_update_pos(entity);
278
279         pthread_rwlock_unlock(&entity->lock_box_eye);
280         pthread_rwlock_unlock(&entity->lock_pos_rot);
281         pthread_rwlock_unlock(&client_player.lock_movement);
282
283         refcount_drp(&entity->rc);
284 }