Guida Compilare i sorgenti con vcpkg (togliendo la Extern)

Arves100

Utente Emerald
15 Febbraio 2011
515
46
378
418
Benvenuti, in questa guida spiegerò come startare e compilare qualunque file server e/o sorgenti di Metin2.
La guida è stata stilizzata molto di più in stile "pappa pronta" senza spiegare al 100% diversi comandi, per questo, potete consulatere la sezione di "approfondimento".

La guida non tratterà dello start, in futuro potrei fare una guida a riguardo simile/generale come questa.

Sommario:

File e competenze richieste

  • Conoscenze basiche del sistema operativo che utilizzerete
  • Qualunque sorgente lato client e server

Introduzione a vcpkg


vcpkg ci farà indirettamente aggiornare tutte le librerie esterne alle ultime versioni, questo è importante perchè gli ultimi aggiornamenti
posso risolvere problemi delle librerie o più veloci rispetti a quelle normali grazie agli ultimi aggiornamenti.
Raramente gli aggiornamenti causano problemi (unico problema che avevo fu Crypto++ 8 su CLang, ma su FreeBSD utilizziamo GCC quindi il problema
non sussiste).


Modifiche effettuate (breve spiegazione, le note finali per maggiori informazioni):

  • Modifica delle inclusioni e delle librerie da collegare per riflettere i nomi di vcpkg (nuovo metodo di Extern più comodo ed automatizzato, leggere in seguito per ulteriori informazioni)
  • Aggiornamento di vari moduli alle ultime versioni attualimente presenti su vcpkg
  • Supporto per MariaDB Connector C 3.0 o superiore oppure MySQL Connector C 8.0 o superiore
  • Supporto a DevIL 1.7 o superiore
  • Supporto a Python 2.7.15 (librerie lato client incluse)
  • Aggiornamento sezioni sicuri di Armadillo e fix di un bug (leggere le note per maggiori informazioni)
  • Pulizia dei Makefile per utilizzare un compilatore senza numero, utilizzare le librerie statiche (quindi evitare di portare i .so in giro) e riflettere i nuovi cambiamenti di vcpkg
  • Modifica del progetto Client per compilare con DirectX SDK 8.1
  • Supporto a Crypto++ 6.0 o superiore
  • Qualche piccola modifica di comodità per Windows riguardante il logging (e bugfix relativi ad esso)

Perchè usare questo metodo?
  • Vuoi un modo più piccolo di distribuire i tuoi sorgenti senza la Extern (ovviamente le altre persone dovranno installare vcpkg)
  • Vuoi vere tutti i componenti di terze parti di Metin2 aggiornate
  • Vuoi aggiornamenti di performance e di sicurezza
  • Vuoi il link statico di tutte le DLL (mettere le DLL all'interno del file exe). Una installazione di base di vcpkg lascia solamente SpeedTree e Granny (che possono essere rimossi se usi Granny 2.9 statico e compili SpeedTreeRT dai sorgenti)
Compatibilità ed incompatibilità
  • Non sono riuscito a far funzionare libmariadb con FreeBSD x64, potrebbero essere problemi di collegamento, suggerisco di mitigare installando questo e mettendo le inclusioni in include e lib nella cartella https://pkg.freebsd.org/FreeBSD:(LA TUA VERSIONE DI FREEBSD):amd64/latest/All/mariadb-connector-c-3.1.9.txz (cartella di vcpkg)\installed\x86-freebsd.
  • Non puoi compilare vcpkg su una macchina 64-bit con dei file 32-bit, bisogna compilare con una macchina FreeBSD 32-bit. Si potrebbe varlo con delle tecniche del multilib, ma non ho idea di come si faccia su FreeBSD con vcpkg
  • Hai bisogno di internet nella tua VPS o macchina per installare vcpkg, e utilizzare una versione attualmente supportata di FreeBSD, maggiori informazioni qui https://www.freebsd.org/
  • Hai bisogno di, almeno, Windows 7 Service Pack 1 per compilare il Client (o il Server su Windows)
  • Ho avuto problemi con clang e Crypto++, suggerisco di usare GCC, se ci saranno cambiamenti lo notificherò nel post.


Prerequisiti Windows (Client e Server)


Utilizzeremo la piattaforma Windows per compilare il Client, ed opzionalmente, il Server se siete interessati ad avviare un Server su Windows.


Scarichiamo ed installare l'ultima versione di Visual Studio disponibile da qui: https://visualstudio.microsoft.com/it/downloads/

Dobbiamo selezionare il carico di lavoro "Sviluppo di applicazioni desktop con C++" nell'installer di Visual Studio.


Scarichiamo Git da qui https://git-scm.com/download/win e scarichiamo CMake da qui https://cmake.org/download/

BISOGNA INSTALLARE ANCHE IL PACCHETTO DI LINGUA IN INGLESE ALTRIMENTI VCPKG NON FUNZIONERA'

Installazione su FreeBSD (solo Server)


FreeBSD include già un compilatore ovvero CLang, esso può dare problemi con i file di Metin2 (personalmente FreeBSD 12.1 + Clang 9 mi crasha con Crypto++), per questo

motivo andremmo ad installare GCC.

Se state utilizzando una versione di FreeBSD non aggiornata, raccomando di proseguire all'intallazione di FreeBSD da 0, per questa parte è necessaria anche una connessione

ad internet, sicuramente cercando su internet sarà pieno di guide, videoguide che spiegano come installare FreeBSD.


Il comando da digitare è il seguente:

pkg install gcc makedepend gmake cmake git openssl ninja bash

Questo installerà GCC (il compilatore), Makedepend (un programma richiesto per compilare i src di Metin2), gmake (il programma che avvia il processo di compilazione) e CMake, git e le dipendenze richieste.


Digitiamo "bash" e questi comandi:

cd (cartella dove vogliamo salvare vcpkg)
git clone --depth=1 https://github.com/microsoft/vcpkg
cd vcpkg
./bootstrap-vcpkg.sh -disableMetrics -useSystemBinaries
./vcpkg install devil cryptopp boost-system boost-container boost-unordered boost-algorithm boost-pool boost-math boost-lexical-cast

Per chi utilizza Beast per identificare l'IP esterno, come spiegato qui https://www.inforge.net/forum/threa...ioni-esterne-al-proprio-server-metin2.556262/ dovete digitare anche questo comando:
vpckg install boost-beast

Installazione Windows (Client e opzionalmente Server)

Digitiamo i seguenti comandi da un prompt dei comandi di Windows CON I PRIVILEGI DI AMMINISTRATORE

Digitiamo il seguente comando:
cd (cartella dove vogliamo salvare vcpkg)
git clone --depth=1 https://github.com/microsoft/vcpkg
cd vcpkg
bootstrap-vcpkg -disableMetrics
vcpkg integrate install
vcpkg install devil:x86-windows-static cryptopp:x86-windows-static boost-system:x86-windows-static boost-container:x86-windows-static boost-unordered:x86-windows-static boost-algorithm:x86-windows-static lzo:x86-windows-static python2:x86-windows-static


vcpkg1.png


Se stiamo compilando il client digitare anche questo comando:
Codice:
vcpkg install lzo python2

Per chi utilizza Type6/MCSP, scritta qui: https://www.inforge.net/forum/threads/supporto-snappy-su-metin2-possibilità-di-caricare-i-nuovi-eterpack-e-proto-dellita.593195/ dovete digitare anche questo comando:

vpckg install snappy:x86-windows-static

vcpkg2.png


Se stiamo compilando il server su Windows digitare anche questo comando:

vcpkg install libmariadb:x86-windows-static openssl:x86-windows-static boost-pool:x86-windows-static boost-math:x86-windows-static boost-lexical-cast:x86-windows-static

vcpkg3.png


Per chi utilizza Beast per identificare l'IP esterno, come spiegato qui https://www.inforge.net/forum/threa...ioni-esterne-al-proprio-server-metin2.556262/ dovete digitare anche questo comando: (Server su Windows)
vpckg install boost-beast:x86-windows-static

vcpkg4.png


All'interno della cartella del client (dove c'è Metin2Client.sln) create una nuova cartella chiamata Extern ed estraete questo pack (purtroppo alcuni componenti non possono essere distribuiti con vcpkg)

Server: Modifiche comuni

Nei sorgenti server possiamo rimuovere le seguenti cartelle se le abbiamo:
- libdevil
- libmysql

Se possedete libserverkey è necessario applicare una modifica per compilarlo con versioni aggiornate di OpenSSL:
https://www.inforge.net/forum/threads/libserverkey-compatibile-conopenssl-v1-0.593582/

Dovete anche seguire i passaggi descritti in questa guida:
https://www.inforge.net/forum/threads/soluzione-compilazione-vid-con-boost-1-47.593601/

Apriamo il file cipher.h e modifichiamo le seguenti righe:
da
Codice:
    encoder_->ProcessData((byte*)buffer, (const byte*)buffer, length);
a
Codice:
    encoder_->ProcessData((CryptoPP::byte*)buffer, (const CryptoPP::byte*)buffer, length);

e da
Codice:
    decoder_->ProcessData((byte*)buffer, (const byte*)buffer, length);
a
Codice:
    decoder_->ProcessData((CryptoPP::byte*)buffer, (const CryptoPP::byte*)buffer, length);

Apriamo cipher.cpp e cancelliamo questa riga
Codice:
#include <cryptopp/cryptoppLibLink.h>

Ora, apriamo il file utils.cpp e controlliamo se abbiamo questo:
Codice:
    make_scrambled_password(hash_buf, tmp_pwd);
Dobbiamo cancellare questo: (se lo avete)
Codice:
#ifdef WIN32
extern "C" void my_make_scrambled_password(char *to, const char *password, size_t pass_len);
#endif
e cambiare questo: (se lo avete)
Codice:
#ifdef WIN32
    my_make_scrambled_password(hash_buf, tmp_pwd, strlen(tmp_pwd));
#else
    make_scrambled_password(hash_buf, tmp_pwd);
#endif
in:
Codice:
    make_scrambled_password(hash_buf, tmp_pwd);

Dopo questa riga
Codice:
#ifndef SHA1_HASH_SIZE
#define SHA1_HASH_SIZE 20
#endif
Aggiungiamo questo:
Codice:
#include "sha1.h"

char *hexify(char * const result, const unsigned char *digest,
         const size_t size_result, size_t size_digest)
{
    static const char * const hexchars = "0123456789ABCDEF";
    char *result_pnt = result;

    if (size_digest <= (size_t) 0 ||
        size_result <= (size_digest * (size_t) 2U)) {
        return NULL;
    }
    do {
        *result_pnt++ = hexchars[(*digest >> 4) & 0xf];
        *result_pnt++ = hexchars[*digest & 0xf];
        digest++;
        size_digest--;
    } while (size_digest > (size_t) 0U);
    *result_pnt = 0;

    return result;
}

// Implementation from commit 2db6b50c7b7c638104bd9639994f0574e8f4813c in Pure-ftp source.
void make_scrambled_password(char scrambled_password[42], const char password[255])
{
    SHA1_CTX      ctx;
    unsigned char h0[20], h1[20];

    SHA1Init(&ctx);
    SHA1Update(&ctx, (unsigned char*)password, strlen(password));
    SHA1Final(h0, &ctx);
    SHA1Init(&ctx);
    SHA1Update(&ctx, h0, sizeof h0);
# ifdef HAVE_EXPLICIT_BZERO
    explicit_bzero(h0, strlen(password));
# else
    volatile unsigned char *pnt_ = (volatile unsigned char *) h0;
    size_t                     i = (size_t) 0U;

    while (i < strlen(password)) {
        pnt_[i++] = 0U;
    }
# endif

    SHA1Final(h1, &ctx);
    *scrambled_password = '*';
    hexify(scrambled_password + 1U, h1,
            42, sizeof h1);
}

Creiamo un nuovo file (sempre in game/src) chiamato "sha1.h" e mettiamo questo contenuto:
Codice:
#ifndef SHA1_H
#define SHA1_H

/*
   SHA-1 in C
   By Steve Reid <[email protected]>
   100% Public Domain
*/

#ifdef __cplusplus
extern "C" {
#endif

#include "stdint.h"

typedef struct
{
    uint32_t state[5];
    uint32_t count[2];
    unsigned char buffer[64];
} SHA1_CTX;

void SHA1Transform(
    uint32_t state[5],
    const unsigned char buffer[64]
    );

void SHA1Init(
    SHA1_CTX * context
    );

void SHA1Update(
    SHA1_CTX * context,
    const unsigned char *data,
    uint32_t len
    );

void SHA1Final(
    unsigned char digest[20],
    SHA1_CTX * context
    );

void SHA1(
    char *hash_out,
    const char *str,
    int len);

#ifdef __cplusplus
}
#endif

#endif /* SHA1_H */
Creiamo un file chiamato sha1.c e mettiamo questo contenuto:
Codice:
/*
SHA-1 in C
By Steve Reid <[email protected]>
100% Public Domain

Test Vectors (from FIPS PUB 180-1)
"abc"
  A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
  84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
A million repetitions of "a"
  34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
*/

/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */
/* #define SHA1HANDSOFF * Copies data before messing with it. */

#define SHA1HANDSOFF

#include <stdio.h>
#include <string.h>

/* for uint32_t */
#include <stdint.h>

#include "sha1.h"


#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))

/* blk0() and blk() perform the initial expand. */
/* I got the idea of expanding during the round function from SSLeay */
#if BYTE_ORDER == LITTLE_ENDIAN
#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
    |(rol(block->l[i],8)&0x00FF00FF))
#elif BYTE_ORDER == BIG_ENDIAN
#define blk0(i) block->l[i]
#else
#error "Endianness not defined!"
#endif
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
    ^block->l[(i+2)&15]^block->l[i&15],1))

/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);


/* Hash a single 512-bit block. This is the core of the algorithm. */

void SHA1Transform(
    uint32_t state[5],
    const unsigned char buffer[64]
)
{
    uint32_t a, b, c, d, e;

    typedef union
    {
        unsigned char c[64];
        uint32_t l[16];
    } CHAR64LONG16;

#ifdef SHA1HANDSOFF
    CHAR64LONG16 block[1];      /* use array to appear as a pointer */

    memcpy(block, buffer, 64);
#else
    /* The following had better never be used because it causes the
     * pointer-to-const buffer to be cast into a pointer to non-const.
     * And the result is written through.  I threw a "const" in, hoping
     * this will cause a diagnostic.
     */
    CHAR64LONG16 *block = (const CHAR64LONG16 *) buffer;
#endif
    /* Copy context->state[] to working vars */
    a = state[0];
    b = state[1];
    c = state[2];
    d = state[3];
    e = state[4];
    /* 4 rounds of 20 operations each. Loop unrolled. */
    R0(a, b, c, d, e, 0);
    R0(e, a, b, c, d, 1);
    R0(d, e, a, b, c, 2);
    R0(c, d, e, a, b, 3);
    R0(b, c, d, e, a, 4);
    R0(a, b, c, d, e, 5);
    R0(e, a, b, c, d, 6);
    R0(d, e, a, b, c, 7);
    R0(c, d, e, a, b, 8);
    R0(b, c, d, e, a, 9);
    R0(a, b, c, d, e, 10);
    R0(e, a, b, c, d, 11);
    R0(d, e, a, b, c, 12);
    R0(c, d, e, a, b, 13);
    R0(b, c, d, e, a, 14);
    R0(a, b, c, d, e, 15);
    R1(e, a, b, c, d, 16);
    R1(d, e, a, b, c, 17);
    R1(c, d, e, a, b, 18);
    R1(b, c, d, e, a, 19);
    R2(a, b, c, d, e, 20);
    R2(e, a, b, c, d, 21);
    R2(d, e, a, b, c, 22);
    R2(c, d, e, a, b, 23);
    R2(b, c, d, e, a, 24);
    R2(a, b, c, d, e, 25);
    R2(e, a, b, c, d, 26);
    R2(d, e, a, b, c, 27);
    R2(c, d, e, a, b, 28);
    R2(b, c, d, e, a, 29);
    R2(a, b, c, d, e, 30);
    R2(e, a, b, c, d, 31);
    R2(d, e, a, b, c, 32);
    R2(c, d, e, a, b, 33);
    R2(b, c, d, e, a, 34);
    R2(a, b, c, d, e, 35);
    R2(e, a, b, c, d, 36);
    R2(d, e, a, b, c, 37);
    R2(c, d, e, a, b, 38);
    R2(b, c, d, e, a, 39);
    R3(a, b, c, d, e, 40);
    R3(e, a, b, c, d, 41);
    R3(d, e, a, b, c, 42);
    R3(c, d, e, a, b, 43);
    R3(b, c, d, e, a, 44);
    R3(a, b, c, d, e, 45);
    R3(e, a, b, c, d, 46);
    R3(d, e, a, b, c, 47);
    R3(c, d, e, a, b, 48);
    R3(b, c, d, e, a, 49);
    R3(a, b, c, d, e, 50);
    R3(e, a, b, c, d, 51);
    R3(d, e, a, b, c, 52);
    R3(c, d, e, a, b, 53);
    R3(b, c, d, e, a, 54);
    R3(a, b, c, d, e, 55);
    R3(e, a, b, c, d, 56);
    R3(d, e, a, b, c, 57);
    R3(c, d, e, a, b, 58);
    R3(b, c, d, e, a, 59);
    R4(a, b, c, d, e, 60);
    R4(e, a, b, c, d, 61);
    R4(d, e, a, b, c, 62);
    R4(c, d, e, a, b, 63);
    R4(b, c, d, e, a, 64);
    R4(a, b, c, d, e, 65);
    R4(e, a, b, c, d, 66);
    R4(d, e, a, b, c, 67);
    R4(c, d, e, a, b, 68);
    R4(b, c, d, e, a, 69);
    R4(a, b, c, d, e, 70);
    R4(e, a, b, c, d, 71);
    R4(d, e, a, b, c, 72);
    R4(c, d, e, a, b, 73);
    R4(b, c, d, e, a, 74);
    R4(a, b, c, d, e, 75);
    R4(e, a, b, c, d, 76);
    R4(d, e, a, b, c, 77);
    R4(c, d, e, a, b, 78);
    R4(b, c, d, e, a, 79);
    /* Add the working vars back into context.state[] */
    state[0] += a;
    state[1] += b;
    state[2] += c;
    state[3] += d;
    state[4] += e;
    /* Wipe variables */
    a = b = c = d = e = 0;
#ifdef SHA1HANDSOFF
    memset(block, '\0', sizeof(block));
#endif
}


/* SHA1Init - Initialize new context */

void SHA1Init(
    SHA1_CTX * context
)
{
    /* SHA1 initialization constants */
    context->state[0] = 0x67452301;
    context->state[1] = 0xEFCDAB89;
    context->state[2] = 0x98BADCFE;
    context->state[3] = 0x10325476;
    context->state[4] = 0xC3D2E1F0;
    context->count[0] = context->count[1] = 0;
}


/* Run your data through this. */

void SHA1Update(
    SHA1_CTX * context,
    const unsigned char *data,
    uint32_t len
)
{
    uint32_t i;

    uint32_t j;

    j = context->count[0];
    if ((context->count[0] += len << 3) < j)
        context->count[1]++;
    context->count[1] += (len >> 29);
    j = (j >> 3) & 63;
    if ((j + len) > 63)
    {
        memcpy(&context->buffer[j], data, (i = 64 - j));
        SHA1Transform(context->state, context->buffer);
        for (; i + 63 < len; i += 64)
        {
            SHA1Transform(context->state, &data[i]);
        }
        j = 0;
    }
    else
        i = 0;
    memcpy(&context->buffer[j], &data[i], len - i);
}


/* Add padding and return the message digest. */

void SHA1Final(
    unsigned char digest[20],
    SHA1_CTX * context
)
{
    unsigned i;

    unsigned char finalcount[8];

    unsigned char c;

#if 0    /* untested "improvement" by DHR */
    /* Convert context->count to a sequence of bytes
     * in finalcount.  Second element first, but
     * big-endian order within element.
     * But we do it all backwards.
     */
    unsigned char *fcp = &finalcount[8];

    for (i = 0; i < 2; i++)
    {
        uint32_t t = context->count[i];

        int j;

        for (j = 0; j < 4; t >>= 8, j++)
            *--fcp = (unsigned char) t}
#else
    for (i = 0; i < 8; i++)
    {
        finalcount[i] = (unsigned char) ((context->count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8)) & 255);      /* Endian independent */
    }
#endif
    c = 0200;
    SHA1Update(context, &c, 1);
    while ((context->count[0] & 504) != 448)
    {
        c = 0000;
        SHA1Update(context, &c, 1);
    }
    SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
    for (i = 0; i < 20; i++)
    {
        digest[i] = (unsigned char)
            ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255);
    }
    /* Wipe variables */
    memset(context, '\0', sizeof(*context));
    memset(&finalcount, '\0', sizeof(finalcount));
}

void SHA1(
    char *hash_out,
    const char *str,
    int len)
{
    SHA1_CTX ctx;
    unsigned int ii;

    SHA1Init(&ctx);
    for (ii=0; ii<len; ii+=1)
        SHA1Update(&ctx, (const unsigned char*)str + ii, 1);
    SHA1Final((unsigned char *)hash_out, &ctx);
    hash_out[20] = '\0';
}

Apriamo il file libsql/AsyncSQL.cpp e cambiamo:
Codice:
fprintf(stdout, "AsyncSQL: connected to %s (reconnect %d)\n", m_stHost.c_str(), m_hDB.reconnect);
in
Codice:
fprintf(stdout, "AsyncSQL: connected to %s\n", m_stHost.c_str());

Apriamo il file libthecore/src/log.c e cambiamo:
Codice:
#ifndef __WIN32__
    // log_level이 1 이상일 경우에는 테스트일 경우가 많으니 stdout에도 출력한다.
    if (log_level_bits > 1)
    {
#endif
in:
Codice:
    // log_level이 1 이상일 경우에는 테스트일 경우가 많으니 stdout에도 출력한다.
    if (log_level_bits > 1)
    {

cambiamo anche: (si trova qualche riga sotto la modifica precedente)
Codice:
#ifndef __WIN32__
    }
#endif
in:
Codice:
}

Apriamo il file game/src/input_auth.cpp e cambiamo (se lo abbiamo):
Codice:
#ifdef __WIN32__
        DBManager::instance().ReturnQuery(QID_AUTH_LOGIN, dwKey, p,
                "SELECT PASSWORD('%s'),password,securitycode,social_id,id,status,availDt - NOW() > 0,"
                "UNIX_TIMESTAMP(silver_expire),"
                "UNIX_TIMESTAMP(gold_expire),"
                "UNIX_TIMESTAMP(safebox_expire),"
                "UNIX_TIMESTAMP(autoloot_expire),"
                "UNIX_TIMESTAMP(fish_mind_expire),"
                "UNIX_TIMESTAMP(marriage_fast_expire),"
                "UNIX_TIMESTAMP(money_drop_rate_expire),"
                "UNIX_TIMESTAMP(create_time)"
                " FROM account WHERE login='%s'", szLogin);
#else
        // @fixme138 1. PASSWORD('%s') -> %s 2. szPasswd wrapped inside mysql_hash_password(%s).c_str()
        DBManager::instance().ReturnQuery(QID_AUTH_LOGIN, dwKey, p,
                "SELECT '%s',password,securitycode,social_id,id,status,availDt - NOW() > 0,"
                "UNIX_TIMESTAMP(silver_expire),"
                "UNIX_TIMESTAMP(gold_expire),"
                "UNIX_TIMESTAMP(safebox_expire),"
                "UNIX_TIMESTAMP(autoloot_expire),"
                "UNIX_TIMESTAMP(fish_mind_expire),"
                "UNIX_TIMESTAMP(marriage_fast_expire),"
                "UNIX_TIMESTAMP(money_drop_rate_expire),"
                "UNIX_TIMESTAMP(create_time)"
                " FROM account WHERE login='%s'",
                mysql_hash_password(szPasswd).c_str(), szLogin);
#endif
in:
Codice:
// @fixme138 1. PASSWORD('%s') -> %s 2. szPasswd wrapped inside mysql_hash_password(%s).c_str()
        DBManager::instance().ReturnQuery(QID_AUTH_LOGIN, dwKey, p,
                "SELECT '%s',password,securitycode,social_id,id,status,availDt - NOW() > 0,"
                "UNIX_TIMESTAMP(silver_expire),"
                "UNIX_TIMESTAMP(gold_expire),"
                "UNIX_TIMESTAMP(safebox_expire),"
                "UNIX_TIMESTAMP(autoloot_expire),"
                "UNIX_TIMESTAMP(fish_mind_expire),"
                "UNIX_TIMESTAMP(marriage_fast_expire),"
                "UNIX_TIMESTAMP(money_drop_rate_expire),"
                "UNIX_TIMESTAMP(create_time)"
                " FROM account WHERE login='%s'",
                mysql_hash_password(szPasswd).c_str(), szLogin);
#endif

Sempre dentro questo file, modifichiamo questo (se lo abbiamo):
Codice:
#ifdef __WIN32__
        DBManager::instance().ReturnQuery(QID_AUTH_LOGIN, dwKey, p,
                "SELECT PASSWORD('%s'),password,securitycode,social_id,id,status,availDt - NOW() > 0,"
                "UNIX_TIMESTAMP(silver_expire),"
                "UNIX_TIMESTAMP(gold_expire),"
                "UNIX_TIMESTAMP(safebox_expire),"
                "UNIX_TIMESTAMP(autoloot_expire),"
                "UNIX_TIMESTAMP(fish_mind_expire),"
                "UNIX_TIMESTAMP(marriage_fast_expire),"
                "UNIX_TIMESTAMP(money_drop_rate_expire),"
                "UNIX_TIMESTAMP(create_time)"
                " FROM account WHERE login='%s'", szLogin);
#else
        // @fixme138 1. PASSWORD('%s') -> %s 2. szPasswd wrapped inside mysql_hash_password(%s).c_str()
        DBManager::instance().ReturnQuery(QID_AUTH_LOGIN, dwKey, p,
                "SELECT '%s',password,securitycode,social_id,id,status,availDt - NOW() > 0,"
                "UNIX_TIMESTAMP(silver_expire),"
                "UNIX_TIMESTAMP(gold_expire),"
                "UNIX_TIMESTAMP(safebox_expire),"
                "UNIX_TIMESTAMP(autoloot_expire),"
                "UNIX_TIMESTAMP(fish_mind_expire),"
                "UNIX_TIMESTAMP(marriage_fast_expire),"
                "UNIX_TIMESTAMP(money_drop_rate_expire),"
                "UNIX_TIMESTAMP(create_time)"
                " FROM account WHERE login='%s'",
                mysql_hash_password(szPasswd).c_str(), szLogin);
#endif
in:
Codice:
// @fixme138 1. PASSWORD('%s') -> %s 2. szPasswd wrapped inside mysql_hash_password(%s).c_str()
        DBManager::instance().ReturnQuery(QID_AUTH_LOGIN, dwKey, p,
                "SELECT '%s',password,securitycode,social_id,id,status,availDt - NOW() > 0,"
                "UNIX_TIMESTAMP(silver_expire),"
                "UNIX_TIMESTAMP(gold_expire),"
                "UNIX_TIMESTAMP(safebox_expire),"
                "UNIX_TIMESTAMP(autoloot_expire),"
                "UNIX_TIMESTAMP(fish_mind_expire),"
                "UNIX_TIMESTAMP(marriage_fast_expire),"
                "UNIX_TIMESTAMP(money_drop_rate_expire),"
                "UNIX_TIMESTAMP(create_time)"
                " FROM account WHERE login='%s'",
                mysql_hash_password(szPasswd).c_str(), szLogin);

Apriamo il file libthecore/include/stdafx.h e cancelliamo:
Codice:
//struct timespec
{
    time_t  tv_sec;         /* seconds */
    long    tv_nsec;        /* and nanoseconds */
};
cancelliamo anche questa riga:
Codice:
#define strtof(str, endptr) (float)strtod(str, endptr)

Apriamo il file libserverkey/RSACrypto.cpp (per chi lo ha) e cancelliamo questa riga:
Codice:
#ifdef _WIN32
#include <atlenc.h>
#endif

Apriamo il file libserverkey/RSACrypto.h (per chi lo ha) e cancelliamo questa riga:
Codice:
#ifdef _WIN32
// needed only for using openssl
#pragma comment(lib, "libeay32")
#endif

Apriamo il file libserverkey/CheckServerKey.h (per chi lo ha) e modifichiamo questa riga:
Codice:
#ifdef _WIN32
#include <atlenc.h>
#else
#include "base64_ssl.h"
#endif
in:
Codice:
#include "base64_ssl.h"
Modificare questo:
Codice:
#ifdef _WIN32
    if (FALSE == Base64Decode(key.c_str(), key.size(), buf, &buflen))
    {
        errorString = "base64 decode failed";
        return false;
    }
#else
    if (false == unbase64_ssl((unsigned char *)key.c_str(), key.size(), buf, buflen))
    {
        errorString = "base64 decode failed";
        return false;
    }
    buflen = strlen((const char *)buf);
#endif
in questo:
Codice:
if (false == unbase64_ssl((unsigned char *)key.c_str(), key.size(), buf, buflen))
    {
        errorString = "base64 decode failed";
        return false;
    }
    buflen = strlen((const char *)buf);

Apriamo il file db/src/CsvReader.h e cambiamo:
Codice:
#if _MSC_VER
    #include <hash_map>
#else
    #include <map>
#endif
in:
Codice:
#include <boost/unordered_map.hpp>

cambia anche questo:
Codice:
#if _MSC_VER
    typedef stdext::hash_map<std::string, size_t> NAME2INDEX_MAP;
    typedef stdext::hash_map<size_t, std::string> INDEX2NAME_MAP;
#else
    typedef std::map<std::string, size_t> NAME2INDEX_MAP;
    typedef std::map<size_t, std::string> INDEX2NAME_MAP;
#endif
in questo:
Codice:
    typedef boost::unordered_map<std::string, size_t> NAME2INDEX_MAP;
    typedef boost::unordered_map<size_t, std::string> INDEX2NAME_MAP;

Apriamo il file db/src/Main.cpp e cancelliamo queste righe:
Codice:
#ifdef __FreeBSD__
    _malloc_options = "A";
#endif
cancelliamo anche queste righe:
Codice:
#ifdef __FreeBSD__
extern const char * _malloc_options;
#endif

Apriamo il file game/src/MarkImage.h e prima di questo:
Codice:
#include <IL/il.h>
aggiungiamo questo:
Codice:
#define IL_STATIC_LIB 1

Server: Modifiche sorgenti per FreeBSD

Dovremmo modificare "CC = (qualunque cosa)" in "CC = g++" nei seguenti file: (Apriteli con un editor di testo)
- libthecore/src/Makefile
- libsql/Makefile
- libpoly/Makefile
- libgame/src/Makefile
- libserverkey/Makefile
- db/src/Makefile
- game/src/Makefile
- game/src/quest/Makefile (Qui si chiama CPP non CC)

Mentre dobbiamo modificare
"CC= gcc (qualunque numero)" in "CC = gcc" nel file "liblua/config" (o liblua/5.0/config)

Apriamo libsql/Makefile ed elimiliamo le seguenti righe:
Codice:
IFLAGS = -I/usr/local/include/

#sometimes necessary included
IFLAGS = -I/usr/local/include/mysql
oppure potreste avere le seguenti righe che sono da rimuovere:
Codice:
IFLAGS = -I../libmysql/5.x-5.1.35
IFLAGS = -I../libmysql/7.x-5.1.35

Prima di "LIBS =" aggiungiamo questo:
Codice:
IFLAGS = -I../../m2pkg/installed/x86-freebsd/include

Verificate nei seguenti file se avete "-m32", altrimenti aggiungete prima di "LIBS =" questo:
Codice:
CFLAGS += -m32

Questo procedimento va fatto per i seguenti file:
- libthecore/src/Makefile
- libsql/Makefile
- libpoly/Makefile
- libserverkey/Makefile
- libgame/src/Makefile

Apriamo il file game/src/quest/Makefile e se non abbiamo "-m32" aggiungiamolo prima di "all: qc cc" questo:
Codice:
CPPFLAGS += -m32
Inoltre, aggiungiamo se non avete "ENABLE_STATIC = 0"
Codice:
CPP += -static
Se avete "ENABLE_STATIC = 0" cambiate lo 0 in 1.

Se siete su FreeBSD x64 dovete aggiungere anche questo:
Codice:
LIBDIR += -L/usr/local/lib32/gcc(numero di gcc, esempio per me è 9)
Su FreeBSD x86 questo:
Codice:
LIBDIR += -L/usr/local/lib/gcc(numero di gcc, esempio per me è 9)

Potete verificare il numero di gcc (la versione maggiore) digitando il comando "gcc --version"
potrebbe uscire una cosa del genere:
gcc (FreeBSD Ports Collection) 9.3.0
Nel mio caso il numero è 9.

Apriamo ora il file "db/src/Makefile", e cancelliamo queste righe se le avete:
Codice:
ifeq ($(BSD_VERSION), 7)
INCDIR += -I../../libmysql/7.x-5.1.35
LIBDIR += -L../../libmysql/7.x-5.1.35
else
INCDIR += -I../../libmysql/5.x-5.1.35
LIBDIR += -L../../libmysql/5.x-5.1.35
endif
queste
Codice:
# boost
INCDIR += -I../../boost
anche queste
Codice:
# Boost
INCDIR += -I../../../Extern/include/boost

# MySQL
INCDIR += -I/usr/local/include/mysql
LIBS += /usr/local/lib/mysql/libmysqlclient.a /usr/lib/libz.a
anche questa
Codice:
INCDIR += -I/usr/local/include
queste:
Codice:
# Project Libraries
INCDIR += -I../../../Extern/include
LIBDIR += -I../../../Extern/lib
e questa parola:
Codice:
-lmysqlclient
e questa:
Codice:
-Wl,-rpath=/usr/local/lib/gcc(ci può essere qualunqe numero qui)

Se non avete "-m32" aggiungete prima di "SRCS = (testo vario)" o "CPPFILE = (testo vario)" questo:
Codice:
CFLAGS += -m32
Per finire, aggiungete questo (sempre sopra SRCS o CPPFILE):
Codice:
INCDIR += -I../../../m2pkg/installed/x86-freebsd/include
LIBDIR += -L../../../m2pkg/installed/x86-freebsd/lib
Aggiungiamo, inoltre, questo prima di INCDIR += e LIBDIR += (quello che abbiamo aggiunto prima):
Codice:
CFLAGS += -static
LIBS += -lmariadbclient -lssl -lcrypto -lz

NOTA: Potete non aggiungere "CFLAGS += -static" e cambiare "ENABLE_STATIC = 0" a "ENABLE_STATIC = 1" se lo avete.

Se siete su FreeBSD x64 dovete aggiungere anche questo:
Codice:
LIBDIR += -L/usr/local/lib32/gcc(numero di gcc, esempio per me è 9)
Su FreeBSD x86 questo:
Codice:
LIBDIR += -L/usr/local/lib/gcc(numero di gcc, esempio per me è 9)

Apriamo ora il file game/src/Makefile
e cancelliamo le seguenti righe:
Codice:
# boost
INCDIR += -I../../../Extern/include/boost

# DevIL
INCDIR += -I../../libdevil
LIBDIR += -L../../libdevil
LIBS += -lIL -lpng -ltiff -lmng -llcms -ljpeg

# MySQL
ifeq ($(BSD_VERSION), 7)
INCDIR += -I../../libmysql/7.x-5.1.35
LIBDIR += -L../../libmysql/7.x-5.1.35
else
INCDIR += -I../../libmysql/5.x-5.1.35
LIBDIR += -L../../libmysql/5.x-5.1.35
endif

LIBS += -lmysqlclient -lz
# Miscellaneous external libraries
INCDIR += -I../../../Extern/include
LIBDIR += -L../../../Extern/lib
LIBS += -lcryptopp -lgtest

# HackShield
INCDIR += -I../../libhackshield/include
LIBDIR += -L../../libhackshield/lib
LIBS += -lanticpxsvr

# XTrap
INCDIR += -I../../libxtrap/include
oppure
Codice:
# Boost
INCDIR += -I../../../Extern/include/boost

# DevIL
INCDIR += -I../../../Extern/include/IL
LIBS += ../../../Extern/lib/libIL.a\
        ../../../Extern/lib/libjasper.a\
        ../../../Extern/lib/libpng.a\
        ../../../Extern/lib/libtiff.a\
        ../../../Extern/lib/libjbig.a\
        ../../../Extern/lib/libmng.a\
        /usr/lib/liblzma.a\
        ../../../Extern/lib/liblcms.a\
        ../../../Extern/lib/libjpeg.a

# MySQL
INCDIR += -I/usr/local/include/mysql
LIBS += /usr/local/lib/mysql/libmysqlclient.a /usr/lib/libz.a

# CryptoPP
LIBS += ../../../Extern/lib/libcryptopp.a
e
Codice:
# OpenSSL
INCDIR += -I/usr/include
LIBS += -lssl -lcrypto
# LIBS += /usr/lib/libssl.a
e questo
Codice:
# Project Libraries
INCDIR += -I../../../Extern/include
INCDIR += -I/usr/local/include
LIBDIR += -L/usr/local/lib

Prima di "CFILE = minilzo.c" aggiungiamo questo:
Codice:
INCDIR += -I../../../m2pkg/installed/x86-freebsd/include
LIBDIR += -L../../../m2pkg/installed/x86-freebsd/lib -L/usr/local/lib32/gcc(numero di gcc, esempio per me è 9)
LIBS += -lmariadbclient -lcryptopp -lIL -lpng -ljpeg -lssl -lcrypto
CFLAGS += -static
Su FreeBSD x86 sostituite "lib32" con "lib"

NOTA: Potete non aggiungere "CFLAGS += -static" e cambiare "ENABLE_STATIC = 0" a "ENABLE_STATIC = 1" se lo avete.

Cerchiamo
Codice:
CFILE    = minilzo.c
e modifichiamolo in
Codice:
CFILE    = minilzo.c sha1.c

NOTA: Se non avete CFILE potete aggiungere sha1.c dopo
Codice:
item_manager_read_tables.cpp
in questo modo:
Codice:
item_manager_read_tables.cpp sha1.c

Aggiungiamo dopo
Codice:
shopEx.cpp
questo:
Codice:
shopEx.cpp vid.cpp

Server: Modifiche sorgenti per Windows

Apriamo il file m2server.sln o Metin2Server.sln e se ci chiede di aggiornare diciamo di si.
NOTA: Potremmo avere errori per la mancanza di "ServerKeyGeneration", ignoriamoli.

All'interno del file game.2008.vcxproj (quello che abbiamo aperto prima) aggiungiamo dopo questo:
Codice:
<ClCompile Include="war_map.cpp" />
questo:
Codice:
<ClCompile Include="sha1.c" />
<ClCompile Include="sha1.h" />
<ClCompile Include="vid.cpp" />

Apriamo il file .sln con visual studio e clicchiamo il tasto destro su "db" e clicchiamo Proprietà.
Scegliamo "Linker" e apriamo il menù a tendina e scegliamo Input.
In alto c'è "Configurazione: " modifichiamo in "Tutte le configurazioni"
vs2.png


In questa finestra clicchiamo su "Dipendenze aggiuntive", clicchiamo il menu in basso e successivamente il bottone Modifica:
vs3.png


Cancelliamo tutto quello che c'è scritto e scriviamo questo:
Codice:
libmariadb.lib
ws2_32.lib
Shlwapi.lib

vs4.png


Poi clicchiamo OK e Applica.

Apriamo il file .sln con visual studio e clicchiamo il tasto destro su "game" e clicchiamo Proprietà.
Scegliamo "Linker" e apriamo il menù a tendina e scegliamo Input.
In alto c'è "Configurazione: " modifichiamo in "Tutte le configurazioni"
vs2.png


In questa finestra clicchiamo su "Dipendenze aggiuntive", clicchiamo il menu in basso e successivamente il bottone Modifica:

vs3.png


Cancelliamo tutto quello che c'è scritto e scriviamo questo:
Codice:
libmariadb.lib
ws2_32.lib
Shlwapi.lib
DevIL.lib
cryptopp-static.lib
libcrypto.lib
libssl.lib
Advapi32.lib
User32.lib

vs5.png


Selezionate TUTTI i progetti, fate il tasto destro e cliccate Proprietà.
All'interno della finestra, cliccate sulla destra "vcpkg" e selezionate:
"Static libraries: Yes"
"Auto link: Yes"
spacer.png
Andate in C/C++, Generale, e troverete "Cartelle di inclusioni aggiuntive" o qualcosa simile. Premete la freccia piccolina nel testo e modificate aggiungendo il seguente:

$(SolutionDir)Extern\include

Scegliete solo UserInterface, andate in Linker e generale e trovate "Cartelle di librerie aggiuntiva". Premete la freccia piccolina nel testo e modificate aggiungendo il seguente:
$(SolutionDir)Extern\lib

Se avete uan vecchia versione del tutorial, rimuovete questa linea:
<VcpkgUserTriplet>x86-windows-static</VcpkgUserTriplet>
Dovete rimuoverla in tutti i file .vcxproj.

Modifiche Client

Apriamo il file EterBase/cipher.h e modifichiamo le seguenti righe:
da
Codice:
    encoder_->ProcessData((byte*)buffer, (const byte*)buffer, length);
a
Codice:
    encoder_->ProcessData((CryptoPP::byte*)buffer, (const CryptoPP::byte*)buffer, length);

e da
Codice:
    decoder_->ProcessData((byte*)buffer, (const byte*)buffer, length);
a
Codice:
    decoder_->ProcessData((CryptoPP::byte*)buffer, (const CryptoPP::byte*)buffer, length);

Apriamo il file Eterbase/lzo.cpp e cancelliamo questa riga:
Codice:
#include <lzo-2.03/lzoLibLink.h>
"lzo-2.03" potrebbe variare.
Apriamo EterBase/lzo.h e verifichiamo che #include con lzo1x.h sia cosi:
Codice:
#include <lzo/lzo1x.h>

Apriamo il file UserInterface/MarkImage.h e prima di questo:
Codice:
#include <IL/il.h>
aggiungiamo questo:
Codice:
#define IL_STATIC_LIB 1

Apriamo UserInterface/UserInterface.cpp ed eliminiamo questa riga:
Codice:
#include <cryptopp/cryptoppLibLink.h>

Sempre all'interno di UserInterface.cpp modifichiamo:
Codice:
static const char * sc_apszPythonLibraryFilenames[] =
{
    "UserDict.pyc",
    "future.pyc",
    "copy_reg.pyc",
    "linecache.pyc",
    "ntpath.pyc",
    "os.pyc",
    "site.pyc",
    "stat.pyc",
    "string.pyc",
    "traceback.pyc",
    "types.pyc",
    "\n",
};
in:
Codice:
static const char * sc_apszPythonLibraryFilenames[] =
{
#if PY_MINOR_VERSION == 7
    "abc.pyc",
    "bisect.pyc",
    "codecs.pyc",
    "collections.pyc",
    "copy.pyc",
    "copy_reg.pyc",
    "fnmatch.pyc",
    "functools.pyc",
    "genericpath.pyc",
    "heapq.pyc",
    "keyword.pyc",
    "linecache.pyc",
    "locale.pyc",
    "ntpath.pyc",
    "os.pyc",
    "pyexpat.pyd",
    "random.pyc",
    "re.pyc",
    "shutil.pyc",
    "site.pyc",
    "sre_compile.pyc",
    "sre_constants.pyc",
    "sre_parse.pyc",
    "stat.pyc",
    "string.pyc",
    "sysconfig.pyc",
    "traceback.pyc",
    "types.pyc",
    "UserDict.pyc",
    "warnings.pyc",
    "weakref.pyc",
    "_abcoll.pyc",
    "_weakrefset.pyc",
    "__future__.pyc",
    "encodings\\aliases.pyc",
    "encodings\\ascii.pyc",
    "encodings\\cp1250.pyc",
    "encodings\\cp1251.pyc",
    "encodings\\cp1252.pyc",
    "encodings\\cp949.pyc",
    "encodings\\utf_8.pyc",
    "encodings\\__init__.pyc",
    "xml\\__init__.pyc",
    "xml\\dom\\domreg.pyc",
    "xml\\dom\\expatbuilder.pyc",
    "xml\\dom\\minicompat.pyc",
    "xml\\dom\\minidom.pyc",
    "xml\\dom\\NodeFilter.pyc",
    "xml\\dom\\xmlbuilder.pyc",
    "xml\\dom\\__init__.pyc",
    "xml\\parsers\\expat.pyc",
    "xml\\parsers\\__init__.pyc",
#else
    "UserDict.pyc",
    "__future__.pyc",
    "copy_reg.pyc",
    "linecache.pyc",
    "ntpath.pyc",
    "os.pyc",
    "site.pyc",
    "stat.pyc",
    "string.pyc",
    "traceback.pyc",
    "types.pyc",
#endif
    "\n",
};

Cancelliamo le seguenti righe: (se lo avete)
Codice:
#if GrannyProductMinorVersion==4
#pragma comment( lib, "granny2.4.0.10.lib" )
#elif GrannyProductMinorVersion==7
#pragma comment( lib, "granny2.7.0.30.lib" )
#elif GrannyProductMinorVersion==8
#pragma comment( lib, "granny2.8.49.0.lib" )
#elif GrannyProductMinorVersion==9
#pragma comment( lib, "granny2.9.12.0.lib" )
#else
#error "unknown granny version"
#endif
Cancelliamo la seguente riga: (se la avete)
Codice:
#pragma comment( lib, "granny2.lib" )

Cancelliamo anche la seguente riga:
Codice:
//ifdef _DEBUG
//#pragma comment( lib, "python2_d.lib" )
//#else
#pragma comment( lib, "python2.lib" )
//#endif

Aggiungiamo sotto:
Codice:
#pragma comment( lib, "devil.lib" )
questo:
Codice:
#ifdef _DEBUG
#pragma comment( lib, "jpegd.lib" )
#else
#pragma comment( lib, "jpeg.lib" )
#endif
#pragma comment( lib, "cryptopp-static.lib" )
#pragma comment( lib, "snappy.lib" )
#pragma comment( lib, "lzo2.lib" )
NOTA: Cancelliamo quello di snappy se non usate Type6.

Se avete:
Codice:
#define ENABLE_PYLIB_CHECK
cambiamolo in:
Codice:
//#define ENABLE_PYLIB_CHECK

Apriamo EterPack/EterPack.cpp ed eliminiamo questa riga:
Codice:
#include <cryptopp/cryptoppLibLink.h>

Apriamo il file UserInterface/GuildMarkUploader.cpp e cancelliamo:
Codice:
(ILvoid*)

Apriamo il file EterLib/JpegFile.cpp e assicuriamoci che l'include prima di jpegLibLink sia così:
Codice:
#include <jpeglib.h>
dopodichè rimuoviamo questa riga:
Codice:
#include <libjpeg-6b/jpegLibLink.h>
"libjpeg-6b" potrebbe variare.

In GrpDetector.h aggiungiamo dopo l'include d3dx8 questo:
Codice:
#include <string>

Apriamo il file ScriptLib\StdAfx.h e modifichiamo:
Codice:
#ifdef _DEBUG
    #undef _DEBUG
    #include "../../Extern/Python2/Python.h"
    #define _DEBUG
#else
    #include "../../Extern/Python2/Python.h"
#endif
#include "../../Extern/Python2/node.h"
#include "../../Extern/Python2/grammar.h"
#include "../../Extern/Python2/token.h"
#include "../../Extern/Python2/parsetok.h"
#include "../../Extern/Python2/errcode.h"
#include "../../Extern/Python2/compile.h"
#include "../../Extern/Python2/symtable.h"
#include "../../Extern/Python2/eval.h"
#include "../../Extern/Python2/marshal.h"
in:
Codice:
typedef struct _mod *mod_ty; // Modern Python compilation fix

#include <python2.7/Python.h>
#include <python2.7/node.h>
#include <python2.7/grammar.h>
#include <python2.7/token.h>
#include <python2.7/parsetok.h>
#include <python2.7/errcode.h>
#include <python2.7/compile.h>
#include <python2.7/symtable.h>
#include <python2.7/eval.h>
#include <python2.7/marshal.h>

#undef BYTE // Fixed python bitset.h build issue

Apriamo il file scriptLib/PythonLauncher.h e modifichiamo:
Codice:
#include "../../Extern/Python2/frameobject.h"
in:
Codice:
#include <python2.7/frameobject.h>

Apriamo il file scriptLib/PythonLauncher.cpp e modifichiamo:
Codice:
#include "../../Extern/Python2/frameobject.h"
in:
Codice:
#include <python2.7/frameobject.h>

Apriamo il file scriptLib/PythonMarshal.cpp e modifichiamo:
Codice:
#include "../../Extern/Python2/longintrepr.h"
in:
Codice:
#include <python2.7/longintrepr.h>

Apriamo ScriptLib/PythonUtils.cpp e se non abbiamo:
Codice:
#define PyLong_AsLong PyLong_AsLongLong
#define PyLong_AsUnsignedLong PyLong_AsUnsignedLongLong
aggiungiamolo sotto:
Codice:
#include "PythonUtils.h"

Apriamo il file EterBase\StdAfx.h e modifichiamo:
Codice:
// Armadillo nanomite protection
#ifndef NANOBEGIN
    #ifdef __BORLANDC__
        #define NANOBEGIN     __emit__ (0xEB,0x03,0xD6,0xD7,0x01)
        #define NANOEND       __emit__ (0xEB,0x03,0xD6,0xD7,0x00)
    #else
        #define NANOBEGIN     __asm _emit 0xEB __asm _emit 0x03 __asm _emit 0xD6 __asm _emit 0xD7 __asm _emit 0x01
        #define NANOEND       __asm _emit 0xEB __asm _emit 0x03 __asm _emit 0xD6 __asm _emit 0xD7 __asm _emit 0x00
    #endif
#endif
in:
Codice:
// Armadillo nanomite protection
#if !defined(NANOBEGIN) && !defined(NANOEND)
    #ifdef _DEBUG
        #define NANOBEGIN
        #define NANOEND
    #else
        #include <armadillo/SecuredSections.h>
    #endif
#endif

Dobbiamo fare questa modifica anche in questi file:
- EterGrnLib/StdAfx.h
- MilesLib/StdAfx.h
- SpeedTreeLib/StdAfx.h

Apriamo il file MilesLib/StdAfx.h e cancelliamo questa riga:
Codice:
#include <mss.h>

Apriamo il file .sln (ad esempio Metin2Client.sln o Metin2Client_VC90.sln)
se ci chiederà l'aggiornamento unidirezionale premiamo OK.

Clicchiamo il tasto destro su "UserInterface" e clicchiamo Proprietà.
Scegliamo "Linker" e apriamo il menù a tendina e scegliamo Avanzate.
In alto c'è "Configurazione: " modifichiamo in "Tutte le configurazioni"
vs2.png


Modifichiamo l'opzione /SAFESEH in /SAFESEH:NO.
vs1.png


Selezionate TUTTI i progetti, fate il tasto destro e cliccate Proprietà.
All'interno della finestra, cliccate sulla destra "vcpkg" e selezionate:
"Static libraries: Yes"
"Auto link: Yes"
spacer.png
Andate in C/C++, Generale, e troverete "Cartelle di inclusioni aggiuntive" o qualcosa simile. Premete la freccia piccolina nel testo e modificate aggiungendo il seguente:

$(SolutionDir)Extern\include

Scegliete solo UserInterface, andate in Linker e generale e trovate "Cartelle di librerie aggiuntiva". Premete la freccia piccolina nel testo e modificate aggiungendo il seguente:
$(SolutionDir)Extern\lib

Se avete uan vecchia versione del tutorial, rimuovete questa linea:
<VcpkgUserTriplet>x86-windows-static</VcpkgUserTriplet>
Dovete rimuoverla in tutti i file .vcxproj.

Client: Pulizia ed aggiornamento

Copiamo il nostro nuovo eseguibile nella cartella del client.
Cancelliamo tutte le DLL ad eccezione di:
- SpeedTreeRT.dll
- granny2.dll
- MSS32.dll
Cancelliamo la cartella "lib" e rimpiazziamola con questa:

Note finali & approfondimenti vari


  • Se volete Granny 2.9 aprite il file EterBase/ServiceDefs.h e aggiungete questo:
Codice:
#define __GRANNY_VERSION__ 9
dopo questo:
Codice:
#define _IMPROVED_PACKET_ENCRYPTION_

  • La cartella di vcpkg include una versione già MSL, verificate in share/moduleinfo.txt la versione del commit e, in caso, potete redistribuire il pack aggiornato (posso tranquillamente modificare la guida).
  • L'aggiornamento di Python a 2.7.15 con le nuove librerie include anche un paio di encoding (Coreano, Europeo e UTF-8 mi pare), mi raccomando, se vcpkg aggiornare ad una nuova versione aggiornare anche questa cartella (potete tranquillamente rispondere con l'aggiornamento e modificherò la guida).
  • Abbiamo compilato tutte le librerie come statiche quindi rimosso tutte le DLL classiche di Metin2 (le uniche tre infatti, sono dipendenze closed source, comunque possibili da togliere).
  • Nella cartella lib (Python 2.7.15) includo già una versione compilata in release di pyexpat.pyd, potete ricompilarla se volete, la mia è compilata con Visual Studio 2019 (Toolchain 16.2) e mitigazione Spectre attiva.
  • Le modifiche di Armadillo consentono di aggiornare le definizioni dei Nanomite all'ultima versione pubblica e di fixare un bug che in debug le funzioni designate da nanobegin e nanoend producono output sbagliati.
  • Le modifiche log.c risparmiano 1058340518920543890 messaggi aggiuntivi su Windows
  • Se volete nuove versioni di Granny modificate granny2.h come volete, sentitevi liberi di rilasciare un aggiornamento
  • La guida potrebbe non essere accurata per tutti i sorgenti, personalmente ho testato su mainline_released e alcuni miei amici hanno testato su sorgenti vari.
Il controllo ENABLE_PYLIB_CHECK lo ho disabilitato in quanto
- Non supporta Python 2.7.15 (chiaramente gli hash dei file sono diversi)
- Non ho avuto tempo/voglia di fare uno script automatizzato che computi gli hash richiesti
- Non ho interesse nell'utilizzare questo controllo (Di fatti togliendo si lascia il controllo di base di Metin2 che in ogni caso funziona anche se meno sicuro)
Sentitevi liberi di commentare con il codice per il controllo funzionante con le librerie che ho rilasciato nell'archivio e provvederò ad aggiornare il post.

Cambiamenti rispetto alla versione precedente:​


  • Rimosso il vecchio m2pkg con una versione più classica
  • Aggiornata la guida come su metin2dev
  • Rimosso il link manuale

Chiedo scusa per eventuali errori di battitura o formattazione, la guida ha richiesto più di una settimana di lavorazione e per me è risultato impossibile controllare tutto.
Se trovate errori di battitura potete segnalarmeli nei commenti. Per la formattazione, potete darmi consigli nei commenti e, quando avrò tempo, potrò applicarli oppure un moderatore
potrebbe applicarla per me XD.



Vorrei ringraziare tutti i demoni che mi hanno convinto e spammato per pubblicare questa guida (Un ringraziamento speciale va a @spaceman33 e @CcC Quisan),
Buona fortuna.
 

Allegati

  • vcpkg5.png
    vcpkg5.png
    49.9 KB · Visualizzazioni: 2,805
Ultima modifica: