11 #include <GLFW/glfw3.h>
14 #include "clientmap.h"
15 #include "clientnode.h"
25 void client_disconnect(bool send, const char *detail)
27 pthread_mutex_lock(&client.mtx);
28 if (client.state != CS_DISCONNECTED) {
30 write_u32(client.fd, SC_DISCONNECT);
32 client.state = CS_DISCONNECTED;
33 printf("Disconnected %s%s%s\n", INBRACES(detail));
36 pthread_mutex_unlock(&client.mtx);
41 static void *reciever_thread(__attribute__((unused)) void *unused)
43 handle_packets(&client);
46 client_disconnect(false, "network error");
51 static void framebuffer_size_callback(__attribute__((unused)) GLFWwindow* window, int width, int height)
53 glViewport(0, 0, width, height);
55 camera_on_resize(width, height);
56 hud_on_resize(width, height);
57 input_on_resize(width, height);
60 static void cursor_pos_callback(__attribute__((unused)) GLFWwindow* window, double current_x, double current_y)
62 input_on_cursor_pos(current_x, current_y);
65 static void window_pos_callback(__attribute__((unused)) GLFWwindow* window, int x, int y)
67 input_on_window_pos(x, y);
70 static void client_loop()
73 printf("Failed to initialize GLFW\n");
77 glfwWindowHint(GLFW_SAMPLES, 8);
78 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
79 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
80 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
86 GLFWwindow *window = glfwCreateWindow(width, height, "Dragonblocks", NULL, NULL);
89 fprintf(stderr, "Failed to create window\n");
94 glfwMakeContextCurrent(window);
95 if (glewInit() != GLEW_OK) {
96 fprintf(stderr, "Failed to initialize GLEW\n");
100 glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
102 ShaderProgram *prog = create_shader_program(RESSOURCEPATH "shaders");
104 fprintf(stderr, "Failed to create shader program\n");
108 init_client_node_definitions();
109 clientmap_start_meshgen();
111 glUseProgram(prog->id);
113 init_camera(window, prog);
115 set_camera_position((v3f) {0.0f, 0.0f, 0.0f});
116 set_camera_angle(0.0f, 0.0f);
118 camera_on_resize(width, height);
121 hud_on_resize(width, height);
123 hud_add(RESSOURCEPATH "textures/crosshair.png", (v3f) {0.0f, 0.0f, 0.0f}, (v2f) {1.0f, 1.0f}, HUD_SCALE_TEXTURE);
125 init_input(&client, window);
126 input_on_resize(width, height);
128 clientplayer_add_to_scene(&client.player);
130 glfwSetFramebufferSizeCallback(window, &framebuffer_size_callback);
131 glfwSetCursorPosCallback(window, &cursor_pos_callback);
132 glfwSetWindowPosCallback(window, &window_pos_callback);
134 struct timespec ts, ts_old;
135 clock_gettime(CLOCK_REALTIME, &ts_old);
137 while (! glfwWindowShouldClose(window) && client.state != CS_DISCONNECTED && ! interrupted) {
138 clock_gettime(CLOCK_REALTIME, &ts);
139 f64 dtime = (f64) (ts.tv_sec - ts_old.tv_sec) + (f64) (ts.tv_nsec - ts_old.tv_nsec) / 1000000000.0;
142 glEnable(GL_DEPTH_TEST);
144 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
145 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
146 glClearColor(0.52941176470588f, 0.8078431372549f, 0.92156862745098f, 1.0f);
149 clientplayer_tick(&client.player, dtime);
152 scene_render(client.scene, prog);
156 glfwSwapBuffers(window);
160 delete_shader_program(prog);
164 static bool client_name_prompt()
166 printf("Enter name: ");
169 if (scanf("%s", name) == EOF)
171 client.name = strdup(name);
172 pthread_mutex_lock(&client.mtx);
173 if (write_u32(client.fd, SC_AUTH) && write(client.fd, client.name, strlen(client.name) + 1)) {
174 client.state = CS_AUTH;
175 printf("Authenticating...\n");
177 pthread_mutex_unlock(&client.mtx);
181 static bool client_authenticate()
184 switch (client.state) {
186 if (client_name_prompt())
198 case CS_DISCONNECTED:
205 static void client_start(int fd)
208 pthread_mutex_init(&client.mtx, NULL);
209 client.state = CS_CREATED;
211 client.map = map_create();
212 client.scene = scene_create();
214 clientplayer_init(&client);
215 clientmap_init(&client);
217 pthread_t recv_thread;
218 pthread_create(&recv_thread, NULL, &reciever_thread, NULL);
220 if (client_authenticate())
223 if (client.state != CS_DISCONNECTED)
224 client_disconnect(true, NULL);
231 map_delete(client.map);
232 scene_delete(client.scene);
234 pthread_mutex_destroy(&client.mtx);
237 int main(int argc, char **argv)
239 program_name = argv[0];
242 internal_error("missing address or port");
244 struct addrinfo hints = {
245 .ai_family = AF_UNSPEC,
246 .ai_socktype = SOCK_STREAM,
248 .ai_flags = AI_NUMERICSERV,
251 struct addrinfo *info = NULL;
253 int gai_state = getaddrinfo(argv[1], argv[2], &hints, &info);
256 internal_error(gai_strerror(gai_state));
258 int fd = socket(info->ai_family, info->ai_socktype, info->ai_protocol);
261 syscall_error("socket");
263 if (connect(fd, info->ai_addr, info->ai_addrlen) == -1)
264 syscall_error("connect");
266 char *addrstr = address_string((struct sockaddr_in6 *) info->ai_addr);
267 printf("Connected to %s\n", addrstr);
272 init_signal_handlers();