Can now load named worlds from beta 1.3

Used Godzil's 3ecd8a418f95e73c60890e13e5e09614234ea1df to load from folder and added the ability to save worlds and list all worlds in minecraft/saves/
This commit is contained in:
Nick Loose 2011-03-10 19:39:20 +01:00
parent 708c880361
commit 9345b2cc7b
5 changed files with 345 additions and 328 deletions

View File

@ -16,9 +16,10 @@
@interface IJInventoryWindowController : NSWindowController <NSWindowDelegate, IJInventoryViewDelegate> {
IJMinecraftLevel *level;
IJMinecraftLevel *player;
NSArray *inventory;
NSSegmentedControl *worldSelectionControl;
NSPopUpButton *worldSelectionControl;
NSTextField *statusTextField;
IJInventoryView *inventoryView;
@ -43,10 +44,11 @@
// Document
int64_t sessionLockValue;
int loadedWorldIndex;
int attemptedLoadWorldIndex;
NSString *loadedWorldFolder;
NSString *attemptedLoadWorldFolder;
}
@property (nonatomic, assign) IBOutlet NSSegmentedControl *worldSelectionControl;
@property (nonatomic, assign) IBOutlet NSPopUpButton *worldSelectionControl;
@property (nonatomic, assign) IBOutlet NSTextField *statusTextField;
@property (nonatomic, assign) IBOutlet IJInventoryView *inventoryView;
@property (nonatomic, assign) IBOutlet IJInventoryView *quickView;
@ -56,6 +58,7 @@
@property (nonatomic, retain) NSNumber *worldTime;
- (IBAction)menuSelectWorldFromPath:(id)sender;
- (IBAction)menuSelectWorld:(id)sender;
- (IBAction)worldSelectionChanged:(id)sender;
- (IBAction)updateItemSearchFilter:(id)sender;

View File

@ -18,6 +18,8 @@
- (void)saveWorld;
- (void)loadWorldAtIndex:(int)worldIndex;
- (BOOL)isDocumentEdited;
- (void)loadWorldAtFolder:(NSString *)worldFolder;
- (void)loadWorldSelectionControl;
@end
@implementation IJInventoryWindowController
@ -30,6 +32,8 @@
- (void)awakeFromNib
{
[self loadWorldSelectionControl];
armorInventory = [[NSMutableArray alloc] init];
quickInventory = [[NSMutableArray alloc] init];
normalInventory = [[NSMutableArray alloc] init];
@ -50,7 +54,6 @@
[itemTableView setTarget:self];
[itemTableView setDoubleAction:@selector(itemTableViewDoubleClicked:)];
}
- (void)dealloc
@ -72,27 +75,27 @@
{
if (returnCode == NSAlertOtherReturn) // Cancel
{
[worldSelectionControl setSelectedSegment:loadedWorldIndex-1];
[worldSelectionControl selectItemWithTitle:[loadedWorldFolder lastPathComponent]];
return;
}
if (returnCode == NSAlertDefaultReturn) // Save
{
[self saveWorld];
[self loadWorldAtIndex:attemptedLoadWorldIndex];
[self loadWorldAtFolder:attemptedLoadWorldFolder];
}
else if (returnCode == NSAlertAlternateReturn) // Don't save
{
[self setDocumentEdited:NO];// Slightly hacky -- prevent the alert from being put up again.
[self loadWorldAtIndex:attemptedLoadWorldIndex];
[self loadWorldAtFolder:attemptedLoadWorldFolder];
}
}
- (void)loadWorldAtIndex:(int)worldIndex
- (void)loadWorldAtFolder:(NSString *)worldPath
{
if ([self isDocumentEdited])
{
attemptedLoadWorldIndex = worldIndex;
attemptedLoadWorldFolder = worldPath;
NSBeginInformationalAlertSheet(@"Do you want to save the changes you made in this world?", @"Save", @"Don't Save", @"Cancel", self.window, self, @selector(dirtyLoadSheetDidEnd:returnCode:contextInfo:), nil, nil, @"Your changes will be lost if you do not save them.");
return;
}
@ -113,24 +116,19 @@
[self didChangeValueForKey:@"worldTime"];
statusTextField.stringValue = @"No world loaded.";
NSString *levelPath = [IJMinecraftLevel pathForLevelDatAtFolder:worldPath];
NSData *fileData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:levelPath]];
if (![IJMinecraftLevel worldExistsAtIndex:worldIndex])
{
NSBeginCriticalAlertSheet(@"No world exists in that slot.", @"Dismiss", nil, nil, self.window, nil, nil, nil, nil, @"Please create a new single player world in this slot using Minecraft and try again.");
return;
}
sessionLockValue = [IJMinecraftLevel writeToSessionLockAtIndex:worldIndex];
if (![IJMinecraftLevel checkSessionLockAtIndex:worldIndex value:sessionLockValue])
sessionLockValue = [IJMinecraftLevel writeToSessionLockAtFolder:worldPath];
if (![IJMinecraftLevel checkSessionLockAtFolder:worldPath value:sessionLockValue])
{
NSBeginCriticalAlertSheet(@"Error loading world.", @"Dismiss", nil, nil, self.window, nil, nil, nil, nil, @"Inside Job was unable obtain the session lock.");
return;
}
NSString *levelPath = [IJMinecraftLevel pathForLevelDatAtIndex:worldIndex];
NSData *fileData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:levelPath]];
if (!fileData)
{
// Error loading
@ -140,9 +138,21 @@
[self willChangeValueForKey:@"worldTime"];
level = [[IJMinecraftLevel nbtContainerWithData:fileData] retain];
inventory = [[level inventory] retain];
/* Now search for first player .dat file (but by default try to load from level.dat */
NSString *playerPath = [IJMinecraftLevel pathForLevelDatAtFolder:worldPath];
NSData *playerFileData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:playerPath]];
if (!fileData)
{
// Error loading
NSBeginCriticalAlertSheet(@"Error loading world.", @"Dismiss", nil, nil, self.window, nil, nil, nil, nil, @"InsideJob was unable to load the level at %@.", levelPath);
return;
}
level = [[IJMinecraftLevel nbtContainerWithData:fileData] retain];
player = [[IJMinecraftLevel nbtContainerWithData:playerFileData] retain];
inventory = [[player inventory] retain];
[self didChangeValueForKey:@"worldTime"];
// Add placeholder inventory items:
@ -184,22 +194,39 @@
[self setDocumentEdited:NO];
statusTextField.stringValue = @"";
loadedWorldIndex = worldIndex;
loadedWorldFolder = [worldPath retain];
NSLog(@"%@",loadedWorldFolder);
NSLog(@"%@",worldPath);
}
- (void)loadWorldAtIndex:(int)worldIndex
{
NSString *worldPath;
worldPath = [IJMinecraftLevel pathForWorldAtIndex:worldIndex];
[self loadWorldAtFolder: worldPath];
}
- (void)saveWorld
{
int worldIndex = loadedWorldIndex;
NSString *worldPath = loadedWorldFolder;
if (inventory == nil)
return; // no world loaded, nothing to save
if (![IJMinecraftLevel checkSessionLockAtIndex:worldIndex value:sessionLockValue])
if (![IJMinecraftLevel checkSessionLockAtFolder:worldPath value:sessionLockValue])
{
NSBeginCriticalAlertSheet(@"Another application has modified this world.", @"Dismiss", nil, nil, self.window, nil, nil, nil, nil, @"The session lock was changed by another application.");
return;
}
NSString *levelPath = [IJMinecraftLevel pathForLevelDatAtIndex:worldIndex];
NSString *levelPath = [worldPath stringByAppendingPathComponent:@"level.dat"];
NSMutableArray *newInventory = [NSMutableArray array];
@ -284,13 +311,90 @@
{
int worldIndex = [sender tag];
[self loadWorldAtIndex:worldIndex];
[worldSelectionControl setSelectedSegment:worldIndex - 1];
[worldSelectionControl selectItemWithTitle:[loadedWorldFolder lastPathComponent]];
}
- (IBAction)menuSelectWorldFromPath:(id)sender
{
NSInteger openResult;
/* Ask user for world folder path */
NSOpenPanel *panel = [NSOpenPanel openPanel];
NSString *worldPath;
/* Only allow to choose a folder */
[panel setCanChooseDirectories:YES];
[panel setCanChooseFiles:NO];
openResult = [panel runModal];
if (openResult == NSOKButton)
{
worldPath = [[panel directoryURL] path];
/* Verify for level.dat */
if (![IJMinecraftLevel worldExistsAtFolder: worldPath])
{
NSBeginCriticalAlertSheet(@"No world exists in that slot.", @"Dismiss", nil, nil, self.window, nil, nil, nil, nil, @"Please create a new single player world in this slot using Minecraft and try again.");
return;
}
/* Now try to open the world... */
[self loadWorldAtFolder:[[panel directoryURL] path]];
[worldSelectionControl addItemWithTitle:[loadedWorldFolder lastPathComponent]];
[worldSelectionControl selectItemWithTitle:[loadedWorldFolder lastPathComponent]];
}
}
- (IBAction)worldSelectionChanged:(id)sender
{
int worldIndex = [worldSelectionControl selectedSegment] + 1;
[self loadWorldAtIndex:worldIndex];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
NSString *path = [paths objectAtIndex:0];
path = [path stringByAppendingPathComponent:@"minecraft"];
path = [path stringByAppendingPathComponent:@"saves"];
NSString* worldName = [worldSelectionControl titleOfSelectedItem];
NSString* worldPath = [path stringByAppendingPathComponent:worldName];
NSLog(@"loadedWorldFolder: %@",loadedWorldFolder);
NSLog(@"worldName: %@",worldName);
NSLog(@"worldPath: %@",worldPath);
[self loadWorldAtFolder:worldPath];
}
- (void)loadWorldSelectionControl
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
NSString *path = [paths objectAtIndex:0];
path = [path stringByAppendingPathComponent:@"minecraft"];
path = [path stringByAppendingPathComponent:@"saves"];
NSFileManager *filemgr;
NSArray *filelist;
NSError *fileError;
int count;
int i;
filemgr = [NSFileManager defaultManager];
filelist = [filemgr contentsOfDirectoryAtPath:path error:&fileError];
count = [filelist count];
[worldSelectionControl removeAllItems];
for (i = 0; i < count; i++)
{
NSLog (@"%@", [filelist objectAtIndex: i]);
if([IJMinecraftLevel worldExistsAtFolder:[path stringByAppendingPathComponent:[filelist objectAtIndex: i]]])
[worldSelectionControl addItemWithTitle:[filelist objectAtIndex: i]];
}
[filemgr release];
}
- (void)saveDocument:(id)sender

View File

@ -4,26 +4,28 @@
//
// Created by Adam Preble on 10/7/10.
// Copyright 2010 Adam Preble. All rights reserved.
// Changes for opening folder Copyright 2011 Manoel Trapier
//
#import <Cocoa/Cocoa.h>
#import "NBTContainer.h"
@interface IJMinecraftLevel : NBTContainer {
}
@property (nonatomic, copy) NSArray *inventory; // Array of IJInventoryItem objects.
@property (nonatomic, readonly) NBTContainer *worldTimeContainer;
+ (NSString *)pathForWorldAtIndex:(int)worldIndex;
+ (NSString *)pathForLevelDatAtIndex:(int)worldIndex;
+ (NSString *)pathForSessionLockAtIndex:(int)worldIndex;
+ (BOOL)worldExistsAtIndex:(int)worldIndex;
+ (NSString *)pathForLevelDatAtFolder:(NSString *)worldPath;
+ (NSString *)pathForSessionLockAtFolder:(NSString *)worldPath;
+ (int64_t)writeToSessionLockAtIndex:(int)worldIndex;
+ (BOOL)checkSessionLockAtIndex:(int)worldIndex value:(int64_t)checkValue;
+ (BOOL)worldExistsAtFolder:(NSString *)worldPath;
+ (int64_t)writeToSessionLockAtFolder:(NSString *)worldPath;
+ (BOOL)checkSessionLockAtFolder:(NSString *)worldPath value:(int64_t)checkValue;
@end
@end

View File

@ -4,6 +4,7 @@
//
// Created by Adam Preble on 10/7/10.
// Copyright 2010 Adam Preble. All rights reserved.
// Changes for opening folder Copyright 2011 Manoel Trapier
//
#import "IJMinecraftLevel.h"
@ -41,7 +42,7 @@
for (NSArray *listItems in [self inventoryList].children)
{
IJInventoryItem *invItem = [[IJInventoryItem alloc] init];
invItem.itemId = [[self containerWithName:@"id" inArray:listItems].numberValue shortValue];
invItem.count = [[self containerWithName:@"Count" inArray:listItems].numberValue unsignedCharValue];
invItem.damage = [[self containerWithName:@"Damage" inArray:listItems].numberValue shortValue];
@ -56,7 +57,7 @@
{
NSMutableArray *newChildren = [NSMutableArray array];
NBTContainer *inventoryList = [self inventoryList];
if (inventoryList.listType != NBTTypeCompound)
{
// There appears to be a bug in the way Minecraft writes empty inventory lists; it appears to
@ -64,7 +65,7 @@
NSLog(@"%s Fixing inventory list type; was %d.", __PRETTY_FUNCTION__, inventoryList.listType);
inventoryList.listType = NBTTypeCompound;
}
for (IJInventoryItem *invItem in newInventory)
{
NSArray *listItems = [NSArray arrayWithObjects:
@ -96,20 +97,6 @@
return path;
}
+ (NSString *)pathForLevelDatAtIndex:(int)worldIndex
{
return [[[self class] pathForWorldAtIndex:worldIndex] stringByAppendingPathComponent:@"level.dat"];
}
+ (NSString *)pathForSessionLockAtIndex:(int)worldIndex
{
return [[[self class] pathForWorldAtIndex:worldIndex] stringByAppendingPathComponent:@"session.lock"];
}
+ (BOOL)worldExistsAtIndex:(int)worldIndex
{
return [[NSFileManager defaultManager] fileExistsAtPath:[[self class] pathForLevelDatAtIndex:worldIndex]];
}
+ (NSData *)dataWithInt64:(int64_t)v
{
NSMutableData *data = [NSMutableData data];
@ -128,31 +115,47 @@
return n;
}
+ (int64_t)writeToSessionLockAtIndex:(int)worldIndex
/******************************************************************************/
+ (NSString *)pathForLevelDatAtFolder:(NSString *)worldPath
{
NSString *path = [IJMinecraftLevel pathForSessionLockAtIndex:worldIndex];
return [worldPath stringByAppendingPathComponent:@"level.dat"];
}
+ (NSString *)pathForSessionLockAtFolder:(NSString *)worldPath
{
return [worldPath stringByAppendingPathComponent:@"session.lock"];
}
+ (BOOL)worldExistsAtFolder:(NSString *)worldPath
{
return [[NSFileManager defaultManager] fileExistsAtPath:[[self class] pathForLevelDatAtFolder:worldPath]];
}
+ (int64_t)writeToSessionLockAtFolder:(NSString *)worldPath
{
NSString *path = [IJMinecraftLevel pathForSessionLockAtFolder:worldPath];
NSDate *now = [NSDate date];
NSTimeInterval interval = [now timeIntervalSince1970];
int64_t milliseconds = (int64_t)(interval * 1000.0);
// write as number of milliseconds
NSData *data = [IJMinecraftLevel dataWithInt64:milliseconds];
[data writeToFile:path atomically:YES];
return milliseconds;
}
+ (BOOL)checkSessionLockAtIndex:(int)worldIndex value:(int64_t)checkValue
+ (BOOL)checkSessionLockAtFolder:(NSString *)worldPath value:(int64_t)checkValue
{
NSString *path = [IJMinecraftLevel pathForSessionLockAtIndex:worldIndex];
NSString *path = [IJMinecraftLevel pathForSessionLockAtFolder:worldPath];
NSData *data = [NSData dataWithContentsOfFile:path];
if (!data)
{
NSLog(@"Failed to read session lock at %@", path);
return NO;
}
int64_t milliseconds = [IJMinecraftLevel int64FromData:data];
return checkValue == milliseconds;
}

View File

@ -12,25 +12,25 @@
</object>
<object class="NSArray" key="IBDocument.IntegratedClassDependencies">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>NSTableColumn</string>
<string>NSSegmentedControl</string>
<string>NSPopUpButtonCell</string>
<string>NSNumberFormatter</string>
<string>NSScroller</string>
<string>NSMenuItem</string>
<string>NSMenu</string>
<string>NSTextFieldCell</string>
<string>NSScrollView</string>
<string>NSPopUpButton</string>
<string>NSBox</string>
<string>NSImageCell</string>
<string>NSSearchField</string>
<string>NSTableView</string>
<string>NSSearchFieldCell</string>
<string>NSCustomView</string>
<string>NSCustomObject</string>
<string>NSSegmentedCell</string>
<string>NSView</string>
<string>NSWindowTemplate</string>
<string>NSTextField</string>
<string>NSCustomView</string>
<string>NSTableColumn</string>
</object>
<object class="NSArray" key="IBDocument.PluginDependencies">
<bool key="EncodedWithXMLCoder">YES</bool>
@ -205,70 +205,14 @@
<string key="NSTitle">World</string>
<object class="NSMutableArray" key="NSMenuItems">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSMenuItem" id="511556069">
<object class="NSMenuItem" id="230766171">
<reference key="NSMenu" ref="720053764"/>
<string key="NSTitle">Open</string>
<string key="NSKeyEquiv"/>
<string key="NSKeyEquiv">o</string>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="35465992"/>
<reference key="NSMixedImage" ref="502551668"/>
<string key="NSAction">submenuAction:</string>
<object class="NSMenu" key="NSSubmenu" id="640710760">
<string key="NSTitle">Open</string>
<object class="NSMutableArray" key="NSMenuItems">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSMenuItem" id="772770630">
<reference key="NSMenu" ref="640710760"/>
<string key="NSTitle">World 1</string>
<string key="NSKeyEquiv">1</string>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="35465992"/>
<reference key="NSMixedImage" ref="502551668"/>
<int key="NSTag">1</int>
</object>
<object class="NSMenuItem" id="136087423">
<reference key="NSMenu" ref="640710760"/>
<string key="NSTitle">World 2</string>
<string key="NSKeyEquiv">2</string>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="35465992"/>
<reference key="NSMixedImage" ref="502551668"/>
<int key="NSTag">2</int>
</object>
<object class="NSMenuItem" id="398683472">
<reference key="NSMenu" ref="640710760"/>
<string key="NSTitle">World 3</string>
<string key="NSKeyEquiv">3</string>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="35465992"/>
<reference key="NSMixedImage" ref="502551668"/>
<int key="NSTag">3</int>
</object>
<object class="NSMenuItem" id="695170288">
<reference key="NSMenu" ref="640710760"/>
<string key="NSTitle">World 4</string>
<string key="NSKeyEquiv">4</string>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="35465992"/>
<reference key="NSMixedImage" ref="502551668"/>
<int key="NSTag">4</int>
</object>
<object class="NSMenuItem" id="788037042">
<reference key="NSMenu" ref="640710760"/>
<string key="NSTitle">World 5</string>
<string key="NSKeyEquiv">5</string>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="35465992"/>
<reference key="NSMixedImage" ref="502551668"/>
<int key="NSTag">5</int>
</object>
</object>
</object>
</object>
<object class="NSMenuItem" id="1023925487">
<reference key="NSMenu" ref="720053764"/>
@ -793,55 +737,6 @@
<int key="NSTitlePosition">0</int>
<bool key="NSTransparent">NO</bool>
</object>
<object class="NSSegmentedControl" id="626341130">
<reference key="NSNextResponder" ref="439893737"/>
<int key="NSvFlags">268</int>
<string key="NSFrame">{{11, 364}, {195, 25}}</string>
<reference key="NSSuperview" ref="439893737"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="574149520"/>
<bool key="NSEnabled">YES</bool>
<object class="NSSegmentedCell" key="NSCell" id="587756353">
<int key="NSCellFlags">67239424</int>
<int key="NSCellFlags2">0</int>
<object class="NSFont" key="NSSupport">
<string key="NSName">LucidaGrande</string>
<double key="NSSize">13</double>
<int key="NSfFlags">16</int>
</object>
<reference key="NSControlView" ref="626341130"/>
<object class="NSMutableArray" key="NSSegmentImages">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSSegmentItem">
<string key="NSSegmentItemLabel">World 1</string>
<int key="NSSegmentItemTag">1</int>
<bool key="NSSegmentItemSelected">YES</bool>
<int key="NSSegmentItemImageScaling">0</int>
</object>
<object class="NSSegmentItem">
<string key="NSSegmentItemLabel">2</string>
<int key="NSSegmentItemTag">2</int>
<int key="NSSegmentItemImageScaling">0</int>
</object>
<object class="NSSegmentItem">
<string key="NSSegmentItemLabel">3</string>
<int key="NSSegmentItemTag">3</int>
<int key="NSSegmentItemImageScaling">0</int>
</object>
<object class="NSSegmentItem">
<string key="NSSegmentItemLabel">4</string>
<int key="NSSegmentItemTag">4</int>
<int key="NSSegmentItemImageScaling">0</int>
</object>
<object class="NSSegmentItem">
<string key="NSSegmentItemLabel">5</string>
<int key="NSSegmentItemTag">5</int>
<int key="NSSegmentItemImageScaling">0</int>
</object>
</object>
<int key="NSSegmentStyle">2</int>
</object>
</object>
<object class="NSCustomView" id="30251356">
<reference key="NSNextResponder" ref="439893737"/>
<int key="NSvFlags">268</int>
@ -1153,7 +1048,6 @@
<string key="NSFrame">{{1, 382}, {190, 15}}</string>
<reference key="NSSuperview" ref="896048265"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView"/>
<int key="NSsFlags">1</int>
<reference key="NSTarget" ref="896048265"/>
<string key="NSAction">_doScroller:</string>
@ -1170,13 +1064,81 @@
<reference key="NSContentView" ref="666454848"/>
<bytes key="NSScrollAmts">QSAAAEEgAABBmAAAQZgAAA</bytes>
</object>
<object class="NSPopUpButton" id="957906746">
<reference key="NSNextResponder" ref="439893737"/>
<int key="NSvFlags">268</int>
<string key="NSFrame">{{11, 363}, {172, 25}}</string>
<reference key="NSSuperview" ref="439893737"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="574149520"/>
<bool key="NSEnabled">YES</bool>
<object class="NSPopUpButtonCell" key="NSCell" id="263349888">
<int key="NSCellFlags">-2080244160</int>
<int key="NSCellFlags2">2048</int>
<reference key="NSSupport" ref="731765667"/>
<reference key="NSControlView" ref="957906746"/>
<int key="NSButtonFlags">-2035269377</int>
<int key="NSButtonFlags2">35</int>
<string key="NSAlternateContents"/>
<string key="NSKeyEquivalent"/>
<int key="NSPeriodicDelay">400</int>
<int key="NSPeriodicInterval">75</int>
<object class="NSMenuItem" key="NSMenuItem" id="299440734">
<reference key="NSMenu" ref="1027841374"/>
<string key="NSTitle">Item 1</string>
<string key="NSKeyEquiv"/>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<int key="NSState">1</int>
<reference key="NSOnImage" ref="35465992"/>
<reference key="NSMixedImage" ref="502551668"/>
<string key="NSAction">_popUpItemAction:</string>
<reference key="NSTarget" ref="263349888"/>
</object>
<bool key="NSMenuItemRespectAlignment">YES</bool>
<object class="NSMenu" key="NSMenu" id="1027841374">
<string key="NSTitle">OtherViews</string>
<object class="NSMutableArray" key="NSMenuItems">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="299440734"/>
<object class="NSMenuItem" id="313633293">
<reference key="NSMenu" ref="1027841374"/>
<string key="NSTitle">Item 2</string>
<string key="NSKeyEquiv"/>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="35465992"/>
<reference key="NSMixedImage" ref="502551668"/>
<string key="NSAction">_popUpItemAction:</string>
<reference key="NSTarget" ref="263349888"/>
</object>
<object class="NSMenuItem" id="900150611">
<reference key="NSMenu" ref="1027841374"/>
<string key="NSTitle">Item 3</string>
<string key="NSKeyEquiv"/>
<int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="35465992"/>
<reference key="NSMixedImage" ref="502551668"/>
<string key="NSAction">_popUpItemAction:</string>
<reference key="NSTarget" ref="263349888"/>
</object>
</object>
<reference key="NSMenuFont" ref="731765667"/>
</object>
<int key="NSPreferredEdge">2</int>
<bool key="NSUsesItemFromMenu">YES</bool>
<bool key="NSAltersState">YES</bool>
<int key="NSArrowPosition">2</int>
</object>
</object>
</object>
<string key="NSFrame">{{7, 11}, {585, 396}}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="626341130"/>
<reference key="NSNextKeyView" ref="957906746"/>
</object>
<string key="NSScreenRect">{{0, 0}, {1440, 878}}</string>
<string key="NSScreenRect">{{0, 0}, {1920, 1178}}</string>
<string key="NSMaxSize">{1e+13, 1e+13}</string>
<string key="NSFrameAutosaveName">MainWindow</string>
</object>
@ -1377,22 +1339,6 @@
</object>
<int key="connectionID">593</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">worldSelectionControl</string>
<reference key="source" ref="760161335"/>
<reference key="destination" ref="626341130"/>
</object>
<int key="connectionID">603</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">worldSelectionChanged:</string>
<reference key="source" ref="760161335"/>
<reference key="destination" ref="626341130"/>
</object>
<int key="connectionID">604</int>
</object>
<object class="IBConnectionRecord">
<object class="IBBindingConnection" key="connection">
<string key="label">value: worldTime</string>
@ -1489,46 +1435,6 @@
</object>
<int key="connectionID">670</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">menuSelectWorld:</string>
<reference key="source" ref="760161335"/>
<reference key="destination" ref="772770630"/>
</object>
<int key="connectionID">680</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">menuSelectWorld:</string>
<reference key="source" ref="760161335"/>
<reference key="destination" ref="136087423"/>
</object>
<int key="connectionID">681</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">menuSelectWorld:</string>
<reference key="source" ref="760161335"/>
<reference key="destination" ref="398683472"/>
</object>
<int key="connectionID">682</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">menuSelectWorld:</string>
<reference key="source" ref="760161335"/>
<reference key="destination" ref="695170288"/>
</object>
<int key="connectionID">683</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">menuSelectWorld:</string>
<reference key="source" ref="760161335"/>
<reference key="destination" ref="788037042"/>
</object>
<int key="connectionID">684</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">setNextDay:</string>
@ -1585,6 +1491,30 @@
</object>
<int key="connectionID">722</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">menuSelectWorldFromPath:</string>
<reference key="source" ref="760161335"/>
<reference key="destination" ref="230766171"/>
</object>
<int key="connectionID">731</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">worldSelectionControl</string>
<reference key="source" ref="760161335"/>
<reference key="destination" ref="957906746"/>
</object>
<int key="connectionID">738</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">worldSelectionChanged:</string>
<reference key="source" ref="760161335"/>
<reference key="destination" ref="957906746"/>
</object>
<int key="connectionID">739</int>
</object>
</object>
<object class="IBMutableOrderedSet" key="objectRecords">
<object class="NSArray" key="orderedObjects">
@ -1851,8 +1781,6 @@
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="263108995"/>
<reference ref="574149520"/>
<reference ref="626341130"/>
<reference ref="17633893"/>
<reference ref="896048265"/>
<reference ref="30251356"/>
@ -1860,6 +1788,8 @@
<reference ref="784892978"/>
<reference ref="395301483"/>
<reference ref="924742053"/>
<reference ref="574149520"/>
<reference ref="957906746"/>
</object>
<reference key="parent" ref="972006081"/>
</object>
@ -1957,20 +1887,6 @@
<reference key="object" ref="263108995"/>
<reference key="parent" ref="439893737"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">600</int>
<reference key="object" ref="626341130"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="587756353"/>
</object>
<reference key="parent" ref="439893737"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">601</int>
<reference key="object" ref="587756353"/>
<reference key="parent" ref="626341130"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">641</int>
<reference key="object" ref="30251356"/>
@ -2101,59 +2017,12 @@
<reference key="object" ref="720053764"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="511556069"/>
<reference ref="579971712"/>
<reference ref="1023925487"/>
<reference ref="230766171"/>
</object>
<reference key="parent" ref="379814623"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">672</int>
<reference key="object" ref="511556069"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="640710760"/>
</object>
<reference key="parent" ref="720053764"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">673</int>
<reference key="object" ref="640710760"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="788037042"/>
<reference ref="695170288"/>
<reference ref="398683472"/>
<reference ref="136087423"/>
<reference ref="772770630"/>
</object>
<reference key="parent" ref="511556069"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">679</int>
<reference key="object" ref="788037042"/>
<reference key="parent" ref="640710760"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">678</int>
<reference key="object" ref="695170288"/>
<reference key="parent" ref="640710760"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">677</int>
<reference key="object" ref="398683472"/>
<reference key="parent" ref="640710760"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">676</int>
<reference key="object" ref="136087423"/>
<reference key="parent" ref="640710760"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">674</int>
<reference key="object" ref="772770630"/>
<reference key="parent" ref="640710760"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">112</int>
<reference key="object" ref="579971712"/>
@ -2265,6 +2134,55 @@
<reference key="object" ref="19459331"/>
<reference key="parent" ref="433773752"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">732</int>
<reference key="object" ref="957906746"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="263349888"/>
</object>
<reference key="parent" ref="439893737"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">733</int>
<reference key="object" ref="263349888"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="1027841374"/>
</object>
<reference key="parent" ref="957906746"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">734</int>
<reference key="object" ref="1027841374"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="299440734"/>
<reference ref="313633293"/>
<reference ref="900150611"/>
</object>
<reference key="parent" ref="263349888"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">735</int>
<reference key="object" ref="299440734"/>
<reference key="parent" ref="1027841374"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">736</int>
<reference key="object" ref="313633293"/>
<reference key="parent" ref="1027841374"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">737</int>
<reference key="object" ref="900150611"/>
<reference key="parent" ref="1027841374"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">730</int>
<reference key="object" ref="230766171"/>
<reference key="parent" ref="720053764"/>
</object>
</object>
</object>
<object class="NSMutableDictionary" key="flattenedProperties">
@ -2369,10 +2287,6 @@
<string>597.IBViewBoundsToFrameTransform</string>
<string>598.IBPluginDependency</string>
<string>599.IBPluginDependency</string>
<string>600.IBPluginDependency</string>
<string>600.IBViewBoundsToFrameTransform</string>
<string>601.IBPluginDependency</string>
<string>601.IBSegmentedControlInspectorSelectedSegmentMetadataKey</string>
<string>641.IBPluginDependency</string>
<string>641.IBViewBoundsToFrameTransform</string>
<string>643.IBPluginDependency</string>
@ -2397,14 +2311,6 @@
<string>667.IBPluginDependency</string>
<string>669.IBPluginDependency</string>
<string>671.IBPluginDependency</string>
<string>672.IBPluginDependency</string>
<string>673.IBEditorWindowLastContentRect</string>
<string>673.IBPluginDependency</string>
<string>674.IBPluginDependency</string>
<string>676.IBPluginDependency</string>
<string>677.IBPluginDependency</string>
<string>678.IBPluginDependency</string>
<string>679.IBPluginDependency</string>
<string>696.IBPluginDependency</string>
<string>701.IBEditorWindowLastContentRect</string>
<string>701.IBPluginDependency</string>
@ -2422,6 +2328,9 @@
<string>726.IBPluginDependency</string>
<string>727.IBEditorWindowLastContentRect</string>
<string>727.IBPluginDependency</string>
<string>730.IBPluginDependency</string>
<string>732.IBPluginDependency</string>
<string>733.IBPluginDependency</string>
<string>75.IBPluginDependency</string>
<string>75.ImportedFromIB2</string>
<string>81.IBEditorWindowLastContentRect</string>
@ -2547,12 +2456,6 @@
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABDiYAAw82AAA</bytes>
</object>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<integer value="0"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform">
<bytes key="NSTransformStruct">AUKcAABDFQAAA</bytes>
</object>
@ -2585,14 +2488,6 @@
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>{{661, 733}, {127, 103}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>{{585, 1083}, {193, 53}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
@ -2610,6 +2505,9 @@
<string>{{778, 1023}, {189, 83}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<integer value="1"/>
<string>{{483, 773}, {178, 63}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
@ -2633,7 +2531,7 @@
<reference key="dict.values" ref="0"/>
</object>
<nil key="sourceID"/>
<int key="maxID">728</int>
<int key="maxID">739</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<object class="NSMutableArray" key="referencedPartialClassDescriptions">
@ -2658,6 +2556,7 @@
<string>loadInventoryItems:</string>
<string>makeSearchFieldFirstResponder:</string>
<string>menuSelectWorld:</string>
<string>menuSelectWorldFromPath:</string>
<string>saveInventoryItems:</string>
<string>setNextDay:</string>
<string>setNextMidnight:</string>
@ -2680,6 +2579,7 @@
<string>id</string>
<string>id</string>
<string>id</string>
<string>id</string>
</object>
</object>
<object class="NSMutableDictionary" key="actionInfosByName">
@ -2691,6 +2591,7 @@
<string>loadInventoryItems:</string>
<string>makeSearchFieldFirstResponder:</string>
<string>menuSelectWorld:</string>
<string>menuSelectWorldFromPath:</string>
<string>saveInventoryItems:</string>
<string>setNextDay:</string>
<string>setNextMidnight:</string>
@ -2721,6 +2622,10 @@
<string key="name">menuSelectWorld:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo">
<string key="name">menuSelectWorldFromPath:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo">
<string key="name">saveInventoryItems:</string>
<string key="candidateClassName">id</string>
@ -2771,7 +2676,7 @@
<string>NSTableView</string>
<string>IJInventoryView</string>
<string>NSTextField</string>
<string>NSSegmentedControl</string>
<string>NSPopUpButton</string>
</object>
</object>
<object class="NSMutableDictionary" key="toOneOutletInfosByName">
@ -2814,7 +2719,7 @@
</object>
<object class="IBToOneOutletInfo">
<string key="name">worldSelectionControl</string>
<string key="candidateClassName">NSSegmentedControl</string>
<string key="candidateClassName">NSPopUpButton</string>
</object>
</object>
</object>