v1.0.0-dev

This commit is contained in:
Alexander Zhirov 2023-04-30 23:29:45 +03:00
commit ccb2b5ec3b
31 changed files with 2087 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
.vscode
build
spaceserver

14
README.md Normal file
View File

@ -0,0 +1,14 @@
![logo](images/logo.png)
[SpaceShooter](https://git.zhirov.kz/games/spaceshooter) Network Game Server.
This server is under development. Currently, the repository has been suspended since 2020.
## Build
```sh
mkdir build
cd build
cmake -B . -S ../server
make
```

BIN
images/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

32
server/CMakeLists.txt Normal file
View File

@ -0,0 +1,32 @@
cmake_minimum_required(VERSION 3.0)
project(spaceserver)
include_directories("lib/" "games/" "objects/" "users/")
set(SRC_SERVER
calculation.c
common.c
connection.c
data.c
main.c
update.c)
set(SRC_LIB
lib/common.c
lib/event.c
lib/enet.c
lib/message.c
lib/timer.c)
set(SRC_USERS users/users.c)
set(SRC_OBJECTS objects/objects.c)
set(SRC_GAMES games/games.c)
find_library(ENET_LIB enet)
find_library(ALLEGRO_LIB allegro)
add_executable(${PROJECT_NAME} ${SRC_SERVER} ${SRC_LIB} ${SRC_USERS} ${SRC_OBJECTS} ${SRC_GAMES})
target_link_libraries(${PROJECT_NAME} ${ENET_LIB} ${ALLEGRO_LIB})

275
server/calculation.c Normal file
View File

@ -0,0 +1,275 @@
#include "calculation.h"
#include <stdbool.h>
#include <stdio.h>
/************************************************************
* SHIP
***********************************************************/
void srv_move_ship(SERVER_DATA* data, SERVER_GAME* game, SERVER_MESSAGE_UPDATE* message)
{
SERVER_OBJECTS* objects = &game->objects;
for(int i = 0; i < objects->ship_size; i++)
{
SERVER_SHIP* ship = objects->ships[i];
if(ship->active)
{
SERVER_USER* user = NULL;
for(int j = 0; j < game->user_size; j++)
if(game->user[j] && game->user[j]->id == ship->ID)
user = game->user[j];
ship->y += user->command.dy * ship->speed * data->timer.elapsed_time;
if(ship->y < 0)
ship->y = 0;
else if(ship->y > game->display_height)
ship->y = game->display_height;
ship->x += user->command.dx * ship->speed * data->timer.elapsed_time;
if(ship->x < 0)
ship->x = 0;
else if(ship->x > 900 * game->scale_factor)
ship->x = 900 * game->scale_factor;
message->ship[i].dx = user->command.dx;
message->ship[i].dy = user->command.dy;
}
message->ship[i].ID = ship->ID;
message->ship[i].x = ship->x;
message->ship[i].y = ship->y;
message->ship[i].lives = ship->lives;
message->ship[i].score = ship->score;
message->ship[i].active = ship->active;
}
}
/************************************************************
* BULLET
***********************************************************/
void srv_fire_bullet(SERVER_GAME* game)
{
for(int i = 0; i < game->user_size; i++)
{
if(game->user[i] && game->user[i]->command.fire)
{
SERVER_OBJECTS* objects = &game->objects;
SERVER_SHIP* ship = NULL;
for(int j = 0; j < objects->ship_size; j++)
if(objects->ships[j]->ID == game->user[i]->id)
ship = objects->ships[j];
if(!ship->active) continue;
for(int j = 0; j < objects->bullet_size; j++)
{
SERVER_BULLET* bullet = objects->bullets[j];
if(!bullet->live && bullet->ID == game->user[i]->id)
{
bullet->x = ship->x + 17;
bullet->y = ship->y;
bullet->live = true;
break;
}
}
}
}
}
void srv_update_bullet(SERVER_DATA* data, SERVER_GAME* game, SERVER_MESSAGE_UPDATE* message)
{
SERVER_OBJECTS* objects = &game->objects;
for(int i = 0; i < objects->bullet_size; i++)
{
SERVER_BULLET* bullet = objects->bullets[i];
if(bullet->live)
{
bullet->x += bullet->speed * data->timer.elapsed_time;
if(bullet->x > game->display_width)
bullet->live = false;
}
message->bullet[i].ID = bullet->ID;
message->bullet[i].active = bullet->active;
message->bullet[i].live = bullet->live;
message->bullet[i].x = bullet->x;
message->bullet[i].y = bullet->y;
}
}
void srv_collide_bullet(SERVER_GAME* game, SERVER_MESSAGE_UPDATE* message)
{
SERVER_OBJECTS* objects = &game->objects;
for(int i = 0; i < objects->bullet_size; i++)
{
SERVER_BULLET* bullet = objects->bullets[i];
if(bullet->live)
{
for(int j = 0; j < objects->comet_size; j++)
{
SERVER_COMET* comet = objects->comets[j];
if(comet->live)
{
if(bullet->x > (comet->x - comet->boundx) &&
bullet->x < (comet->x + comet->boundx) &&
bullet->y > (comet->y - comet->boundy) &&
bullet->y < (comet->y + comet->boundy))
{
bullet->live = false;
comet->live = false;
for(int k = 0; k < objects->ship_size; k++)
if(bullet->ID == objects->ships[k]->ID)
objects->ships[k]->score++;
srv_start_explosions(game, message, bullet->x, bullet->y);
}
}
}
}
}
}
/************************************************************
* COMET
***********************************************************/
void srv_start_comet(SERVER_GAME* game)
{
SERVER_OBJECTS* objects = &game->objects;
for(int i = 0; i < objects->comet_size; i++)
{
SERVER_COMET* comet = objects->comets[i];
if(!comet->live)
{
if(rand() % 500 == 0)
{
comet->live = true;
comet->x = game->display_width;
comet->y = 30 + rand() % (game->display_height - 60);
break;
}
}
}
}
void srv_update_comet(SERVER_DATA* data, SERVER_GAME* game, SERVER_MESSAGE_UPDATE* message)
{
SERVER_OBJECTS* objects = &game->objects;
for(int i = 0; i < objects->comet_size; i++)
{
SERVER_COMET* comet = objects->comets[i];
if(comet->live)
comet->x -= comet->speed * data->timer.elapsed_time;
message->comet[i].live = comet->live;
message->comet[i].x = comet->x;
message->comet[i].y = comet->y;
}
}
void srv_collide_comet(SERVER_GAME* game, SERVER_MESSAGE_UPDATE* message)
{
SERVER_OBJECTS* objects = &game->objects;
for(int i = 0; i < objects->comet_size; i++)
{
SERVER_COMET* comet = objects->comets[i];
if(!comet->live) continue;
for(int j = 0; j < objects->ship_size; j++)
{
SERVER_SHIP* ship = objects->ships[j];
if(!ship->active) continue;
if((comet->x - comet->boundx) < (ship->x + ship->boundx) &&
(comet->x + comet->boundx) > (ship->x - ship->boundx) &&
(comet->y - comet->boundy) < (ship->y + ship->boundy) &&
(comet->y + comet->boundy) > (ship->y - ship->boundy))
{
ship->lives--;
comet->live = false;
srv_start_explosions(game, message, ship->x, ship->y);
}
else if(comet->x < 0)
{
comet->live = false;
ship->lives--;
}
if(ship->lives <= 0)
ship->active = false;
}
}
}
/************************************************************
* EXPLOSION
***********************************************************/
static void srv_start_explosions(SERVER_GAME* game, SERVER_MESSAGE_UPDATE* message, int x, int y)
{
SERVER_OBJECTS* objects = &game->objects;
for(int i = 0; i < objects->explosion_size; i++)
{
SERVER_EXPLOSION* explosion = objects->explosions[i];
if(!explosion->live)
{
explosion->live = true;
explosion->x = x;
explosion->y = y;
message->explosion[i].live = explosion->live;
message->explosion[i].x = explosion->x;
message->explosion[i].y = explosion->y;
break;
}
}
}
void srv_update_explosions(SERVER_DATA* data, SERVER_GAME* game)
{
SERVER_OBJECTS* objects = &game->objects;
for(int i = 0; i < objects->explosion_size; i++)
{
SERVER_EXPLOSION* explosion = objects->explosions[i];
if(explosion->live)
{
explosion->lifetime += data->timer.elapsed_time;
if(explosion->lifetime >= 1.5)
{
explosion->lifetime = 0;
explosion->live = false;
}
}
}
}

41
server/calculation.h Normal file
View File

@ -0,0 +1,41 @@
/*
* File: calculation.h
* Author: Alexander Zhirov
* Connection with me (telegram messanger): @alexanderzhirov
*
* Created on 2020.06.26
*/
#ifndef server_calculation
#define server_calculation
#include "games.h"
#include "common.h"
#include "connection.h"
/************************************************************
* SHIP
***********************************************************/
void srv_move_ship(SERVER_DATA* data, SERVER_GAME* game, SERVER_MESSAGE_UPDATE* message);
/************************************************************
* BULLET
***********************************************************/
void srv_fire_bullet(SERVER_GAME* game);
void srv_update_bullet(SERVER_DATA* data, SERVER_GAME* game, SERVER_MESSAGE_UPDATE* message);
void srv_collide_bullet(SERVER_GAME* game, SERVER_MESSAGE_UPDATE* message);
/************************************************************
* COMET
***********************************************************/
void srv_start_comet(SERVER_GAME* game);
void srv_update_comet(SERVER_DATA* data, SERVER_GAME* game, SERVER_MESSAGE_UPDATE* message);
void srv_collide_comet(SERVER_GAME* game, SERVER_MESSAGE_UPDATE* message);
/************************************************************
* EXPLOSION
***********************************************************/
static void srv_start_explosions(SERVER_GAME* game, SERVER_MESSAGE_UPDATE* message, int x, int y);
void srv_update_explosions(SERVER_DATA* data, SERVER_GAME* game);
#endif

26
server/common.c Normal file
View File

@ -0,0 +1,26 @@
#define _DEFAULT_SOURCE
#include <signal.h>
#include <stdio.h>
#include "common.h"
#include "lib/message.h"
void srv_catch_signal(int signal, void (*handler)(int))
{
struct sigaction action;
action.sa_handler = handler;
sigemptyset(&action.sa_mask);
action.sa_flags = 0;
show_message_error(sigaction(signal, &action, NULL) == 0, "Failed to register signal");
}
void srv_stop_server(int signal)
{
SERVER_DATA* data = srv_get_server_data(NULL);
data->done = true;
puts("--------------------------------------------------");
puts("Останавливаю сервер! Без паники!");
}

33
server/common.h Normal file
View File

@ -0,0 +1,33 @@
/*
* File: common.h
* Author: Alexander Zhirov
* Connection with me (telegram messanger): @alexanderzhirov
*
* Created on 2020.06.14
*/
#ifndef server_data
#define server_data
#include "lib/common.h"
#include "users.h"
#include "games.h"
typedef struct srv_data
{
SERVER_ENET enet;
SERVER_TIMER timer;
SERVER_EVENT event;
SERVER_USERS users;
SERVER_GAMES games;
bool done;
} SERVER_DATA;
SERVER_DATA* srv_create_data(SERVER_DATA* data, SERVER_PARAMETRS parametrs);
void srv_destroy_data(SERVER_DATA* data);
SERVER_DATA* srv_get_server_data(SERVER_DATA* data);
void srv_catch_signal(int signal, void (*handler)(int));
void srv_stop_server(int signal);
#endif

334
server/connection.c Normal file
View File

@ -0,0 +1,334 @@
#include "connection.h"
#include <stdio.h>
#include "message.h"
/************************************************************
* CONNECTION HANDLING
***********************************************************/
void srv_send_receive(SERVER_DATA* data)
{
ENetPacket *packet;
ENetEvent event;
SERVER_MESSAGE_NONE* message_none;
SERVER_MESSAGE_JOINGAME* message_list;
SERVER_MESSAGE_SENDPARTY* message_party;
SERVER_MESSAGE_GAME* message_game;
while (enet_host_service(data->enet.server, &event, 0) > 0)
{
switch(event.type)
{
case ENET_EVENT_TYPE_NONE:
break;
case ENET_EVENT_TYPE_CONNECT:
printf("Сервер: новый пользователь из %x:%hu\n", event.peer->address.host, event.peer->address.port);
SERVER_USER* user = srv_get_free_user(&data->users);
show_message_error(user, "Failed to allocate free game");
// Отсоединить пользователя
// enet_peer_disconnect_now(event.peer, 0);
user->peer = event.peer; // сохранить пир в пользователе
event.peer->data = malloc(sizeof(int));
*(int*)event.peer->data = user->id;
printf("Сервер: пользователь присоединён #%d\n", user->id);
break;
case ENET_EVENT_TYPE_RECEIVE:
{
int user_id = *(int*)event.peer->data;
switch(data->users.user[user_id]->state)
{
case STATE_NONE:
message_none = (SERVER_MESSAGE_NONE*)event.packet->data;
srv_readmessage_none(data, user_id, message_none);
break;
case STATE_LIST:
message_list = (SERVER_MESSAGE_JOINGAME*)event.packet->data;
srv_readmessage_list(data, user_id, message_list);
break;
case STATE_PARTY:
message_party = (SERVER_MESSAGE_SENDPARTY*)event.packet->data;
srv_readmessage_party(data, user_id, message_party);
break;
case STATE_GAME:
message_game = (SERVER_MESSAGE_GAME*)event.packet->data;
srv_readmessage_game(data, user_id, message_game);
break;
}
enet_packet_destroy(event.packet);
break;
}
case ENET_EVENT_TYPE_DISCONNECT:
{
int user_id = *(int*)event.peer->data;
srv_removing_from_game(data, data->users.user[user_id]);
srv_clear_user(data->users.user[user_id]);
printf("Сервер: пользователь #%d был отсоединён\n", user_id);
// сообщить пользователям об отсоединении клиента
free(event.peer->data);
event.peer->data = NULL;
break;
}
}
}
}
static void srv_readmessage_none(SERVER_DATA* data, int user_id, SERVER_MESSAGE_NONE* message)
{
SERVER_USER* user = data->users.user[user_id];
user->display_height = message->display_height;
user->display_width = message->display_width;
user->scale_factor = message->scale_factor;
user->is_creator = message->is_creator;
user->is_ready = message->is_ready;
strncpy(user->nickname, message->nickname, 40);
if(message->is_creator)
srv_create_new_game(data, user, message->game_name);
srv_change_state(data, user_id, message->state);
}
static void srv_readmessage_list(SERVER_DATA* data, int user_id, SERVER_MESSAGE_JOINGAME* message)
{
SERVER_USER* user = data->users.user[user_id];
SERVER_GAME* game = data->games.game[message->id];
ENetPacket *packet;
SERVER_MESSAGE_LIST answer;
if(game->count_connected < 3)
{
game->count_connected++;
srv_change_state(data, user_id, message->state);
user->game_id = message->id;
user->in_game = true;
for(int i = 0; i < game->user_size; i++)
if(!game->user[i])
{
game->user[i] = user;
break;
}
answer.state = message->state;
packet = enet_packet_create(&answer, sizeof(answer), ENET_PACKET_FLAG_RELIABLE);
enet_peer_send(user->peer, 0, packet);
}
}
static void srv_readmessage_party(SERVER_DATA* data, int user_id, SERVER_MESSAGE_SENDPARTY* message)
{
SERVER_USER* user = data->users.user[user_id];
switch(message->state)
{
case STATE_LIST:
if(message->kick_user)
user = data->users.user[message->user_id];
srv_removing_from_game(data, user);
user->state = message->state;
user->in_game = false;
user->is_ready = false;
user->game_id = -1;
user->is_creator = false;
srv_send_change_state(user, message->state);
break;
case STATE_PARTY:
user->is_ready = message->is_ready;
break;
case STATE_GAME:
srv_start_game(data, user);
break;
}
}
static void srv_readmessage_game(SERVER_DATA* data, int user_id, SERVER_MESSAGE_GAME* message)
{
SERVER_USER* user = data->users.user[user_id];
switch(message->state)
{
case STATE_GAME:
{
user->command.dx = message->dx;
user->command.dy = message->dy;
user->command.fire = message->fire;
break;
}
}
}
static void srv_change_state(SERVER_DATA* data, int user_id, SERVER_STATE state)
{
SERVER_USER* user = data->users.user[user_id];
user->state = state;
}
static void srv_create_new_game(SERVER_DATA* data, SERVER_USER* user, const char* game_name)
{
// Creating a new game and placing the user there
SERVER_GAME* game = srv_get_free_game(&data->games);
// Отправить сообщение в случае, если нет места для создания новой игры
show_message_error(game, "Failed to allocate free game");
user->game_id = game->id;
user->in_game = true;
game->user[0] = user;
game->count_connected++;
strncpy(game->game_name, game_name, 40);
}
static void srv_removing_from_game(SERVER_DATA* data, SERVER_USER* user)
{
if(user->in_game)
{
SERVER_GAME* game = data->games.game[user->game_id];
for(int i = 0; i < game->user_size; i++)
if(game->user[i] && game->user[i]->id == user->id)
{
game->user[i] = NULL;
--game->count_connected;
if(game->game_started)
{
for(int j = 0; j < game->objects.ship_size; j++)
if(user->id == game->objects.ships[j]->ID)
game->objects.ships[j]->active = false;
for(int j = 0; j < game->objects.bullet_size; j++)
if(user->id == game->objects.bullets[j]->ID)
game->objects.bullets[j]->active = false;
}
if(game->count_connected == 0)
{
if(game->game_started)
srv_destroy_objects(&game->objects);
srv_clear_games(game);
}
else if(user->is_creator)
{
for(int j = 0; j < game->user_size; j++)
if(game->user[j])
{
game->user[j]->is_creator = true;
game->user[j]->is_ready = true;
break;
}
}
break;
}
}
}
static void srv_start_game(SERVER_DATA* data, SERVER_USER* user)
{
if(user->in_game)
{
bool users_ready = true;
SERVER_GAME* game = data->games.game[user->game_id];
for(int i = 0; i < game->user_size; i++)
if(game->user[i])
if(!game->user[i]->is_ready)
{
users_ready = false;
break;
}
if(users_ready)
{
game->game_started = true;
srv_init_objects(game);
for(int i = 0; i < game->user_size; i++)
if(game->user[i])
{
game->user[i]->command.dx = 0;
game->user[i]->command.dy = 0;
game->user[i]->command.fire = false;
game->user[i]->state = STATE_GAME;
srv_send_change_state(game->user[i], STATE_GAME);
}
}
}
}
static void srv_send_change_state(SERVER_USER* user, SERVER_STATE state)
{
ENetPacket *packet;
SERVER_MESSAGE_PARTY message;
message.state = state;
packet = enet_packet_create(&message, sizeof(message), ENET_PACKET_FLAG_RELIABLE);
enet_peer_send(user->peer, 0, packet);
}
static void srv_init_objects(SERVER_GAME* game)
{
SERVER_OBJECTS* objects = &game->objects;
int count_users = game->count_connected;
int start_position = 0;
int position_ratio = 1; // part user position
bool start_ratio = false;
int iterator = 0;
srv_create_objects(objects, count_users, 5 * count_users, 15, 5 * count_users);
for(int i = 0; i < game->user_size; i++)
if(game->user[i] && game->user[i]->is_creator)
{
game->display_width = game->user[i]->display_width;
game->display_height = game->user[i]->display_height;
game->scale_factor = game->user[i]->scale_factor;
break;
}
start_position = game->display_height / (count_users * 2);
for(int i = 0; i < game->user_size; i++)
if(game->user[i])
{
if(start_ratio)
position_ratio += 2;
else
start_ratio = true;
srv_init_ships(objects, iterator, game->user[i]->id, 3, 1, 1, 10, 12, 0, 0, 50, 41, 46, 3, 3, 0, 250, 20, start_position * position_ratio);
for(int j = iterator++ * 5; j < iterator * 5; j++)
srv_init_bullets(objects, j, game->user[i]->id, 500, 0, 0);
}
for(int i = 0; i < objects->comet_size; i++)
srv_init_comets(objects, i, 0, 21, rand() % 2 ? 1 : -1, 35, 35, 0, 0, 2, 96, 96, 143, 250, 0, 0);
for(int i = 0; i < objects->explosion_size; i++)
srv_init_explosions(objects, i, 8, 1, 0, 0, 1, 128, 128, 31, 0, 0);
}

155
server/connection.h Normal file
View File

@ -0,0 +1,155 @@
/*
* File: connection.h
* Author: Alexander Zhirov
* Connection with me (telegram messanger): @alexanderzhirov
*
* Created on 2020.06.14
*/
#ifndef server_connection
#define server_connection
#include "common.h"
typedef struct srv_usercommand
{
int dx;
int dy;
bool fire;
} SERVER_USER_COMMAND;
typedef struct srv_userdata
{
int id;
char nickname[40];
bool is_ready;
SERVER_USER_COMMAND command;
} SERVER_USER_DATA;
typedef struct srv_gamedata
{
int id;
char game_name[40];
int count_connected;
} SERVER_GAME_DATA;
typedef struct srv_message_none
{
int display_width;
int display_height;
float scale_factor;
SERVER_STATE state;
char game_name[40];
char nickname[40];
bool is_creator;
bool is_ready;
} SERVER_MESSAGE_NONE;
typedef struct srv_message_list
{
SERVER_GAME_DATA games[3];
SERVER_STATE state;
int count_game;
} SERVER_MESSAGE_LIST;
typedef struct srv_message_party
{
int game_id;
int user_id;
SERVER_USER_DATA users[3];
char game_name[40];
int count_connected;
bool game_started;
bool active;
bool is_creator;
bool is_ready;
SERVER_STATE state;
} SERVER_MESSAGE_PARTY;
typedef struct srv_message_sendparty
{
SERVER_STATE state;
bool is_creator;
bool is_ready;
bool kick_user;
int user_id;
} SERVER_MESSAGE_SENDPARTY;
typedef struct srv_message_joingame
{
int id;
SERVER_STATE state;
} SERVER_MESSAGE_JOINGAME;
typedef struct srv_message_game
{
int dx;
int dy;
bool fire;
SERVER_STATE state;
} SERVER_MESSAGE_GAME;
// GAME
typedef struct srv_update_ship
{
int ID;
int x;
int y;
int dx;
int dy;
int lives;
int score;
bool active;
} SERVER_UPDATE_SHIP;
typedef struct srv_update_bullet
{
int ID;
int x;
int y;
bool live;
bool active;
} SERVER_UPDATE_BULLET;
typedef struct srv_update_comet
{
int x;
int y;
bool live;
} SERVER_UPDATE_COMET;
typedef struct srv_update_explosion
{
int x;
int y;
bool live;
} SERVER_UPDATE_EXPLOSION;
typedef struct srv_message_update
{
SERVER_UPDATE_SHIP ship[3];
SERVER_UPDATE_BULLET bullet[15];
SERVER_UPDATE_COMET comet[15];
SERVER_UPDATE_EXPLOSION explosion[15];
} SERVER_MESSAGE_UPDATE;
void srv_send_receive(SERVER_DATA* data);
static void srv_readmessage_none(SERVER_DATA* data, int user_id, SERVER_MESSAGE_NONE* message);
static void srv_readmessage_list(SERVER_DATA* data, int user_id, SERVER_MESSAGE_JOINGAME* message);
static void srv_readmessage_party(SERVER_DATA* data, int user_id, SERVER_MESSAGE_SENDPARTY* message);
static void srv_readmessage_game(SERVER_DATA* data, int user_id, SERVER_MESSAGE_GAME* message);
static void srv_change_state(SERVER_DATA* data, int user_id, SERVER_STATE state);
static void srv_create_new_game(SERVER_DATA* data, SERVER_USER* user, const char* game_name);
static void srv_removing_from_game(SERVER_DATA* data, SERVER_USER* user);
static void srv_start_game(SERVER_DATA* data, SERVER_USER* user);
static void srv_send_change_state(SERVER_USER* user, SERVER_STATE state);
static void srv_init_objects(SERVER_GAME* game);
#endif

60
server/data.c Normal file
View File

@ -0,0 +1,60 @@
#include <signal.h>
#include "common.h"
#include "message.h"
SERVER_DATA* srv_create_data(SERVER_DATA* data, SERVER_PARAMETRS parametrs)
{
if(!data)
{
data = (SERVER_DATA*)malloc(sizeof(SERVER_DATA));
show_message_error(data, "Failed to allocate space for SERVER_DATA");
}
srv_create_enet(&data->enet, parametrs.port);
puts("Enet создан!");
srv_create_timer(&data->timer, parametrs.FPS);
puts("Таймер загружен. Готов к запуску!");
srv_create_event(&data->event, &data->timer);
puts("События ждут указаний!");
srv_create_users(&data->users, parametrs.users);
puts("Место для игроков выделено!");
srv_create_games(&data->games, parametrs.games);
puts("Место для игр выделено!");
puts("Все системы в норме! Запускаю сервер!");
puts("--------------------------------------------------");
data->done = false;
srv_get_server_data(data);
// Server Stop Event Logging
srv_catch_signal(SIGINT, srv_stop_server);
return data;
}
void srv_destroy_data(SERVER_DATA* data)
{
srv_destroy_enet(&data->enet);
puts("Почистил Enet!");
srv_destroy_event(&data->event);
puts("С событиями тоже разобрался!");
srv_destroy_timer(&data->timer);
puts("Кто говорил, что временем нельзя управлять? Таймер остановлен!");
srv_destroy_users(&data->users);
puts("Освободил выделенное место для игроков!");
srv_destroy_games(&data->games);
puts("Освободил выделенное место для игр!");
free(data);
puts("Сервер остановлен! Порядок!");
}
SERVER_DATA* srv_get_server_data(SERVER_DATA* data)
{
static SERVER_DATA* server;
if(data)
server = data;
return server;
}

89
server/games/games.c Normal file
View File

@ -0,0 +1,89 @@
#include "games.h"
#include "message.h"
SERVER_GAMES* srv_create_games(SERVER_GAMES* games, int game_size)
{
if(!games)
{
games = (SERVER_GAMES*)malloc(sizeof(SERVER_GAMES));
show_message_error(games, "Failed to allocate space for SERVER_GAMES");
}
games->game_size = game_size;
if(game_size)
{
games->game = (SERVER_GAME**)malloc(sizeof(SERVER_GAME*) * game_size);
show_message_error(games->game, "Failed to allocate space for SERVER_GAME collection");
for(int i = 0; i < game_size; i++)
{
games->game[i] = (SERVER_GAME*)malloc(sizeof(SERVER_GAME));
show_message_error(games->game[i], "Failed to allocate space for SERVER_USER");
games->game[i]->user = (SERVER_USER**)malloc(sizeof(SERVER_USER*) * 3);
show_message_error(games->game[i]->user, "Failed to allocate space for SERVER_USER collection");
games->game[i]->active = false;
games->game[i]->game_started = false;
games->game[i]->count_connected = 0;
games->game[i]->user_size = 3;
games->game[i]->game_name[0] = '\0';
games->game[i]->display_width = 0;
games->game[i]->display_height = 0;
games->game[i]->scale_factor = 0;
for(int j = 0; j < 3; j++)
games->game[i]->user[j] = NULL;
}
}
else
games->game = NULL;
return games;
}
void srv_free_games(SERVER_GAMES* games)
{
srv_destroy_games(games);
free(games);
}
void srv_destroy_games(SERVER_GAMES* games)
{
for(int i = 0; i < games->game_size; i++)
{
free(games->game[i]->user);
free(games->game[i]);
}
free(games->game);
}
// return pointer
SERVER_GAME* srv_get_free_game(SERVER_GAMES* games)
{
for(int i = 0; i < games->game_size; i++)
if(!games->game[i]->active)
{
games->game[i]->active = true;
games->game[i]->id = i;
return games->game[i];
}
return NULL;
}
void srv_clear_games(SERVER_GAME* game)
{
for(int i = 0; i < game->user_size; i++)
game->user[i] = NULL;
game->active = false;
game->game_started = false;
game->count_connected = 0;
game->game_name[0] = '\0';
game->display_width = 0;
game->display_height = 0;
game->scale_factor = 0;
}

46
server/games/games.h Normal file
View File

@ -0,0 +1,46 @@
/*
* File: games.h
* Author: Alexander Zhirov
* Connection with me (telegram messanger): @alexanderzhirov
*
* Created on 2020.06.15
*/
#ifndef server_games
#define server_games
#include "users.h"
#include "objects.h"
typedef struct srv_game
{
int id;
int display_width;
int display_height;
float scale_factor;
char game_name[40];
SERVER_USER** user;
int user_size;
int count_connected;
bool game_started;
bool active;
SERVER_OBJECTS objects;
} SERVER_GAME;
typedef struct srv_games
{
SERVER_GAME** game;
int game_size;
} SERVER_GAMES;
SERVER_GAMES* srv_create_games(SERVER_GAMES* games, int game_size);
void srv_free_games(SERVER_GAMES* games);
void srv_destroy_games(SERVER_GAMES* games);
void srv_clear_games(SERVER_GAME* game);
SERVER_GAME* srv_get_free_game(SERVER_GAMES* games);
#endif

10
server/lib/common.c Normal file
View File

@ -0,0 +1,10 @@
#include <allegro5/allegro.h>
#include "common.h"
#include "message.h"
void srv_load_resources()
{
show_message_error(al_init(), "Failed to initialize Allegro");
show_message_error(srv_check_init_enet(enet_initialize()), "Failed to enet initialize");
}

33
server/lib/common.h Normal file
View File

@ -0,0 +1,33 @@
/*
* File: common.h
* Author: Alexander Zhirov
* Connection with me (telegram messanger): @alexanderzhirov
*
* Created on 2020.06.13
*/
#ifndef server_common
#define server_common
#include "enet.h"
#include "timer.h"
#include "event.h"
typedef struct srv_resource
{
SERVER_ENET enet;
SERVER_TIMER timer;
SERVER_EVENT event;
} SERVER_RESOURCE;
typedef struct cl_parametrs
{
int port;
int FPS;
int users;
int games;
} SERVER_PARAMETRS;
void srv_load_resources();
#endif

36
server/lib/enet.c Normal file
View File

@ -0,0 +1,36 @@
#include "enet.h"
#include "message.h"
SERVER_ENET* srv_create_enet(SERVER_ENET* enet, int port)
{
if(!enet)
{
enet = (SERVER_ENET*)malloc(sizeof(SERVER_ENET));
show_message_error(enet, "Failed to allocate space for SERVER_ENET");
}
enet->address.host = ENET_HOST_ANY;
enet->address.port = port;
enet->server = enet_host_create(&enet->address, 32, 2, 0, 0);
show_message_error(enet->server, "Failed to enet host create");
return enet;
}
void srv_free_enet(SERVER_ENET* enet)
{
srv_destroy_enet(enet);
free(enet);
}
void srv_destroy_enet(SERVER_ENET* enet)
{
enet_host_destroy(enet->server);
enet_deinitialize();
}
bool srv_check_init_enet(int result)
{
return result == 0;
}

27
server/lib/enet.h Normal file
View File

@ -0,0 +1,27 @@
/*
* File: enet.h
* Author: Alexander Zhirov
* Connection with me (telegram messanger): @alexanderzhirov
*
* Created on 2020.06.13
*/
#ifndef server_enet
#define server_enet
#include <enet/enet.h>
#include <stdbool.h>
typedef struct srv_enet
{
ENetHost* server;
ENetAddress address;
} SERVER_ENET;
SERVER_ENET* srv_create_enet(SERVER_ENET* enet, int port);
void srv_free_enet(SERVER_ENET* enet);
void srv_destroy_enet(SERVER_ENET* enet);
bool srv_check_init_enet(int result);
#endif

30
server/lib/event.c Normal file
View File

@ -0,0 +1,30 @@
#include "event.h"
#include "message.h"
SERVER_EVENT* srv_create_event(SERVER_EVENT* event, SERVER_TIMER* timer)
{
if(!event)
{
event = (SERVER_EVENT*)malloc(sizeof(SERVER_EVENT));
show_message_error(event, "Failed to allocate space for SERVER_EVENT");
}
event->queue = al_create_event_queue();
show_message_error(event->queue, "Failed to create Allegro event");
if(timer)
al_register_event_source(event->queue, al_get_timer_event_source(timer->al_timer));
return event;
}
void srv_free_event(SERVER_EVENT* event)
{
srv_destroy_event(event);
free(event);
};
void srv_destroy_event(SERVER_EVENT* event)
{
al_destroy_event_queue(event->queue);
}

28
server/lib/event.h Normal file
View File

@ -0,0 +1,28 @@
/*
* File: event.h
* Author: Alexander Zhirov
* Connection with me (telegram messanger): @alexanderzhirov
*
* Created on 2020.06.13
*/
#ifndef server_event
#define server_event
#include <allegro5/allegro5.h>
#include "timer.h"
typedef struct srv_event
{
ALLEGRO_EVENT_QUEUE* queue;
ALLEGRO_EVENT current;
} SERVER_EVENT;
SERVER_EVENT* srv_create_event(SERVER_EVENT* event, SERVER_TIMER* timer);
void srv_free_event(SERVER_EVENT* event);
void srv_destroy_event(SERVER_EVENT* event);
#endif

10
server/lib/message.c Normal file
View File

@ -0,0 +1,10 @@
#include "message.h"
void show_message_error(bool result, const char* message)
{
if(!result)
{
printf("%s\n", message);
exit(EXIT_FAILURE);
}
}

21
server/lib/message.h Normal file
View File

@ -0,0 +1,21 @@
/*
* File: message.h
* Author: Alexander Zhirov
* Connection with me (telegram messanger): @alexanderzhirov
*
* Created on 2020.06.13
*/
#ifndef server_message
#define server_message
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
void show_message_error(bool result, const char* message);
#endif

38
server/lib/timer.c Normal file
View File

@ -0,0 +1,38 @@
#include "timer.h"
#include "message.h"
SERVER_TIMER* srv_create_timer(SERVER_TIMER* timer, int FPS)
{
if(!timer)
{
timer = (SERVER_TIMER*)malloc(sizeof(SERVER_TIMER));
show_message_error(timer, "Failed to allocate space for SERVER_TIMER");
}
timer->al_timer = al_create_timer(1.0 / FPS);
show_message_error(timer->al_timer, "Failed to create Allegro timer");
timer->last_time = 0.0;
timer->current_time = 0.0;
timer->elapsed_time = 0.0;
return timer;
}
void srv_free_timer(SERVER_TIMER* timer)
{
srv_destroy_timer(timer);
free(timer);
}
void srv_destroy_timer(SERVER_TIMER* timer)
{
al_destroy_timer(timer->al_timer);
}
void srv_update_time(SERVER_TIMER* timer)
{
timer->last_time = timer->current_time;
timer->current_time = al_get_time();
timer->elapsed_time = timer->current_time - timer->last_time;
}

31
server/lib/timer.h Normal file
View File

@ -0,0 +1,31 @@
/*
* File: timer.h
* Author: Alexander Zhirov
* Connection with me (telegram messanger): @alexanderzhirov
*
* Created on 2020.06.13
*/
#ifndef server_timer
#define server_timer
#include <allegro5/allegro5.h>
typedef struct srv_timer
{
ALLEGRO_TIMER* al_timer;
double last_time;
double current_time;
double elapsed_time;
} SERVER_TIMER;
SERVER_TIMER* srv_create_timer(SERVER_TIMER* timer, int FPS);
void srv_free_timer(SERVER_TIMER* timer);
void srv_destroy_timer(SERVER_TIMER* timer);
void srv_update_time(SERVER_TIMER* timer);
#endif

41
server/main.c Normal file
View File

@ -0,0 +1,41 @@
#include <stdio.h>
#include "server.h"
int main(int argc, char** argv)
{
srv_load_resources();
SERVER_PARAMETRS parametrs =
{
.port = 9234,
.FPS = 60,
.users = 30,
.games = 3
};
SERVER_DATA* data = srv_create_data(NULL, parametrs);
al_start_timer(data->timer.al_timer);
data->timer.current_time = al_current_time();
srand(time(NULL));
while(!data->done)
{
al_wait_for_event(data->event.queue, &data->event.current);
if(data->event.current.type == ALLEGRO_EVENT_TIMER)
{
srv_update_time(&data->timer);
// возможно тут нужно сделать потоки
srv_game_update(data);
srv_client_update(data);
srv_send_receive(data);
}
}
srv_destroy_data(data);
return EXIT_SUCCESS;
}

194
server/objects/objects.c Normal file
View File

@ -0,0 +1,194 @@
#include "objects.h"
#include "message.h"
SERVER_OBJECTS* srv_create_objects(SERVER_OBJECTS* objects, int ship_size, int bullet_size, int comet_size, int explosion_size)
{
if(!objects)
{
SERVER_OBJECTS* objects = (SERVER_OBJECTS*)malloc(sizeof(SERVER_OBJECTS));
show_message_error(objects, "Failed to allocate space for SERVER_OBJECTS");
}
objects->ship_size = ship_size;
objects->bullet_size = bullet_size;
objects->comet_size = comet_size;
objects->explosion_size = explosion_size;
objects->ships = srv_create_ships(ship_size);
objects->bullets = srv_create_bullets(bullet_size);
objects->comets = srv_create_comets(comet_size);
objects->explosions = srv_create_explosions(explosion_size);
return objects;
}
void srv_free_objects(SERVER_OBJECTS* objects)
{
srv_destroy_objects(objects);
free(objects);
}
void srv_destroy_objects(SERVER_OBJECTS* objects)
{
if(objects->ship_size > 0)
{
for(int i = 0; i < objects->ship_size; i++)
free(objects->ships[i]);
free(objects->ships);
}
if(objects->bullet_size > 0)
{
for(int i = 0; i < objects->bullet_size; i++)
free(objects->bullets[i]);
free(objects->bullets);
}
if(objects->comet_size > 0)
{
for(int i = 0; i < objects->comet_size; i++)
free(objects->comets[i]);
free(objects->comets);
}
if(objects->explosion_size > 0)
{
for(int i = 0; i < objects->explosion_size; i++)
free(objects->explosions[i]);
free(objects->explosions);
}
}
static SERVER_SHIP** srv_create_ships(int size)
{
SERVER_SHIP** ships = (SERVER_SHIP**)malloc(sizeof(SERVER_SHIP*) * size);
show_message_error(ships, "Failed to allocate space for SERVER_SHIP collection");
for(int i = 0; i < size; i++)
{
ships[i] = (SERVER_SHIP*)malloc(sizeof(SERVER_SHIP));
show_message_error(ships[i], "Failed to allocate space for SERVER_SHIP");
}
return ships;
}
static SERVER_BULLET** srv_create_bullets(int size)
{
SERVER_BULLET** bullets = (SERVER_BULLET**)malloc(sizeof(SERVER_BULLET*) * size);
show_message_error(bullets, "Failed to allocate space for SERVER_BULLET collection");
for(int i = 0; i < size; i++)
{
bullets[i] = (SERVER_BULLET*)malloc(sizeof(SERVER_BULLET));
show_message_error(bullets[i], "Failed to allocate space for SERVER_BULLET");
}
return bullets;
}
static SERVER_COMET** srv_create_comets(int size)
{
SERVER_COMET** comets = (SERVER_COMET**)malloc(sizeof(SERVER_COMET*) * size);
show_message_error(comets, "Failed to allocate space for SERVER_COMET collection");
for(int i = 0; i < size; i++)
{
comets[i] = (SERVER_COMET*)malloc(sizeof(SERVER_COMET));
show_message_error(comets[i], "Failed to allocate space for SERVER_COMET");
}
return comets;
}
static SERVER_EXPLOSION** srv_create_explosions(int size)
{
SERVER_EXPLOSION** explosions = (SERVER_EXPLOSION**)malloc(sizeof(SERVER_EXPLOSION*) * size);
show_message_error(explosions, "Failed to allocate space for SERVER_EXPLOSION collection");
for(int i = 0; i < size; i++)
{
explosions[i] = (SERVER_EXPLOSION*)malloc(sizeof(SERVER_EXPLOSION));
show_message_error(explosions[i], "Failed to allocate space for SERVER_EXPLOSION");
}
return explosions;
}
void srv_init_ships(SERVER_OBJECTS* objects, int key_ship, int ID, int animation_columns, int animation_direction, int animation_row, int boundx, int boundy, int cur_frame,
int frame_count, int frame_delay, int frame_height, int frame_width, int lives, int max_frame, int score, int speed, int x, int y)
{
SERVER_SHIP* ship = objects->ships[key_ship];
ship->ID = ID;
ship->animation_columns = animation_columns;
ship->animation_direction = animation_direction;
ship->animation_row = animation_row;
ship->boundx = boundx;
ship->boundy = boundy;
ship->cur_frame = cur_frame;
ship->frame_count = frame_count;
ship->frame_delay = frame_delay;
ship->frame_height = frame_height;
ship->frame_width = frame_width;
ship->lives = lives;
ship->max_frame = max_frame;
ship->score = score;
ship->speed = speed;
ship->x = x;
ship->y = y;
ship->active = true;
}
void srv_init_bullets(SERVER_OBJECTS* objects, int key_bullet, int ID, int speed, int x, int y)
{
SERVER_BULLET* bullet = objects->bullets[key_bullet];
bullet->ID = ID;
bullet->live = false;
bullet->speed = speed;
bullet->x = x;
bullet->y = y;
bullet->active = true;
}
void srv_init_comets(SERVER_OBJECTS* objects, int key_comet, int ID, int animation_columns, int animation_direction, int boundx, int boundy, int cur_frame,
int frame_count, int frame_delay, int frame_height, int frame_width, int max_frame, int speed, int x, int y)
{
SERVER_COMET* comet = objects->comets[key_comet];
comet->ID = ID;
comet->animation_columns = animation_columns;
comet->animation_direction = animation_direction;
comet->boundx = boundx;
comet->boundy = boundy;
comet->cur_frame = cur_frame;
comet->frame_count = frame_count;
comet->frame_delay = frame_delay;
comet->frame_height = frame_height;
comet->frame_width = frame_width;
comet->max_frame = max_frame;
comet->speed = speed;
comet->live = false;
comet->x = x;
comet->y = y;
}
void srv_init_explosions(SERVER_OBJECTS* objects, int key_explosion, int animation_columns, int animation_direction, int cur_frame,
int frame_count, int frame_delay, int frame_height, int frame_width, int max_frame, int x, int y)
{
SERVER_EXPLOSION* explosion = objects->explosions[key_explosion];
explosion->animation_columns = animation_columns;
explosion->animation_direction = animation_direction;
explosion->cur_frame = cur_frame;
explosion->frame_count = frame_count;
explosion->frame_delay = frame_delay;
explosion->frame_height = frame_height;
explosion->frame_width = frame_width;
explosion->live = false;
explosion->max_frame = max_frame;
explosion->x = x;
explosion->y = y;
explosion->lifetime = 0;
}

114
server/objects/objects.h Normal file
View File

@ -0,0 +1,114 @@
/*
* File: objects.h
* Author: Alexander Zhirov
* Connection with me (telegram messanger): @alexanderzhirov
*
* Created on 2020.06.03
*/
#ifndef server_objects
#define server_objects
#include <stdbool.h>
typedef struct srv_ship
{
int ID;
int x;
int y;
int lives;
int speed;
int boundx;
int boundy;
int score;
bool active;
int max_frame;
int cur_frame;
int frame_count;
int frame_delay;
int frame_width;
int frame_height;
int animation_columns;
int animation_direction;
int animation_row;
} SERVER_SHIP;
typedef struct srv_bullet
{
int ID;
int x;
int y;
bool live;
int speed;
bool active;
} SERVER_BULLET;
typedef struct srv_comet
{
int ID;
int x;
int y;
bool live;
int speed;
int boundx;
int boundy;
int max_frame;
int cur_frame;
int frame_count;
int frame_delay;
int frame_width;
int frame_height;
int animation_columns;
int animation_direction;
} SERVER_COMET;
typedef struct srv_explosion
{
int x;
int y;
bool live;
float lifetime;
int max_frame;
int cur_frame;
int frame_count;
int frame_delay;
int frame_width;
int frame_height;
int animation_columns;
int animation_direction;
} SERVER_EXPLOSION;
typedef struct srv_objects
{
SERVER_SHIP** ships;
int ship_size;
SERVER_BULLET** bullets;
int bullet_size;
SERVER_COMET** comets;
int comet_size;
SERVER_EXPLOSION** explosions;
int explosion_size;
} SERVER_OBJECTS;
SERVER_OBJECTS* srv_create_objects(SERVER_OBJECTS* data, int ship_size, int bullet_size, int comet_size, int explosion_size);
void srv_free_objects(SERVER_OBJECTS* objects);
void srv_destroy_objects(SERVER_OBJECTS* objects);
static SERVER_SHIP** srv_create_ships(int size);
static SERVER_BULLET** srv_create_bullets(int size);
static SERVER_COMET** srv_create_comets(int size);
static SERVER_EXPLOSION** srv_create_explosions(int size);
void srv_init_ships(SERVER_OBJECTS* objects, int key_ship, int ID, int animation_columns, int animation_direction, int animation_row, int boundx, int boundy, int cur_frame,
int frame_count, int frame_delay, int frame_height, int frame_width, int lives, int max_frame, int score, int speed, int x, int y);
void srv_init_bullets(SERVER_OBJECTS* objects, int key_bullet, int ID, int speed, int x, int y);
void srv_init_comets(SERVER_OBJECTS* objects, int key_comet, int ID, int animation_columns, int animation_direction, int boundx, int boundy, int cur_frame,
int frame_count, int frame_delay, int frame_height, int frame_width, int max_frame, int speed, int x, int y);
void srv_init_explosions(SERVER_OBJECTS* objects, int key_explosion, int animation_columns, int animation_direction, int cur_frame,
int frame_count, int frame_delay, int frame_height, int frame_width, int max_frame, int x, int y);
#endif

19
server/server.h Normal file
View File

@ -0,0 +1,19 @@
/*
* File: server.h
* Author: Alexander Zhirov
* Connection with me (telegram messanger): @alexanderzhirov
*
* Created on 2020.06.14
*/
#ifndef SERVER_H
#define SERVER_H
#include "common.h"
#include "connection.h"
#include "update.h"
#endif

164
server/update.c Normal file
View File

@ -0,0 +1,164 @@
#include "update.h"
#include "connection.h"
#include <stdio.h>
/************************************************************
* UPDATE GAMES
***********************************************************/
void srv_game_update(SERVER_DATA* data)
{
for(int i = 0; i < data->games.game_size; i++)
{
if(!data->games.game[i]->active) continue;
SERVER_GAME* game = data->games.game[i];
if(game->game_started)
srv_handle_game(data, game);
else
srv_handle_party(data, game);
}
}
static void srv_handle_party(SERVER_DATA* data, SERVER_GAME* game)
{
ENetPacket *packet;
SERVER_MESSAGE_PARTY message;
int iterator = 0;
for(int i = 0; i < game->user_size; i++)
if(game->user[i])
{
message.users[iterator].id = game->user[i]->id;
message.users[iterator].is_ready = game->user[i]->is_ready;
strncpy(message.users[iterator].nickname, game->user[i]->nickname, 40);
iterator++;
}
message.count_connected = game->count_connected;
message.game_id = game->id;
message.active = game->active;
message.game_started = game->game_started;
strncpy(message.game_name, game->game_name, 40);
for(int i = 0; i < game->user_size; i++)
if(game->user[i])
{
message.is_creator = game->user[i]->is_creator;
message.is_ready = game->user[i]->is_ready;
message.user_id = game->user[i]->id;
packet = enet_packet_create(&message, sizeof(message), ENET_PACKET_FLAG_RELIABLE);
enet_peer_send(game->user[i]->peer, 0, packet);
}
}
static void srv_handle_game(SERVER_DATA* data, SERVER_GAME* game)
{
ENetPacket *packet;
SERVER_MESSAGE_UPDATE message;
srv_clear_message(&message);
srv_update_explosions(data, game);
srv_move_ship(data, game, &message);
srv_fire_bullet(game);
srv_update_bullet(data, game, &message);
srv_start_comet(game);
srv_update_comet(data, game, &message);
srv_collide_bullet(game, &message);
srv_collide_comet(game, &message);
for(int i = 0; i < game->user_size; i++)
if(game->user[i])
{
packet = enet_packet_create(&message, sizeof(message), ENET_PACKET_FLAG_RELIABLE);
enet_peer_send(game->user[i]->peer, 0, packet);
}
}
static void srv_clear_message(SERVER_MESSAGE_UPDATE* message)
{
for(int i = 0; i < 15; i++)
{
message->explosion[i].live = false;
message->explosion[i].x = 0;
message->explosion[i].y = 0;
}
for(int i = 0; i < 15; i++)
{
message->comet[i].live = false;
message->comet[i].x = 0;
message->comet[i].y = 0;
}
for(int i = 0; i < 15; i++)
{
message->bullet[i].ID = -1;
message->bullet[i].active = false;
message->bullet[i].live = false;
message->bullet[i].x = 0;
message->bullet[i].y = 0;
}
for(int i = 0; i < 3; i++)
{
message->ship[i].ID = -1;
message->ship[i].active = false;
message->ship[i].dx = 0;
message->ship[i].dy = 0;
message->ship[i].lives = 0;
message->ship[i].score = 0;
message->ship[i].x = 0;
message->ship[i].y = 0;
}
}
/************************************************************
* UPDATE USERS
***********************************************************/
void srv_client_update(SERVER_DATA* data)
{
for(int i = 0; i < data->users.user_size; i++)
{
if(!data->users.user[i]->active) continue;
SERVER_USER* user = data->users.user[i];
switch(user->state)
{
case STATE_LIST:
srv_handle_userlist(data, user);
break;
case STATE_PARTY:
break;
case STATE_GAME:
break;
}
}
}
static void srv_handle_userlist(SERVER_DATA* data, SERVER_USER* user)
{
ENetPacket *packet;
SERVER_MESSAGE_LIST message;
message.count_game = 0;
int iterator = 0;
for(int i = 0; i < 3; i++)
if(data->games.game[i]->active && !data->games.game[i]->game_started)
{
message.games[iterator].id = data->games.game[i]->id;
message.games[iterator].count_connected = data->games.game[i]->count_connected;
strncpy(message.games[iterator].game_name, data->games.game[i]->game_name, 40);
message.count_game++;
iterator++;
}
message.state = STATE_LIST;
packet = enet_packet_create(&message, sizeof(message), ENET_PACKET_FLAG_RELIABLE);
enet_peer_send(user->peer, 0, packet);
}

31
server/update.h Normal file
View File

@ -0,0 +1,31 @@
/*
* File: update.h
* Author: Alexander Zhirov
* Connection with me (telegram messanger): @alexanderzhirov
*
* Created on 2020.06.15
*/
#ifndef server_update
#define server_update
#include "common.h"
#include "calculation.h"
/************************************************************
* UPDATE USERS
***********************************************************/
void srv_client_update(SERVER_DATA* data);
static void srv_handle_userlist(SERVER_DATA* data, SERVER_USER* user);
/************************************************************
* UPDATE GAMES
***********************************************************/
void srv_game_update(SERVER_DATA* data);
static void srv_handle_party(SERVER_DATA* data, SERVER_GAME* game);
static void srv_handle_game(SERVER_DATA* data, SERVER_GAME* game);
static void srv_clear_message(SERVER_MESSAGE_UPDATE* message);
#endif

88
server/users/users.c Normal file
View File

@ -0,0 +1,88 @@
#include "users.h"
#include "message.h"
SERVER_USERS* srv_create_users(SERVER_USERS* users, int user_size)
{
if(!users)
{
users = (SERVER_USERS*)malloc(sizeof(SERVER_USERS));
show_message_error(users, "Failed to allocate space for SERVER_USERS");
}
users->user_size = user_size;
if(user_size)
{
users->user = (SERVER_USER**)malloc(sizeof(SERVER_USER*) * user_size);
show_message_error(users->user, "Failed to allocate space for SERVER_USER collection");
for(int i = 0; i < user_size; i++)
{
users->user[i] = (SERVER_USER*)malloc(sizeof(SERVER_USER));
show_message_error(users->user[i], "Failed to allocate space for SERVER_USER");
users->user[i]->id = -1;
users->user[i]->active = false;
users->user[i]->is_creator = false;
users->user[i]->is_ready = false;
users->user[i]->in_game = false;
users->user[i]->game_id = -1;
users->user[i]->state = STATE_NONE;
users->user[i]->nickname[0] = '\0';
users->user[i]->display_width = 0;
users->user[i]->display_height = 0;
users->user[i]->scale_factor = 0;
users->user[i]->command.dx = 0;
users->user[i]->command.dy = 0;
users->user[i]->command.fire = false;
}
}
else
users->user = NULL;
return users;
}
void srv_free_users(SERVER_USERS* users)
{
srv_destroy_users(users);
free(users);
}
void srv_destroy_users(SERVER_USERS* users)
{
for(int i = 0; i < users->user_size; i++)
free(users->user[i]);
free(users->user);
}
SERVER_USER* srv_get_free_user(SERVER_USERS* users)
{
for(int i = 0; i < users->user_size; i++)
if(!users->user[i]->active)
{
users->user[i]->id = i;
users->user[i]->active = true;
return users->user[i];
}
return NULL;
}
void srv_clear_user(SERVER_USER* user)
{
user->id = -1;
user->game_id = -1;
user->active = false;
user->is_ready = false;
user->in_game = false;
user->state = STATE_NONE;
user->nickname[0] = '\0';
user->display_width = 0;
user->display_height = 0;
user->command.dx = 0;
user->command.dy = 0;
user->command.fire = false;
user->scale_factor = 0;
}

64
server/users/users.h Normal file
View File

@ -0,0 +1,64 @@
/*
* File: users.h
* Author: Alexander Zhirov
* Connection with me (telegram messanger): @alexanderzhirov
*
* Created on 2020.06.14
*/
#ifndef server_users
#define server_users
#include <stdbool.h>
#include <enet/enet.h>
typedef enum srv_state
{
STATE_NONE,
STATE_LIST,
STATE_PARTY,
STATE_GAME,
STATE_DISCONNECT
} SERVER_STATE;
typedef struct srv_game_command
{
int dx;
int dy;
bool fire;
} SERVER_GAME_COMMAND;
typedef struct srv_user
{
int id;
int game_id;
char nickname[40];
int display_width;
int display_height;
float scale_factor;
SERVER_STATE state;
bool in_game;
bool is_creator; // game creator
bool is_ready;
bool active;
ENetPeer* peer;
SERVER_GAME_COMMAND command;
} SERVER_USER;
typedef struct srv_users
{
SERVER_USER** user;
int user_size;
} SERVER_USERS;
SERVER_USERS* srv_create_users(SERVER_USERS* users, int user_size);
void srv_free_users(SERVER_USERS* users);
void srv_destroy_users(SERVER_USERS* users);
void srv_clear_user(SERVER_USER* user);
SERVER_USER* srv_get_free_user(SERVER_USERS* users);
#endif