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
, g_player
[i
].shoot
));
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, PLAYER_SHOOT
);
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, 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
&& m
.cl
.does
.code
.bits
)
81 if(!g_player
[id
].live
)
84 g_player_does(id
, m
.cl
.does
.code
);
87 static void sv_kill_address(IPaddress address
, const char * msg
) {
88 SDL_Log("sv_kill_address: %s", msg
);
89 SendMessage(sock
, address
, sv_kill(msg
));
92 static void sv_register_player(IPaddress address
, ClInfo info
) {
93 if(info
.version
!= PROTOCOL_VERSION
) {
94 sv_kill_address(address
, "Uncompatible version");
99 while((i
< clientlimit
) && (client
[i
].connected
))
102 if(i
>= clientlimit
) {
103 sv_kill_address(address
, "Too many clients");
107 client
[i
].connected
= true;
108 client
[i
].address
= address
;
109 strncpy(client
[i
].name
, (char*) info
.name
, MAX_NAMESIZE
);
110 client
[i
].name
[MAX_NAMESIZE
- 1] = 0;
112 SDL_Log("Player %s (%i) connected", client
[i
].name
, i
);
113 SendMessage(sock
, address
, sv_info(name
, i
, clientlimit
));
116 sv_sync_client(i
, true);
119 static void sv_recv_ipmsg(IPaddress address
, ProtocolMessage m
) {
120 int id
= sv_find_client(address
);
121 if(id
< 0 && m
.type
!= CL_INFO
)
125 case CL_INFO
: sv_register_player(address
, m
.cl
.info
); break;
126 case CL_KILL
: sv_kill_player(id
, false, ""); break;
127 case CL_DOES
: sv_move_player(id
, m
); break;
128 default: sv_kill_address(address
, "Invalid message");
132 static void sv_recv() {
135 while(RecvMessage(sock
, &address
, &m
))
136 sv_recv_ipmsg(address
, m
);
139 static void sv_send() {
140 for(int i
= 0; i
< clientlimit
; i
++)
141 if(client
[i
].connected
)
142 sv_sync_client(i
, false);
144 for(int i
= 0; i
< clientlimit
; i
++)
145 g_player
[i
].updated
= false;
147 for(int i
= 0; i
< MAX_BULLETS
; i
++)
148 g_bullet
[i
].updated
= false;
151 void sv_start(uint16_t port
) {
153 sock
= OpenPort(port
);
154 lastTime
= SDL_GetTicks();
155 currTime
= SDL_GetTicks();
159 for(int i
= 0; i
< clientlimit
; i
++)
160 if(client
[i
].connected
)
161 sv_kill_player(i
, true, "Server shutdown");
165 void sv_setclientlimit(unsigned int maxclients
) {
166 // TODO disconnect clients
167 clientlimit
= (maxclients
> MAX_PLAYERS
) ? (MAX_PLAYERS
) : (maxclients
);
171 if(currTime
- lastTime
>= TICK_DELAY
) {
175 lastTime
= SDL_GetTicks();
177 currTime
= SDL_GetTicks();