mac docu fixes, mac launcher backport from sauer, etc
git-svn-id: svn://svn.code.sf.net/p/actiongame/code/trunk/ac@3372 e016b1c5-ed68-44aa-a2f7-31cac88cffde
This commit is contained in:
+88
-30
@@ -1,30 +1,88 @@
|
||||
{
|
||||
IBClasses = (
|
||||
{CLASS = ConsoleView; LANGUAGE = ObjC; SUPERCLASS = NSView; },
|
||||
{CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
|
||||
{
|
||||
ACTIONS = {
|
||||
helpAction = id;
|
||||
multiplayerAction = id;
|
||||
playAction = id;
|
||||
playMap = id;
|
||||
playRpg = id;
|
||||
};
|
||||
CLASS = Launcher;
|
||||
LANGUAGE = ObjC;
|
||||
OUTLETS = {
|
||||
console = ConsoleView;
|
||||
keys = NSArrayController;
|
||||
maps = NSArrayController;
|
||||
multiplayer = NSButton;
|
||||
resolutions = NSPopUpButton;
|
||||
view1 = NSView;
|
||||
view2 = NSView;
|
||||
view3 = NSView;
|
||||
window = NSWindow;
|
||||
};
|
||||
SUPERCLASS = NSObject;
|
||||
}
|
||||
);
|
||||
IBVersion = 1;
|
||||
}
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IBClasses</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>ACTIONS</key>
|
||||
<dict>
|
||||
<key>helpAction</key>
|
||||
<string>id</string>
|
||||
<key>multiplayerAction</key>
|
||||
<string>id</string>
|
||||
<key>openUserdir</key>
|
||||
<string>id</string>
|
||||
<key>playAction</key>
|
||||
<string>id</string>
|
||||
<key>playMap</key>
|
||||
<string>id</string>
|
||||
<key>playRpg</key>
|
||||
<string>id</string>
|
||||
<key>showForum</key>
|
||||
<string>id</string>
|
||||
</dict>
|
||||
<key>CLASS</key>
|
||||
<string>Launcher</string>
|
||||
<key>LANGUAGE</key>
|
||||
<string>ObjC</string>
|
||||
<key>OUTLETS</key>
|
||||
<dict>
|
||||
<key>console</key>
|
||||
<string>ConsoleView</string>
|
||||
<key>keys</key>
|
||||
<string>NSArrayController</string>
|
||||
<key>maps</key>
|
||||
<string>NSArrayController</string>
|
||||
<key>multiplayer</key>
|
||||
<string>NSButton</string>
|
||||
<key>prog</key>
|
||||
<string>NSProgressIndicator</string>
|
||||
<key>resolutions</key>
|
||||
<string>NSPopUpButton</string>
|
||||
<key>stencil</key>
|
||||
<string>NSButton</string>
|
||||
<key>tabs</key>
|
||||
<string>NSTabView</string>
|
||||
<key>view1</key>
|
||||
<string>NSView</string>
|
||||
<key>view2</key>
|
||||
<string>NSView</string>
|
||||
<key>view3</key>
|
||||
<string>NSView</string>
|
||||
<key>view4</key>
|
||||
<string>NSView</string>
|
||||
<key>view5</key>
|
||||
<string>NSView</string>
|
||||
<key>window</key>
|
||||
<string>NSWindow</string>
|
||||
</dict>
|
||||
<key>SUPERCLASS</key>
|
||||
<string>NSObject</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>ACTIONS</key>
|
||||
<dict>
|
||||
<key></key>
|
||||
<string>id</string>
|
||||
</dict>
|
||||
<key>CLASS</key>
|
||||
<string>FirstResponder</string>
|
||||
<key>LANGUAGE</key>
|
||||
<string>ObjC</string>
|
||||
<key>SUPERCLASS</key>
|
||||
<string>NSObject</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CLASS</key>
|
||||
<string>ConsoleView</string>
|
||||
<key>LANGUAGE</key>
|
||||
<string>ObjC</string>
|
||||
<key>SUPERCLASS</key>
|
||||
<string>NSView</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>IBVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
+12
-20
@@ -1,32 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IBDocumentLocation</key>
|
||||
<string>363 148 569 391 0 0 1920 1178 </string>
|
||||
<key>IBEditorPositions</key>
|
||||
<dict>
|
||||
<key>208</key>
|
||||
<string>709 615 502 340 0 0 1920 1178 </string>
|
||||
<key>213</key>
|
||||
<string>709 615 502 340 0 0 1920 1178 </string>
|
||||
<key>264</key>
|
||||
<string>709 615 502 340 0 0 1920 1178 </string>
|
||||
<key>29</key>
|
||||
<string>149 405 230 44 0 0 1920 1178 </string>
|
||||
</dict>
|
||||
<key>IBFramework Version</key>
|
||||
<string>446.1</string>
|
||||
<key>IBLockedObjects</key>
|
||||
<array/>
|
||||
<string>672</string>
|
||||
<key>IBLastKnownRelativeProjectPath</key>
|
||||
<string>../actioncube.xcodeproj</string>
|
||||
<key>IBOldestOS</key>
|
||||
<integer>5</integer>
|
||||
<key>IBOpenObjects</key>
|
||||
<array>
|
||||
<integer>264</integer>
|
||||
<integer>213</integer>
|
||||
<integer>208</integer>
|
||||
<integer>336</integer>
|
||||
<integer>240</integer>
|
||||
<integer>21</integer>
|
||||
<integer>213</integer>
|
||||
</array>
|
||||
<key>IBSystem Version</key>
|
||||
<string>8P2137</string>
|
||||
<string>9F33</string>
|
||||
<key>targetFramework</key>
|
||||
<string>IBCocoaFramework</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
Binary file not shown.
+26
-12
@@ -3,24 +3,38 @@
|
||||
@class ConsoleView;
|
||||
|
||||
@interface Launcher : NSObject {
|
||||
IBOutlet NSWindow *window;
|
||||
IBOutlet NSView *view1;
|
||||
IBOutlet NSView *view2;
|
||||
IBOutlet NSView *view3;
|
||||
IBOutlet NSWindow *window;
|
||||
|
||||
IBOutlet NSArrayController *maps;
|
||||
IBOutlet NSArrayController *keys;
|
||||
//able to leave these disconnected
|
||||
IBOutlet NSView *view1; //Main
|
||||
IBOutlet NSView *view2; //Maps
|
||||
IBOutlet NSView *view3; //Keys
|
||||
IBOutlet NSView *view4; //Server
|
||||
|
||||
|
||||
IBOutlet NSProgressIndicator *prog; //while scanning maps - it's there if you want to wire it up
|
||||
IBOutlet NSArrayController *maps;
|
||||
IBOutlet NSArrayController *keys;
|
||||
IBOutlet NSPopUpButton *resolutions;
|
||||
IBOutlet NSButton *multiplayer;
|
||||
IBOutlet ConsoleView *console;
|
||||
IBOutlet NSButton *stencil;
|
||||
|
||||
IBOutlet NSButton *multiplayer;
|
||||
IBOutlet ConsoleView *console;
|
||||
@private
|
||||
NSMutableDictionary *toolBarItems;
|
||||
pid_t server;
|
||||
NSMutableDictionary *toolBarItems;
|
||||
pid_t server;
|
||||
NSMutableDictionary *fileRoles;
|
||||
BOOL forcename;
|
||||
}
|
||||
|
||||
- (IBAction)playAction:(id)sender;
|
||||
|
||||
- (IBAction)multiplayerAction:(id)sender;
|
||||
|
||||
- (IBAction)helpAction:(id)sender;
|
||||
@end
|
||||
- (IBAction)playRpg:(id)sender;
|
||||
|
||||
- (IBAction)playMap:(id)sender;
|
||||
|
||||
- (IBAction)openUserdir:(id)sender;
|
||||
|
||||
@end
|
||||
|
||||
+453
-271
@@ -1,35 +1,70 @@
|
||||
#import "Launcher.h"
|
||||
#import "ConsoleView.h"
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h> /* unlink */
|
||||
#include <util.h> /* forkpty */
|
||||
#include <unistd.h> /* _exit() */
|
||||
#include <util.h> /* forkpty() */
|
||||
|
||||
// User default keys
|
||||
#define dkVERSION @"version"
|
||||
#define dkFULLSCREEN @"fullscreen"
|
||||
#define dkFSAA @"fsaa"
|
||||
|
||||
#define dkRESOLUTION @"resolution"
|
||||
#define dkADVANCEDOPTS @"advancedOptions"
|
||||
#define dkSERVEROPTS @"server_options"
|
||||
#define dkDESCRIPTION @"server_description"
|
||||
#define dkPASSWORD @"server_password"
|
||||
#define dkMAXCLIENTS @"server_maxclients"
|
||||
|
||||
#define kMaxDisplays 16
|
||||
|
||||
// unless you want strings with "(null)" in them :-/
|
||||
@interface NSUserDefaults(Extras)
|
||||
- (NSString*)nonNullStringForKey:(NSString*)key;
|
||||
@end
|
||||
//If you make a MOD then please change this, the bundle indentifier, the file extensions (.ogz, .dmo), and the url registration.
|
||||
#define kSAUERBRATEN @"assaultcube"
|
||||
|
||||
@implementation NSUserDefaults(Extras)
|
||||
- (NSString*)nonNullStringForKey:(NSString*)key {
|
||||
NSString *result = [self stringForKey:key];
|
||||
return (result?result:@"");
|
||||
//tab names, i.e. image names (text is localised)
|
||||
#define tkMAIN @"Main"
|
||||
#define tkMAPS @"Maps"
|
||||
#define tkKEYS @"Keys"
|
||||
#define tkSERVER @"Server"
|
||||
|
||||
|
||||
@interface NSString(Extras)
|
||||
@end
|
||||
@implementation NSString(Extras)
|
||||
- (NSString*)expand {
|
||||
NSMutableString *str = [NSMutableString string];
|
||||
[str setString:self];
|
||||
[str replaceOccurrencesOfString:@":s" withString:kSAUERBRATEN options:0 range:NSMakeRange(0, [str length])];
|
||||
return str;
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
@interface NSUserDefaults(Extras) // unless you want strings with "(null)" in them :-/
|
||||
- (NSString*)nonNullStringForKey:(NSString*)key;
|
||||
@end
|
||||
@implementation NSUserDefaults(Extras)
|
||||
- (NSString*)nonNullStringForKey:(NSString*)key {
|
||||
NSString *result = [self stringForKey:key];
|
||||
return (result ? result : @"");
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
@interface Map : NSObject {
|
||||
NSString *path;
|
||||
BOOL demo, user;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation Map
|
||||
- (id)initWithPath:(NSString*)aPath
|
||||
- (id)initWithPath:(NSString*)aPath user:(BOOL)aUser demo:(BOOL)aDemo
|
||||
{
|
||||
if((self = [super init]))
|
||||
{
|
||||
path = [[aPath stringByDeletingPathExtension] retain];
|
||||
user = aUser;
|
||||
demo = aDemo;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
- (void)dealloc
|
||||
@@ -37,26 +72,42 @@
|
||||
[path release];
|
||||
[super dealloc];
|
||||
}
|
||||
- (NSString*)path { return path; }
|
||||
- (NSString*)path { return (demo ? [NSString stringWithFormat:@"-xdemo \"%@\"", path] : path); } // minor hack
|
||||
- (NSString*)name { return [path lastPathComponent]; }
|
||||
- (NSImage*)image { return [[NSImage alloc] initWithContentsOfFile:[path stringByAppendingString:@".jpg"]]; }
|
||||
- (NSImage*)image
|
||||
{
|
||||
NSImage *image = [[NSImage alloc] initWithContentsOfFile:[path stringByAppendingString:@".jpg"]];
|
||||
if(!image && demo) image = [NSImage imageNamed:tkMAIN];
|
||||
if(!image) image = [NSImage imageNamed:@"Nomap"];
|
||||
return image;
|
||||
}
|
||||
- (NSString*)text
|
||||
{
|
||||
NSString *text = [NSString alloc];
|
||||
NSError *error;
|
||||
return [[NSString alloc] initWithContentsOfFile:[path stringByAppendingString:@".txt"] encoding:NSASCIIStringEncoding error:&error];
|
||||
if([text respondsToSelector:@selector(initWithContentsOfFile:encoding:error:)])
|
||||
text = [text initWithContentsOfFile:[path stringByAppendingString:@".txt"] encoding:NSASCIIStringEncoding error:&error];
|
||||
else
|
||||
text = [text initWithContentsOfFile:[path stringByAppendingString:@".txt"]]; //deprecated in 10.4
|
||||
if(!text) text = (demo)?@"Recorded demo data":@"";
|
||||
return text;
|
||||
}
|
||||
- (void)setText:(NSString*)text { } // wtf? - damn textfield believes it's editable
|
||||
- (NSString*)tickIfExists:(NSString*)ext
|
||||
{
|
||||
unichar tickCh = 0x2713;
|
||||
return [[NSFileManager defaultManager] fileExistsAtPath:[path stringByAppendingString:ext]] ? [NSString stringWithCharacters:&tickCh length:1] : @"";
|
||||
return ([[NSFileManager defaultManager] fileExistsAtPath:[path stringByAppendingString:ext]] ? [NSString stringWithCharacters:&tickCh length:1] : @"");
|
||||
}
|
||||
- (NSString*)hasImage { return [self tickIfExists:@".jpg"]; }
|
||||
- (NSString*)hasText { return [self tickIfExists:@".txt"]; }
|
||||
- (NSString*)hasCfg { return [self tickIfExists:@".cfg"]; }
|
||||
- (NSString*)user {
|
||||
unichar tickCh = 0x2713;
|
||||
return (user ? [NSString stringWithCharacters:&tickCh length:1] : @"");
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
|
||||
static int numberForKey(CFDictionaryRef desc, CFStringRef key)
|
||||
{
|
||||
CFNumberRef value;
|
||||
@@ -67,19 +118,15 @@ static int numberForKey(CFDictionaryRef desc, CFStringRef key)
|
||||
return num;
|
||||
}
|
||||
|
||||
@implementation Launcher
|
||||
|
||||
@interface Launcher(ToolBar)
|
||||
@end
|
||||
@implementation Launcher(ToolBar)
|
||||
|
||||
- (void)switchViews:(NSToolbarItem *)item
|
||||
{
|
||||
NSView *prefsView;
|
||||
switch([item tag])
|
||||
{
|
||||
case 1: prefsView = view1; break;
|
||||
case 2: prefsView = view2; break;
|
||||
case 3: prefsView = view3; break;
|
||||
//extend as see fit...
|
||||
default: return;
|
||||
}
|
||||
NSView *views[] = {view1, view2, view3, view4};
|
||||
NSView *prefsView = views[[item tag]-1];
|
||||
|
||||
//to stop flicker, we make a temp blank view.
|
||||
NSView *tempView = [[NSView alloc] initWithFrame:[[window contentView] frame]];
|
||||
@@ -94,39 +141,38 @@ static int numberForKey(CFDictionaryRef desc, CFStringRef key)
|
||||
|
||||
//set the frame to newFrame and animate it.
|
||||
[window setFrame:newFrame display:YES animate:YES];
|
||||
//set the main content view to the new view we have picked through the if structure above.
|
||||
//set the main content view to the new view we have picked through.
|
||||
[window setContentView:prefsView];
|
||||
[window setContentMinSize:[prefsView bounds].size];
|
||||
}
|
||||
|
||||
- (NSToolbarItem*)addToolBarItem:(NSString*)name
|
||||
{
|
||||
int n = [toolBarItems count] + 1;
|
||||
NSToolbarItem *item = [[NSToolbarItem alloc] initWithItemIdentifier:[NSString stringWithFormat:@"%0d", n]];
|
||||
[item setTag:n];
|
||||
[item setTarget:self];
|
||||
[item setAction:@selector(switchViews:)];
|
||||
[toolBarItems setObject:item forKey:[item itemIdentifier]];
|
||||
[item setLabel:NSLocalizedString(name, @"")];
|
||||
[item setImage:[NSImage imageNamed:name]];
|
||||
[item release];
|
||||
return item;
|
||||
}
|
||||
|
||||
- (void)initViews
|
||||
- (void)initToolBar
|
||||
{
|
||||
toolBarItems = [[NSMutableDictionary alloc] init];
|
||||
NSToolbarItem *first = [self addToolBarItem:@"Main"];
|
||||
[self addToolBarItem:@"Keys"];
|
||||
[self addToolBarItem:@"Server"];
|
||||
|
||||
NSToolbarItem *item = [[NSToolbarItem alloc] initWithItemIdentifier:NSToolbarFlexibleSpaceItemIdentifier];
|
||||
[toolBarItems setObject:item forKey:[item itemIdentifier]];
|
||||
[item release];
|
||||
|
||||
[[self addToolBarItem:@"Help"] setAction:@selector(helpAction:)];
|
||||
|
||||
NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:@"PreferencePanes"];
|
||||
NSEnumerator *e = [[self toolbarDefaultItemIdentifiers:nil] objectEnumerator];
|
||||
NSString *identifier;
|
||||
while(identifier = [e nextObject])
|
||||
{
|
||||
NSToolbarItem *item = [[NSToolbarItem alloc] initWithItemIdentifier:identifier];
|
||||
int tag = [identifier intValue];
|
||||
NSString *name = identifier;
|
||||
SEL action = @selector(displayHelp:);
|
||||
id target = self;
|
||||
if(tag) {
|
||||
NSString *names[] = {tkMAIN, tkMAPS, tkKEYS, tkSERVER};
|
||||
name = names[tag-1];
|
||||
action = @selector(switchViews:);
|
||||
target = self;
|
||||
}
|
||||
[item setTag:tag];
|
||||
[item setTarget:target];
|
||||
[item setAction:action];
|
||||
[item setLabel:NSLocalizedString(name, @"")];
|
||||
[item setImage:[NSImage imageNamed:name]];
|
||||
[toolBarItems setObject:item forKey:identifier];
|
||||
[item release];
|
||||
}
|
||||
NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:@""];
|
||||
[toolbar setDelegate:self];
|
||||
[toolbar setAllowsUserCustomization:NO];
|
||||
[toolbar setAutosavesConfiguration:NO];
|
||||
@@ -134,14 +180,14 @@ static int numberForKey(CFDictionaryRef desc, CFStringRef key)
|
||||
[toolbar release];
|
||||
if([window respondsToSelector:@selector(setShowsToolbarButton:)]) [window setShowsToolbarButton:NO]; //10.4+
|
||||
|
||||
//Make it select the first by default
|
||||
//select the first by default
|
||||
NSToolbarItem *first = [toolBarItems objectForKey:[[self toolbarDefaultItemIdentifiers:nil] objectAtIndex:0]];
|
||||
[toolbar setSelectedItemIdentifier:[first itemIdentifier]];
|
||||
[self switchViews:first];
|
||||
}
|
||||
|
||||
/*
|
||||
* toolbar delegate methods
|
||||
*/
|
||||
#pragma mark toolbar delegate methods
|
||||
|
||||
- (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag
|
||||
{
|
||||
return [toolBarItems objectForKey:itemIdentifier];
|
||||
@@ -152,19 +198,58 @@ static int numberForKey(CFDictionaryRef desc, CFStringRef key)
|
||||
return [self toolbarDefaultItemIdentifiers:theToolbar];
|
||||
}
|
||||
|
||||
- (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar*)theToolbar
|
||||
- (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar*)toolbar
|
||||
{
|
||||
return [NSArray arrayWithObjects:@"1", @"2", @"3", NSToolbarFlexibleSpaceItemIdentifier, @"5", nil];
|
||||
NSMutableArray *array = (NSMutableArray *)[self toolbarSelectableItemIdentifiers:toolbar];
|
||||
[array addObject:NSToolbarFlexibleSpaceItemIdentifier];
|
||||
[array addObject:@"Help"];
|
||||
return array;
|
||||
}
|
||||
|
||||
- (NSArray *)toolbarSelectableItemIdentifiers: (NSToolbar *)toolbar {
|
||||
return [NSArray arrayWithObjects:@"1", @"2", @"3", nil];
|
||||
- (NSArray *)toolbarSelectableItemIdentifiers: (NSToolbar *)toolbar
|
||||
{
|
||||
NSMutableArray *array = [NSMutableArray array];
|
||||
NSView *views[] = {view1, view2, view3, view4};
|
||||
int i;
|
||||
for(i = 0; i < sizeof(views)/sizeof(NSView*); i++) if(views[i]) [array addObject:[NSString stringWithFormat:@"%d", i+1]];
|
||||
return array;
|
||||
}
|
||||
|
||||
- (void)displayHelp:(id)sender
|
||||
{
|
||||
NSString *path = [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/help/README.html"];
|
||||
|
||||
if (![[NSWorkspace sharedWorkspace] openFile:path])
|
||||
NSLog(@"Warning: [[NSWorkspace sharedWorkspace] openFile:path] failed");
|
||||
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
@implementation Launcher
|
||||
|
||||
/* directory where the executable lives */
|
||||
+ (NSString *)cwd
|
||||
{
|
||||
return [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"Contents/gamedata"];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* directory where user files are kept - typically /Users/<name>/Application Support/sauerbraten */
|
||||
+ (NSString*)userdir
|
||||
{
|
||||
FSRef folder;
|
||||
NSString *path = nil;
|
||||
if(FSFindFolder(kUserDomain, kApplicationSupportFolderType, NO, &folder) == noErr) {
|
||||
CFURLRef url = CFURLCreateFromFSRef(kCFAllocatorDefault, &folder);
|
||||
path = [(NSURL *)url path];
|
||||
CFRelease(url);
|
||||
path = [path stringByAppendingPathComponent:kSAUERBRATEN];
|
||||
NSFileManager *fm = [NSFileManager defaultManager];
|
||||
if(![fm fileExistsAtPath:path]) [fm createDirectoryAtPath:path attributes:nil]; //ensure it exists
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
- (void)addResolutionsForDisplay:(CGDirectDisplayID)dspy
|
||||
{
|
||||
@@ -190,63 +275,51 @@ static int numberForKey(CFDictionaryRef desc, CFStringRef key)
|
||||
for (i = 0; i < numDisplays; i++)
|
||||
[self addResolutionsForDisplay:display[i]];
|
||||
}
|
||||
[resolutions selectItemAtIndex: [[NSUserDefaults standardUserDefaults] integerForKey:@"resolution"]];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* directory where the executable lives */
|
||||
-(NSString *)cwd
|
||||
{
|
||||
return [[[[NSBundle mainBundle] bundlePath] stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"assaultcube"];
|
||||
[resolutions selectItemAtIndex: [[NSUserDefaults standardUserDefaults] integerForKey:dkRESOLUTION]];
|
||||
}
|
||||
|
||||
/* build key array from config data */
|
||||
-(NSArray *)getKeys:(NSDictionary *)dict
|
||||
{
|
||||
NSMutableArray *arr = [[NSMutableArray alloc] init];
|
||||
NSMutableArray *arr = [NSMutableArray array];
|
||||
NSEnumerator *e = [dict keyEnumerator];
|
||||
NSString *key;
|
||||
while ((key = [e nextObject]))
|
||||
{
|
||||
NSString *trig;
|
||||
if([key hasPrefix:@"editbind"])
|
||||
trig = [key substringFromIndex:9];
|
||||
else if([key hasPrefix:@"bind"])
|
||||
trig = [key substringFromIndex:5];
|
||||
else
|
||||
continue;
|
||||
int pos = [key rangeOfString:@"bind."].location;
|
||||
if(pos == NSNotFound || pos > 5) continue;
|
||||
[arr addObject:[NSDictionary dictionaryWithObjectsAndKeys: //keys used in nib
|
||||
trig, @"key",
|
||||
[key hasPrefix:@"editbind"]?@"edit":@"", @"mode",
|
||||
[key substringFromIndex:pos+5], @"key",
|
||||
[key substringToIndex:pos], @"mode",
|
||||
[dict objectForKey:key], @"action",
|
||||
nil]];
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* extract a dictionary from the config files containing:
|
||||
* - name, gamma strings
|
||||
* - name, team, gamma strings
|
||||
* - bind/editbind '.' key strings
|
||||
*/
|
||||
-(NSDictionary *)readConfigFiles
|
||||
{
|
||||
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
|
||||
[dict setObject:@"" forKey:@"name"]; //ensure these entries are never nil
|
||||
[dict setObject:@"" forKey:@"team"];
|
||||
|
||||
NSString *files[] = {@"config.cfg", @"autoexec.cfg"};
|
||||
int i;
|
||||
for(i = 0; i < sizeof(files)/sizeof(NSString*); i++)
|
||||
{
|
||||
NSString *file = [[self cwd] stringByAppendingPathComponent:files[i]];
|
||||
NSString *file = [Launcher userdir];
|
||||
file = [file stringByAppendingPathComponent:files[i]];
|
||||
|
||||
NSArray *lines = [[NSString stringWithContentsOfFile:file] componentsSeparatedByString:@"\n"];
|
||||
|
||||
if(i==0 && !lines) // ugh - special case when first run...
|
||||
{
|
||||
file = [[self cwd] stringByAppendingPathComponent:@"config/defaults.cfg"];
|
||||
file = [[Launcher cwd] stringByAppendingPathComponent:@"config/defaults.cfg"];
|
||||
lines = [[NSString stringWithContentsOfFile:file] componentsSeparatedByString:@"\n"];
|
||||
}
|
||||
|
||||
@@ -257,6 +330,7 @@ static int numberForKey(CFDictionaryRef desc, CFStringRef key)
|
||||
NSRange r; // more flexible to do this manually rather than via NSScanner...
|
||||
int j = 0;
|
||||
while(j < [line length] && [line characterAtIndex:j] <= ' ') j++; //skip white
|
||||
if(j != 0) continue; // shouldn't be indented
|
||||
r.location = j;
|
||||
while(j < [line length] && [line characterAtIndex:j] > ' ') j++; //until white
|
||||
r.length = j - r.location;
|
||||
@@ -273,139 +347,28 @@ static int numberForKey(CFDictionaryRef desc, CFStringRef key)
|
||||
while(j < [line length] && [line characterAtIndex:j] > ' ') j++; //until white
|
||||
r.length = j - r.location;
|
||||
}
|
||||
if(r.location+r.length >= [line length]) continue; //missing value
|
||||
NSString *value = [line substringWithRange:r];
|
||||
|
||||
while(j < [line length] && [line characterAtIndex:j] <= ' ') j++; //skip white
|
||||
NSString *remainder = [line substringFromIndex:j];
|
||||
|
||||
if([type isEqual:@"name"] || [type isEqual:@"gamma"])
|
||||
if([type isEqual:@"name"] || [type isEqual:@"team"] || [type isEqual:@"gamma"])
|
||||
[dict setObject:value forKey:type];
|
||||
else if([type isEqual:@"bind"] || [type isEqual:@"editbind"])
|
||||
else if([type isEqual:@"bind"] || [type isEqual:@"editbind"] || [type isEqual:@"specbind"])
|
||||
[dict setObject:remainder forKey:[NSString stringWithFormat:@"%@.%@", type,value]];
|
||||
}
|
||||
}
|
||||
return dict;
|
||||
}
|
||||
|
||||
-(void)updateAutoexecFile:(NSDictionary *)updates
|
||||
{
|
||||
NSString *file = [[self cwd] stringByAppendingPathComponent:@"config/autoexec.cfg"];
|
||||
//build the data
|
||||
NSString *result = nil;
|
||||
NSArray *lines = [[NSString stringWithContentsOfFile:file] componentsSeparatedByString:@"\n"];
|
||||
if(lines)
|
||||
{
|
||||
NSString *line;
|
||||
NSEnumerator *e = [lines objectEnumerator];
|
||||
while(line = [e nextObject])
|
||||
{
|
||||
NSScanner *scanner = [NSScanner scannerWithString:line];
|
||||
NSString *type;
|
||||
if([scanner scanCharactersFromSet:[NSCharacterSet letterCharacterSet] intoString:&type])
|
||||
if([updates objectForKey:type]) continue; //skip things declared in updates
|
||||
result = (result) ? [NSString stringWithFormat:@"%@\n%@", result, line] : line;
|
||||
}
|
||||
}
|
||||
NSEnumerator *e = [updates keyEnumerator];
|
||||
NSString *type;
|
||||
while(type = [e nextObject])
|
||||
{
|
||||
id value = [updates objectForKey:type];
|
||||
if([type isEqual:@"name"]) value = [NSString stringWithFormat:@"\"%@\"", value];
|
||||
NSString *line = [NSString stringWithFormat:@"%@ %@", type, value];
|
||||
result = (result) ? [NSString stringWithFormat:@"%@\n%@", result, line] : line;
|
||||
}
|
||||
//backup
|
||||
NSFileManager *fm = [NSFileManager defaultManager];
|
||||
NSString *backupfile = nil;
|
||||
if([fm fileExistsAtPath:file])
|
||||
{
|
||||
backupfile = [file stringByAppendingString:@".bak"];
|
||||
if(![fm movePath:file toPath:backupfile handler:nil]) return; //can't create backup
|
||||
}
|
||||
//write the new file
|
||||
if(![fm createFileAtPath:file contents:[result dataUsingEncoding:NSASCIIStringEncoding] attributes:nil]) return; //can't create new file
|
||||
//remove the backup
|
||||
if(backupfile) [fm removeFileAtPath:backupfile handler:nil];
|
||||
}
|
||||
|
||||
- (void)serverTerminated
|
||||
{
|
||||
if(server==-1) return;
|
||||
- (void)killServer {
|
||||
if(server > 0) kill(server, SIGKILL); //@WARNING - you do NOT want a 0 or -1 to be accidentally sent a kill!
|
||||
server = -1;
|
||||
[multiplayer setTitle:@"Start"];
|
||||
[multiplayer setTitle:NSLocalizedString(@"Start", @"")];
|
||||
[console appendText:@"\n \n"];
|
||||
}
|
||||
|
||||
- (void)setServerActive:(BOOL)start
|
||||
{
|
||||
if((server==-1) != start) return;
|
||||
|
||||
if(!start)
|
||||
{ //STOP
|
||||
|
||||
//damn server, terminate isn't good enough for you - die, die, die...
|
||||
if((server!=-1) && (server!=0)) kill(server, SIGKILL); //@WARNING - you do not want a 0 or -1 to be accidentally sent a kill!
|
||||
[self serverTerminated];
|
||||
}
|
||||
else
|
||||
{ //START
|
||||
NSString *cwd = [self cwd];
|
||||
NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
|
||||
|
||||
NSArray *opts = [[defs nonNullStringForKey:@"server_options"] componentsSeparatedByString:@" "];
|
||||
|
||||
const char *childCwd = [cwd fileSystemRepresentation];
|
||||
const char *childPath = [[cwd stringByAppendingPathComponent:@"actioncube.app/Contents/MacOS/actioncube"] fileSystemRepresentation];
|
||||
const char **args = (const char**)malloc(sizeof(char*)*([opts count] + 3 + 3)); //3 = {path, -d, NULL}, and +3 again for optional settings...
|
||||
int i, fdm, argc = 0;
|
||||
|
||||
args[argc++] = childPath;
|
||||
args[argc++] = "-d";
|
||||
|
||||
for(i = 0; i < [opts count]; i++)
|
||||
{
|
||||
NSString *opt = [opts objectAtIndex:i];
|
||||
if([opt length] == 0) continue; //skip empty
|
||||
args[argc++] = [opt UTF8String];
|
||||
}
|
||||
|
||||
NSString *desc = [[NSUserDefaults standardUserDefaults] nonNullStringForKey:@"server_description"];
|
||||
if (![desc isEqualToString:@""]) args[argc++] = [[NSString stringWithFormat:@"-n%@", desc] UTF8String];
|
||||
|
||||
NSString *pass = [[NSUserDefaults standardUserDefaults] nonNullStringForKey:@"server_password"];
|
||||
if (![pass isEqualToString:@""]) args[argc++] = [[NSString stringWithFormat:@"-x%@", pass] UTF8String];
|
||||
|
||||
int clients = [[NSUserDefaults standardUserDefaults] integerForKey:@"server_maxclients"];
|
||||
if (clients > 0) args[argc++] = [[NSString stringWithFormat:@"-c%d", clients] UTF8String];
|
||||
|
||||
args[argc++] = NULL;
|
||||
|
||||
switch ( (server = forkpty(&fdm, NULL, NULL, NULL)) ) // forkpty so we can reliably grab SDL console
|
||||
{
|
||||
case -1:
|
||||
[console appendLine:@"Error - can't launch server"];
|
||||
[self serverTerminated];
|
||||
break;
|
||||
case 0: // child
|
||||
chdir(childCwd);
|
||||
execv(childPath, (char*const*)args);
|
||||
fprintf(stderr, "Error - can't launch server\n");
|
||||
_exit(0);
|
||||
default: // parent
|
||||
free(args);
|
||||
//fprintf(stderr, "fdm=%d\n", slave_name, fdm);
|
||||
[multiplayer setTitle:@"Stop"];
|
||||
|
||||
NSFileHandle *taskOutput = [[NSFileHandle alloc] initWithFileDescriptor:fdm];
|
||||
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
|
||||
[nc addObserver:self selector:@selector(serverDataAvailable:) name:NSFileHandleReadCompletionNotification object:taskOutput];
|
||||
[taskOutput readInBackgroundAndNotify];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)serverDataAvailable:(NSNotification *)note
|
||||
{
|
||||
NSFileHandle *taskOutput = [note object];
|
||||
@@ -413,7 +376,7 @@ static int numberForKey(CFDictionaryRef desc, CFStringRef key)
|
||||
|
||||
if (data && [data length])
|
||||
{
|
||||
NSString *text = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
|
||||
NSString *text = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
|
||||
[console appendText:text];
|
||||
[text release];
|
||||
[taskOutput readInBackgroundAndNotify]; //wait for more data
|
||||
@@ -423,105 +386,324 @@ static int numberForKey(CFDictionaryRef desc, CFStringRef key)
|
||||
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
|
||||
[nc removeObserver:self name:NSFileHandleReadCompletionNotification object:taskOutput];
|
||||
close([taskOutput fileDescriptor]);
|
||||
[self setServerActive:NO];
|
||||
[self killServer];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)playFile
|
||||
- (BOOL)launchGame:(NSArray *)args {
|
||||
NSString *cwd = [Launcher cwd];
|
||||
NSString *exe = [[NSBundle bundleWithPath:[cwd stringByAppendingPathComponent:[@":s.app" expand]]] executablePath];
|
||||
|
||||
BOOL okay = YES;
|
||||
|
||||
if([args containsObject:@"-d"])
|
||||
{
|
||||
if(server != -1) return NO; // server is already running
|
||||
|
||||
const char **argv = (const char**)malloc(sizeof(char*)*([args count] + 2)); //{path, <args>, NULL};
|
||||
argv[0] = [exe fileSystemRepresentation];
|
||||
argv[[args count]+1] = NULL;
|
||||
int i;
|
||||
for(i = 0; i < [args count]; i++) argv[i+1] = [[args objectAtIndex:i] UTF8String];
|
||||
|
||||
int fdm;
|
||||
NSString *fail = [NSLocalizedString(@"ServerAlertMesg", nil) expand];
|
||||
switch ( (server = forkpty(&fdm, NULL, NULL, NULL)) ) // forkpty so we can reliably grab SDL console
|
||||
{
|
||||
case -1:
|
||||
[console appendLine:fail];
|
||||
[self killServer];
|
||||
okay = NO;
|
||||
break;
|
||||
case 0: // child
|
||||
chdir([cwd fileSystemRepresentation]);
|
||||
if(execv([exe fileSystemRepresentation], (char*const*)argv) == -1) fprintf(stderr, "%s\n", [fail UTF8String]);
|
||||
_exit(0);
|
||||
default: // parent
|
||||
[multiplayer setTitle:NSLocalizedString(@"Stop", @"")];
|
||||
NSFileHandle *taskOutput = [[NSFileHandle alloc] initWithFileDescriptor:fdm];
|
||||
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
|
||||
[nc addObserver:self selector:@selector(serverDataAvailable:) name:NSFileHandleReadCompletionNotification object:taskOutput];
|
||||
[taskOutput readInBackgroundAndNotify];
|
||||
break;
|
||||
}
|
||||
free(argv);
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_DURING
|
||||
NSTask *task = [[NSTask alloc] init];
|
||||
[task setCurrentDirectoryPath:cwd];
|
||||
[task setLaunchPath:exe];
|
||||
[task setArguments:args];
|
||||
[task setEnvironment:[NSDictionary dictionaryWithObjectsAndKeys:
|
||||
@"1", @"SDL_SINGLEDISPLAY",
|
||||
@"1", @"SDL_ENABLEAPPEVENTS", nil
|
||||
]]; // makes Command-H, Command-M and Command-Q work at least when not in fullscreen
|
||||
|
||||
[task launch];
|
||||
if(server == -1) [NSApp terminate:self]; //if there is a server then don't exit!
|
||||
NS_HANDLER
|
||||
//NSLog(@"%@", localException);
|
||||
NSBeginCriticalAlertSheet(
|
||||
[NSLocalizedString(@"ClientAlertTitle", @"") expand] , nil, nil, nil,
|
||||
window, nil, nil, nil, nil,
|
||||
[NSLocalizedString(@"ClientAlertMesg", @"") expand]);
|
||||
okay = NO;
|
||||
NS_ENDHANDLER
|
||||
}
|
||||
|
||||
return okay;
|
||||
}
|
||||
|
||||
/*
|
||||
* nil will just launch the fps game
|
||||
* "-rpg" will launch the rpg demo
|
||||
* "-x.." will launch and run commands
|
||||
* otherwise we are specifying a map to play
|
||||
*/
|
||||
- (BOOL)playFile:(id)filename
|
||||
{
|
||||
NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
|
||||
|
||||
NSArray *res = [[resolutions titleOfSelectedItem] componentsSeparatedByString:@" x "];
|
||||
NSMutableArray *args = [[NSMutableArray alloc] init];
|
||||
NSString *cwd = [self cwd];
|
||||
NSMutableArray *args = [NSMutableArray array];
|
||||
|
||||
//suppose could use this to update gamma and keys too, but can't be bothered...
|
||||
[self updateAutoexecFile:[NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[defs nonNullStringForKey:@"name"], @"name",
|
||||
nil]];
|
||||
|
||||
[args addObject:[NSString stringWithFormat:@"-w%@", [res objectAtIndex:0]]];
|
||||
[args addObject:[NSString stringWithFormat:@"-h%@", [res objectAtIndex:1]]];
|
||||
[args addObject:@"-z32"];
|
||||
[args addObject:@"-z32"]; //otherwise seems to have a fondness to use -z16 which looks crap
|
||||
|
||||
if([defs integerForKey:@"fullscreen"] == 0) [args addObject:@"-t"];
|
||||
[args addObject:[NSString stringWithFormat:@"-a%d", [defs integerForKey:@"fsaa"]]];
|
||||
[args addObject:[NSString stringWithFormat:@"-f%d", [defs integerForKey:@"shader"]]];
|
||||
if([defs integerForKey:dkFULLSCREEN] == 0) [args addObject:@"-t"];
|
||||
[args addObject:[NSString stringWithFormat:@"-a%d", [defs integerForKey:dkFSAA]]];
|
||||
|
||||
if ([stencil state] == NSOnState) [args addObject:@"-z8"];
|
||||
|
||||
NSString *adv = [defs nonNullStringForKey:@"advancedOptions"];
|
||||
if(![adv isEqual:@""]) [args addObjectsFromArray:[adv componentsSeparatedByString:@" "]];
|
||||
[args addObject:[NSString stringWithFormat:@"--home=%@", [Launcher userdir]]];
|
||||
|
||||
NSMutableArray *cmds = [NSMutableArray array];
|
||||
if(forcename) [cmds addObject:[NSString stringWithFormat:@"name \"%@\"", NSUserName()]];
|
||||
|
||||
NSTask *task = [[NSTask alloc] init];
|
||||
[task setCurrentDirectoryPath:cwd];
|
||||
[task setLaunchPath:[cwd stringByAppendingPathComponent:@"actioncube.app/Contents/MacOS/actioncube"]];
|
||||
[task setArguments:args];
|
||||
[task setEnvironment:[NSDictionary dictionaryWithObjectsAndKeys:
|
||||
@"1", @"SDL_SINGLEDISPLAY",
|
||||
@"1", @"SDL_ENABLEAPPEVENTS", nil
|
||||
]]; // makes Command-H, Command-M and Command-Q work at least when not in fullscreen
|
||||
[args release];
|
||||
|
||||
BOOL okay = YES;
|
||||
|
||||
NS_DURING
|
||||
[task launch];
|
||||
if(server==-1) [NSApp terminate:self]; //if there is a server then don't exit!
|
||||
NS_HANDLER
|
||||
//NSLog(@"%@", localException);
|
||||
NSBeginCriticalAlertSheet(
|
||||
@"Can't start AssaultCube", nil, nil, nil,
|
||||
window, nil, nil, nil, nil,
|
||||
@"Please move the directory containing AssaultCube to a path that doesn't contain weird characters or start AssaultCube manually.");
|
||||
okay = NO;
|
||||
NS_ENDHANDLER
|
||||
|
||||
return okay;
|
||||
if(filename)
|
||||
{
|
||||
if([filename isEqual:@"-rpg"]) {
|
||||
[cmds removeAllObjects]; // rpg current doesn't require name/team
|
||||
[args addObject:@"-grpg"]; //demo the rpg game
|
||||
} else if([filename hasPrefix:@"-x"])
|
||||
[cmds addObject:[filename substringFromIndex:2]];
|
||||
else
|
||||
[args addObject:[NSString stringWithFormat:@"-l%@", filename]];
|
||||
}
|
||||
|
||||
if([cmds count] > 0)
|
||||
{
|
||||
NSString *script = [cmds objectAtIndex:0];
|
||||
int i;
|
||||
for(i = 1; i < [cmds count]; i++) script = [NSString stringWithFormat:@"%@;%@", script, [cmds objectAtIndex:i]];
|
||||
[args addObject:[NSString stringWithFormat:@"-x%@", script]];
|
||||
}
|
||||
|
||||
NSEnumerator *e = [[[defs nonNullStringForKey:dkADVANCEDOPTS] componentsSeparatedByString:@" "] objectEnumerator];
|
||||
NSString *opt;
|
||||
while(opt = [e nextObject]) if([opt length] != 0) [args addObject:opt]; //skip empty ones
|
||||
|
||||
return [self launchGame:args];
|
||||
}
|
||||
|
||||
- (void)scanMaps:(id)obj //@note threaded!
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
int i;
|
||||
for(i = 0; i < 2; i++)
|
||||
{
|
||||
NSString *dir = (i==0) ? [Launcher cwd] : [Launcher userdir];
|
||||
NSDirectoryEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtPath:dir];
|
||||
NSString *file;
|
||||
while(file = [enumerator nextObject])
|
||||
{
|
||||
NSString *role = [fileRoles objectForKey:[file pathExtension]];
|
||||
if(role)
|
||||
{
|
||||
Map *map = [[Map alloc] initWithPath:[dir stringByAppendingPathComponent:file] user:(i==1) demo:[role isEqual:@"Viewer"]];
|
||||
[maps performSelectorOnMainThread:@selector(addObject:) withObject:map waitUntilDone:NO];
|
||||
}
|
||||
}
|
||||
}
|
||||
[prog performSelectorOnMainThread:@selector(stopAnimation:) withObject:nil waitUntilDone:NO];
|
||||
[pool release];
|
||||
}
|
||||
|
||||
- (void)initMaps
|
||||
{
|
||||
[prog startAnimation:nil];
|
||||
[maps removeObjects:[maps arrangedObjects]];
|
||||
[NSThread detachNewThreadSelector: @selector(scanMaps:) toTarget:self withObject:nil];
|
||||
}
|
||||
|
||||
- (void)awakeFromNib
|
||||
{
|
||||
[self initViews];
|
||||
//generate some pretty icons if they are missing
|
||||
NSRect region = NSMakeRect(0, 0, 64, 64);
|
||||
NSImage *image = [NSImage imageNamed:tkMAIN];
|
||||
if(!image) {
|
||||
image = [[NSImage imageNamed:@"NSApplicationIcon"] copy];
|
||||
[image setSize:region.size];
|
||||
[image setName:tkMAIN]; //one less image to include
|
||||
}
|
||||
|
||||
[self initToolBar];
|
||||
[window setBackgroundColor:[NSColor colorWithDeviceRed:0.90 green:0.90 blue:0.90 alpha:1.0]]; //Apples 'mercury' crayon color
|
||||
|
||||
//from the plist we determine that dmo->Viewer, and ogz->Editor
|
||||
fileRoles = [[NSMutableDictionary dictionary] retain];
|
||||
NSEnumerator *types = [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDocumentTypes"] objectEnumerator];
|
||||
NSDictionary *type;
|
||||
while((type = [types nextObject])) {
|
||||
NSString *role = [type objectForKey:@"CFBundleTypeRole"];
|
||||
NSEnumerator *exts = [[type objectForKey:@"CFBundleTypeExtensions"] objectEnumerator];
|
||||
NSString *ext;
|
||||
while((ext = [exts nextObject])) [fileRoles setObject:role forKey:ext];
|
||||
}
|
||||
|
||||
NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
|
||||
NSFileManager *fm = [NSFileManager defaultManager];
|
||||
|
||||
NSString *appVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"];
|
||||
NSString *version = [defs stringForKey:dkVERSION];
|
||||
if(!version || ![version isEqual:appVersion])
|
||||
{
|
||||
NSLog(@"Upgraded Version...");
|
||||
//need to flush lurking config files - they're automatically generated, so no big deal...
|
||||
NSString *dir = [Launcher userdir];
|
||||
[fm removeFileAtPath:[dir stringByAppendingPathComponent:@"init.cfg"] handler:nil];
|
||||
[fm removeFileAtPath:[dir stringByAppendingPathComponent:@"config.cfg"] handler:nil];
|
||||
}
|
||||
[defs setObject:appVersion forKey:dkVERSION];
|
||||
|
||||
NSDictionary *dict = [self readConfigFiles];
|
||||
[keys addObjects:[self getKeys:dict]];
|
||||
NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
|
||||
if([[defs nonNullStringForKey:@"name"] isEqual:@""])
|
||||
{
|
||||
NSString *name = [dict objectForKey:@"name"];
|
||||
if([name isEqual:@""] || [name isEqual:@"unnamed"]) name = NSUserName();
|
||||
[defs setValue:name forKey:@"name"];
|
||||
}
|
||||
|
||||
|
||||
//encourage people not to remain unnamed
|
||||
NSString *name = [dict objectForKey:@"name"];
|
||||
forcename = (!name || [name isEqual:@""] || [name isEqual:@"unnamed"]);
|
||||
|
||||
[self initMaps];
|
||||
[self initResolutions];
|
||||
server = -1;
|
||||
[window setDelegate:self]; // so can catch the window close
|
||||
[NSApp setDelegate:self]; //so can catch the double-click & dropped files
|
||||
[NSApp setDelegate:self]; //so can catch the double-click, dropped files, termination
|
||||
[[NSAppleEventManager sharedAppleEventManager] setEventHandler:self andSelector:@selector(getUrl:withReplyEvent:) forEventClass:kInternetEventClass andEventID:kAEGetURL];
|
||||
}
|
||||
|
||||
-(void)windowWillClose:(NSNotification *)notification
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark application delegate
|
||||
|
||||
- (void)applicationDidFinishLaunching:(NSNotification *)note {
|
||||
NSFileManager *fm = [NSFileManager defaultManager];
|
||||
NSString *dir = [Launcher cwd];
|
||||
if(![fm fileExistsAtPath:dir])
|
||||
NSBeginCriticalAlertSheet(
|
||||
[NSLocalizedString(@"InitAlertTitle", @"") expand], nil, nil, nil,
|
||||
window, self, nil, nil, nil,
|
||||
[NSLocalizedString(@"InitAlertMesg", @"") expand]);
|
||||
}
|
||||
|
||||
-(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)applicationWillTerminate: (NSNotification *)note {
|
||||
[self killServer];
|
||||
}
|
||||
|
||||
//we register 'ogz' and 'dmo' as doc types
|
||||
- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
|
||||
{
|
||||
[self setServerActive:NO];
|
||||
[NSApp terminate:self];
|
||||
NSString *role = [fileRoles objectForKey:[filename pathExtension]];
|
||||
if(!role) return NO;
|
||||
BOOL demo = [role isEqual:@"Viewer"];
|
||||
filename = [filename stringByDeletingPathExtension]; //chop off extension
|
||||
int i;
|
||||
for(i = 0; i < 2; i++) {
|
||||
NSString *pkg = (i == 0) ? [Launcher cwd] : [Launcher userdir];
|
||||
if(!demo) pkg = [pkg stringByAppendingPathComponent:@"packages"];
|
||||
if([filename hasPrefix:pkg])
|
||||
return [self playFile:(demo ? [NSString stringWithFormat:@"-xdemo \"%@\"", filename] : filename)];
|
||||
}
|
||||
NSBeginCriticalAlertSheet(
|
||||
[NSLocalizedString(@"FileAlertMesg", @"") expand], NSLocalizedString(@"Ok", @""), NSLocalizedString(@"Cancel", @""), nil,
|
||||
window, self, @selector(openPackageFolder:returnCode:contextInfo:), nil, nil,
|
||||
[NSLocalizedString(@"FileAlertMesg", @"") expand]);
|
||||
return NO;
|
||||
}
|
||||
|
||||
/*
|
||||
* Interface actions
|
||||
*/
|
||||
- (void)openPackageFolder:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
|
||||
{
|
||||
if(returnCode == 0) return;
|
||||
[self openUserdir:nil];
|
||||
}
|
||||
|
||||
//we register 'sauerbraten' as a url scheme
|
||||
- (void)getUrl:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent
|
||||
{
|
||||
NSURL *url = [NSURL URLWithString:[[event paramDescriptorForKeyword:keyDirectObject] stringValue]];
|
||||
if(!url) return;
|
||||
[self playFile:[NSString stringWithFormat:@"-xconnect %@", [url host]]];
|
||||
}
|
||||
|
||||
#pragma mark interface actions
|
||||
|
||||
- (IBAction)multiplayerAction:(id)sender
|
||||
{
|
||||
[window makeFirstResponder:window]; //ensure fields are exited and committed
|
||||
[self setServerActive:(server==-1)];
|
||||
if(server != -1)
|
||||
{
|
||||
[self killServer];
|
||||
}
|
||||
else
|
||||
{
|
||||
NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
|
||||
|
||||
NSMutableArray *args = [NSMutableArray arrayWithObject:@"-d"];
|
||||
|
||||
NSEnumerator *e = [[[defs nonNullStringForKey:dkSERVEROPTS] componentsSeparatedByString:@" "] objectEnumerator];
|
||||
NSString *opt;
|
||||
while(opt = [e nextObject]) if([opt length] != 0) [args addObject:opt]; //skip empty ones
|
||||
|
||||
NSString *desc = [defs nonNullStringForKey:dkDESCRIPTION];
|
||||
if (![desc isEqual:@""]) [args addObject:[NSString stringWithFormat:@"-n%@", desc]];
|
||||
|
||||
NSString *pass = [defs nonNullStringForKey:dkPASSWORD];
|
||||
if (![pass isEqual:@""]) [args addObject:[NSString stringWithFormat:@"-p%@", pass]];
|
||||
|
||||
int clients = [defs integerForKey:dkMAXCLIENTS];
|
||||
if (clients > 0) [args addObject:[NSString stringWithFormat:@"-c%d", clients]];
|
||||
|
||||
[args addObject:[NSString stringWithFormat:@"-q%@", [Launcher userdir]]];
|
||||
|
||||
[self launchGame:args];
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction)playAction:(id)sender
|
||||
{
|
||||
[window makeFirstResponder:window]; //ensure fields are exited and committed
|
||||
[self playFile];
|
||||
[self playFile:nil];
|
||||
}
|
||||
|
||||
- (IBAction)helpAction:(id)sender
|
||||
{
|
||||
NSString *file = [[[[NSBundle mainBundle] bundlePath] stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"README.html"];
|
||||
[[NSWorkspace sharedWorkspace] openURL:[NSURL fileURLWithPath:file]];
|
||||
- (IBAction)playRpg:(id)sender
|
||||
{
|
||||
[self playFile:@"-rpg"];
|
||||
}
|
||||
@end
|
||||
|
||||
- (IBAction)playMap:(id)sender
|
||||
{
|
||||
NSArray *sel = [maps selectedObjects];
|
||||
if(sel && [sel count] > 0) [self playFile:[[sel objectAtIndex:0] path]];
|
||||
}
|
||||
|
||||
- (IBAction)openUserdir:(id)sender
|
||||
{
|
||||
[[NSWorkspace sharedWorkspace] openFile:[Launcher userdir]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>actioncube</string>
|
||||
<string>assaultcube</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
B96D0D590920970C00B6C936 /* Launcher.m in Sources */ = {isa = PBXBuildFile; fileRef = B96D0D580920970C00B6C936 /* Launcher.m */; };
|
||||
B96D0D630920971300B6C936 /* MainMenu.nib in Resources */ = {isa = PBXBuildFile; fileRef = B96D0D5A0920971300B6C936 /* MainMenu.nib */; };
|
||||
B96D0D6D0920976E00B6C936 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = B96D0D6C0920976E00B6C936 /* main.m */; };
|
||||
B975E7F40EBCC3A200880D5D /* map.icns in Resources */ = {isa = PBXBuildFile; fileRef = B975E7F30EBCC3A200880D5D /* map.icns */; };
|
||||
B98944640EA68F70003CC623 /* shadow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B98944630EA68F70003CC623 /* shadow.cpp */; };
|
||||
B9FA3B420DD9E6C900581F8D /* worldrender.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B9FA3B090DD9E6C900581F8D /* worldrender.cpp */; };
|
||||
B9FA3B430DD9E6C900581F8D /* editing.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B9FA3B0A0DD9E6C900581F8D /* editing.cpp */; };
|
||||
@@ -154,12 +155,13 @@
|
||||
B2F67ED704C74A3F00A80002 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = /System/Library/Frameworks/OpenGL.framework; sourceTree = "<absolute>"; };
|
||||
B92DC0F909D08CF9008219BD /* SDL_image.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL_image.framework; path = /Library/Frameworks/SDL_image.framework; sourceTree = "<absolute>"; };
|
||||
B92DC0FB09D08CF9008219BD /* SDL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL.framework; path = /Library/Frameworks/SDL.framework; sourceTree = "<absolute>"; };
|
||||
B94198CB09207E810029DAD1 /* actioncube.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = actioncube.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
B94198CB09207E810029DAD1 /* assaultcube.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = assaultcube.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
B96D0D4C092096F200B6C936 /* launcher.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = launcher.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
B96D0D570920970C00B6C936 /* Launcher.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Launcher.h; sourceTree = "<group>"; };
|
||||
B96D0D580920970C00B6C936 /* Launcher.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = Launcher.m; sourceTree = "<group>"; };
|
||||
B96D0D5B0920971300B6C936 /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/MainMenu.nib; sourceTree = "<group>"; };
|
||||
B96D0D6C0920976E00B6C936 /* main.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
B975E7F30EBCC3A200880D5D /* map.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = map.icns; sourceTree = "<group>"; };
|
||||
B98944630EA68F70003CC623 /* shadow.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = shadow.cpp; sourceTree = "<group>"; };
|
||||
B9CACA12092099DF00A13F04 /* launcher-Info.plist */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.plist.xml; path = "launcher-Info.plist"; sourceTree = "<group>"; };
|
||||
B9FA3B090DD9E6C900581F8D /* worldrender.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = worldrender.cpp; sourceTree = "<group>"; };
|
||||
@@ -292,7 +294,7 @@
|
||||
19C28FACFE9D520D11CA2CBB /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B94198CB09207E810029DAD1 /* actioncube.app */,
|
||||
B94198CB09207E810029DAD1 /* assaultcube.app */,
|
||||
B96D0D4C092096F200B6C936 /* launcher.app */,
|
||||
);
|
||||
name = Products;
|
||||
@@ -327,6 +329,7 @@
|
||||
B96D0D5A0920971300B6C936 /* MainMenu.nib */,
|
||||
089C165CFE840E0CC02AAC07 /* InfoPlist.strings */,
|
||||
665CDD4A0AFE7FBD0030D605 /* actioncube.icns */,
|
||||
B975E7F30EBCC3A200880D5D /* map.icns */,
|
||||
66899EA80C14887F00927C34 /* Help.tiff */,
|
||||
66899EA90C14887F00927C34 /* Keys.gif */,
|
||||
66899EAA0C14887F00927C34 /* Main.gif */,
|
||||
@@ -485,9 +488,9 @@
|
||||
/* End PBXHeadersBuildPhase section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
B941988A09207E810029DAD1 /* actioncube */ = {
|
||||
B941988A09207E810029DAD1 /* assaultcube */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = B94198C609207E810029DAD1 /* Build configuration list for PBXNativeTarget "actioncube" */;
|
||||
buildConfigurationList = B94198C609207E810029DAD1 /* Build configuration list for PBXNativeTarget "assaultcube" */;
|
||||
buildPhases = (
|
||||
B941988B09207E810029DAD1 /* Headers */,
|
||||
B94198A409207E810029DAD1 /* Resources */,
|
||||
@@ -500,10 +503,10 @@
|
||||
dependencies = (
|
||||
B96D0D790920980E00B6C936 /* PBXTargetDependency */,
|
||||
);
|
||||
name = actioncube;
|
||||
name = assaultcube;
|
||||
productInstallPath = "$(HOME)/Applications";
|
||||
productName = sauerbraten;
|
||||
productReference = B94198CB09207E810029DAD1 /* actioncube.app */;
|
||||
productReference = B94198CB09207E810029DAD1 /* assaultcube.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
B96D0D4B092096F200B6C936 /* launcher */ = {
|
||||
@@ -533,9 +536,9 @@
|
||||
hasScannedForEncodings = 1;
|
||||
mainGroup = 29B97314FDCFA39411CA2CEA /* sauerbraten */;
|
||||
projectDirPath = "";
|
||||
projectRoot = ..;
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
B941988A09207E810029DAD1 /* actioncube */,
|
||||
B941988A09207E810029DAD1 /* assaultcube */,
|
||||
B96D0D4B092096F200B6C936 /* launcher */,
|
||||
);
|
||||
};
|
||||
@@ -562,6 +565,7 @@
|
||||
66899EB90C14898500927C34 /* Server.gif in Resources */,
|
||||
B90357B509D09B9D002C9DC7 /* InfoPlist.strings in Resources */,
|
||||
665CDFD20AFE90F30030D605 /* actioncube.icns in Resources */,
|
||||
B975E7F40EBCC3A200880D5D /* map.icns in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -579,7 +583,7 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "echo $TARGET_BUILD_DIR\ncd $TARGET_BUILD_DIR\n\n#make the directory which our disk image will be made of\nmkdir AssaultCube\nmkdir AssaultCube/assaultcube\n\n#copy sauerbraten there\n/Developer/Tools/CpMac -r $TARGET_BUILD_DIR/actioncube.app AssaultCube/assaultcube\n/Developer/Tools/CpMac -r $TARGET_BUILD_DIR/launcher.app AssaultCube/\nmv AssaultCube/launcher.app AssaultCube/AssaultCube.app\nstrip -u -r $TARGET_BUILD_DIR/AssaultCube/assaultcube/actioncube.app/Contents/MacOS/actioncube -o $TARGET_BUILD_DIR/AssaultCube/assaultcube/actioncube.app/Contents/MacOS/actioncube_stripped\nmv $TARGET_BUILD_DIR/AssaultCube/assaultcube/actioncube.app/Contents/MacOS/actioncube $TARGET_BUILD_DIR/actioncube_nonstripped\nmv $TARGET_BUILD_DIR/AssaultCube/assaultcube/actioncube.app/Contents/MacOS/actioncube_stripped $TARGET_BUILD_DIR/AssaultCube/assaultcube/actioncube.app/Contents/MacOS/actioncube\ncp $SRCROOT/../../README.html $TARGET_BUILD_DIR/AssaultCube/\n\n#install all frameworks into app bundle\nmkdir AssaultCube/assaultcube/actioncube.app/Contents/Frameworks\nfor framework in SDL.framework SDL_image.framework Ogg.framework Vorbis.framework\ndo\n\tif [ -d $LOCAL_LIBRARY_DIR/Frameworks/$framework/ ] \n\tthen\t\n\t\t/Developer/Tools/CpMac -r $LOCAL_LIBRARY_DIR/Frameworks/$framework/ AssaultCube/assaultcube/actioncube.app/Contents/Frameworks\n\t\trm -rf AssaultCube/assaultcube/actioncube.app/Contents/Frameworks/$framework/Versions/A/Headers\n\telse\n\t\texit 1\n\tfi\ndone\n\n#copy readme and data and remove unneccesary stuff\n/Developer/Tools/CpMac -r $SRCROOT/../../docs AssaultCube/\n/Developer/Tools/CpMac -r $SRCROOT/../../bot AssaultCube/assaultcube/\n/Developer/Tools/CpMac -r $SRCROOT/../../config AssaultCube/assaultcube/\n/Developer/Tools/CpMac -r $SRCROOT/../../packages AssaultCube/assaultcube/\nrm -rf AssaultCube/docs/CVS/\nrm -rf AssaultCube/docs/*/CVS/\nrm -rf AssaultCube/docs/*/*/CVS/\nrm -f AssaultCube/docs/.DS_Store\nrm -f AssaultCube/docs/*/.DS_Store\nrm -f AssaultCube/docs/*/*/.DS_Store\nrm -rf AssaultCube/assaultcube/packages/CVS/\nrm -rf AssaultCube/assaultcube/packages/*/CVS/\nrm -rf AssaultCube/assaultcube/packages/*/*/CVS/\nrm -f AssaultCube/assaultcube/packages/.DS_Store\nrm -f AssaultCube/assaultcube/packages/*/.DS_Store\nrm -f AssaultCube/assaultcube/packages/*/*/.DS_Store\nrm -rf AssaultCube/assaultcube/config/CVS/\nrm -f AssaultCube/assaultcube/config/.DS_Store\nrm -rf AssaultCube/assaultcube/bot/CVS/\nrm -rf AssaultCube/assaultcube/bot/*/CVS/\nrm -f AssaultCube/assaultcube/bot/.DS_Store\nrm -f AssaultCube/assaultcube/bot/*/.DS_Store\nrm -rf AssaultCube/assaultcube/data/CVS/\nrm -rf AssaultCube/assaultcube/data/*/CVS/\nrm -f AssaultCube/assaultcube/data/.DS_Store\nrm -f AssaultCube/assaultcube/data/*/.DS_Store\n\n#finally make a disk image out of the stuff\nhdiutil create -srcfolder AssaultCube AssaultCube.dmg\nhdiutil internet-enable -yes AssaultCube.dmg\n\n#cleanup\nrm -r AssaultCube";
|
||||
shellScript = "echo $TARGET_BUILD_DIR\ncd $TARGET_BUILD_DIR\n\n#ensure old package is gone\nrm -f assaultcube.dmg\n\n#make the directory which our disk image will be made of\n#use /tmp as a destination because copying ourself (xcode folder) whilst compling causes the dog to chase its tail\nACPKG=`mktemp -d /tmp/acpkg.XXXXXX` || exit 1\n\n#leave indicator of where temp directory is in case things break\nln -sf $ACPKG $TARGET_BUILD_DIR/acpkg\n\n#copy launcher\n/Developer/Tools/CpMac -r $TARGET_BUILD_DIR/launcher.app $ACPKG/AssaultCube.app\n\nHELPDIR=$ACPKG/AssaultCube.app/Contents/Resources/help/\nGAMEDIR=$ACPKG/AssaultCube.app/Contents/gamedata\nmkdir $GAMEDIR\nmkdir $HELPDIR\n\n#copy assaultcube\n/Developer/Tools/CpMac -r $TARGET_BUILD_DIR/assaultcube.app $GAMEDIR/\nstrip -u -r $GAMEDIR/assaultcube.app/Contents/MacOS/assaultcube\n\n#install all frameworks into app bundle\nmkdir $GAMEDIR/assaultcube.app/Contents/Frameworks\nfor framework in SDL.framework SDL_image.framework Ogg.framework Vorbis.framework\ndo\n\tif [ -d $LOCAL_LIBRARY_DIR/Frameworks/$framework/ ] \n\tthen\t\n\t\t/Developer/Tools/CpMac -r $LOCAL_LIBRARY_DIR/Frameworks/$framework/ $GAMEDIR/assaultcube.app/Contents/Frameworks\n\t\trm -rf $GAMEDIR/assaultcube.app/Contents/Frameworks/$framework/Versions/A/Headers\n\telse\n\t\texit 1\n\tfi\ndone\n\n\n#copy readme and data and remove unneccesary stuff\n/Developer/Tools/CpMac -r $SRCROOT/../../README.html $HELPDIR/\n/Developer/Tools/CpMac -r $SRCROOT/../../docs $HELPDIR/\n/Developer/Tools/CpMac -r $SRCROOT/../../bot $GAMEDIR/\n/Developer/Tools/CpMac -r $SRCROOT/../../config $GAMEDIR/\n/Developer/Tools/CpMac -r $SRCROOT/../../screenshots $GAMEDIR/\n/Developer/Tools/CpMac -r $SRCROOT/../../mods $GAMEDIR/\n/Developer/Tools/CpMac -r $SRCROOT/../../packages $GAMEDIR/\n/Developer/Tools/CpMac -r $SRCROOT/../../source $ACPKG/sourcecode\nfind -d $ACPKG -name \"CVS\" -exec rm -rf {} \\;\nfind $ACPKG -name \".DS_Store\" -exec rm -f {} \\;\nrm -rf $ACPKG/sourcecode/xcode/build\n\n#add alias to readme\n/usr/bin/osascript <<EOT\ntell application \"Finder\"\nset macSrcPath to POSIX file \"$HELPDIR/README.html\" as text\nset macDestPath to POSIX file \"$ACPKG\" as text\nmake new alias file to file macSrcPath at folder macDestPath\nend tell\nEOT\n\n#finally make a disk image out of the stuff\nhdiutil create -srcfolder $ACPKG -volname assaultcube assaultcube.dmg\nhdiutil internet-enable -yes assaultcube.dmg\n\n#cleanup\nrm -rf $ACPKG";
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
@@ -696,7 +700,7 @@
|
||||
);
|
||||
INFOPLIST_FILE = "actioncube-Info.plist";
|
||||
OTHER_LDFLAGS = "-lz";
|
||||
PRODUCT_NAME = actioncube;
|
||||
PRODUCT_NAME = assaultcube;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -712,7 +716,7 @@
|
||||
);
|
||||
INFOPLIST_FILE = "actioncube-Info.plist";
|
||||
OTHER_LDFLAGS = "-lz";
|
||||
PRODUCT_NAME = actioncube;
|
||||
PRODUCT_NAME = assaultcube;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
@@ -731,7 +735,7 @@
|
||||
);
|
||||
INFOPLIST_FILE = "actioncube-Info.plist";
|
||||
OTHER_LDFLAGS = "-lz";
|
||||
PRODUCT_NAME = actioncube;
|
||||
PRODUCT_NAME = assaultcube;
|
||||
};
|
||||
name = "Release-Deployment";
|
||||
};
|
||||
@@ -889,7 +893,7 @@
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
B94198C609207E810029DAD1 /* Build configuration list for PBXNativeTarget "actioncube" */ = {
|
||||
B94198C609207E810029DAD1 /* Build configuration list for PBXNativeTarget "assaultcube" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
B94198C709207E810029DAD1 /* Debug */,
|
||||
|
||||
@@ -1,7 +1,42 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDocumentTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>dmo</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>map.icns</string>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>AssaultCube demo</string>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
<key>LSTypeIsPackage</key>
|
||||
<false/>
|
||||
<key>NSPersistentStoreTypeKey</key>
|
||||
<string>Binary</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>cgz</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>map.icns</string>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>AssaultCube map</string>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>LSTypeIsPackage</key>
|
||||
<false/>
|
||||
<key>NSPersistentStoreTypeKey</key>
|
||||
<string>Binary</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#define _MAXDEFSTR 260
|
||||
#define MAXSTRLEN 260
|
||||
inline char *s_strncpy(char *d, const char *s, size_t m) { strncpy(d,s,m); d[m-1] = 0; return d; };
|
||||
inline char *s_strcat(char *d, const char *s) { size_t n = strlen(d); return s_strncpy(d+n,s,_MAXDEFSTR-n); };
|
||||
inline char *s_strcat(char *d, const char *s) { size_t n = strlen(d); return s_strncpy(d+n,s,MAXSTRLEN-n); };
|
||||
|
||||
void mac_pasteconsole(char *commandbuf)
|
||||
{
|
||||
@@ -13,4 +13,16 @@ void mac_pasteconsole(char *commandbuf)
|
||||
if (contents != nil)
|
||||
s_strcat(commandbuf, [contents lossyCString]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 0x1030 = 10.3
|
||||
* 0x1040 = 10.4
|
||||
* 0x1050 = 10.5
|
||||
*/
|
||||
int mac_osversion()
|
||||
{
|
||||
SInt32 MacVersion;
|
||||
Gestalt(gestaltSystemVersion, &MacVersion);
|
||||
return MacVersion;
|
||||
}
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user