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

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