diff --git a/OpenRA.Launcher.Mac/Controller.h b/OpenRA.Launcher.Mac/Controller.h
index b7ecca9b7d..f3ac59463c 100644
--- a/OpenRA.Launcher.Mac/Controller.h
+++ b/OpenRA.Launcher.Mac/Controller.h
@@ -16,6 +16,5 @@
GameInstall *game;
IBOutlet NSOutlineView *outlineView;
}
-- (ModEntry *)modTree;
- (IBAction)launchGame:(id)sender;
@end
diff --git a/OpenRA.Launcher.Mac/Controller.m b/OpenRA.Launcher.Mac/Controller.m
index 10a17ece8f..9ae22ee67f 100644
--- a/OpenRA.Launcher.Mac/Controller.m
+++ b/OpenRA.Launcher.Mac/Controller.m
@@ -15,8 +15,9 @@
- (void) awakeFromNib
{
+ game = [[GameInstall alloc] initWithPath:@"/Users/paul/src/OpenRA"];
sidebarItems = [[ModEntry headerWithTitle:@""] retain];
- [sidebarItems addChild:[self modTree]];
+ [sidebarItems addChild:[game modTree]];
NSTableColumn *col = [outlineView tableColumnWithIdentifier:@"mods"];
ImageAndTextCell *imageAndTextCell = [[[ImageAndTextCell alloc] init] autorelease];
@@ -25,8 +26,6 @@
[outlineView reloadData];
[outlineView expandItem:[outlineView itemAtRow:1] expandChildren:YES];
[outlineView selectRowIndexes:[NSIndexSet indexSetWithIndex:1] byExtendingSelection:NO];
-
- game = [[GameInstall alloc] initWithPath:@"/Users/paul/src/OpenRA"];
}
- (void) dealloc
@@ -35,24 +34,6 @@
[super dealloc];
}
-- (ModEntry *)modTree
-{
- // Create root item
- ModEntry *rootItem = [ModEntry headerWithTitle:@"MODS"];
-
- NSString* imageName = [[NSBundle mainBundle] pathForResource:@"OpenRA" ofType:@"icns"];
- NSImage* imageObj = [[NSImage alloc] initWithContentsOfFile:imageName];
-
- NSDictionary *foo = [NSDictionary dictionaryWithObjectsAndKeys:
- @"Test mod", @"Title",
- @"Foobar", @"Author",
- imageObj, @"Icon",
- nil];
- [imageObj release];
- [rootItem addChild:[ModEntry modWithFields:foo]];
- return rootItem;
-}
-
#pragma mark Sidebar Datasource and Delegate
- (int)outlineView:(NSOutlineView *)anOutlineView numberOfChildrenOfItem:(id)item
{
@@ -100,7 +81,12 @@ objectValueForTableColumn:(NSTableColumn *)tableColumn
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldSelectItem:(id)item;
{
// don't allow headers to be selected
- return ![item isHeader];
+ if ([item isHeader])
+ return NO;
+
+ // TODO: Display the webpage
+
+ return YES;
}
- (void)outlineView:(NSOutlineView *)olv willDisplayCell:(NSCell*)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
diff --git a/OpenRA.Launcher.Mac/English.lproj/MainMenu.xib b/OpenRA.Launcher.Mac/English.lproj/MainMenu.xib
index 77f762be9e..89a3fbc3e5 100644
--- a/OpenRA.Launcher.Mac/English.lproj/MainMenu.xib
+++ b/OpenRA.Launcher.Mac/English.lproj/MainMenu.xib
@@ -13,7 +13,7 @@
- {145, 469}
+ {189, 469}
2
NSView
@@ -447,8 +447,8 @@
YES
- 268
- {{383, 15}, {111, 27}}
+ 289
+ {{339, 19}, {111, 27}}
YES
@@ -466,7 +466,7 @@
- {{146, 0}, {513, 469}}
+ {{190, 0}, {469, 469}}
2
NSView
@@ -1089,7 +1089,7 @@
com.apple.InterfaceBuilder.CocoaPlugin
- P4AAAL+AAABDnQAAw6CAAA
+ P4AAAL+AAABDv4AAwiAAAA
com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
diff --git a/OpenRA.Launcher.Mac/GameInstall.h b/OpenRA.Launcher.Mac/GameInstall.h
index aec58557b5..efc22a5558 100644
--- a/OpenRA.Launcher.Mac/GameInstall.h
+++ b/OpenRA.Launcher.Mac/GameInstall.h
@@ -1,18 +1,21 @@
-//
-// GameInstall.h
-// OpenRA
-//
-// Created by Paul Chote on 15/11/10.
-// Copyright 2010 __MyCompanyName__. All rights reserved.
-//
+/*
+ * Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
+ * This file is part of OpenRA, which is free software. It is made
+ * available to you under the terms of the GNU General Public License
+ * as published by the Free Software Foundation. For more information,
+ * see LICENSE.
+ */
#import
-
+@class ModEntry;
@interface GameInstall : NSObject {
NSString *gamePath;
+ NSMutableString *utilityBuffer;
}
-(id)initWithPath:(NSString *)path;
+- (ModEntry *)modTree;
-(void)launchGame;
+- (void)runUtilityApp:(NSString *)arg handleOutput:(id)obj withMethod:(SEL)sel;
@end
diff --git a/OpenRA.Launcher.Mac/GameInstall.m b/OpenRA.Launcher.Mac/GameInstall.m
index a41607e31c..a3ee9e5401 100644
--- a/OpenRA.Launcher.Mac/GameInstall.m
+++ b/OpenRA.Launcher.Mac/GameInstall.m
@@ -1,13 +1,13 @@
-//
-// GameInstall.m
-// OpenRA
-//
-// Created by Paul Chote on 15/11/10.
-// Copyright 2010 __MyCompanyName__. All rights reserved.
-//
+/*
+ * Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
+ * This file is part of OpenRA, which is free software. It is made
+ * available to you under the terms of the GNU General Public License
+ * as published by the Free Software Foundation. For more information,
+ * see LICENSE.
+ */
#import "GameInstall.h"
-
+#import "ModEntry.h"
@implementation GameInstall
@@ -16,13 +16,98 @@
self = [super init];
if (self != nil)
{
- NSLog(@"creating game at path %@",path);
-
gamePath = path;
}
return self;
}
+- (void)dealloc
+{
+ [utilityBuffer release];
+ [super dealloc];
+}
+
+-(void)clearBuffer
+{
+ [utilityBuffer release];
+ utilityBuffer = [[NSMutableString stringWithString:@""] retain];
+}
+
+- (void)bufferData:(NSString *)string
+{
+ if (string == nil) return;
+ [utilityBuffer appendString:string];
+}
+
+- (NSArray *)installedMods
+{
+ [self clearBuffer];
+ [self runUtilityApp:@"-l" handleOutput:self withMethod:@selector(bufferData:)];
+ id mods = [[NSString stringWithString:utilityBuffer] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
+ return [mods componentsSeparatedByString:@"\n"];
+}
+
+- (NSArray *)infoForMods:(NSArray *)mods
+{
+ [self clearBuffer];
+ [self runUtilityApp:[NSString stringWithFormat:@"-i=%@",[mods componentsJoinedByString:@","]] handleOutput:self withMethod:@selector(bufferData:)];
+ NSArray *lines = [utilityBuffer componentsSeparatedByString:@"\n"];
+
+ NSMutableArray *ret = [NSMutableArray array];
+ NSMutableDictionary *fields = nil;
+ NSString *current = nil;
+ for (id l in lines)
+ {
+ id line = [l stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
+ if (line == nil || [line length] == 0)
+ continue;
+
+ id kv = [line componentsSeparatedByString:@":"];
+ id key = [kv objectAtIndex:0];
+ id value = [kv objectAtIndex:1];
+
+ if ([key isEqualToString:@"Error"])
+ {
+ NSLog(@"Error: %@",value);
+ continue;
+ }
+
+ if ([key isEqualToString:@"Mod"])
+ {
+ // Commit prev mod
+ if (current != nil)
+ [ret addObject:[ModEntry modWithId:current fields:fields]];
+ NSLog(@"Parsing mod %@",value);
+ current = value;
+ fields = [NSMutableDictionary dictionary];
+ }
+
+ if (fields != nil)
+ [fields setObject:[value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]
+ forKey:key];
+ }
+ return ret;
+}
+
+- (ModEntry *)modTree
+{
+ // Get info for all installed mods
+ id modnames = [self installedMods];
+ NSArray *allMods = [self infoForMods:modnames];
+
+ ModEntry *rootItem = [ModEntry headerWithTitle:@"MODS"];
+ for (id aMod in allMods)
+ {
+ if ([aMod standalone])
+ {
+ [rootItem addChild:aMod];
+ [aMod buildChildTree:allMods];
+ }
+ }
+
+ return rootItem;
+}
+
-(void)launchGame
{
// Use LaunchServices because neither NSTask or NSWorkspace support Info.plist _and_ arguments pre-10.6
@@ -49,4 +134,27 @@
if (err == noErr)
SetFrontProcess(&psn);
}
+
+- (void)runUtilityApp:(NSString *)arg handleOutput:(id)obj withMethod:(SEL)sel
+{
+ NSTask *aTask = [[NSTask alloc] init];
+ NSPipe *aPipe = [NSPipe pipe];
+ NSFileHandle *readHandle = [aPipe fileHandleForReading];
+
+ NSMutableArray *taskArgs = [NSMutableArray arrayWithObject:@"OpenRA.Utility.exe"];
+ [taskArgs addObject:arg];
+
+ [aTask setCurrentDirectoryPath:gamePath];
+ [aTask setLaunchPath:@"/Library/Frameworks/Mono.framework/Commands/mono"];
+ [aTask setArguments:taskArgs];
+ [aTask setStandardOutput:aPipe];
+ [aTask launch];
+
+ NSData *inData = nil;
+ while ((inData = [readHandle availableData]) && [inData length])
+ [obj performSelector:sel withObject:[NSString stringWithUTF8String:[inData bytes]]];
+
+ [aTask release];
+}
+
@end
diff --git a/OpenRA.Launcher.Mac/ModEntry.h b/OpenRA.Launcher.Mac/ModEntry.h
index 38dad235ab..e78d35dc1f 100644
--- a/OpenRA.Launcher.Mac/ModEntry.h
+++ b/OpenRA.Launcher.Mac/ModEntry.h
@@ -10,6 +10,7 @@
@interface ModEntry : NSObject {
BOOL isHeader;
+ NSString *mod;
NSString *title;
NSString *version;
NSString *author;
@@ -20,6 +21,7 @@
}
@property (readonly) BOOL isHeader;
+@property (readonly) NSString *mod;
@property (readonly) NSString *title;
@property (readonly) NSString *version;
@property (readonly) NSString *author;
@@ -30,8 +32,10 @@
@property (readonly) NSImage* icon;
+ (id)headerWithTitle:(NSString *)aTitle;
-+ (id)modWithFields:(id)fields;
-- (id)initWithFields:(NSDictionary *)fields isHeader:(BOOL)header;
++ (id)errorWithTitle:(NSString *)aTitle;
++ (id)modWithId:(NSString *)mid fields:(id)fields;
+- (id)initWithId:(NSString *)mod fields:(NSDictionary *)fields isHeader:(BOOL)header;
- (void)addChild:(id)child;
+- (void)buildChildTree:(NSArray *)allMods;
- (id)icon;
@end
diff --git a/OpenRA.Launcher.Mac/ModEntry.m b/OpenRA.Launcher.Mac/ModEntry.m
index a8225ebe91..57e30e040c 100644
--- a/OpenRA.Launcher.Mac/ModEntry.m
+++ b/OpenRA.Launcher.Mac/ModEntry.m
@@ -10,6 +10,7 @@
@implementation ModEntry
+@synthesize mod;
@synthesize isHeader;
@synthesize title;
@synthesize version;
@@ -22,31 +23,44 @@
+ (id)headerWithTitle:(NSString *)aTitle
{
- id newObject = [[self alloc] initWithFields:[NSDictionary dictionaryWithObject:aTitle forKey:@"Title"] isHeader:YES];
+ id newObject = [[self alloc] initWithId:@"title" fields:[NSDictionary dictionaryWithObject:aTitle forKey:@"Title"] isHeader:YES];
[newObject autorelease];
return newObject;
}
-+ (id)modWithFields:(id)fields
++ (id)errorWithTitle:(NSString *)aTitle
{
- id newObject = [[self alloc] initWithFields:fields isHeader:NO];
+ id newObject = [[self alloc] initWithId:@"error" fields:[NSDictionary dictionaryWithObject:aTitle forKey:@"Title"] isHeader:NO];
[newObject autorelease];
return newObject;
}
-- (id)initWithFields:(NSDictionary *)fields isHeader:(BOOL)header
++ (id)modWithId:(NSString *)mod fields:(id)fields
+{
+ id newObject = [[self alloc] initWithId:mod fields:fields isHeader:NO];
+ [newObject autorelease];
+ return newObject;
+}
+
+- (id)initWithId:(NSString *)anId fields:(NSDictionary *)fields isHeader:(BOOL)header
{
self = [super init];
if (self)
{
+ mod = anId;
isHeader = header;
- title = [fields objectForKey:@"Title"];
- version = [fields objectForKey:@"Version"];
- author = [fields objectForKey:@"Author"];
- description = [fields objectForKey:@"Description"];
- requires = [fields objectForKey:@"Requires"];
- standalone = ([fields objectForKey:@"Standalone"] == @"True");
- icon = [[fields objectForKey:@"Icon"] retain];
+ title = [[fields objectForKey:@"Title"] retain];
+ version = [[fields objectForKey:@"Version"] retain];
+ author = [[fields objectForKey:@"Author"] retain];
+ description = [[fields objectForKey:@"Description"] retain];
+ requires = [[fields objectForKey:@"Requires"] retain];
+ standalone = ([[fields objectForKey:@"Standalone"] isEqualToString:@"True"]);
+
+ if (!isHeader)
+ {
+ NSString* imageName = [[NSBundle mainBundle] pathForResource:@"OpenRA" ofType:@"icns"];
+ icon = [[NSImage alloc] initWithContentsOfFile:imageName];
+ }
children = [[NSMutableArray alloc] init];
}
return self;
@@ -54,11 +68,29 @@
- (void)addChild:(ModEntry *)child
{
+ NSLog(@"Adding child %@ to %@",[child mod], mod);
[children addObject:child];
}
+- (void)buildChildTree:(NSArray *)allMods
+{
+ for (id aMod in allMods)
+ {
+ if (![[aMod requires] isEqualToString:mod])
+ continue;
+
+ [self addChild:aMod];
+ [aMod buildChildTree:allMods];
+ }
+}
+
- (void) dealloc
{
+ [title release]; title = nil;
+ [version release]; version = nil;
+ [author release]; author = nil;
+ [description release]; description = nil;
+ [requires release]; requires = nil;
[icon release]; icon = nil;
[super dealloc];
}
diff --git a/OpenRA.Utility/Command.cs b/OpenRA.Utility/Command.cs
index 11ee54238d..7faf5bfe21 100644
--- a/OpenRA.Utility/Command.cs
+++ b/OpenRA.Utility/Command.cs
@@ -42,7 +42,7 @@ namespace OpenRA.Utility
return;
}
- Console.WriteLine("{0}:", m);
+ Console.WriteLine("Mod:{0}", m);
Console.WriteLine(" Title: {0}", mod.Title);
Console.WriteLine(" Version: {0}", mod.Version);
Console.WriteLine(" Author: {0}", mod.Author);
diff --git a/mods/cnc/mod.yaml b/mods/cnc/mod.yaml
index 9edd27eb3d..d8c97437f5 100644
--- a/mods/cnc/mod.yaml
+++ b/mods/cnc/mod.yaml
@@ -2,7 +2,8 @@ Metadata:
Title: C&C
Description: OpenRA Reimagining of the classic game
Version: a0001
-
+ Author: The OpenRA Developers
+ Standalone: true
Folders:
.
mods/cnc