Legends-of-Azeroth-Pandaria-5.4.8

Форк
0
642 строки · 17.8 Кб
1
/*
2
 * Copyright (C) 2011-2016 Project SkyFire <http://www.projectskyfire.org/>
3
 * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
4
 * Copyright (C) 2005-2016 MaNGOS <http://getmangos.com/>
5
 *
6
 * This program is free software; you can redistribute it and/or modify it
7
 * under the terms of the GNU General Public License as published by the
8
 * Free Software Foundation; either version 3 of the License, or (at your
9
 * option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful, but WITHOUT
12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14
 * more details.
15
 *
16
 * You should have received a copy of the GNU General Public License along
17
 * with this program. If not, see <http://www.gnu.org/licenses/>.
18
 */
19

20
#define _CRT_SECURE_NO_DEPRECATE
21
#include <cstdio>
22
#include <iostream>
23
#include <vector>
24
#include <list>
25
#include <errno.h>
26

27
#ifdef WIN32
28
    #include <Windows.h>
29
    #include <sys/stat.h>
30
    #include <direct.h>
31
    #define mkdir _mkdir
32
#else
33
    #include <sys/stat.h>
34
    #define ERROR_PATH_NOT_FOUND ERROR_FILE_NOT_FOUND
35
#endif
36

37
#undef min
38
#undef max
39

40
//#pragma warning(disable : 4505)
41
//#pragma comment(lib, "Winmm.lib")
42

43
#include <map>
44

45
//From Extractor
46
#include "adtfile.h"
47
#include "wdtfile.h"
48
#include "dbcfile.h"
49
#include "StringFormat.h"
50
#include "wmo.h"
51
#include "mpqfile.h"
52

53
#include "vmapexport.h"
54

55
//------------------------------------------------------------------------------
56
// Defines
57

58
#define MPQ_BLOCK_SIZE 0x1000
59

60
//-----------------------------------------------------------------------------
61

62
HANDLE WorldMpq = NULL;
63
HANDLE LocaleMpq = NULL;
64

65
uint32 CONF_TargetBuild = 18273;              // 5.4.8.18273
66

67
// List MPQ for extract maps from
68
char const* CONF_mpq_list[]=
69
{
70
    "world.MPQ",
71
    "model.MPQ", // added in 5.x.x
72
    "misc.MPQ", // added in 5.x.x
73
    "expansion1.MPQ",
74
    "expansion2.MPQ",
75
    "expansion3.MPQ",
76
    "expansion4.MPQ", // added in 5.x.x
77
};
78

79
uint32 const Builds[] = {16016, 16048, 16057, 16309, 16357, 16516, 16650, 16844, 16965, 17116, 17266, 17325, 17345, 17538, 17645, 17688, 17898, 18273, 0};
80
#define LAST_DBC_IN_DATA_BUILD 15595    // after this build mpqs with dbc are back to locale folder
81
#define NEW_BASE_SET_BUILD 16016 // 15211
82

83
#define LOCALES_COUNT 12
84

85
char const* Locales[LOCALES_COUNT] =
86
{
87
    "enGB", "enUS",
88
    "deDE", "esES",
89
    "frFR", "koKR",
90
    "zhCN", "zhTW",
91
    "enCN", "enTW",
92
    "esMX", "ruRU"
93
};
94

95
TCHAR const* LocalesT[LOCALES_COUNT] =
96
{
97
    _T("enGB"), _T("enUS"),
98
    _T("deDE"), _T("esES"),
99
    _T("frFR"), _T("koKR"),
100
    _T("zhCN"), _T("zhTW"),
101
    _T("enCN"), _T("enTW"),
102
    _T("esMX"), _T("ruRU"),
103
};
104

105
typedef struct
106
{
107
    char name[64];
108
    unsigned int id;
109
} map_id;
110

111
std::vector<map_id> map_ids;
112
uint32 map_count;
113
uint16 *LiqType = 0;
114
char output_path[128]=".";
115
char input_path[1024]=".";
116
bool preciseVectorData = false;
117
std::unordered_map<std::string, WMODoodadData> WmoDoodads;
118

119
// Constants
120

121
const char* szWorkDirWmo = "./Buildings";
122

123
std::map<std::pair<uint32, uint16>, uint32> uniqueObjectIds;
124

125
uint32 GenerateUniqueObjectId(uint32 clientId, uint16 clientDoodadId)
126
{
127
    return uniqueObjectIds.emplace(std::make_pair(clientId, clientDoodadId), uniqueObjectIds.size() + 1).first->second;
128
}
129

130
bool LoadLocaleMPQFile(int locale)
131
{
132
    TCHAR buff[512];
133
    memset(buff, 0, sizeof(buff));
134
    _stprintf(buff, _T("%s%s/locale-%s.MPQ"), input_path, LocalesT[locale], LocalesT[locale]);
135
    if (!SFileOpenArchive(buff, 0, MPQ_OPEN_READ_ONLY, &LocaleMpq))
136
    {
137
        if (GetLastError() != ERROR_PATH_NOT_FOUND)
138
        {
139
            _tprintf(_T("Loading %s locale MPQs\n"), LocalesT[locale]);
140
            _tprintf(_T("Cannot open archive %s\n"), buff);
141
        }
142
        return false;
143
    }
144

145
    _tprintf(_T("Loading %s locale MPQs\n"), LocalesT[locale]);
146
    char const* prefix = NULL;
147
    for (int i = 0; Builds[i] && Builds[i] <= CONF_TargetBuild; ++i)
148
    {
149
        // Do not attempt to read older MPQ patch archives past this build, they were merged with base
150
        // and trying to read them together with new base will not end well
151
        if (CONF_TargetBuild >= NEW_BASE_SET_BUILD && Builds[i] < NEW_BASE_SET_BUILD)
152
            continue;
153

154
        memset(buff, 0, sizeof(buff));
155
        if (Builds[i] > LAST_DBC_IN_DATA_BUILD)
156
        {
157
            prefix = "";
158
            _stprintf(buff, _T("%s%s/wow-update-%s-%u.MPQ"), input_path, LocalesT[locale], LocalesT[locale], Builds[i]);
159
        }
160
        else
161
        {
162
            prefix = Locales[locale];
163
            _stprintf(buff, _T("%swow-update-base-%u.MPQ"), input_path, Builds[i]);
164
        }
165

166
        if (!SFileOpenPatchArchive(LocaleMpq, buff, prefix, 0))
167
        {
168
            if (GetLastError() != ERROR_FILE_NOT_FOUND)
169
                _tprintf(_T("Cannot open patch archive %s\n"), buff);
170
            continue;
171
        }
172
    }
173

174
    printf("\n");
175
    return true;
176
}
177

178
void LoadCommonMPQFiles(uint32 build)
179
{
180
    TCHAR filename[512];
181
    _stprintf(filename, _T("%sworld.MPQ"), input_path);
182
    _tprintf(_T("Loading common MPQ files\n"));
183
    if (!SFileOpenArchive(filename, 0, MPQ_OPEN_READ_ONLY, &WorldMpq))
184
    {
185
        if (GetLastError() != ERROR_PATH_NOT_FOUND)
186
            _tprintf(_T("Cannot open archive %s\n"), filename);
187
        return;
188
    }
189

190
    int count = sizeof(CONF_mpq_list) / sizeof(char*);
191
    for (int i = 1; i < count; ++i)
192
    {
193
        if (build < 15211 && !strcmp("world2.MPQ", CONF_mpq_list[i]))   // 4.3.2 and higher MPQ
194
            continue;
195

196
        _stprintf(filename, _T("%s%s"), input_path, CONF_mpq_list[i]);
197
        if (!SFileOpenPatchArchive(WorldMpq, filename, "", 0))
198
        {
199
            if (GetLastError() != ERROR_PATH_NOT_FOUND)
200
                _tprintf(_T("Cannot open archive %s\n"), filename);
201
            else
202
                _tprintf(_T("Not found %s\n"), filename);
203
        }
204
        else
205
            _tprintf(_T("Loaded %s\n"), filename);
206
    }
207

208
    char const* prefix = NULL;
209
    for (int i = 0; Builds[i] && Builds[i] <= CONF_TargetBuild; ++i)
210
    {
211
        // Do not attempt to read older MPQ patch archives past this build, they were merged with base
212
        // and trying to read them together with new base will not end well
213
        if (CONF_TargetBuild >= NEW_BASE_SET_BUILD && Builds[i] < NEW_BASE_SET_BUILD)
214
            continue;
215

216
        memset(filename, 0, sizeof(filename));
217
        if (Builds[i] > LAST_DBC_IN_DATA_BUILD)
218
        {
219
            prefix = "";
220
            _stprintf(filename, _T("%swow-update-base-%u.MPQ"), input_path, Builds[i]);
221
        }
222
        else
223
        {
224
            prefix = "base";
225
            _stprintf(filename, _T("%swow-update-%u.MPQ"), input_path, Builds[i]);
226
        }
227

228
        if (!SFileOpenPatchArchive(WorldMpq, filename, prefix, 0))
229
        {
230
            if (GetLastError() != ERROR_PATH_NOT_FOUND)
231
                _tprintf(_T("Cannot open patch archive %s\n"), filename);
232
            else
233
                _tprintf(_T("Not found %s\n"), filename);
234
            continue;
235
        }
236
        else
237
            _tprintf(_T("Loaded %s\n"), filename);
238
    }
239

240
    printf("\n");
241
}
242

243

244
// Local testing functions
245

246
bool FileExists(const char* file)
247
{
248
    if (FILE* n = fopen(file, "rb"))
249
    {
250
        fclose(n);
251
        return true;
252
    }
253
    return false;
254
}
255

256
void strToLower(char* str)
257
{
258
    while(*str)
259
    {
260
        *str=tolower(*str);
261
        ++str;
262
    }
263
}
264

265
// copied from contrib/extractor/System.cpp
266
void ReadLiquidTypeTableDBC()
267
{
268
    HANDLE localeFile;
269
    char localMPQ[512];
270

271
    sprintf(localMPQ, "%smisc.MPQ", input_path);
272
    if (FileExists(localMPQ)==false)
273
    {   // Use misc.mpq
274
        printf(localMPQ, "%s/Data/%s/locale-%s.MPQ", input_path);
275
    }
276
    
277
    if (!SFileOpenArchive(localMPQ, 0, MPQ_OPEN_READ_ONLY, &localeFile))
278
    {
279
        exit(1);
280
    }
281
    
282
    printf("Read LiquidType.dbc file...");
283

284
    HANDLE dbcFile;
285
    if (!SFileOpenFileEx(localeFile, "DBFilesClient\\LiquidType.dbc", SFILE_OPEN_PATCHED_FILE, &dbcFile))
286
    {
287
        if (!SFileOpenFileEx(localeFile, "DBFilesClient\\LiquidType.dbc", SFILE_OPEN_PATCHED_FILE, &dbcFile))
288
        {
289
            printf("Fatal error: Cannot find LiquidType.dbc in archive!\n");
290
            exit(1);
291
        }
292
    }
293

294
    DBCFile dbc(localeFile, "DBFilesClient\\LiquidType.dbc");
295
    if (!dbc.open())
296
    {
297
        printf("Fatal error: Invalid LiquidType.dbc file format!\n");
298
        exit(1);
299
    }
300

301
    size_t LiqType_count = dbc.getRecordCount();
302
    size_t LiqType_maxid = dbc.getMaxId();
303
    LiqType = new uint16[LiqType_maxid + 1];
304
    memset(LiqType, 0xff, (LiqType_maxid + 1) * sizeof(uint16));
305

306
    for (uint32 x = 0; x < LiqType_count; ++x)
307
        LiqType[dbc.getRecord(x).getUInt(0)] = dbc.getRecord(x).getUInt(3);
308

309
    printf("Done! (%zu LiqTypes loaded)\n", LiqType_count);
310
}
311

312
// bool ExtractWmo()
313
// {
314
//     bool success = false;
315

316
//     //const char* ParsArchiveNames[] = {"patch-2.MPQ", "patch.MPQ", "common.MPQ", "expansion.MPQ"};
317

318
//     SFILE_FIND_DATA data;
319
//     HANDLE find = SFileFindFirstFile(WorldMpq, "*.wmo", &data, NULL);
320
//     if (find != NULL)
321
//     {
322
//         do
323
//         {
324
//             std::string str = data.cFileName;
325
//             //printf("Extracting wmo %s\n", str.c_str());
326
//             success |= ExtractSingleWmo(str);
327
//         }
328
//         while (SFileFindNextFile(find, &data));
329
//     }
330
//     SFileFindClose(find);
331

332
//     if (success)
333
//         printf("\nExtract wmo complete (No (fatal) errors)\n");
334

335
//     return success;
336
// }
337

338
bool ExtractSingleWmo(std::string& fname)
339
{
340
    // Copy files from archive
341
    std::string originalName = fname;
342

343
    char szLocalFile[1024];
344
    char* plain_name = GetPlainName(&fname[0]);
345
    fixnamen(plain_name, strlen(plain_name));
346
    fixname2(plain_name, strlen(plain_name));    
347
    sprintf(szLocalFile, "%s/%s", szWorkDirWmo, plain_name);
348

349
    if (FileExists(szLocalFile))
350
        return true;
351

352
    int p = 0;
353
    // Select root wmo files
354
    char const* rchr = strrchr(plain_name, '_');
355
    if (rchr != nullptr)
356
    {
357
        char cpy[4];
358
        strncpy((char*)cpy, rchr, 4);
359
        for (int i = 0; i < 4; ++i)
360
        {
361
            int m = cpy[i];
362
            if (isdigit(m))
363
                p++;
364
        }
365
    }
366

367
    if (p == 3)
368
        return true;
369

370
    bool file_ok = true;
371
    printf("Extracting %s\n", originalName.c_str());
372
    WMORoot froot(originalName);
373
    if(!froot.open())
374
    {
375
        printf("Couldn't open RootWmo!!!\n");
376
        return true;
377
    }
378
    FILE *output = fopen(szLocalFile,"wb");
379
    if(!output)
380
    {
381
        printf("couldn't open %s for writing!\n", szLocalFile);
382
        return false;
383
    }
384
    froot.ConvertToVMAPRootWmo(output);
385
    WMODoodadData& doodads = WmoDoodads[plain_name];
386
    std::swap(doodads, froot.DoodadData);
387
    int Wmo_nVertices = 0;
388
    uint32 groupCount = 0;
389
    //printf("root has %d groups\n", froot->nGroups);
390
    if (froot.nGroups !=0)
391
    {
392
        for (uint32 i = 0; i < froot.nGroups; ++i)
393
        {
394
            char temp[1024];
395
            strncpy(temp, fname.c_str(), 1024);
396
            temp[fname.length()-4] = 0;
397

398
            WMOGroup fgroup(Trinity::StringFormat("%s_%03u.wmo", temp, i));
399
            if (!fgroup.open(&froot))
400
            {
401
                printf("Could not open all Group file for: %s\n", plain_name);
402
                file_ok = false;
403
                break;
404
            }
405

406
            if (fgroup.ShouldSkip(&froot))
407
                continue;            
408

409
            Wmo_nVertices += fgroup.ConvertToVMAPGroupWmo(output, preciseVectorData);
410
            ++groupCount;
411
            for (uint16 groupReference : fgroup.DoodadReferences)
412
            {
413
                if (groupReference >= doodads.Spawns.size())
414
                    continue;
415

416
                uint32 doodadNameIndex = doodads.Spawns[groupReference].NameIndex;
417
                if (froot.ValidDoodadNames.find(doodadNameIndex) == froot.ValidDoodadNames.end())
418
                    continue;
419

420
                doodads.References.insert(groupReference);
421
            }
422
        }
423
    }
424

425
    fseek(output, 8, SEEK_SET); // store the correct no of vertices
426
    fwrite(&Wmo_nVertices,sizeof(int),1,output);
427
    // store the correct no of groups
428
    fwrite(&groupCount, sizeof(uint32), 1, output);    
429
    fclose(output);
430

431
    // Delete the extracted file in the case of an error
432
    if (!file_ok)
433
        remove(szLocalFile);
434
    return true;
435
}
436

437
void ParsMapFiles()
438
{
439
    char fn[512];
440
    //char id_filename[64];
441
    for (unsigned int i=0; i<map_count; ++i)
442
    {
443
        sprintf(fn,"World\\Maps\\%s\\%s.wdt", map_ids[i].name, map_ids[i].name);
444
        WDTFile WDT(fn,map_ids[i].name);
445
        if (WDT.init(map_ids[i].id))
446
        {
447
            printf("Processing Map %u\n[", map_ids[i].id);
448
            for (int x=0; x<64; ++x)
449
            {
450
                for (int y=0; y<64; ++y)
451
                {
452
                    if (ADTFile *ADT = WDT.GetMap(x,y))
453
                    {
454
                        //sprintf(id_filename,"%02u %02u %03u",x,y,map_ids[i].id);//!!!!!!!!!
455
                        ADT->init(map_ids[i].id, x, y);
456
                        delete ADT;
457
                    }
458
                }
459
                printf("#");
460
                fflush(stdout);
461
            }
462
            printf("]\n");
463
        }
464
    }
465
}
466

467
void getGamePath()
468
{
469
#ifdef _WIN32
470
    strcpy(input_path,"Data\\");
471
#else
472
    strcpy(input_path,"Data/");
473
#endif
474
}
475

476
bool processArgv(int argc, char ** argv, const char *versionString)
477
{
478
    bool result = true;
479
    bool hasInputPathParam = false;
480
    preciseVectorData = false;
481

482
    for(int i = 1; i < argc; ++i)
483
    {
484
        if(strcmp("-s",argv[i]) == 0)
485
        {
486
            preciseVectorData = false;
487
        }
488
        else if(strcmp("-d",argv[i]) == 0)
489
        {
490
            if((i+1)<argc)
491
            {
492
                hasInputPathParam = true;
493
                strcpy(input_path, argv[i+1]);
494
                if (input_path[strlen(input_path) - 1] != '\\' || input_path[strlen(input_path) - 1] != '/')
495
                    strcat(input_path, "/");
496
                ++i;
497
            }
498
            else
499
            {
500
                result = false;
501
            }
502
        }
503
        else if(strcmp("-?",argv[1]) == 0)
504
        {
505
            result = false;
506
        }
507
        else if(strcmp("-l",argv[i]) == 0)
508
        {
509
            preciseVectorData = true;
510
        }
511
        else if(strcmp("-b",argv[i]) == 0)
512
        {
513
            if (i + 1 < argc)                            // all ok
514
                CONF_TargetBuild = atoi(argv[i++ + 1]);
515
        }
516
        else
517
        {
518
            result = false;
519
            break;
520
        }
521
    }
522

523
    if(!result)
524
    {
525
        printf("Extract %s.\n",versionString);
526
        printf("%s [-?][-s][-l][-d <path>]\n", argv[0]);
527
        printf("   -s : (default) small size (data size optimization), ~500MB less vmap data.\n");
528
        printf("   -l : large size, ~500MB more vmap data. (might contain more details)\n");
529
        printf("   -d <path>: Path to the vector data source folder.\n");
530
        printf("   -b : target build (default %u)\n", CONF_TargetBuild);
531
        printf("   -? : This message.\n");
532
    }
533

534
    if(!hasInputPathParam)
535
        getGamePath();
536

537
    return result;
538
}
539

540

541
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
542
// Main
543
//
544
// The program must be run with two command line arguments
545
//
546
// Arg1 - The source MPQ name (for testing reading and file find)
547
// Arg2 - Listfile name
548
//
549

550
int main(int argc, char ** argv)
551
{
552
    bool success=true;
553
    const char *versionString = "V4.03 2017_04";
554

555
    // Use command line arguments, when some
556
    if (!processArgv(argc, argv, versionString))
557
        return 1;
558

559
    // some simple check if working dir is dirty
560
    else
561
    {
562
        std::string sdir = std::string(szWorkDirWmo) + "/dir";
563
        std::string sdir_bin = std::string(szWorkDirWmo) + "/dir_bin";
564
        struct stat status;
565
        if (!stat(sdir.c_str(), &status) || !stat(sdir_bin.c_str(), &status))
566
        {
567
            printf("Your output directory seems to be polluted, please use an empty directory!\n");
568
            printf("<press return to exit>");
569
            char garbage[2];
570
            return scanf("%c", garbage);
571
        }
572
    }
573

574
    printf("Extract %s. Beginning work ....\n\n",versionString);
575
    //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
576
    // Create the working directory
577
    if (mkdir(szWorkDirWmo
578
#if defined(__linux__) || defined(__APPLE__)
579
                    , 0711
580
#endif
581
                    ))
582
            success = (errno == EEXIST);
583

584
    LoadCommonMPQFiles(CONF_TargetBuild);
585

586
    for (int i = 0; i < LOCALES_COUNT; ++i)
587
    {
588
        //Open MPQs
589
        if (!LoadLocaleMPQFile(i))
590
        {
591
            if (GetLastError() != ERROR_PATH_NOT_FOUND)
592
                printf("Unable to load %s locale archives!\n", Locales[i]);
593
            continue;
594
        }
595

596
        printf("Detected and using locale: %s\n", Locales[i]);
597
        break;
598
    }
599

600
    ReadLiquidTypeTableDBC();
601

602
    //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
603
    //map.dbc
604
    if (success)
605
    {
606
        DBCFile * dbc = new DBCFile(LocaleMpq, "DBFilesClient\\Map.dbc");
607
        if (!dbc->open())
608
        {
609
            delete dbc;
610
            printf("FATAL ERROR: Map.dbc not found in data file.\n");
611
            return 1;
612
        }
613
        map_count = dbc->getRecordCount();
614
        map_ids.resize(map_count);
615
        for (unsigned int x = 0; x < map_count; ++x)
616
        {
617
            map_ids[x].id = dbc->getRecord(x).getUInt(0);
618
            strcpy(map_ids[x].name, dbc->getRecord(x).getString(1));
619
            printf("Map - %s\n",map_ids[x].name);
620
        }
621

622
        delete dbc;
623
        ParsMapFiles();
624

625
        // Extract models, listed in GameObjectDisplayInfo.dbc
626
        ExtractGameobjectModels(&input_path[0]);
627
    }
628

629
    SFileCloseArchive(LocaleMpq);
630
    SFileCloseArchive(WorldMpq);
631

632
    printf("\n");
633
    if (!success)
634
    {
635
        printf("ERROR: Extract %s. Work NOT complete.\n   Precise vector data=%d.\nPress any key.\n",versionString, preciseVectorData);
636
        getchar();
637
    }
638

639
    printf("Extract %s. Work complete. No errors.\n",versionString);
640
    delete [] LiqType;
641
    return 0;
642
}
643

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.