Компиляция ядра, создание сборки Trinity Core 3.3.5a [Часть 1]

| понедельник, октября 17, 2011


Хочу вашему вниманию предоставить отличный гайд по компилированию ядра Trinity Core, когда-то я сам делал свое первое ядро по этому гайду...
Даный гайд будет поделен на две части.



Сегодня мы будем компилировать ядро Trinity Core и создавать на его основе полноценную рабочую сборку.
Гайд ориентирован на новичков, но все таки понимающих то, что они будут делать.

Нам понадобится:

Visual C++ 2008 Express или Visual C++ 2010. Express издания не поддерживают компиляцию на системах с 64 битной архитектурой Для х64 - Visual Studio 2010 (или 2008) Professional Edition

.NET Framework 3.5 - вполне возможно, что он уже
скачан вами во время обновления системы Windows.

MySQL - сервер баз данных, рекомендуется использовать версии 5.1.х.

TortoiseHg – графическая оболочка для управления системой контроля версий Mercurial.

Git - распределённая система управления версиями файлов.

CMake - программа для построения проекта и подготовки исходного кода непосредственно к процессу компиляции.

OpenSSL - система безопасных сокетов позволяющая создавать ключи RSA, DH, DSA и сертификаты.

Navicat - приложение для графического управления сервером MySQL, рекомендуется использовать Lite версию программы.

После того как мы скачали и установили весь необходимый софт, идём дальше по плану, который состоит из следующих пунктов:

1. Скачивание исходников.
2. "Накатывание" патчей на ядро.
3. Сборка компилятора.
4. Компиляция ядра.
5. Настройка ядра.
6. Работа с базами.

6.1. Создание баз.
6.2. Заполнение баз.
6.3. Настройки баз.

7. Запуск сервера.
8. F.A.Q.

Начинаем.
1. Скачивание исходников.
Создаем рабочий каталог в "корне" диска, например:
Code
D:\Trinity - Путь не должен содержать кириллицы.

В контекстном меню созданной нами папки выбираем TortoiseHg - Clone...:

В появившемся окне, в графе Source Path, указываем адрес официального репозитория Trinity Core:
https://trinitycore.googlecode.com/hg/ и нажимаем Clone


После скачивания, переименуем папку с нашими исходниками, в source (для удобства), так, чтобы путь к исходникам был такой:
Code
D:\work\source


Скачивание исходников завершено.

2. "Накатывание" патчей на ядро.
Патч - это некая модификация для ядра, написанная на CPP, которая может в корне изменить работоспособность сервера, начиная от работы спелов заканчивая Гильд-Хаусами.
Установка патчей производится с помощью программы Git.
Для примера "накатывания" патча, я предлагаю Вам воспользоваться патчем, который дает возможность игрокам получать различные звания за убийства игроков противоположной фракции в зависимости от количества убийств.

Сам патч:
Code
# HG changeset patch -- Bitbucket.org
# Project EasyCore
# URL [url]http://bitbucket.org/easytrinity/easycore/overview[/url]
# User easytrinity <admin@likenet.ru>
# Date 1285770323 -14400
# Node ID ccb906b16695e1f93c91ea9d6f173f60968b9c45
# Parent  9696c9e8cca39bf0626faaf07240ed434d2df805
added PvP Rank system
                
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -862,6 +862,18 @@ void World::LoadConfigSettings(bool relo
                   sLog.outError("MinPetitionSigns (%i) must be in range 0..9. Set to 9.", m_int_configs[CONFIG_MIN_PETITION_SIGNS]);
                   m_int_configs[CONFIG_MIN_PETITION_SIGNS] = 9;
               }
+    rate_values[RATE_PVP_RANK_EXTRA_HONOR] = sConfig.GetFloatDefault("PvPRank.Rate.ExtraHonor", 1);
+    std::string s_pvp_ranks = sConfig.GetStringDefault("PvPRank.HKPerRank", "10,50,100,200,450,750,1300,2000,3500,6000,9500,15000,21000,30000");
+    char *c_pvp_ranks = const_cast<char*>(s_pvp_ranks.c_str());
+    for (int i = 0; i !=HKRANKMAX; i++)
+    {
+        if (i==0)
+            pvp_ranks[0] = 0;
+        else if (i==1)
+            pvp_ranks[1] = atoi(strtok (c_pvp_ranks, ","));
+        else
+            pvp_ranks[i] = atoi(strtok (NULL, ","));
+    }
                
               m_int_configs[CONFIG_GM_LOGIN_STATE]        = sConfig.GetIntDefault("GM.LoginState", 2);
               m_int_configs[CONFIG_GM_VISIBLE_STATE]      = sConfig.GetIntDefault("GM.Visible", 2);
                
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -390,9 +390,30 @@ enum Rates
               RATE_DURABILITY_LOSS_PARRY,
               RATE_DURABILITY_LOSS_ABSORB,
               RATE_DURABILITY_LOSS_BLOCK,
+    R  ATE _PV P_R ANK _EX TRA _HO NOR,        
               RATE_MOVESPEED,
               MAX_RATES
           };
+         
+enum HonorKillPvPRank
+{
+    HKRANK00,
+    HKRANK01,
+    HKRANK02,
+    HKRANK03,
+    HKRANK04,
+    HKRANK05,
+    HKRANK06,
+    H         KRANK07,
+    HKRANK08,
+    HKRANK09,
+    HKRANK10,
+    HKRANK11,
+    HKRANK12,
+    HKRANK13,
+    HKRANK14,
+    HKRAN K M A X 
+  }  ;
                
           /// Can be used in SMSG_AUTH_RESPONSE packet
           enum BillingPlanFlags
@@ -639,6 +660,8 @@ class World
                   void SendZoneText(uint32 zone, const char *text, WorldSession *self = 0, uint32 team = 0);
                   void SendServerMessage(ServerMessageType type, const char *text = "", Player* player = NULL);
                
+        uint32 pvp_ranks[HKRANKMAX];
+
                   /// Are we in the middle of a shutdown?
                   bool IsShutdowning() const { return m_ShutdownTimer > 0; }
                   void ShutdownServ(uint32 time, uint32 options, uint8 exitcode);
                
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -6770,6 +6770,7 @@ bool Player::RewardHonor(Unit *uVictim,      
                
               uint64 victim_guid = 0;
               uint32 victim_rank = 0;
+    uint32 rank_diff = 0;
                
               // need call before fields update to have chance move yesterday data to appropriate fields before today data change.
               UpdateHonorFields();
@@ -6808,22 +6809,52 @@ bool Player::RewardHonor(Unit *uVictim,      
                       //  [15..28] Horde honor titles and player name
                       //  [29..38] Other title and player name
                       //  [39+]    Nothing
-            uint32 victim_title = pVictim->GetUInt32Value(PLAYER_CHOSEN_TITLE);
-                    // Get Killer titles, CharTitlesEntry::bit_index
+            // PLAYER__FIELD_KNOWN_TITLES describe which titles player can use,
+            // so we must find biggest pvp title , even for killer to find extra honor value
+            uint32 vtitle = pVictim->GetUInt32Value(PLAYER__FIELD_KNOWN_TITLES);
+            uint32 victim_title = 0;
+            uint32 ktitle = GetUInt32Value(PLAYER__FIELD_KNOWN_TITLES);
+            uint32 killer_title = 0;
+            if (PLAYER_TITLE_MASK_ALL_PVP & ktitle)
+            {
+                for (int i = ((GetTeam() == ALLIANCE) ? 1:HKRANKMAX);i!=((GetTeam() == ALLIANCE) ? HKRANKMAX : (2*HKRANKMAX-1));i++)
+                {
+                    if (ktitle & (1<<i))
+                        killer_title = i;
+                }
+            }
+            if (PLAYER_TITLE_MASK_ALL_PVP & vtitle)
+            {
+                for (int i = ((pVictim->GetTeam() == ALLIANCE) ? 1:HKRANKMAX);i!=((pVictim->GetTeam() == ALLIANCE) ? HKRANKMAX : (2*HKRANKMAX-1));i++)
+                {
+                    if (vtitle & (1<<i))
+                        victim_title = i;
+                }
+            }
+            // Get Killer titles, CharTitlesEntry::bit_index
                       // Ranks:
                       //  title[1..14]  -> rank[5..18]
                       //  title[15..28] -> rank[5..18]
                       //  title[other]  -> 0
                       if (victim_title == 0)
+                victim_guid = 0;                        // Don't show HK: <rank> message, only log.]
+            else if (victim_title < HKRANKMAX)
+                victim_rank = victim_title + 4;
+            else if (victim_title < (2*HKRANKMAX-1))
+                victim_rank = victim_title - (HKRANKMAX-1) + 4;
+            else
                           victim_guid = 0;                        // Don't show HK: <rank> message, only log.
-            else if (victim_title < 15)
-                victim_rank = victim_title + 4;
-            else if (victim_title < 29)
-                victim_rank = victim_title - 14 + 4;
-            else
-                victim_guid = 0;                        // Don't show HK: <rank> message, only log.
+      
+            // now find rank difference
+            if (killer_title == 0 && victim_rank>4)
+                rank_diff = victim_rank - 4;
+            else if (killer_title < HKRANKMAX)
+                rank_diff = (victim_rank>(killer_title + 4))? (victim_rank - (killer_title + 4)) : 0;
+            else if (killer_title < (2*HKRANKMAX-1))
+                rank_diff = (victim_rank>(killer_title - (HKRANKMAX-1) +4))? (victim_rank - (killer_title - (HKRANKMAX-1) + 4)) : 0;
                
-             honor_f = ceil(Trinity::Honor::hk_honor_at_level_f(k_level) * (v_level - k_grey) / (k_level - k_grey));
+            honor_f = 1 + sWorld.getRate(RATE_PVP_RANK_EXTRA_HONOR)*(((float)rank_diff) / 10.0f);
                
                       // count the number of playerkills in one day
                       ApplyModUInt32Value(PLAYER_FIELD_KILLS, 1, true);
@@ -6832,6 +6863,7 @@ bool Player::RewardHonor(Unit *uVictim,      
                       UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL);
                       UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS, pVictim->getClass());
                       UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HK_RACE, pVictim->getRace());
+            UpdateKnownTitles();
                   }
                   else
                   {
@@ -6905,6 +6937,30 @@ bool Player::RewardHonor(Unit *uVictim,      
               return true;
           }
                
+void Player::UpdateKnownTitles()
+{
+    uint32 new_title = 0;
+    uint32 honor_kills = GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS);
+    uint32 old_title = GetUInt32Value(PLAYER_CHOSEN_TITLE);
+    RemoveFlag64(PLAYER__FIELD_KNOWN_TITLES,PLAYER_TITLE_MASK_ALL_PVP);
+    if (honor_kills < 0)
+        return;
+    bool max_rank = ((honor_kills >= sWorld.pvp_ranks[HKRANKMAX-1]) ? true : false);
+    for (int i = HKRANK01; i != HKRANKMAX; ++i)
+    {
+        if (honor_kills < sWorld.pvp_ranks[i] || (max_rank))
+        {
+            new_title = ((max_rank) ? (HKRANKMAX-1) : (i-1));
+            if (new_title > 0)
+                new_title += ((GetTeam() == ALLIANCE) ? 0 : (HKRANKMAX-1));
+            break;
+        }
+    }
+    SetFlag64(PLAYER__FIELD_KNOWN_TITLES,uint64(1) << new_title);
+    if (old_title > 0 && old_title < (2*HKRANKMAX-1) && new_title > old_title)
+        SetUInt32Value(PLAYER_CHOSEN_TITLE,new_title);
+}
+
           void Player::ModifyHonorPoints(int32 value)
           {
               if (value < 0)
                
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -387,6 +387,27 @@ enum PlayerFlags
               PLAYER_FLAGS_NO_XP_GAIN     = 0x02000000
           };
                
+#define PLAYER_TITLE_MASK_ALLIANCE_PVP             \
+    (PLAYER_TITLE_PRIVATE | PLAYER_TITLE_CORPORAL |       
+      PLAYER_TITLE_SERGEANT_A | PLAYER_TITLE_MASTER_SERGEANT |      
+      PLAYER_TITLE_SERGEANT_MAJOR | PLAYER_TITLE_KNIGHT |      
+      PLAYER_TITLE_KNIGHT_LIEUTENANT | PLAYER_TITLE_KNIGHT_CAPTAIN |      
+      PLAYER_TITLE_KNIGHT_CHAMPION | PLAYER_TITLE_LIEUTENANT_COMMANDER |      
+      PLAYER_TITLE_COMMANDER | PLAYER_TITLE_MARSHAL |      
+      PLAYER_TITLE_FIELD_MARSHAL | PLAYER_TITLE_GRAND_MARSHAL)
+
+#define PLAYER_TITLE_MASK_HORDE_PVP                           \
+    (PLAYER_TITLE_SCOUT | PLAYER_TITLE_GRUNT |       
+      PLAYER_TITLE_SERGEANT_H | PLAYER_TITLE_SENIOR_SERGEANT |      
+      PLAYER_TITLE_FIRST_SERGEANT | PLAYER_TITLE_STONE_GUARD |      
+      PLAYER_TITLE_BLOOD_GUARD | PLAYER_TITLE_LEGIONNAIRE |      
+      PLAYER_TITLE_CENTURION | PLAYER_TITLE_CHAMPION |      
+      PLAYER_TITLE_LIEUTENANT_GENERAL | PLAYER_TITLE_GENERAL |      
+      PLAYER_TITLE_WARLORD | PLAYER_TITLE_HIGH_WARLORD)
+
+#define PLAYER_TITLE_MASK_ALL_PVP  \
+    (PLAYER_TITLE_MASK_ALLIANCE_PVP | PLAYER_TITLE_MASK_HORDE_PVP)
+
           // used for PLAYER__FIELD_KNOWN_TITLES field (uint64), (1<<bit_index) without (-1)
           // can't use enum for uint64 values
           #define PLAYER_TITLE_DISABLED              UI64LIT(0x0000000000000000)
@@ -1975,6 +1996,7 @@ class Player : public Unit, public GridO
                       if (value)
                           AddKnownCurrency(ITEM_ARENA_POINTS_ID); // Arena Points
                   }
+        void UpdateKnownTitles();
                
                   //End of PvP System      
           


Копируем всё это содержимое, сохраняем в файл с расширением .patch, например:
Code
rank.patch

После того как мы сохранили наш патч на компьютере, нам необходимо перенести его в папку с нашими исходниками, а точнее:
Code
D:\work\source

Так чтобы полный путь к патчу был такой:
Code
D:\work\source\rank.patch

Так следует поступать с любым устанавливаемым патчем.

После того как мы перенесли наш патч, жмем ПКМ по папке с исходниками, а точнее:
Code
D:\work\source

И выбераем Git Bash Here:

В появившемся окне, пишем:
Code
patch -p1 < название.patch, в нашем случае:


Жмем Enter.

Если после завершения вы видите:

Значит всё в порядке, можно продолжать.
Вы можете продолжить установку других патчей (если они у вас имеются), но у нас он один, так что мы продолжим. Закрываем Git.

3. Сборка компилятора.
Создаем новую папку в нашей рабочей директории, например:
Code
D:\work\tc - в этой папке будет хранится готовый к компиляции проект.

После того как мы подготовили директорию, запускаем ранее нами установленный CMake.

Where is the source code - папка с исходниками, у нас это:
Code
D:\work\source

Where to build the binaries - папка для готового проекта VS, у нас это:
Code
D:\work\tc

Указываем эти данные в программе:

После жмем Configure и выбираем, на какой платформе будем компилировать, в моем случае это Visual Studio 10, выбираем, после чего жмем Finish:

Ждем завершение процесса, после чего вы увидите:

Столбец - TOOLS, позволяет нам после компилирования получить экстракторы карт. Так что ставим галочку.
Больше ничего не меняем.
Снова жмем Configure и видим:

После жмем:

Если все прошло успешно - то мы увидим:

Можно закрывать CMake.

(c) by knyaz