11 #include <GLFW/glfw3.h>
13 #include "clientmap.h"
14 #include "clientnode.h"
21 void client_disconnect(bool send, const char *detail)
23 pthread_mutex_lock(&client.mtx);
24 if (client.state != CS_DISCONNECTED) {
26 write_u32(client.fd, SC_DISCONNECT);
28 client.state = CS_DISCONNECTED;
29 printf("Disconnected %s%s%s\n", INBRACES(detail));
32 pthread_mutex_unlock(&client.mtx);
37 static void *reciever_thread(__attribute__((unused)) void *unused)
39 handle_packets(&client);
42 client_disconnect(false, "network error");
47 static void update_view_matrix(ShaderProgram *prog, mat4x4 view)
49 mat4x4_translate(view, -client.pos.x, -client.pos.y, -client.pos.z);
50 glUniformMatrix4fv(prog->loc_view, 1, GL_FALSE, view[0]);
53 static void client_loop()
56 printf("Failed to initialize GLFW\n");
60 glfwWindowHint(GLFW_SAMPLES, 8);
61 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
62 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
63 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
69 GLFWwindow *window = glfwCreateWindow(width, height, "Dragonblocks", NULL, NULL);
72 fprintf(stderr, "Failed to create window\n");
77 glfwMakeContextCurrent(window);
78 if (glewInit() != GLEW_OK) {
79 fprintf(stderr, "Failed to initialize GLEW\n");
83 glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
85 ShaderProgram *prog = create_shader_program(RESSOURCEPATH "shaders");
87 fprintf(stderr, "Failed to create shader program\n");
91 init_client_node_definitions();
92 clientmap_start_meshgen();
94 mat4x4 view, projection;
96 update_view_matrix(prog, view);
97 mat4x4_perspective(projection, 86.1f / 180.0f * M_PI, (float) width / (float) height, 0.01f, 1000.0f);
99 glUseProgram(prog->id);
100 glUniformMatrix4fv(prog->loc_view, 1, GL_FALSE, view[0]);
101 glUniformMatrix4fv(prog->loc_projection, 1, GL_FALSE, projection[0]);
103 while (! glfwWindowShouldClose(window) && client.state != CS_DISCONNECTED && ! interrupted) {
104 glEnable(GL_DEPTH_TEST);
105 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
106 glClearColor(0.52941176470588f, 0.8078431372549f, 0.92156862745098f, 1.0f);
108 bool pos_changed = false;
110 if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) {
112 client.pos.z -= 1.0f;
113 } else if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) {
115 client.pos.z += 1.0f;
116 } if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) {
118 client.pos.x -= 1.0f;
119 } else if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) {
121 client.pos.x += 1.0f;
122 } if (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) {
124 client.pos.y -= 1.0f;
125 } else if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS) {
127 client.pos.y += 1.0f;
131 update_view_matrix(prog, view);
132 pthread_mutex_lock(&client.mtx);
133 (void) (write_u32(client.fd, SC_POS) && write_v3f32(client.fd, client.pos));
134 pthread_mutex_unlock(&client.mtx);
137 scene_render(client.scene, prog);
139 glfwSwapBuffers(window);
143 delete_shader_program(prog);
146 static bool client_name_prompt()
148 printf("Enter name: ");
151 if (scanf("%s", name) == EOF)
153 client.name = strdup(name);
154 pthread_mutex_lock(&client.mtx);
155 if (write_u32(client.fd, SC_AUTH) && write(client.fd, client.name, strlen(client.name) + 1)) {
156 client.state = CS_AUTH;
157 printf("Authenticating...\n");
159 pthread_mutex_unlock(&client.mtx);
163 static bool client_authenticate()
166 switch (client.state) {
168 if (client_name_prompt())
180 case CS_DISCONNECTED:
187 static void client_start(int fd)
190 pthread_mutex_init(&client.mtx, NULL);
191 client.state = CS_CREATED;
193 client.map = map_create();
194 client.scene = scene_create();
195 client.pos = (v3f) {0.0f, 0.0f, 0.0f};
197 clientmap_init(&client);
199 pthread_t recv_thread;
200 pthread_create(&recv_thread, NULL, &reciever_thread, NULL);
202 if (client_authenticate())
205 if (client.state != CS_DISCONNECTED)
206 client_disconnect(true, NULL);
213 map_delete(client.map, NULL);
214 scene_delete(client.scene);
216 pthread_mutex_destroy(&client.mtx);
219 int main(int argc, char **argv)
221 program_name = argv[0];
224 internal_error("missing address or port");
226 struct addrinfo hints = {
227 .ai_family = AF_UNSPEC,
228 .ai_socktype = SOCK_STREAM,
230 .ai_flags = AI_NUMERICSERV,
233 struct addrinfo *info = NULL;
235 int gai_state = getaddrinfo(argv[1], argv[2], &hints, &info);
238 internal_error(gai_strerror(gai_state));
240 int fd = socket(info->ai_family, info->ai_socktype, info->ai_protocol);
243 syscall_error("socket");
245 if (connect(fd, info->ai_addr, info->ai_addrlen) == -1)
246 syscall_error("connect");
248 char *addrstr = address_string((struct sockaddr_in6 *) info->ai_addr);
249 printf("Connected to %s\n", addrstr);
254 init_signal_handlers();