Support launching an arbitrary mod. Hook up package detection for cnc.
This commit is contained in:
@@ -16,10 +16,14 @@
|
|||||||
{
|
{
|
||||||
SidebarEntry *sidebarItems;
|
SidebarEntry *sidebarItems;
|
||||||
GameInstall *game;
|
GameInstall *game;
|
||||||
|
NSDictionary *allMods;
|
||||||
IBOutlet NSOutlineView *outlineView;
|
IBOutlet NSOutlineView *outlineView;
|
||||||
IBOutlet WebView *webView;
|
IBOutlet WebView *webView;
|
||||||
}
|
}
|
||||||
- (void)launchGame;
|
@property(readonly) NSDictionary *allMods;
|
||||||
|
|
||||||
|
- (void)launchMod:(NSString *)mod;
|
||||||
|
- (void)populateModInfo;
|
||||||
- (SidebarEntry *)sidebarModsTree;
|
- (SidebarEntry *)sidebarModsTree;
|
||||||
- (SidebarEntry *)sidebarOtherTree;
|
- (SidebarEntry *)sidebarOtherTree;
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#import "JSBridge.h"
|
#import "JSBridge.h"
|
||||||
|
|
||||||
@implementation Controller
|
@implementation Controller
|
||||||
|
@synthesize allMods;
|
||||||
|
|
||||||
- (void) awakeFromNib
|
- (void) awakeFromNib
|
||||||
{
|
{
|
||||||
@@ -25,6 +26,7 @@
|
|||||||
[col setDataCell:imageAndTextCell];
|
[col setDataCell:imageAndTextCell];
|
||||||
|
|
||||||
sidebarItems = [[SidebarEntry headerWithTitle:@""] retain];
|
sidebarItems = [[SidebarEntry headerWithTitle:@""] retain];
|
||||||
|
[self populateModInfo];
|
||||||
id modsRoot = [self sidebarModsTree];
|
id modsRoot = [self sidebarModsTree];
|
||||||
[sidebarItems addChild:modsRoot];
|
[sidebarItems addChild:modsRoot];
|
||||||
id otherRoot = [self sidebarOtherTree];
|
id otherRoot = [self sidebarOtherTree];
|
||||||
@@ -45,21 +47,25 @@
|
|||||||
[outlineView expandItem:otherRoot expandChildren:YES];
|
[outlineView expandItem:otherRoot expandChildren:YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) dealloc
|
- (void)dealloc
|
||||||
{
|
{
|
||||||
[sidebarItems release]; sidebarItems = nil;
|
[sidebarItems release]; sidebarItems = nil;
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (SidebarEntry *)sidebarModsTree
|
- (void)populateModInfo
|
||||||
{
|
{
|
||||||
// Get info for all installed mods
|
// Get info for all installed mods
|
||||||
id modnames = [game installedMods];
|
[allMods autorelease];
|
||||||
NSArray *allMods = [game infoForMods:modnames];
|
allMods = [[game infoForMods:[game installedMods]] retain];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (SidebarEntry *)sidebarModsTree
|
||||||
|
{
|
||||||
SidebarEntry *rootItem = [SidebarEntry headerWithTitle:@"MODS"];
|
SidebarEntry *rootItem = [SidebarEntry headerWithTitle:@"MODS"];
|
||||||
for (id aMod in allMods)
|
for (id key in allMods)
|
||||||
{
|
{
|
||||||
|
id aMod = [allMods objectForKey:key];
|
||||||
if ([aMod standalone])
|
if ([aMod standalone])
|
||||||
{
|
{
|
||||||
id child = [SidebarEntry entryWithMod:aMod allMods:allMods baseURL:[[game gameURL] URLByAppendingPathComponent:@"mods"]];
|
id child = [SidebarEntry entryWithMod:aMod allMods:allMods baseURL:[[game gameURL] URLByAppendingPathComponent:@"mods"]];
|
||||||
@@ -79,9 +85,9 @@
|
|||||||
return rootItem;
|
return rootItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)launchGame
|
- (void)launchMod:(NSString *)mod
|
||||||
{
|
{
|
||||||
[game launchGame];
|
[game launchMod:mod];
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark Sidebar Datasource and Delegate
|
#pragma mark Sidebar Datasource and Delegate
|
||||||
@@ -156,4 +162,8 @@ objectValueForTableColumn:(NSTableColumn *)tableColumn
|
|||||||
[windowObject setValue:[JSBridge sharedInstance] forKey:@"external"];
|
[windowObject setValue:[JSBridge sharedInstance] forKey:@"external"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)webView:(WebView *)webView addMessageToConsole:(NSDictionary *)dictionary
|
||||||
|
{
|
||||||
|
NSLog(@"%@",dictionary);
|
||||||
|
}
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -15,9 +15,9 @@
|
|||||||
@property(readonly) NSURL *gameURL;
|
@property(readonly) NSURL *gameURL;
|
||||||
|
|
||||||
-(id)initWithURL:(NSURL *)path;
|
-(id)initWithURL:(NSURL *)path;
|
||||||
-(void)launchGame;
|
-(void)launchMod:(NSString *)mod;
|
||||||
- (NSString *)runUtilityQuery:(NSString *)arg;
|
- (NSString *)runUtilityQuery:(NSString *)arg;
|
||||||
- (void)runUtilityQuery:(NSString *)arg handleOutput:(id)obj withMethod:(SEL)sel;
|
- (void)runUtilityQuery:(NSString *)arg handleOutput:(id)obj withMethod:(SEL)sel;
|
||||||
- (NSArray *)installedMods;
|
- (NSArray *)installedMods;
|
||||||
- (NSArray *)infoForMods:(NSArray *)mods;
|
- (NSDictionary *)infoForMods:(NSArray *)mods;
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -35,12 +35,12 @@
|
|||||||
return [mods componentsSeparatedByString:@"\n"];
|
return [mods componentsSeparatedByString:@"\n"];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray *)infoForMods:(NSArray *)mods
|
- (NSDictionary *)infoForMods:(NSArray *)mods
|
||||||
{
|
{
|
||||||
id query = [NSString stringWithFormat:@"-i=%@",[mods componentsJoinedByString:@","]];
|
id query = [NSString stringWithFormat:@"-i=%@",[mods componentsJoinedByString:@","]];
|
||||||
NSArray *lines = [[self runUtilityQuery:query] componentsSeparatedByString:@"\n"];
|
NSArray *lines = [[self runUtilityQuery:query] componentsSeparatedByString:@"\n"];
|
||||||
|
|
||||||
NSMutableArray *ret = [NSMutableArray array];
|
NSMutableDictionary *ret = [NSMutableDictionary dictionary];
|
||||||
NSMutableDictionary *fields = nil;
|
NSMutableDictionary *fields = nil;
|
||||||
NSString *current = nil;
|
NSString *current = nil;
|
||||||
for (id l in lines)
|
for (id l in lines)
|
||||||
@@ -68,7 +68,7 @@
|
|||||||
if (current != nil)
|
if (current != nil)
|
||||||
{
|
{
|
||||||
id url = [gameURL URLByAppendingPathComponent:[NSString stringWithFormat:@"mods/%@",current]];
|
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);
|
NSLog(@"Parsing mod %@",value);
|
||||||
current = value;
|
current = value;
|
||||||
@@ -82,17 +82,17 @@
|
|||||||
if (current != nil)
|
if (current != nil)
|
||||||
{
|
{
|
||||||
id url = [gameURL URLByAppendingPathComponent:[NSString stringWithFormat:@"mods/%@",current]];
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void)launchGame
|
-(void)launchMod:(NSString *)mod
|
||||||
{
|
{
|
||||||
// Use LaunchServices because neither NSTask or NSWorkspace support Info.plist _and_ arguments pre-10.6
|
// 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"];
|
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;
|
FSRef appRef;
|
||||||
CFURLGetFSRef((CFURLRef)[NSURL URLWithString:path], &appRef);
|
CFURLGetFSRef((CFURLRef)[NSURL URLWithString:path], &appRef);
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ static JSBridge *SharedInstance;
|
|||||||
if (self != nil)
|
if (self != nil)
|
||||||
{
|
{
|
||||||
methods = [[NSDictionary dictionaryWithObjectsAndKeys:
|
methods = [[NSDictionary dictionaryWithObjectsAndKeys:
|
||||||
@"launchCurrentMod", NSStringFromSelector(@selector(launchCurrentMod)),
|
@"launchMod", NSStringFromSelector(@selector(launchMod:)),
|
||||||
@"log", NSStringFromSelector(@selector(log:)),
|
@"log", NSStringFromSelector(@selector(log:)),
|
||||||
@"fileExistsInMod", NSStringFromSelector(@selector(fileExists:inMod:)),
|
@"fileExistsInMod", NSStringFromSelector(@selector(fileExists:inMod:)),
|
||||||
nil] retain];
|
nil] retain];
|
||||||
@@ -59,10 +59,17 @@ static JSBridge *SharedInstance;
|
|||||||
|
|
||||||
#pragma mark JS methods
|
#pragma mark JS methods
|
||||||
|
|
||||||
- (void)launchCurrentMod
|
- (BOOL)launchMod:(NSString *)aMod
|
||||||
{
|
{
|
||||||
NSLog(@"launchcurrent");
|
id mod = [[controller allMods] objectForKey:aMod];
|
||||||
[controller launchGame];
|
if (mod == nil)
|
||||||
|
{
|
||||||
|
NSLog(@"Invalid or unknown mod: %@", aMod);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
[controller launchMod:aMod];
|
||||||
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)log:(NSString *)message
|
- (void)log:(NSString *)message
|
||||||
@@ -72,8 +79,19 @@ static JSBridge *SharedInstance;
|
|||||||
|
|
||||||
- (BOOL)fileExists:(NSString *)aFile inMod:(NSString *)aMod
|
- (BOOL)fileExists:(NSString *)aFile inMod:(NSString *)aMod
|
||||||
{
|
{
|
||||||
NSLog(@"File %@ exists in mod %@",aFile, aMod);
|
id mod = [[controller allMods] objectForKey:aMod];
|
||||||
|
if (mod == nil)
|
||||||
|
{
|
||||||
|
NSLog(@"Invalid or unknown mod: %@", aMod);
|
||||||
return NO;
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disallow traversing up the directory tree
|
||||||
|
id path = [[[mod baseURL] absoluteString]
|
||||||
|
stringByAppendingPathComponent:[aFile stringByReplacingOccurrencesOfString:@"../"
|
||||||
|
withString:@""]];
|
||||||
|
|
||||||
|
return [[NSFileManager defaultManager] fileExistsAtPath:path];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -24,10 +24,9 @@
|
|||||||
@property (readonly) NSString *author;
|
@property (readonly) NSString *author;
|
||||||
@property (readonly) NSString *description;
|
@property (readonly) NSString *description;
|
||||||
@property (readonly) NSString *requires;
|
@property (readonly) NSString *requires;
|
||||||
|
@property (readonly) NSURL *baseURL;
|
||||||
@property (readonly) BOOL standalone;
|
@property (readonly) BOOL standalone;
|
||||||
|
|
||||||
+ (id)modWithId:(NSString *)mid fields:(id)fields baseURL:(NSURL *)url;
|
+ (id)modWithId:(NSString *)mid fields:(id)fields baseURL:(NSURL *)url;
|
||||||
- (id)initWithId:(NSString *)anId fields:(NSDictionary *)fields baseURL:(NSURL *)url;
|
- (id)initWithId:(NSString *)anId fields:(NSDictionary *)fields baseURL:(NSURL *)url;
|
||||||
|
|
||||||
- (NSURL *)pageURL;
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
@synthesize description;
|
@synthesize description;
|
||||||
@synthesize requires;
|
@synthesize requires;
|
||||||
@synthesize standalone;
|
@synthesize standalone;
|
||||||
|
@synthesize baseURL;
|
||||||
|
|
||||||
+ (id)modWithId:(NSString *)mod fields:(id)fields baseURL:(NSURL *)url
|
+ (id)modWithId:(NSString *)mod fields:(id)fields baseURL:(NSURL *)url
|
||||||
{
|
{
|
||||||
@@ -54,9 +55,4 @@
|
|||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSURL *)pageURL
|
|
||||||
{
|
|
||||||
return [baseURL URLByAppendingPathComponent:@"mod.html"];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
+ (id)headerWithTitle:(NSString *)aTitle;
|
+ (id)headerWithTitle:(NSString *)aTitle;
|
||||||
+ (id)entryWithTitle:(NSString *)aTitle url:(NSURL *)aURL icon:(id)anIcon;
|
+ (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;
|
- (id)initWithTitle:(NSString *)aTitle url:(NSURL *)aURL icon:(id)anIcon isHeader:(BOOL)aHeader;
|
||||||
- (void)addChild:(id)child;
|
- (void)addChild:(id)child;
|
||||||
- (NSURL *)url;
|
- (NSURL *)url;
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
return newObject;
|
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
|
// TODO: Get the mod icon from the Mod
|
||||||
// Temporary hack until mods define an icon
|
// Temporary hack until mods define an icon
|
||||||
@@ -40,8 +40,9 @@
|
|||||||
|
|
||||||
id ret = [SidebarEntry entryWithTitle:[baseMod title] url:url icon:icon];
|
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]])
|
if (![[aMod requires] isEqualToString:[baseMod mod]])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
padding: 20px 0px;
|
padding: 20px 0px;
|
||||||
width:100%;
|
width:100%;
|
||||||
height:100%;
|
height:100%;
|
||||||
|
overflow:hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
div#header
|
div#header
|
||||||
@@ -21,6 +22,7 @@
|
|||||||
margin-top: 30px;
|
margin-top: 30px;
|
||||||
height: 66px;
|
height: 66px;
|
||||||
text-align:center;
|
text-align:center;
|
||||||
|
overflow:hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.bar
|
div.bar
|
||||||
@@ -40,24 +42,29 @@
|
|||||||
div#content
|
div#content
|
||||||
{
|
{
|
||||||
text-align: justify;
|
text-align: justify;
|
||||||
width:50%;
|
|
||||||
padding-left:50px;
|
padding-left:50px;
|
||||||
|
overflow:hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
div#buttons
|
div.buttons
|
||||||
{
|
{
|
||||||
position:absolute;
|
position:absolute;
|
||||||
bottom:0px;
|
bottom:0px;
|
||||||
padding:20px;
|
padding:20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.desc
|
||||||
|
{
|
||||||
|
font-size:0.75em;
|
||||||
|
}
|
||||||
|
|
||||||
.button
|
.button
|
||||||
{
|
{
|
||||||
border: solid 3px #650b03;
|
border: solid 3px #650b03;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
margin:10px;
|
margin:10px;
|
||||||
height:40px;
|
height:40px;
|
||||||
width:150px;
|
width:170px;
|
||||||
color:white;
|
color:white;
|
||||||
font-weight:bold;
|
font-weight:bold;
|
||||||
font-size:1em;
|
font-size:1em;
|
||||||
@@ -75,8 +82,42 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
<script type="text/javascript">
|
||||||
|
// Check which packages are installed.
|
||||||
|
// Returns 1 if basic files are installed
|
||||||
|
// Returns 2 if basic files plus music are installed
|
||||||
|
function packagesInstalled()
|
||||||
|
{
|
||||||
|
if (window.external.fileExistsInMod('packages/conquer.mix','cnc') != 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return (window.external.fileExistsInMod('packages/scores.mix','cnc') == 1) ? 2 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function play()
|
||||||
|
{
|
||||||
|
window.external.launchMod("cnc");
|
||||||
|
}
|
||||||
|
|
||||||
|
function installFromCD()
|
||||||
|
{
|
||||||
|
window.external.log("installFromCD()");
|
||||||
|
}
|
||||||
|
|
||||||
|
function installFromWeb()
|
||||||
|
{
|
||||||
|
window.external.log("installFromWeb()");
|
||||||
|
}
|
||||||
|
|
||||||
|
function onLoad()
|
||||||
|
{
|
||||||
|
document.getElementById("buttons-install").style.display = (packagesInstalled() == 0) ? "" : "none";
|
||||||
|
document.getElementById("buttons-upgrade").style.display = (packagesInstalled() == 1) ? "" : "none";
|
||||||
|
document.getElementById("buttons-play").style.display = (packagesInstalled() == 2) ? "" : "none";
|
||||||
|
}
|
||||||
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body onload="onLoad();">
|
||||||
<div id="header" class="bar">
|
<div id="header" class="bar">
|
||||||
<h1>Command & Conquer</h1>
|
<h1>Command & Conquer</h1>
|
||||||
</div>
|
</div>
|
||||||
@@ -93,9 +134,23 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="buttons">
|
<div id="buttons-install" class="buttons">
|
||||||
<input type="button" class="button" onclick="window.external.launchCurrentMod();" value="Play" />
|
<div class="desc">The original game data is required before you can play this mod.<br />
|
||||||
<input type="button" class="button" onclick="window.external.fileExistsInMod('foo.mix','ra');"value="Debug" />
|
Installing from web will install the minimal files required to play.<br />
|
||||||
|
Installing from CD will also install the music and movie files for an improved game experience.
|
||||||
|
</div>
|
||||||
|
<input type="button" class="button" onclick="installFromWeb();" value="Install from Web" />
|
||||||
|
<input type="button" class="button" onclick="installFromCD();" value="Install from CD" />
|
||||||
|
</div>
|
||||||
|
<div id="buttons-upgrade" class="buttons" style="display:none">
|
||||||
|
<div class="desc">
|
||||||
|
Upgrade from CD to install the original music and movie files for an improved game experience.
|
||||||
|
</div>
|
||||||
|
<input type="button" class="button" onclick="play();" value="Play" />
|
||||||
|
<input type="button" class="button" onclick="installFromCD();" value="Upgrade from CD" />
|
||||||
|
</div>
|
||||||
|
<div id="buttons-play" class="buttons" style="display:none">
|
||||||
|
<input type="button" class="button" onclick="play();" value="Play" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<html>
|
<html>
|
||||||
<body>
|
<body>
|
||||||
<h1>Dune 2000</h1>
|
<h1>Dune 2000</h1>
|
||||||
<input type="button" class="button" onclick="window.external.launchCurrentMod();" value="Play" />
|
<input type="button" class="button" onclick="window.external.launchMod('d2k')" value="Play" />
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<html>
|
<html>
|
||||||
<body>
|
<body>
|
||||||
<h1>Default Mod</h1>
|
<h1>Default Mod</h1>
|
||||||
<input type="button" class="button" onclick="window.external.launchCurrentMod();" value="Play" />
|
<input type="button" class="button" onclick="window.external.launchMod('default')" value="Play" />
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -2,6 +2,6 @@
|
|||||||
<body>
|
<body>
|
||||||
<h1>Example Mod</h1>
|
<h1>Example Mod</h1>
|
||||||
<h2>Demonstrates how to add a new unit by adding a soviet supply truck.</h2>
|
<h2>Demonstrates how to add a new unit by adding a soviet supply truck.</h2>
|
||||||
<input type="button" class="button" onclick="window.external.launchCurrentMod();" value="Play" />
|
<input type="button" class="button" onclick="window.external.launchMod('example')" value="Play" />
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<html>
|
<html>
|
||||||
<body>
|
<body>
|
||||||
<h1>Red Alert</h1>
|
<h1>Red Alert</h1>
|
||||||
<input type="button" class="button" onclick="window.external.launchCurrentMod();" value="Play" />
|
<input type="button" class="button" onclick="window.external.launchMod('ra')" value="Play" />
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -2,6 +2,6 @@
|
|||||||
<body>
|
<body>
|
||||||
<h1>RA Performance Tests</h1>
|
<h1>RA Performance Tests</h1>
|
||||||
<h2>Adds special performance test maps to ra.</h2>
|
<h2>Adds special performance test maps to ra.</h2>
|
||||||
<input type="button" class="button" onclick="window.external.launchCurrentMod();" value="Play" />
|
<input type="button" class="button" onclick="window.external.launchMod('ra_perf')" value="Play" />
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user