From ccb2b5ec3b61c0afb9a90ce3f5c22e6a00e9d261 Mon Sep 17 00:00:00 2001 From: Alexander Zhirov Date: Sun, 30 Apr 2023 23:29:45 +0300 Subject: [PATCH] v1.0.0-dev --- .gitignore | 3 + README.md | 14 ++ images/logo.png | Bin 0 -> 8754 bytes server/CMakeLists.txt | 32 ++++ server/calculation.c | 275 ++++++++++++++++++++++++++++++++ server/calculation.h | 41 +++++ server/common.c | 26 +++ server/common.h | 33 ++++ server/connection.c | 334 +++++++++++++++++++++++++++++++++++++++ server/connection.h | 155 ++++++++++++++++++ server/data.c | 60 +++++++ server/games/games.c | 89 +++++++++++ server/games/games.h | 46 ++++++ server/lib/common.c | 10 ++ server/lib/common.h | 33 ++++ server/lib/enet.c | 36 +++++ server/lib/enet.h | 27 ++++ server/lib/event.c | 30 ++++ server/lib/event.h | 28 ++++ server/lib/message.c | 10 ++ server/lib/message.h | 21 +++ server/lib/timer.c | 38 +++++ server/lib/timer.h | 31 ++++ server/main.c | 41 +++++ server/objects/objects.c | 194 +++++++++++++++++++++++ server/objects/objects.h | 114 +++++++++++++ server/server.h | 19 +++ server/update.c | 164 +++++++++++++++++++ server/update.h | 31 ++++ server/users/users.c | 88 +++++++++++ server/users/users.h | 64 ++++++++ 31 files changed, 2087 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 images/logo.png create mode 100644 server/CMakeLists.txt create mode 100644 server/calculation.c create mode 100644 server/calculation.h create mode 100644 server/common.c create mode 100644 server/common.h create mode 100644 server/connection.c create mode 100644 server/connection.h create mode 100644 server/data.c create mode 100644 server/games/games.c create mode 100644 server/games/games.h create mode 100644 server/lib/common.c create mode 100644 server/lib/common.h create mode 100644 server/lib/enet.c create mode 100644 server/lib/enet.h create mode 100644 server/lib/event.c create mode 100644 server/lib/event.h create mode 100644 server/lib/message.c create mode 100644 server/lib/message.h create mode 100644 server/lib/timer.c create mode 100644 server/lib/timer.h create mode 100644 server/main.c create mode 100644 server/objects/objects.c create mode 100644 server/objects/objects.h create mode 100644 server/server.h create mode 100644 server/update.c create mode 100644 server/update.h create mode 100644 server/users/users.c create mode 100644 server/users/users.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9624c75 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.vscode +build +spaceserver diff --git a/README.md b/README.md new file mode 100644 index 0000000..a579533 --- /dev/null +++ b/README.md @@ -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 +``` diff --git a/images/logo.png b/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..47c7ae91574184730320c92d124e1bcb33dad904 GIT binary patch literal 8754 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 literal 0 HcmV?d00001 diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt new file mode 100644 index 0000000..94bd23a --- /dev/null +++ b/server/CMakeLists.txt @@ -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}) diff --git a/server/calculation.c b/server/calculation.c new file mode 100644 index 0000000..5210c1e --- /dev/null +++ b/server/calculation.c @@ -0,0 +1,275 @@ +#include "calculation.h" +#include +#include + +/************************************************************ + * 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; + } + } + } +} + diff --git a/server/calculation.h b/server/calculation.h new file mode 100644 index 0000000..f4d088f --- /dev/null +++ b/server/calculation.h @@ -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 + + + diff --git a/server/common.c b/server/common.c new file mode 100644 index 0000000..250b86d --- /dev/null +++ b/server/common.c @@ -0,0 +1,26 @@ +#define _DEFAULT_SOURCE +#include +#include + +#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("Останавливаю сервер! Без паники!"); +} diff --git a/server/common.h b/server/common.h new file mode 100644 index 0000000..bc0c54a --- /dev/null +++ b/server/common.h @@ -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 diff --git a/server/connection.c b/server/connection.c new file mode 100644 index 0000000..c360fd0 --- /dev/null +++ b/server/connection.c @@ -0,0 +1,334 @@ +#include "connection.h" +#include +#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); +} + diff --git a/server/connection.h b/server/connection.h new file mode 100644 index 0000000..2bd157d --- /dev/null +++ b/server/connection.h @@ -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 + + + diff --git a/server/data.c b/server/data.c new file mode 100644 index 0000000..7118367 --- /dev/null +++ b/server/data.c @@ -0,0 +1,60 @@ +#include + +#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; +} diff --git a/server/games/games.c b/server/games/games.c new file mode 100644 index 0000000..80ff138 --- /dev/null +++ b/server/games/games.c @@ -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; +} diff --git a/server/games/games.h b/server/games/games.h new file mode 100644 index 0000000..78978b8 --- /dev/null +++ b/server/games/games.h @@ -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 + + + diff --git a/server/lib/common.c b/server/lib/common.c new file mode 100644 index 0000000..9ecdf1c --- /dev/null +++ b/server/lib/common.c @@ -0,0 +1,10 @@ +#include + +#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"); +} diff --git a/server/lib/common.h b/server/lib/common.h new file mode 100644 index 0000000..7e066be --- /dev/null +++ b/server/lib/common.h @@ -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 diff --git a/server/lib/enet.c b/server/lib/enet.c new file mode 100644 index 0000000..fe6c017 --- /dev/null +++ b/server/lib/enet.c @@ -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; +} diff --git a/server/lib/enet.h b/server/lib/enet.h new file mode 100644 index 0000000..4a2cda7 --- /dev/null +++ b/server/lib/enet.h @@ -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 +#include + +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 diff --git a/server/lib/event.c b/server/lib/event.c new file mode 100644 index 0000000..17fa7ae --- /dev/null +++ b/server/lib/event.c @@ -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); +} diff --git a/server/lib/event.h b/server/lib/event.h new file mode 100644 index 0000000..683ea2b --- /dev/null +++ b/server/lib/event.h @@ -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 +#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 + + + diff --git a/server/lib/message.c b/server/lib/message.c new file mode 100644 index 0000000..218d1af --- /dev/null +++ b/server/lib/message.c @@ -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); + } +} diff --git a/server/lib/message.h b/server/lib/message.h new file mode 100644 index 0000000..8cf8524 --- /dev/null +++ b/server/lib/message.h @@ -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 +#include +#include + +void show_message_error(bool result, const char* message); + +#endif + + + diff --git a/server/lib/timer.c b/server/lib/timer.c new file mode 100644 index 0000000..e602440 --- /dev/null +++ b/server/lib/timer.c @@ -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; +} diff --git a/server/lib/timer.h b/server/lib/timer.h new file mode 100644 index 0000000..1a9cb29 --- /dev/null +++ b/server/lib/timer.h @@ -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 + +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 + + + diff --git a/server/main.c b/server/main.c new file mode 100644 index 0000000..4728866 --- /dev/null +++ b/server/main.c @@ -0,0 +1,41 @@ +#include +#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; +} diff --git a/server/objects/objects.c b/server/objects/objects.c new file mode 100644 index 0000000..7750d57 --- /dev/null +++ b/server/objects/objects.c @@ -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; +} diff --git a/server/objects/objects.h b/server/objects/objects.h new file mode 100644 index 0000000..0f17fdb --- /dev/null +++ b/server/objects/objects.h @@ -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 + +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 diff --git a/server/server.h b/server/server.h new file mode 100644 index 0000000..b6bb4dd --- /dev/null +++ b/server/server.h @@ -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 + + + diff --git a/server/update.c b/server/update.c new file mode 100644 index 0000000..cb8e375 --- /dev/null +++ b/server/update.c @@ -0,0 +1,164 @@ +#include "update.h" +#include "connection.h" +#include + +/************************************************************ + * 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); +} + diff --git a/server/update.h b/server/update.h new file mode 100644 index 0000000..c4240b2 --- /dev/null +++ b/server/update.h @@ -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 + + + diff --git a/server/users/users.c b/server/users/users.c new file mode 100644 index 0000000..c526c64 --- /dev/null +++ b/server/users/users.c @@ -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; +} diff --git a/server/users/users.h b/server/users/users.h new file mode 100644 index 0000000..7506f56 --- /dev/null +++ b/server/users/users.h @@ -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 +#include + +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 + + +