Решил я тут текстовую MMORPG на C++ написать

Итак, я вас сюда заманил, НО сразу повторю, это не гайд по созданию MMORPG на C++. Это нечто вроде моего дневника, куда я буду скидывать процесс разработки (Да, проект ещё не завершён, даже не близко, скорее только начат…). Почему я вообще тогда создал эту статью? Ну, коли ты крутой true-программист, буду рад советам, критике, помощи, ругани, проще говоря всему, что может помочь мне улучшить это. С другой стороны, если ты сам захотел создать нечто похожее, то, быть может, сможешь избежать всех трудностей, с которыми столкнулся я. И для первой, и для второй цели (и для того, чтобы сделать вид хоть сколько-то проделанной работы), я постараюсь как можно доступнее разжевывать всё, что делаю, так начнём же!

Начало

С чего начинается любой проект? С идеи и плана конечно! Идею я, пожалуй, поясню по ходу изложения, в любом случае она будет меняться… План же я нарисовал в виде схемки:

ecafc04813b8dd0eea69c4a44cb4efae.png

Вам страшно? У вас болят глаза? Вы желаете мне удачи (или гореть в аду) и покидаете эту статью? Ваша реакция оправдана, но я всё же не имею совести пояснить, что здесь, да как.

БД — это база данных, что будет хранить всю информацию по проекту, к ней мы вернёмся, но надолго не остановимся.

Админка — это некая панель управления миром, на ней будут создаваться новые объекты и размещаться в мире, а также писаться необходимые скрипты.

Мировой сервер — это сервер, что будет управлять автоматическими изменениями в мире, к примеру (просто пример, далеко не факт, что так и будет): горит огонь и со временем, соседние клетки начинают загораться, вот как-раз подобными процессами и будет управлять мировой сервер (не готов, но уже начат).

Клиентский менеджер (или менеджер клиентов) будет отвечать за работу с игроками, через него игроки будут как авторизироваться, так и получать необходимую клиенту информацию.

Чат будет встроен в клиентский менеджер (поэтому в зелёном кружочке), модерация чата также будет через него.

Клиенты — это уже приложения, через которые в теории будут играть пользователи, на их долю остаётся только то, как будет интерпретироваться, полученная от менеджера, информация.

БД

БД? БД! Но БД же? БД, БД, БД!!! Ох, ok. СУБД=MySQL, почему?

  1. Куча документации.

  2. Лёгкость установки и настройки

  3. Нет проблем с лицензией!

Как установить MySQL на Windows: пошаговая инструкция | Timeweb Cloud

Коли вы осилили скачать и установить VS (или на чём вы там пишете), то проблем с установкой и настройкой MySQL быть не должно. Единственное укажу, что выбрал на данный момент я локальный сервер, ибо один!

И всё же я новичок в работе с MySQL, трудности у меня возникли с присоединением его к моему проекту C++. Впрочем, не так много, ибо документация на любой вкус и цвет решает). А начал я на VS, но мне показалось слишком муторно копаться в его настройках, потому я решил перенести весь процесс компоновки на CMake (да и вообще на VS Code перешёл зачем-то), и-и-и вот, что у меня получилось:

В папке MySQL Server 8.0 (по умолчанию устанавливается по пути: «C:\Program Files\MySQL\MySQL Server 8.0») нашёл папки include и lib. В папку с проектом копировал папку include, а из папки lib туда же копировал libmysql.lib и libmysql.dll (Изначально я с чего-то решил, что эти файлы будут в компоновщике SQL и C++ (он шёл комплектом к серверу), но оказались они по итогу именно в папке сервера). Далее пишу CMakeLists.txt:

cmake_minimum_required (VERSION 3.8)#установил минимальную версию(шаблон)

project (AdminPanel)#Да начал я с админки

add_executable(AdminPanel "main.cpp")#добавил cpp файл

target_include_directories(AdminPanel PRIVATE "include")
#дабы использовать либы из include

find_library(LIBMYSQL NAMES libmysql.lib PATHS ${PROJECT_SOURCE_DIR})
#найти либу libmysql.lib и записать её абсолютный путь в LIBMYSQL

if(LIBMYSQL)#коли либа есть, то линкуем её!
    target_link_libraries(AdminPanel PRIVATE "${LIBMYSQL}")
else()#коли нет - код=death;
    message(FATAL_ERROR "libmysql.lib not found\n")
endif()

find_file(DLLMYSQL NAMES "libmysql.dll" PATHS  $)
#найти libmysql.dll в папке с exe файлом
if(NOT DLLMYSQL)#коли нет её там
    
    find_file(DLLMYSQL NAMES "libmysql.dll" PATHS ${PROJECT_SOURCE_DIR})
    #то ищем в корневом каталоге!

    if(DLLMYSQL)#коли нашли, то копируем к exe!
        add_custom_command(TARGET AdminPanel POST_BUILD        
        COMMAND ${CMAKE_COMMAND} -E copy_if_different  
        "${DLLMYSQL}"     
        $)    
    else()#иначе смерть.
        message(FATAL_ERROR "\nlibmysql.dll not found\n")
    endif()         

endif()

unset(DLLMYSQL CACHE)#удаляем переменную из кэша(надо, без этого работать не будет)
unset(LIBMYSQL CACHE)#удаляем переменную из кэшаX2

Да, find’ы тут явно лишние, но что сделано, то сделано, они не мешают!!!

Админка

А начну я с небольшого теста работоспособности MySQL (или внебрачного сына документации и моей лени):

#include 
#include 
#include 
#include 
#pragma comment(lib, "libmysql.lib")
MYSQL *conn;

void exiting()//Закрыли прогу преждевременно? Не беда!
{
    mysql_close(conn);
}
int main()
{
    // Получаем дескриптор соединения
    conn = mysql_init(NULL);
    if (conn == NULL)
    {
        // Если дескриптор не получен – выводим сообщение об ошибке
        fprintf(stderr, "Error: can'tcreate MySQL-descriptor\n");
    }
    // Подключаемся к серверу
    if (!mysql_real_connect(conn, "localhost", "Spidery", "1322213222Mz", "World", NULL, NULL, 0))
    {
        // Если нет возможности установить соединение с сервером
        // базы данных выводим сообщение об ошибке
        fprintf(stderr, "Error: can't connect to database %s\n", mysql_error(conn));
    }
    else
    {
        std::string S = "";//В ней храним введённый запрос
        while (S != "cls" && S != "close")//сам знаю, что перед закрытием 
                            //код ещё один цикл сделает, но это тест мне плевать
        {
            getline(std::cin, S);//Вводим строку
            if (mysql_query(conn, S.c_str()))//Отправляем запрос на сервер
            {
                fprintf(stderr, "Error with query\nYour input: //не вышло если
                std::cout << S << '\n';//Что с запросом не так.
            }
            else // Если запрос успешно отправлен
            {
                MYSQL_RES *result = mysql_store_result(conn);
                if (result) // забрать весь результат
                {
                    MYSQL_ROW row;
                    while (row = mysql_fetch_row(result))//выводим каждую строку отдельно
                    {
                        std::cout << *row << '\n';
                    }
                    // пока есть строки результата(Вот такая вот матрёшка)
                }
                else if (mysql_field_count(conn) != 0) // коли нет результата, то и бог с ним, но вот если ошибка!!!
                {
                    mysql_free_result(result);
                    fprintf(stderr, "Error: %s\n", mysql_error(conn));
                }
                mysql_free_result(result);
            }
        }
    }
    system("cls");//работаю в терминале VSCode, потому и очищаю его
    return 0;
}

*На этом пока всё, ждите, верьте, надейтесь, но лучше отпишите коммент и идите дальше*

© Habrahabr.ru