]> git.lizzy.rs Git - dragonblocks_alpha.git/blob - src/client/interact.c
Rework structure
[dragonblocks_alpha.git] / src / client / interact.c
1 #include <linmath.h>
2 #include <stdio.h>
3 #include "client/camera.h"
4 #include "client/client.h"
5 #include "client/client_item.h"
6 #include "client/client_node.h"
7 #include "client/client_player.h"
8 #include "client/cube.h"
9 #include "client/debug_menu.h"
10 #include "client/frustum.h"
11 #include "client/gl_debug.h"
12 #include "client/gui.h"
13 #include "client/interact.h"
14 #include "client/mesh.h"
15 #include "client/raycast.h"
16 #include "client/shader.h"
17
18 struct InteractPointed interact_pointed;
19
20 static GLuint shader_prog;
21 static GLint loc_MVP;
22 static GLint loc_color;
23 static mat4x4 model;
24
25 typedef struct {
26         v3f32 position;
27 } __attribute__((packed)) SelectionVertex;
28 static Mesh selection_mesh = {
29         .layout = &(VertexLayout) {
30                 .attributes = (VertexAttribute[]) {
31                         {GL_FLOAT, 3, sizeof(v3f32)},
32                 },
33                 .count = 1,
34                 .size = sizeof(SelectionVertex),
35         },
36         .vao = 0,
37         .vbo = 0,
38         .data = NULL,
39         .count = 36,
40         .free_data = false,
41 };
42
43 void interact_init()
44 {
45         shader_prog = shader_program_create(ASSET_PATH "shaders/3d/selection", NULL);
46         loc_MVP = glGetUniformLocation(shader_prog, "MVP"); GL_DEBUG
47         loc_color = glGetUniformLocation(shader_prog, "color"); GL_DEBUG
48
49         SelectionVertex vertices[6][6];
50         for (int f = 0; f < 6; f++)
51                 for (int v = 0; v < 6; v++)
52                         vertices[f][v].position = v3f32_scale(cube_vertices[f][v].position, 1.1f);
53
54         selection_mesh.data = vertices;
55         mesh_upload(&selection_mesh);
56
57         gui_add(NULL, (GUIElementDef) {
58                 .pos = {0.5f, 0.5f},
59                 .z_index = 0.0f,
60                 .offset = {0, 0},
61                 .margin = {0, 0},
62                 .align = {0.5f, 0.5f},
63                 .scale = {1.0f, 1.0f},
64                 .scale_type = SCALE_IMAGE,
65                 .affect_parent_scale = false,
66                 .text = NULL,
67                 .image = texture_load(ASSET_PATH "textures/crosshair.png", false),
68                 .text_color = {0.0f, 0.0f, 0.0f, 0.0f},
69                 .bg_color = {0.0f, 0.0f, 0.0f, 0.0f},
70         });
71 }
72
73 void interact_deinit()
74 {
75         glDeleteProgram(shader_prog); GL_DEBUG
76         mesh_destroy(&selection_mesh);
77 }
78
79 #include "client/client_terrain.h"
80
81 void interact_tick()
82 {
83         bool old_exists = interact_pointed.exists;
84         v3s32 old_pointed = interact_pointed.pos;
85         if ((interact_pointed.exists = raycast(
86                                 (v3f64) {camera.eye  [0], camera.eye  [1], camera.eye  [2]},
87                                 (v3f64) {camera.front[0], camera.front[1], camera.front[2]},
88                                 5, &interact_pointed.pos, &interact_pointed.node))
89                         && !v3s32_equals(interact_pointed.pos, old_pointed)) {
90                 mat4x4_translate(model,
91                         interact_pointed.pos.x, interact_pointed.pos.y, interact_pointed.pos.z);
92                 v3f32 *color = &client_node_def[interact_pointed.node].selection_color;
93                 glProgramUniform3f(shader_prog, loc_color, color->x, color->y, color->z); GL_DEBUG
94                 debug_menu_changed(ENTRY_POINTED);
95         }
96
97         if (old_exists && !interact_pointed.exists)
98                 debug_menu_changed(ENTRY_POINTED);
99 }
100
101 void interact_render()
102 {
103         if (!interact_pointed.exists)
104                 return;
105
106         mat4x4 mvp;
107         mat4x4_mul(mvp, frustum, model);
108
109         glUseProgram(shader_prog); GL_DEBUG
110         glUniformMatrix4fv(loc_MVP, 1, GL_FALSE, mvp[0]); GL_DEBUG
111         mesh_render(&selection_mesh);
112 }
113
114 void interact_use(bool left)
115 {
116         ClientEntity *entity = client_player_entity_local();
117         if (!entity)
118                 return;
119
120         ClientPlayerData *data = entity->extra;
121         pthread_mutex_lock(&data->mtx_inv);
122
123         ItemStack *stack = left ? &data->inventory.left : &data->inventory.right;
124         if (client_item_def[stack->type].use && client_item_def[stack->type].use(stack))
125                 dragonnet_peer_send_ToServerInteract(client, &(ToServerInteract) {
126                         .left = left,
127                         .pointed = interact_pointed.exists,
128                         .pos = interact_pointed.pos,
129                 });
130
131         pthread_mutex_unlock(&data->mtx_inv);
132         refcount_drp(&entity->rc);
133 }