source: AE/Installer/trunk/source/subs.cpp @ 298

Last change on this file since 298 was 298, checked in by gumby, 11 years ago
File size: 12.3 KB
Line 
1#define DEBUG
2/*
3AE\Mod Installer.
4
5Needs getPackages() now!
6*/
7//#include <dir.h>
8#include <string>
9
10#include <direct.h>
11
12#include "boost/filesystem/operations.hpp"
13#include "boost/filesystem/path.hpp"
14#include "boost/filesystem.hpp"   // includes all needed Boost.Filesystem declarations
15#include <iostream>               // for std::cout
16         // for ease of tutorial presentation;
17                                  //  a namespace alias is preferred practice in real code
18
19#include <cctype>
20#include <iostream>
21#include "methods.h"
22#include <vector>
23#include <fstream>
24
25
26
27#include <errno.h>
28#ifdef WIN32
29        #include "Include\dirent.h"
30        #include <windows.h>
31        static const string Onisplit = "Onisplit.exe";
32        string import = "-import:nosep";
33#else
34#include <stdlib.h>
35#include <dirent.h> //??? is this included for Macs?
36        string import = "-import:sep";
37        static const string Onisplit = "./mono Onisplit.exe";
38#endif
39
40
41
42using namespace boost::filesystem; 
43using namespace std;
44//bool FALSE = 0;
45//bool TRUE = 0;
46
47const bool SPLIT = 1;
48const bool NOT_SPLIT = 0;
49
50bool splitInstances = SPLIT;
51
52int main(void)
53{
54       
55        //      SetConsoleTitle("AE Installer"); windows junk, convert to SDL
56        //      system("color 0A");
57
58        cout << "\nWelcome to the AE installer!\n";
59
60        cout << "\nWhat would you like to do?\n";
61
62        return mainMenu();
63}
64
65vector<ModPackage> getPackages(void) {
66        vector<ModPackage> packages;
67        packages.reserve(65536); //comeon, we shouldn't need this much space...right?!
68        fstream file;
69#ifdef DEBUG
70#ifdef WIN32
71        string path = ".\\packages"; //only for my build. :P
72         _chdir(path.c_str());
73
74         _chdir("..");
75         cout << path;
76#else
77        string path = "K:\\Oni\\edition\\install\\packages"; //change this, 'scen.
78#endif
79#else
80        string path = ".";
81#endif
82
83        string filename = "\0";
84        string MODINFO_CFG = "\\Mod_Info.cfg";
85
86
87
88        DIR *pdir;
89        struct dirent *pent;
90
91        pdir = opendir( path.c_str() ); //"." refers to the current dir
92        if (!pdir){
93                printf ("\nopendir() failure; terminating");
94                exit(1);
95        }
96        errno=0; 
97
98        while (( pent = readdir(pdir) )){
99
100                filename = path + '\\' + pent->d_name + MODINFO_CFG;
101                file.open(filename.c_str());
102
103                //cout << filename << "\n";
104
105                if(!file.fail() )
106                {
107                        //file.open(filename.c_str(), fstream::out);
108
109                        //do stuff like adding to vector :P
110
111                        //would prefer to push a pointer to a package, but this will do for now
112                        packages.push_back( fileToModPackage(file) );
113
114                }       
115                file.close();
116                file.clear();
117
118        }
119
120
121        if (errno){
122                printf ("readdir() failure; terminating");
123                exit(1);
124        }
125        closedir(pdir);
126
127
128        return packages;
129}
130
131ModPackage fileToModPackage(fstream &file) {
132        /*
133        This converts a file to a ModPackage struct.
134
135        A few notes...
136        "iter" is the current word we are on. I should have named it "token" or something, but I don't have multiple iterators, so its ok.
137        I refer to (*iter) at the beginning of each if statement block. I could probably store it as a variable, but I'm pretty sure that dereferencing a pointer\iterator isn't much slower than reading a variable.
138        */
139        ModPackage package;
140        string line;
141        static string NameOfMod = "NameOfMod";  //used for comparing to the current token...
142        //I could have done it in reverse (*iter).compare("ModString") or 
143        static string ARROW = "->";                             //did something like "ModString".compare(*iter), and it would have been
144        static string ModString = "ModString";  //functionably the same.
145        static string HasOnis = "HasOnis";
146        static string HasDeltas = "HasDeltas";
147        static string HasBSL = "HasBSL";
148        static string HasDats = "HasDats";
149        static string IsEngine = "IsEngine";
150        static string Readme = "Readme";
151        static string GlobalNeeded = "GlobalNeeded";
152        static string Category = "Category";
153        static string Creator = "Creator";
154        while (! file.eof() )
155        {
156                getline (file,line);
157                vector<string> tokens; 
158                vector<string>::iterator iter;
159                Tokenize(line, tokens);                                 //string to vector of "words"
160                if (tokens.capacity() >= 2) {                   //make sure they are using enough stuff
161                        iter = tokens.begin();                          //what word we are on, starts at first word
162                        /*
163                        if (!AEInstallVersion.compare(*iter))
164                        If mod is too old, skip this mod.
165                        */
166                        /*else*/if (!NameOfMod.compare(*iter))  {       //if it contains the name
167                                for ( ; iter !=tokens.end() && SLASHSLASH.compare(*iter); iter++) {     //interates through the words, ends if it reaches the end of the line or a "//" comment
168                                        if (ARROW.compare(*iter) && NameOfMod.compare(*iter)) {                 //ignores "->" and "NameOfMod"
169                                                //cout << *iter;
170                                                //cout << " ";
171                                                package.name += *iter + " ";
172                                        }
173                                }
174
175                        }
176                        else if (!ModString.compare(*iter)) {
177                                iter++; iter++;
178                                package.modStringName = *iter;
179                                iter++;
180                                package.modStringVersion = atoi((*iter).c_str());
181                        }
182                        else if (!HasOnis.compare(*iter)) {
183                                iter++; iter++; 
184                                if (toupper((*iter)[0]) + toupper((*iter)[1]) + toupper((*iter)[2]) == 'Y' + 'E' + 'S') package.hasOnis = 1; //Gotta love c++'s lack of a standard case-insensitive string comparer...I know my implementation here sucks. I need to change it to check each character one by one. At the moment, using "YFR" would probably set it off. :<
185                        }
186                        else if (!HasBSL.compare(*iter)) {
187                                iter++; iter++; 
188                                if (toupper((*iter)[0]) + toupper((*iter)[1]) + toupper((*iter)[2]) == 'Y' + 'E' + 'S') package.hasBSL = 1;
189                        }
190                        else if (!HasDeltas.compare(*iter)) {
191                                iter++; iter++; 
192                                if (toupper((*iter)[0]) + toupper((*iter)[1]) + toupper((*iter)[2]) == 'Y' + 'E' + 'S') package.hasDeltas = 1;
193                        }
194                        else if (!HasDats.compare(*iter)) {
195                                iter++; iter++; 
196                                if (toupper((*iter)[0]) + toupper((*iter)[1]) + toupper((*iter)[2]) == 'Y' + 'E' + 'S') package.hasDats = 1;
197                        }
198                        else if (!IsEngine.compare(*iter)) {
199                                iter++; iter++; 
200                                if (toupper((*iter)[0]) + toupper((*iter)[1]) + toupper((*iter)[2]) == 'Y' + 'E' + 'S') package.isEngine = 1;
201                        }
202                        else if (!GlobalNeeded.compare(*iter)) {
203                                iter++; iter++; 
204                                if (toupper((*iter)[0]) + toupper((*iter)[1]) + toupper((*iter)[2]) == 'Y' + 'E' + 'S') package.globalNeeded = 1;
205                                else if (toupper((*iter)[0]) + toupper((*iter)[1]) == 'N' + 'O') package.globalNeeded = 1; //Really the only place where checking for "No" is important atm.
206                        }
207                        else if (!Category.compare(*iter))  {   
208                                for ( ; iter !=tokens.end() && SLASHSLASH.compare(*iter); iter++) {     //interates through the words, ends if it reaches the end of the line or a "//" comment
209                                        if (ARROW.compare(*iter) && Category.compare(*iter)) {                  //ignores "->" and "Category"
210                                                //cout << *iter;
211                                                //cout << " ";
212                                                package.category += *iter + " ";
213                                        }
214                                }
215                        }
216                        else if (!Creator.compare(*iter))  {    //if it contains the name
217                                for ( ; iter !=tokens.end() && SLASHSLASH.compare(*iter); iter++) {     //interates through the words, ends if it reaches the end of the line or a "//" comment
218                                        if (ARROW.compare(*iter) && Creator.compare(*iter)) {                   //ignores "->" and "Category"
219                                                //cout << *iter;
220                                                //cout << " ";
221                                                package.creator += *iter + " ";
222                                        }
223                                }
224                        }
225                        else if (!Readme.compare(*iter))  {     //if it contains the name
226                                for ( ; iter !=tokens.end() && SLASHSLASH.compare(*iter); iter++) {     //interates through the words, ends if it reaches the end of the line or a "//" comment
227                                        if (ARROW.compare(*iter) && Readme.compare(*iter)) {                    //ignores "->" and "Category"
228                                                //cout << *iter;
229                                                //cout << " ";
230                                                package.readme += *iter + " ";
231                                        }
232                                }
233                        }
234                }
235
236        }
237        package.doOutput();
238        return package;
239}
240
241int mainMenu(void) {
242        int choice = '0';
243        bool ok = FALSE;
244        cout << "1. Install new packages\n";
245        cout << "2. Uninstall packages\n";
246        cout << "3. See what is installed\n";
247        cout << "4. About AE\n";
248        cout << "5. Quit\n\n";
249
250        do {
251                ok = TRUE;
252                choice = cin.get();
253                cin.ignore(128, '\n');
254                switch(choice) {
255                        case '1':
256                                installPackages();
257                                break;
258                        case '2':
259                                uninstallPackages();
260                                break;
261                        case '3':
262                                //listInstalledPackages();
263                                break;
264                        case '5':
265                                return 0;
266                        default:
267                                ok = FALSE;
268                }
269        } while(ok == FALSE);
270        return 0;
271}
272
273
274void installPackages() {
275        ModPackage package;
276        vector<string> installed_packages;
277        vector<ModPackage> packages; 
278        vector<ModPackage>::iterator iter;
279        iter = packages.begin();
280        vector<string> installString;
281        packages = getPackages();
282        vector<string> installedMods = getInstallString();
283
284        if (packages.empty()) {
285                cout << "Error: You have no packages!\n";
286                return;
287        }
288        cout << "Detecting installed packages...\n";
289       
290        int index = 1;
291        char  choice = '0';
292        for (vector<ModPackage>::iterator package_iter = packages.begin(); package_iter != packages.end(); ++package_iter) {
293                if (!binary_search(installedMods.begin(), installedMods.end(), package_iter->modStringName)) { //package_iter->isInstalled :< I forgot about this...
294                        //cout << index << " ";
295                        system("cls");
296                        cout << (*package_iter).name <<"\n";
297                        for( int character = 1; character <= (*package_iter).name.length() - 1; character++) cout << char(196); //does extended ASCII work in UNIX?
298                        cout << "\n"
299                                << (*package_iter).readme << "\n"
300                                << "\n"
301                                << "Please enter a number choice\n"
302                                << " 1. Install\n"
303                                << " 2. Don't Install\n"
304                                << "";
305                        index++;
306                        choice = 0;
307                       
308                        do {
309                        choice = cin.get();
310                        cin.ignore(1280, '\n');
311                        } while(choice == 0);
312                        if (choice == '1') {
313                                cout << "\nInstalling...\n\n";
314                                if ( package_iter->hasOnis || ( package_iter->hasDeltas /*(*package_iter).isUnpacked */ )) {
315                                        installedMods.push_back(package_iter->modStringName);                           
316                                               
317                                                system("PAUSE");
318                                               
319
320                                }
321                        }
322
323                }
324        }
325        if (index == 1) {
326                cout << "Error: All packages are already installed\n";
327                return;
328        }
329        sort(installedMods.begin(), installedMods.end());
330         
331         //system(Onisplit.c_str());
332        RecompileAll(installedMods);
333         system("PAUSE");
334}
335void uninstallPackages() {
336        ;
337}
338
339void getInstalledPackages() {
340        ;
341}
342
343void RecompileAll(vector<string> installedMods) {
344        cout << "Recompiling Data...\n";
345        path vanilla_dir = "./packages/VanillaDats/";
346        string importCommand = "";
347        if(splitInstances == SPLIT){
348                recursive_directory_iterator end_iter;
349                                try {
350                for ( recursive_directory_iterator dir_itr( vanilla_dir );
351                        dir_itr != end_iter;
352                        ++dir_itr )
353                {
354                        try
355                        {
356                                if ( is_directory( dir_itr->status() ) &&  dir_itr.level() == 1)
357                                {
358                                        importCommand =  Onisplit + " " + import + " " + dir_itr->path().parent_path().string() + '/' + dir_itr->path().filename();
359                                        for (int i = 0; i < installedMods.size(); ++i) {
360                                                if (exists("packages/" + installedMods[i] + "/oni/" + dir_itr->path().parent_path().filename() + '/' + dir_itr->path().filename()  ))
361                                                        importCommand += " packages/" + installedMods[i] + "/oni/" + dir_itr->path().parent_path().filename() + '/' + dir_itr->path().filename();
362                                               
363                                                //else cout << " packages/VanillaDats/" + installedMods[i] + "/oni/";
364                                                }
365                                        importCommand += " ../GameDataFolder/" + dir_itr->path().filename() + ".dat";
366                                                system(importCommand.c_str());
367//cout << importCommand << "\n";
368                                }
369                        }
370                        catch ( const std::exception & ex )
371                        {
372                                cout << "Warning, exception " << ex.what() << "!";
373                        }
374                }
375                                }
376                                catch( const std::exception & ex ) {
377                                        cout << "Warning, exception " << ex.what() << "!\n"
378                                                << "You probably need to reGlobalize.;
379                                        create_directory( "./packages/VanillaDats" );
380                                }
381
382        }
383        else if(splitInstances == NOT_SPLIT){
384                directory_iterator end_iter;
385                for ( directory_iterator dir_itr( vanilla_dir );
386                        dir_itr != end_iter;
387                        ++dir_itr )
388                {
389                        try
390                        {
391                                if ( is_directory( dir_itr->status() ) )
392                                {
393                                        system((Onisplit + " " + import + " " + vanilla_dir.string() + dir_itr->path().filename() + " " + "../GameDataFolder/" + dir_itr->path().filename() + ".dat").c_str());
394                                }
395                        }
396                        catch ( const std::exception & ex )
397                        {
398                                cout << "Warning, something odd happened!\n";
399                        }
400                }
401
402
403
404        }
405}
406
407vector<string> getInstallString() {
408        system("PAUSE");
409        vector<string> returnval;
410                string file_name = "../GameDataFolder/ImportList.cfg";
411                string line;
412                fstream file;
413                if( exists(file_name) ) {
414                        file.open(file_name.c_str());
415                        getline (file,line);
416                        Tokenize(line, returnval);             
417                        file.close();
418                        file.clear();
419                        sort(returnval.begin(), returnval.end());
420                                       
421                }
422                else cout << "fail";
423               
424        return returnval;
425}
Note: See TracBrowser for help on using the repository browser.