d6cbfcc3b3c07cb1670bb914466dd414dca5136d
2 #include <SDL2/SDL_net.h>
9 #define MAX_NAMESIZE 32
11 typedef struct Client
{
14 char name
[MAX_NAMESIZE
];
17 static Uint32 lastTime
;
18 static Uint32 currTime
;
20 static UDPsocket sock
;
21 static Client client
[MAX_PLAYERS
];
22 static char name
[MAX_NAMESIZE
] = "netwar! server";
23 static int clientlimit
= 0;
25 static inline float randf() {
26 return (float) rand() / (float) RAND_MAX
;
29 static inline float randfm() {
30 return (rand() % 2) ? (-randf()) : (+randf());
33 static inline bool cmpaddr(IPaddress a
, IPaddress b
) {
34 return (a
.host
== b
.host
) && (a
.port
== b
.port
);
37 static int sv_find_client(IPaddress address
) {
38 for(int i
= 0; i
< clientlimit
; i
++)
39 if(client
[i
].connected
&& cmpaddr(client
[i
].address
, address
))
44 static void sv_sync_client(int id
, bool full
) {
46 assert(client
[id
].connected
);
48 for(int i
= 0; i
< clientlimit
; i
++)
49 if(full
|| g_player
[i
].updated
)
50 SendMessage(sock
, client
[id
].address
, sv_splr(i
, g_player
[i
].live
, g_player
[i
].x
, g_player
[i
].y
, g_player
[i
].r
, g_player
[i
].vx
, g_player
[i
].vy
, g_player
[i
].vr
));
52 for(int i
= 0; i
< MAX_BULLETS
; i
++)
53 if(full
|| g_bullet
[i
].updated
)
54 SendMessage(sock
, client
[id
].address
, sv_sbul(i
, g_bullet
[i
].owner
, g_bullet
[i
].live
, g_bullet
[i
].x
, g_bullet
[i
].y
, g_bullet
[i
].vx
, g_bullet
[i
].vy
, g_bullet
[i
].tick
));
57 static void sv_spawn_player(int id
) {
59 g_player_set(id
, true, randfm(), randfm(), randfm(), 0, 0, 0);
62 static void sv_kill_player(int id
, bool send
, const char * msg
) {
64 assert(client
[id
].connected
);
67 SendMessage(sock
, client
[id
].address
, sv_kill(msg
));
69 client
[id
].connected
= false;
70 g_player_set(id
, false, 0, 0, 0, 0, 0, 0);
71 SDL_Log("Player %s (%i) disconnected: %s", client
[id
].name
, id
, msg
);
74 static void sv_move_player(int id
, ProtocolMessage m
) {
76 assert(client
[id
].connected
);
78 if(!g_player
[id
].live
)
81 g_player_does(id
, m
.cl
.does
.code
);
84 static void sv_register_player(IPaddress address
, ProtocolMessage m
) {
85 if(m
.cl
.info
.version
!= PROTOCOL_VERSION
)
86 SendMessage(sock
, address
, sv_kill("Uncompatible version"));
89 while((i
< clientlimit
) && (client
[i
].connected
))
92 int namesize
= sizeof(m
.cl
.info
.name
);
93 if(i
>= clientlimit
) {
94 SDL_Log("Too may clints, player %.*s disconnected", namesize
, m
.cl
.info
.name
);
95 SendMessage(sock
, address
, sv_kill("Too many clients"));
99 client
[i
].connected
= true;
100 client
[i
].address
= address
;
101 strncpy(client
[i
].name
, (char*) m
.cl
.info
.name
, MAX_NAMESIZE
);
102 client
[i
].name
[MAX_NAMESIZE
- 1] = 0;
104 SDL_Log("Player %s (%i) connected", client
[i
].name
, i
);
105 SendMessage(sock
, address
, sv_info(name
, i
, clientlimit
));
108 sv_sync_client(i
, true);
111 static void sv_recv() {
114 if(!RecvMessage(sock
, &address
, &m
))
118 case CL_INFO
: sv_register_player(address
, m
); break;
119 case CL_KILL
: sv_kill_player(sv_find_client(address
), false, ""); break;
120 case CL_DOES
: sv_move_player(sv_find_client(address
), m
); break;
121 default: SDL_Log("invalid message %i", m
.type
);
125 static void sv_send() {
126 for(int i
= 0; i
< clientlimit
; i
++)
127 if(client
[i
].connected
)
128 sv_sync_client(i
, false);
130 for(int i
= 0; i
< clientlimit
; i
++)
131 g_player
[i
].updated
= false;
133 for(int i
= 0; i
< MAX_BULLETS
; i
++)
134 g_bullet
[i
].updated
= false;
137 void sv_start(uint16_t port
) {
138 sock
= OpenPort(port
);
139 lastTime
= SDL_GetTicks();
140 currTime
= SDL_GetTicks();
144 for(int i
= 0; i
< clientlimit
; i
++)
145 if(client
[i
].connected
)
146 sv_kill_player(i
, true, "Server shutdown");
150 void sv_setclientlimit(unsigned int maxclients
) {
151 // TODO disconnect clients
152 clientlimit
= (maxclients
> MAX_PLAYERS
) ? (MAX_PLAYERS
) : (maxclients
);
156 if(currTime
- lastTime
>= TICK_DELAY
) {
160 lastTime
= SDL_GetTicks();
162 currTime
= SDL_GetTicks();