diff --git a/OpenRA.Launcher.Mac/Controller.h b/OpenRA.Launcher.Mac/Controller.h index 5840cb83a6..d16ba4bcff 100644 --- a/OpenRA.Launcher.Mac/Controller.h +++ b/OpenRA.Launcher.Mac/Controller.h @@ -16,10 +16,14 @@ { SidebarEntry *sidebarItems; GameInstall *game; + NSDictionary *allMods; IBOutlet NSOutlineView *outlineView; IBOutlet WebView *webView; } -- (void)launchGame; +@property(readonly) NSDictionary *allMods; + +- (void)launchMod:(NSString *)mod; +- (void)populateModInfo; - (SidebarEntry *)sidebarModsTree; - (SidebarEntry *)sidebarOtherTree; diff --git a/OpenRA.Launcher.Mac/Controller.m b/OpenRA.Launcher.Mac/Controller.m index 161de5409b..be31fcda18 100644 --- a/OpenRA.Launcher.Mac/Controller.m +++ b/OpenRA.Launcher.Mac/Controller.m @@ -14,6 +14,7 @@ #import "JSBridge.h" @implementation Controller +@synthesize allMods; - (void) awakeFromNib { @@ -25,6 +26,7 @@ [col setDataCell:imageAndTextCell]; sidebarItems = [[SidebarEntry headerWithTitle:@""] retain]; + [self populateModInfo]; id modsRoot = [self sidebarModsTree]; [sidebarItems addChild:modsRoot]; id otherRoot = [self sidebarOtherTree]; @@ -45,21 +47,25 @@ [outlineView expandItem:otherRoot expandChildren:YES]; } -- (void) dealloc +- (void)dealloc { [sidebarItems release]; sidebarItems = nil; [super dealloc]; } -- (SidebarEntry *)sidebarModsTree +- (void)populateModInfo { // Get info for all installed mods - id modnames = [game installedMods]; - NSArray *allMods = [game infoForMods:modnames]; - + [allMods autorelease]; + allMods = [[game infoForMods:[game installedMods]] retain]; +} + +- (SidebarEntry *)sidebarModsTree +{ SidebarEntry *rootItem = [SidebarEntry headerWithTitle:@"MODS"]; - for (id aMod in allMods) + for (id key in allMods) { + id aMod = [allMods objectForKey:key]; if ([aMod standalone]) { id child = [SidebarEntry entryWithMod:aMod allMods:allMods baseURL:[[game gameURL] URLByAppendingPathComponent:@"mods"]]; @@ -79,9 +85,9 @@ return rootItem; } -- (void)launchGame +- (void)launchMod:(NSString *)mod { - [game launchGame]; + [game launchMod:mod]; } #pragma mark Sidebar Datasource and Delegate @@ -156,4 +162,8 @@ objectValueForTableColumn:(NSTableColumn *)tableColumn [windowObject setValue:[JSBridge sharedInstance] forKey:@"external"]; } +- (void)webView:(WebView *)webView addMessageToConsole:(NSDictionary *)dictionary +{ + NSLog(@"%@",dictionary); +} @end diff --git a/OpenRA.Launcher.Mac/GameInstall.h b/OpenRA.Launcher.Mac/GameInstall.h index 52b0e6721a..be32a7d3b1 100644 --- a/OpenRA.Launcher.Mac/GameInstall.h +++ b/OpenRA.Launcher.Mac/GameInstall.h @@ -15,9 +15,9 @@ @property(readonly) NSURL *gameURL; -(id)initWithURL:(NSURL *)path; --(void)launchGame; +-(void)launchMod:(NSString *)mod; - (NSString *)runUtilityQuery:(NSString *)arg; - (void)runUtilityQuery:(NSString *)arg handleOutput:(id)obj withMethod:(SEL)sel; - (NSArray *)installedMods; -- (NSArray *)infoForMods:(NSArray *)mods; +- (NSDictionary *)infoForMods:(NSArray *)mods; @end diff --git a/OpenRA.Launcher.Mac/GameInstall.m b/OpenRA.Launcher.Mac/GameInstall.m index 61d520bfb9..1a71013bcd 100644 --- a/OpenRA.Launcher.Mac/GameInstall.m +++ b/OpenRA.Launcher.Mac/GameInstall.m @@ -35,12 +35,12 @@ return [mods componentsSeparatedByString:@"\n"]; } -- (NSArray *)infoForMods:(NSArray *)mods +- (NSDictionary *)infoForMods:(NSArray *)mods { id query = [NSString stringWithFormat:@"-i=%@",[mods componentsJoinedByString:@","]]; NSArray *lines = [[self runUtilityQuery:query] componentsSeparatedByString:@"\n"]; - NSMutableArray *ret = [NSMutableArray array]; + NSMutableDictionary *ret = [NSMutableDictionary dictionary]; NSMutableDictionary *fields = nil; NSString *current = nil; for (id l in lines) @@ -68,7 +68,7 @@ if (current != nil) { id url = [gameURL URLByAppendingPathComponent:[NSString stringWithFormat:@"mods/%@",current]]; - [ret addObject:[Mod modWithId:current fields:fields baseURL:url]]; + [ret setObject:[Mod modWithId:current fields:fields baseURL:url] forKey:current]; } NSLog(@"Parsing mod %@",value); current = value; @@ -82,17 +82,17 @@ if (current != nil) { id url = [gameURL URLByAppendingPathComponent:[NSString stringWithFormat:@"mods/%@",current]]; - [ret addObject:[Mod modWithId:current fields:fields baseURL:url]]; + [ret setObject:[Mod modWithId:current fields:fields baseURL:url] forKey:current]; } return ret; } --(void)launchGame +-(void)launchMod:(NSString *)mod { // Use LaunchServices because neither NSTask or NSWorkspace support Info.plist _and_ arguments pre-10.6 NSString *path = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"OpenRA.app/Contents/MacOS/OpenRA"]; - NSArray *args = [NSArray arrayWithObjects:[gameURL absoluteString], @"mono", @"--debug", @"OpenRA.Game.exe", @"Game.Mods=ra",nil]; + NSArray *args = [NSArray arrayWithObjects:[gameURL absoluteString], @"mono", @"--debug", @"OpenRA.Game.exe", [NSString stringWithFormat:@"Game.Mods=%@",mod],nil]; FSRef appRef; CFURLGetFSRef((CFURLRef)[NSURL URLWithString:path], &appRef); diff --git a/OpenRA.Launcher.Mac/JSBridge.m b/OpenRA.Launcher.Mac/JSBridge.m index 394119df5d..d1ae80e43c 100644 --- a/OpenRA.Launcher.Mac/JSBridge.m +++ b/OpenRA.Launcher.Mac/JSBridge.m @@ -38,7 +38,7 @@ static JSBridge *SharedInstance; if (self != nil) { methods = [[NSDictionary dictionaryWithObjectsAndKeys: - @"launchCurrentMod", NSStringFromSelector(@selector(launchCurrentMod)), + @"launchMod", NSStringFromSelector(@selector(launchMod:)), @"log", NSStringFromSelector(@selector(log:)), @"fileExistsInMod", NSStringFromSelector(@selector(fileExists:inMod:)), nil] retain]; @@ -59,10 +59,17 @@ static JSBridge *SharedInstance; #pragma mark JS methods -- (void)launchCurrentMod +- (BOOL)launchMod:(NSString *)aMod { - NSLog(@"launchcurrent"); - [controller launchGame]; + id mod = [[controller allMods] objectForKey:aMod]; + if (mod == nil) + { + NSLog(@"Invalid or unknown mod: %@", aMod); + return NO; + } + + [controller launchMod:aMod]; + return YES; } - (void)log:(NSString *)message @@ -72,8 +79,19 @@ static JSBridge *SharedInstance; - (BOOL)fileExists:(NSString *)aFile inMod:(NSString *)aMod { - NSLog(@"File %@ exists in mod %@",aFile, aMod); - return NO; + id mod = [[controller allMods] objectForKey:aMod]; + if (mod == nil) + { + NSLog(@"Invalid or unknown mod: %@", aMod); + return NO; + } + + // Disallow traversing up the directory tree + id path = [[[mod baseURL] absoluteString] + stringByAppendingPathComponent:[aFile stringByReplacingOccurrencesOfString:@"../" + withString:@""]]; + + return [[NSFileManager defaultManager] fileExistsAtPath:path]; } @end diff --git a/OpenRA.Launcher.Mac/Mod.h b/OpenRA.Launcher.Mac/Mod.h index b8ea2393db..58d34c503b 100644 --- a/OpenRA.Launcher.Mac/Mod.h +++ b/OpenRA.Launcher.Mac/Mod.h @@ -24,10 +24,9 @@ @property (readonly) NSString *author; @property (readonly) NSString *description; @property (readonly) NSString *requires; +@property (readonly) NSURL *baseURL; @property (readonly) BOOL standalone; + (id)modWithId:(NSString *)mid fields:(id)fields baseURL:(NSURL *)url; - (id)initWithId:(NSString *)anId fields:(NSDictionary *)fields baseURL:(NSURL *)url; - -- (NSURL *)pageURL; @end diff --git a/OpenRA.Launcher.Mac/Mod.m b/OpenRA.Launcher.Mac/Mod.m index 68ecff5770..f8d90941e7 100644 --- a/OpenRA.Launcher.Mac/Mod.m +++ b/OpenRA.Launcher.Mac/Mod.m @@ -17,6 +17,7 @@ @synthesize description; @synthesize requires; @synthesize standalone; +@synthesize baseURL; + (id)modWithId:(NSString *)mod fields:(id)fields baseURL:(NSURL *)url { @@ -54,9 +55,4 @@ [super dealloc]; } -- (NSURL *)pageURL -{ - return [baseURL URLByAppendingPathComponent:@"mod.html"]; -} - @end diff --git a/OpenRA.Launcher.Mac/SidebarEntry.h b/OpenRA.Launcher.Mac/SidebarEntry.h index ba83f1a6f9..02d0337a00 100644 --- a/OpenRA.Launcher.Mac/SidebarEntry.h +++ b/OpenRA.Launcher.Mac/SidebarEntry.h @@ -25,7 +25,7 @@ + (id)headerWithTitle:(NSString *)aTitle; + (id)entryWithTitle:(NSString *)aTitle url:(NSURL *)aURL icon:(id)anIcon; -+ (id)entryWithMod:(Mod *)baseMod allMods:(NSArray *)allMods baseURL:(NSURL *)aURL; ++ (id)entryWithMod:(Mod *)baseMod allMods:(NSDictionary *)allMods baseURL:(NSURL *)aURL; - (id)initWithTitle:(NSString *)aTitle url:(NSURL *)aURL icon:(id)anIcon isHeader:(BOOL)aHeader; - (void)addChild:(id)child; - (NSURL *)url; diff --git a/OpenRA.Launcher.Mac/SidebarEntry.m b/OpenRA.Launcher.Mac/SidebarEntry.m index 2310149576..ad2a088275 100644 --- a/OpenRA.Launcher.Mac/SidebarEntry.m +++ b/OpenRA.Launcher.Mac/SidebarEntry.m @@ -29,7 +29,7 @@ return newObject; } -+ (id)entryWithMod:(Mod *)baseMod allMods:(NSArray *)allMods baseURL:(NSURL *)baseURL ++ (id)entryWithMod:(Mod *)baseMod allMods:(NSDictionary *)allMods baseURL:(NSURL *)baseURL { // TODO: Get the mod icon from the Mod // Temporary hack until mods define an icon @@ -40,8 +40,9 @@ id ret = [SidebarEntry entryWithTitle:[baseMod title] url:url icon:icon]; - for (id aMod in allMods) + for (id key in allMods) { + id aMod = [allMods objectForKey:key]; if (![[aMod requires] isEqualToString:[baseMod mod]]) continue; diff --git a/mods/cnc/mod.html b/mods/cnc/mod.html index f84065e5b1..7de0b9f6d0 100644 --- a/mods/cnc/mod.html +++ b/mods/cnc/mod.html @@ -14,6 +14,7 @@ padding: 20px 0px; width:100%; height:100%; + overflow:hidden; } div#header @@ -21,6 +22,7 @@ margin-top: 30px; height: 66px; text-align:center; + overflow:hidden; } div.bar @@ -40,16 +42,21 @@ div#content { text-align: justify; - width:50%; padding-left:50px; + overflow:hidden; } - div#buttons + div.buttons { position:absolute; bottom:0px; padding:20px; } + + div.desc + { + font-size:0.75em; + } .button { @@ -57,7 +64,7 @@ border-radius: 10px; margin:10px; height:40px; - width:150px; + width:170px; color:white; font-weight:bold; font-size:1em; @@ -75,8 +82,42 @@ } + - + @@ -93,9 +134,23 @@ -
- - +
+
The original game data is required before you can play this mod.
+ Installing from web will install the minimal files required to play.
+ Installing from CD will also install the music and movie files for an improved game experience. +
+ + +
+ +
diff --git a/mods/d2k/mod.html b/mods/d2k/mod.html index f838912df8..b165eb0d51 100644 --- a/mods/d2k/mod.html +++ b/mods/d2k/mod.html @@ -1,6 +1,6 @@

Dune 2000

- + diff --git a/mods/default/mod.html b/mods/default/mod.html index 143ce7d04e..33580f99be 100644 --- a/mods/default/mod.html +++ b/mods/default/mod.html @@ -1,6 +1,6 @@

Default Mod

- + diff --git a/mods/example/mod.html b/mods/example/mod.html index cd00c6bc33..b57a2f3614 100644 --- a/mods/example/mod.html +++ b/mods/example/mod.html @@ -2,6 +2,6 @@

Example Mod

Demonstrates how to add a new unit by adding a soviet supply truck.

- + diff --git a/mods/ra/mod.html b/mods/ra/mod.html index e44446f9a9..1b4994d62d 100644 --- a/mods/ra/mod.html +++ b/mods/ra/mod.html @@ -1,6 +1,6 @@

Red Alert

- + diff --git a/mods/ra_perf/mod.html b/mods/ra_perf/mod.html index 0c95bf1dc9..a036413a4b 100644 --- a/mods/ra_perf/mod.html +++ b/mods/ra_perf/mod.html @@ -2,6 +2,6 @@

RA Performance Tests

Adds special performance test maps to ra.

- +