+ client_inventory_init_player(entity);
+ free(entity->extra);
+}
+
+static void on_transform(ClientEntity *entity)
+{
+ ClientPlayerData *data = entity->extra;
+
+ entity->model->root->rot.x = entity->model->root->rot.z = 0.0f;
+
+ if (data->bones.neck) {
+ data->bones.neck->rot.x = entity->data.rot.x;
+ model_node_transform(data->bones.neck);
+ }
+}
+
+static void local_on_add(ClientEntity *entity)
+{
+ pthread_rwlock_wrlock(&lock_player_entity);
+
+ if (player_entity) {
+ fprintf(stderr, "[error] attempt to re-add localplayer entity\n");
+ exit(EXIT_FAILURE);
+ }
+
+ on_add(entity);
+
+ player_entity = refcount_grb(&entity->rc);
+ recv_pos_rot();
+
+ entity->type->update_nametag(entity);
+
+ pthread_rwlock_unlock(&lock_player_entity);
+}
+
+static void local_on_remove(ClientEntity *entity)
+{
+ pthread_rwlock_wrlock(&lock_player_entity);
+ refcount_drp(&entity->rc);
+ player_entity = NULL;
+ pthread_rwlock_unlock(&lock_player_entity);
+
+ on_remove(entity);
+}
+
+static void local_on_update_pos_rot(__attribute__((unused)) ClientEntity *entity)
+{
+ recv_pos_rot();
+}
+
+static void local_on_update_nametag(ClientEntity *entity)
+{
+ if (entity->data.nametag) {
+ free(entity->data.nametag);
+ entity->data.nametag = NULL;
+ }
+}
+
+static void __attribute__((unused)) on_model_step(Model *model, __attribute__((unused)) f64 dtime)
+{
+ ClientPlayerData *data = ((ClientEntity *) model->extra)->extra;
+ (void) data; // ToDo: animations
+}
+
+static void on_model_delete(Model *model)
+{
+ if (model->extra)
+ refcount_drp(&((ClientEntity *) model->extra)->rc);
+}
+
+// called on startup
+void client_player_init()
+{
+ client_player.movement = (ToClientMovement) {
+ .flight = false,
+ .collision = true,
+ .speed = 0.0f,
+ .jump = 0.0f,
+ .gravity = 0.0f,
+ };
+
+ client_entity_types[ENTITY_PLAYER] = (ClientEntityType) {
+ .add = &on_add,
+ .remove = &on_remove,
+ .free = &on_free,
+ .update_pos_rot = NULL,
+ .update_nametag = NULL,
+ .transform = &on_transform,
+ };
+
+ client_entity_types[ENTITY_LOCALPLAYER] = (ClientEntityType) {
+ .add = &local_on_add,
+ .remove = &local_on_remove,
+ .free = &on_free,
+ .update_pos_rot = &local_on_update_pos_rot,
+ .update_nametag = &local_on_update_nametag,
+ .transform = &on_transform,