]> git.lizzy.rs Git - dragonblocks_alpha.git/blob - src/server/server.c
refactoring
[dragonblocks_alpha.git] / src / server / server.c
1 #define _GNU_SOURCE // don't worry, GNU extensions are only used when available
2 #include <dragonnet/addr.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <pthread.h>
6 #include "interrupt.h"
7 #include "server/database.h"
8 #include "server/server.h"
9 #include "server/server_player.h"
10 #include "server/server_terrain.h"
11
12 DragonnetListener *server;
13
14 static bool on_recv(DragonnetPeer *peer, DragonnetTypeId type, __attribute__((unused)) void *pkt)
15 {
16         // this is recv thread, so we don't need lock_auth
17         return ((ServerPlayer *) peer->extra)->auth != (type == DRAGONNET_TYPE_ToServerAuth);
18 }
19
20 static void on_ToServerAuth(DragonnetPeer *peer, ToServerAuth *pkt)
21 {
22         if (server_player_auth(peer->extra, pkt->name))
23                 pkt->name = NULL;
24 }
25
26 // set a node on the map
27 static void on_ToServerSetnode(__attribute__((unused)) DragonnetPeer *peer, ToServerSetnode *pkt)
28 {
29         terrain_set_node(server_terrain, pkt->pos,
30                 terrain_node_create(pkt->node, (Blob) {0, NULL}),
31                 false, NULL);
32 }
33
34 // update player's position
35 static void on_ToServerPosRot(DragonnetPeer *peer, ToServerPosRot *pkt)
36 {
37         ServerPlayer *player = peer->extra;
38
39         pthread_rwlock_wrlock(&player->lock_pos);
40         player->pos = pkt->pos;
41         player->rot = pkt->rot;
42
43         // this is recv thread, no lock_auth needed
44         database_update_player_pos_rot(player->name, player->pos, player->rot);
45         pthread_rwlock_unlock(&player->lock_pos);
46 }
47
48 // tell server map manager client requested the chunk
49 static void on_ToServerRequestChunk(DragonnetPeer *peer, ToServerRequestChunk *pkt)
50 {
51         server_terrain_requested_chunk(peer->extra, pkt->pos);
52 }
53
54 // server entry point
55 int main(int argc, char **argv)
56 {
57 #ifdef __GLIBC__ // check whether bloat is enabled
58         pthread_setname_np(pthread_self(), "main");
59 #endif // __GLIBC__
60
61         if (argc < 2) {
62                 fprintf(stderr, "[error] missing address\n");
63                 return EXIT_FAILURE;
64         }
65
66         if (!(server = dragonnet_listener_new(argv[1]))) {
67                 fprintf(stderr, "[error] failed to listen to connections\n");
68                 return EXIT_FAILURE;
69         }
70
71         char *address = dragonnet_addr_str(server->laddr);
72         printf("[info] listening on %s\n", address);
73         free(address);
74
75         server->on_connect = &server_player_add;
76         server->on_disconnect = &server_player_remove;
77         server->on_recv = &on_recv;
78         server->on_recv_type[DRAGONNET_TYPE_ToServerAuth        ] = (void *) &on_ToServerAuth;
79         server->on_recv_type[DRAGONNET_TYPE_ToServerSetnode     ] = (void *) &on_ToServerSetnode;
80         server->on_recv_type[DRAGONNET_TYPE_ToServerPosRot      ] = (void *) &on_ToServerPosRot;
81         server->on_recv_type[DRAGONNET_TYPE_ToServerRequestChunk] = (void *) &on_ToServerRequestChunk;
82
83         interrupt_init();
84         if (!database_init())
85                 return EXIT_FAILURE;
86         server_terrain_init();
87         server_player_init();
88
89         server_terrain_prepare_spawn();
90         dragonnet_listener_run(server);
91
92         flag_slp(&interrupt);
93
94         printf("[info] shutting down\n");
95         dragonnet_listener_close(server);
96
97         server_player_deinit();
98         server_terrain_deinit();
99         database_deinit();
100         interrupt_deinit();
101
102         dragonnet_listener_delete(server);
103
104         return EXIT_SUCCESS;
105 }