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

Last change on this file since 306 was 306, checked in by gumby, 16 years ago
File size: 12.2 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 try
87 {
88
89
90 directory_iterator end_iter;
91 for ( directory_iterator dir_itr( "./packages" );
92 dir_itr != end_iter;
93 ++dir_itr )
94 {
95
96
97 file.open( (dir_itr->path().string() + "/" + MODINFO_CFG ).c_str());
98
99 //cout << filename << "\n";
100
101 if(!file.fail() )
102 {
103 cout << dir_itr->path().string() + MODINFO_CFG ;
104 //would prefer to push a pointer to a package, but this will do for now
105 packages.push_back( fileToModPackage(file) );
106
107 }
108 file.close();
109 file.clear();
110
111
112
113 }
114
115
116 }
117 catch ( const std::exception & ex )
118 {
119 cout << "Warning, something odd happened!\n";
120 }
121
122 return packages;
123}
124
125ModPackage fileToModPackage(fstream &file) {
126 /*
127 This converts a file to a ModPackage struct.
128
129 A few notes...
130 "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.
131 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.
132 */
133 ModPackage package;
134 string line;
135 static string NameOfMod = "NameOfMod"; //used for comparing to the current token...
136 //I could have done it in reverse (*iter).compare("ModString") or
137 static string ARROW = "->"; //did something like "ModString".compare(*iter), and it would have been
138 static string ModString = "ModString"; //functionably the same.
139 static string HasOnis = "HasOnis";
140 static string HasDeltas = "HasDeltas";
141 static string HasBSL = "HasBSL";
142 static string HasDats = "HasDats";
143 static string IsEngine = "IsEngine";
144 static string Readme = "Readme";
145 static string GlobalNeeded = "GlobalNeeded";
146 static string Category = "Category";
147 static string Creator = "Creator";
148 while (! file.eof() )
149 {
150 getline (file,line);
151 vector<string> tokens;
152 vector<string>::iterator iter;
153 Tokenize(line, tokens); //string to vector of "words"
154 if (tokens.capacity() >= 2) { //make sure they are using enough stuff
155 iter = tokens.begin(); //what word we are on, starts at first word
156 /*
157 if (!AEInstallVersion.compare(*iter))
158 If mod is too old, skip this mod.
159 */
160 /*else*/if (!NameOfMod.compare(*iter)) { //if it contains the name
161 for ( ; iter !=tokens.end() && SLASHSLASH.compare(*iter); iter++) { //interates through the words, ends if it reaches the end of the line or a "//" comment
162 if (ARROW.compare(*iter) && NameOfMod.compare(*iter)) { //ignores "->" and "NameOfMod"
163 //cout << *iter;
164 //cout << " ";
165 package.name += *iter + " ";
166 }
167 }
168
169 }
170 else if (!ModString.compare(*iter)) {
171 iter++; iter++;
172 package.modStringName = *iter;
173 iter++;
174 package.modStringVersion = atoi((*iter).c_str());
175 }
176 else if (!HasOnis.compare(*iter)) {
177 iter++; iter++;
178 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. :<
179 }
180 else if (!HasBSL.compare(*iter)) {
181 iter++; iter++;
182 if (toupper((*iter)[0]) + toupper((*iter)[1]) + toupper((*iter)[2]) == 'Y' + 'E' + 'S') package.hasBSL = 1;
183 }
184 else if (!HasDeltas.compare(*iter)) {
185 iter++; iter++;
186 if (toupper((*iter)[0]) + toupper((*iter)[1]) + toupper((*iter)[2]) == 'Y' + 'E' + 'S') package.hasDeltas = 1;
187 }
188 else if (!HasDats.compare(*iter)) {
189 iter++; iter++;
190 if (toupper((*iter)[0]) + toupper((*iter)[1]) + toupper((*iter)[2]) == 'Y' + 'E' + 'S') package.hasDats = 1;
191 }
192 else if (!IsEngine.compare(*iter)) {
193 iter++; iter++;
194 if (toupper((*iter)[0]) + toupper((*iter)[1]) + toupper((*iter)[2]) == 'Y' + 'E' + 'S') package.isEngine = 1;
195 }
196 else if (!GlobalNeeded.compare(*iter)) {
197 iter++; iter++;
198 if (toupper((*iter)[0]) + toupper((*iter)[1]) + toupper((*iter)[2]) == 'Y' + 'E' + 'S') package.globalNeeded = 1;
199 else if (toupper((*iter)[0]) + toupper((*iter)[1]) == 'N' + 'O') package.globalNeeded = 1; //Really the only place where checking for "No" is important atm.
200 }
201 else if (!Category.compare(*iter)) {
202 for ( ; iter !=tokens.end() && SLASHSLASH.compare(*iter); iter++) { //interates through the words, ends if it reaches the end of the line or a "//" comment
203 if (ARROW.compare(*iter) && Category.compare(*iter)) { //ignores "->" and "Category"
204 //cout << *iter;
205 //cout << " ";
206 package.category += *iter + " ";
207 }
208 }
209 }
210 else if (!Creator.compare(*iter)) { //if it contains the name
211 for ( ; iter !=tokens.end() && SLASHSLASH.compare(*iter); iter++) { //interates through the words, ends if it reaches the end of the line or a "//" comment
212 if (ARROW.compare(*iter) && Creator.compare(*iter)) { //ignores "->" and "Category"
213 //cout << *iter;
214 //cout << " ";
215 package.creator += *iter + " ";
216 }
217 }
218 }
219 else if (!Readme.compare(*iter)) { //if it contains the name
220 for ( ; iter !=tokens.end() && SLASHSLASH.compare(*iter); iter++) { //interates through the words, ends if it reaches the end of the line or a "//" comment
221 if (ARROW.compare(*iter) && Readme.compare(*iter)) { //ignores "->" and "Category"
222 //cout << *iter;
223 //cout << " ";
224 package.readme += *iter + " ";
225 }
226 }
227 }
228 }
229
230 }
231 package.doOutput();
232 return package;
233}
234
235int mainMenu(void) {
236 int choice = '0';
237 bool ok = FALSE;
238 cout << "1. Install new packages\n";
239 cout << "2. Uninstall packages\n";
240 cout << "3. See what is installed\n";
241 cout << "4. About AE\n";
242 cout << "5. Quit\n\n";
243
244 do {
245 ok = TRUE;
246 choice = cin.get();
247 cin.ignore(128, '\n');
248 switch(choice) {
249 case '1':
250 installPackages();
251 break;
252 case '2':
253 uninstallPackages();
254 break;
255 case '3':
256 //listInstalledPackages();
257 break;
258 case '5':
259 return 0;
260 default:
261 ok = FALSE;
262 }
263 } while(ok == FALSE);
264 return 0;
265}
266
267
268void installPackages() {
269 ModPackage package;
270 vector<string> installed_packages;
271 vector<ModPackage> packages;
272 vector<ModPackage>::iterator iter;
273 iter = packages.begin();
274 vector<string> installString;
275 packages = getPackages();
276 vector<string> installedMods = getInstallString();
277
278 if (packages.empty()) {
279 cout << "Error: You have no packages!\n";
280 return;
281 }
282 cout << "Detecting installed packages...\n";
283
284 int index = 1;
285 char choice = '0';
286 for (vector<ModPackage>::iterator package_iter = packages.begin(); package_iter != packages.end(); ++package_iter) {
287 if (!binary_search(installedMods.begin(), installedMods.end(), package_iter->modStringName)) { //package_iter->isInstalled :< I forgot about this...
288 //cout << index << " ";
289 system("cls");
290 cout << (*package_iter).name <<"\n";
291 for( int character = 1; character <= (*package_iter).name.length() - 1; character++) cout << char(196); //does extended ASCII work in UNIX?
292 cout << "\n"
293 << (*package_iter).readme << "\n"
294 << "\n"
295 << "Please enter a number choice\n"
296 << " 1. Install\n"
297 << " 2. Don't Install\n"
298 << "";
299 index++;
300 choice = 0;
301
302 do {
303 choice = cin.get();
304 cin.ignore(1280, '\n');
305 } while(choice == 0);
306 if (choice == '1') {
307 cout << "\nInstalling...\n\n";
308 if ( package_iter->hasOnis || ( package_iter->hasDeltas /*(*package_iter).isUnpacked */ )) {
309 installedMods.push_back(package_iter->modStringName);
310
311 system("PAUSE");
312
313
314 }
315 }
316
317 }
318 }
319 if (index == 1) {
320 cout << "Error: All packages are already installed\n";
321 return;
322 }
323 sort(installedMods.begin(), installedMods.end());
324
325 //system(Onisplit.c_str());
326 RecompileAll(installedMods);
327 system("PAUSE");
328}
329void uninstallPackages() {
330 ;
331}
332
333void getInstalledPackages() {
334 ;
335}
336
337void RecompileAll(vector<string> installedMods) {
338 cout << "Recompiling Data...\n";
339 path vanilla_dir = "./packages/VanillaDats/";
340 string importCommand = "";
341 if(splitInstances == SPLIT){
342 recursive_directory_iterator end_iter;
343 try {
344 for ( recursive_directory_iterator dir_itr( vanilla_dir );
345 dir_itr != end_iter;
346 ++dir_itr )
347 {
348 try
349 {
350 if ( is_directory( dir_itr->status() ) && dir_itr.level() == 1)
351 {
352 importCommand = Onisplit + " " + import + " " + dir_itr->path().parent_path().string() + '/' + dir_itr->path().filename();
353 for (int i = 0; i < installedMods.size(); ++i) {
354 if (exists("packages/" + installedMods[i] + "/oni/" + dir_itr->path().parent_path().filename() + '/' + dir_itr->path().filename() ))
355 importCommand += " packages/" + installedMods[i] + "/oni/" + dir_itr->path().parent_path().filename() + '/' + dir_itr->path().filename();
356
357 //else cout << " packages/VanillaDats/" + installedMods[i] + "/oni/";
358 }
359 importCommand += " ../GameDataFolder/" + dir_itr->path().filename() + ".dat";
360 system(importCommand.c_str());
361//cout << importCommand << "\n";
362 }
363 }
364 catch ( const std::exception & ex )
365 {
366 cout << "Warning, exception " << ex.what() << "!";
367 }
368 }
369 }
370 catch( const std::exception & ex ) {
371 cout << "Warning, exception " << ex.what() << "!\n"
372 << "You probably need to reGlobalize.";
373 create_directory( "./packages/VanillaDats" );
374 }
375
376 }
377 else if(splitInstances == NOT_SPLIT){
378 directory_iterator end_iter;
379 for ( directory_iterator dir_itr( vanilla_dir );
380 dir_itr != end_iter;
381 ++dir_itr )
382 {
383 try
384 {
385 if ( is_directory( dir_itr->status() ) )
386 {
387 system((Onisplit + " " + import + " " + vanilla_dir.string() + dir_itr->path().filename() + " " + "../GameDataFolder/" + dir_itr->path().filename() + ".dat").c_str());
388 }
389 }
390 catch ( const std::exception & ex )
391 {
392 cout << "Warning, something odd happened!\n";
393 }
394 }
395
396
397
398 }
399}
400
401vector<string> getInstallString() {
402 system("PAUSE");
403 vector<string> returnval;
404 string file_name = "../GameDataFolder/ImportList.cfg";
405 string line;
406 fstream file;
407 if( exists(file_name) ) {
408 file.open(file_name.c_str());
409 getline (file,line);
410 Tokenize(line, returnval);
411 file.close();
412 file.clear();
413 sort(returnval.begin(), returnval.end());
414
415 }
416 else cout << "fail";
417
418 return returnval;
419}
Note: See TracBrowser for help on using the repository browser.