11 #include <GLFW/glfw3.h>
13 #include "clientmap.h"
20 void client_disconnect(bool send, const char *detail)
22 pthread_mutex_lock(&client.mtx);
23 if (client.state != CS_DISCONNECTED) {
25 write_u32(client.fd, SC_DISCONNECT);
27 client.state = CS_DISCONNECTED;
28 printf("Disconnected %s%s%s\n", INBRACES(detail));
31 pthread_mutex_unlock(&client.mtx);
36 static void *reciever_thread(void *unused)
40 handle_packets(&client);
43 client_disconnect(false, "network error");
48 static void update_view_matrix(ShaderProgram *prog, mat4x4 view)
50 mat4x4_translate(view, -client.pos.x, -client.pos.y, -client.pos.z);
51 glUniformMatrix4fv(prog->loc_view, 1, GL_FALSE, view[0]);
54 static void client_loop()
57 printf("Failed to initialize GLFW\n");
61 glfwWindowHint(GLFW_SAMPLES, 8);
62 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
63 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
64 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
70 GLFWwindow *window = glfwCreateWindow(width, height, "Dragonblocks", NULL, NULL);
73 fprintf(stderr, "Failed to create window\n");
78 glfwMakeContextCurrent(window);
79 if (glewInit() != GLEW_OK) {
80 fprintf(stderr, "Failed to initialize GLEW\n");
84 glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
86 const char *shader_path;
89 shader_path = "shaders";
91 shader_path = "../shaders";
94 ShaderProgram *prog = create_shader_program(shader_path);
96 fprintf(stderr, "Failed to create shader program\n");
100 mat4x4 view, projection;
102 update_view_matrix(prog, view);
103 mat4x4_perspective(projection, 86.1f / 180.0f * M_PI, (float) width / (float) height, 0.01f, 1000.0f);
105 glUseProgram(prog->id);
106 glUniformMatrix4fv(prog->loc_view, 1, GL_FALSE, view[0]);
107 glUniformMatrix4fv(prog->loc_projection, 1, GL_FALSE, projection[0]);
109 while (! glfwWindowShouldClose(window) && client.state != CS_DISCONNECTED && ! interrupted) {
110 glEnable(GL_DEPTH_TEST);
111 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
112 glClearColor(0.52941176470588f, 0.8078431372549f, 0.92156862745098f, 1.0f);
114 bool pos_changed = false;
116 if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) {
118 client.pos.z -= 1.0f;
119 } else if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) {
121 client.pos.z += 1.0f;
122 } if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) {
124 client.pos.x -= 1.0f;
125 } else if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) {
127 client.pos.x += 1.0f;
128 } if (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) {
130 client.pos.y -= 1.0f;
131 } else if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS) {
133 client.pos.y += 1.0f;
137 update_view_matrix(prog, view);
138 pthread_mutex_lock(&client.mtx);
139 (void) (write_u32(client.fd, SC_POS) && write_v3f32(client.fd, client.pos));
140 pthread_mutex_unlock(&client.mtx);
143 scene_render(client.scene, prog);
145 glfwSwapBuffers(window);
149 delete_shader_program(prog);
152 static bool client_name_prompt()
154 printf("Enter name: ");
157 if (scanf("%s", name) == EOF)
159 client.name = strdup(name);
160 pthread_mutex_lock(&client.mtx);
161 if (write_u32(client.fd, SC_AUTH) && write(client.fd, client.name, strlen(client.name) + 1)) {
162 client.state = CS_AUTH;
163 printf("Authenticating...\n");
165 pthread_mutex_unlock(&client.mtx);
169 static bool client_authenticate()
172 switch (client.state) {
174 if (client_name_prompt())
186 case CS_DISCONNECTED:
193 static void client_start(int fd)
196 pthread_mutex_init(&client.mtx, NULL);
197 client.state = CS_CREATED;
199 client.map = map_create();
200 client.scene = scene_create();
201 client.pos = (v3f) {0.0f, 0.0f, 0.0f};
203 clientmap_init(&client);
205 pthread_t recv_thread;
206 pthread_create(&recv_thread, NULL, &reciever_thread, NULL);
208 if (client_authenticate())
211 if (client.state != CS_DISCONNECTED)
212 client_disconnect(true, NULL);
219 map_delete(client.map);
220 scene_delete(client.scene);
222 pthread_mutex_destroy(&client.mtx);
225 int main(int argc, char **argv)
227 program_name = argv[0];
230 internal_error("missing address or port");
232 struct addrinfo hints = {
233 .ai_family = AF_UNSPEC,
234 .ai_socktype = SOCK_STREAM,
236 .ai_flags = AI_NUMERICSERV,
239 struct addrinfo *info = NULL;
241 int gai_state = getaddrinfo(argv[1], argv[2], &hints, &info);
244 internal_error(gai_strerror(gai_state));
246 int fd = socket(info->ai_family, info->ai_socktype, info->ai_protocol);
249 syscall_error("socket");
251 if (connect(fd, info->ai_addr, info->ai_addrlen) == -1)
252 syscall_error("connect");
254 char *addrstr = address_string((struct sockaddr_in6 *) info->ai_addr);
255 printf("Connected to %s\n", addrstr);
260 init_signal_handlers();