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

Last change on this file since 301 was 298, checked in by gumby, 16 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.