Change backen for loading world, now use folder path as index instead of slot id.

This commit is contained in:
Manoël Trapier 2011-03-05 15:29:54 +01:00
parent caff4127c2
commit 3ecd8a418f
13 changed files with 3038 additions and 691 deletions

View File

@ -16,6 +16,7 @@
@interface IJInventoryWindowController : NSWindowController <NSWindowDelegate, IJInventoryViewDelegate> {
IJMinecraftLevel *level;
IJMinecraftLevel *player; /***< SMP Player.dat file use same format as level.dat */
NSArray *inventory;
NSSegmentedControl *worldSelectionControl;
@ -42,8 +43,9 @@
// Document
int64_t sessionLockValue;
int loadedWorldIndex;
int attemptedLoadWorldIndex;
int loadedWorldIndex;
NSString *loadedWorldFolder;
NSString *attemptedLoadWorldFolder;
}
@property (nonatomic, assign) IBOutlet NSSegmentedControl *worldSelectionControl;
@ -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

@ -16,6 +16,7 @@
@interface IJInventoryWindowController ()
- (void)saveWorld;
- (void)loadWorldAtIndex:(int)worldIndex;
- (void)loadWorldAtFolder:(NSString *)worldFolder;
- (BOOL)isDocumentEdited;
@end
@ -77,20 +78,29 @@
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)loadWorldPlayerInventory:(NSString *)PlayerName
{
/*
* If passing NULL to PlayerName, we will use level.dat instead of
* Players/PlayerName.dat file
*/
}
- (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;
}
@ -111,22 +121,9 @@
[self didChangeValueForKey:@"worldTime"];
statusTextField.stringValue = @"No world loaded.";
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])
{
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];
NSString *levelPath = [IJMinecraftLevel pathForLevelDatAtFolder:worldPath];
NSData *fileData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:levelPath]];
if (!fileData)
@ -138,8 +135,19 @@
[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"];
@ -173,8 +181,8 @@
}
}
// NSLog(@"normal: %@", normalInventory);
// NSLog(@"quick: %@", quickInventory);
// NSLog(@"normal: %@", normalInventory);
// NSLog(@"quick: %@", quickInventory);
[inventoryView setItems:normalInventory];
[quickView setItems:quickInventory];
@ -182,11 +190,21 @@
[self setDocumentEdited:NO];
statusTextField.stringValue = @"";
loadedWorldIndex = worldIndex;
loadedWorldFolder = worldPath;
}
- (void)loadWorldAtIndex:(int)worldIndex
{
NSString *worldPath;
worldPath = [IJMinecraftLevel pathForWorldAtIndex:worldIndex];
[self loadWorldAtFolder: worldPath];
}
- (void)saveWorld
{
#if 0
int worldIndex = loadedWorldIndex;
if (inventory == nil)
return; // no world loaded, nothing to save
@ -260,6 +278,7 @@
[self setDocumentEdited:NO];
statusTextField.stringValue = @"Saved.";
#endif
}
- (void)setDocumentEdited:(BOOL)edited
@ -284,6 +303,34 @@
[worldSelectionControl setSelectedSegment:worldIndex - 1];
}
- (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]];
}
}
- (IBAction)worldSelectionChanged:(id)sender
{
int worldIndex = [worldSelectionControl selectedSegment] + 1;

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 <Cocoa/Cocoa.h>
@ -17,13 +18,14 @@
@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

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"
@ -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,9 +115,25 @@
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);
@ -142,11 +145,11 @@
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);

View File

@ -1,11 +1,14 @@
{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf320
{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf350
{\fonttbl\f0\fnil\fcharset0 LucidaGrande;}
{\colortbl;\red255\green255\blue255;}
\vieww9000\viewh8400\viewkind0
\paperw12240\paperh15840\vieww9000\viewh8400\viewkind0
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
\f0\fs20 \cf0 A Minecraft Inventory Editor\
\f0\fs20 \cf0 A Minecraft Inventory Editor - SMP Friendly Version\
\
{\field{\*\fldinst{HYPERLINK "http://github.com/godzil/InsideJob"}}{\fldrslt http://github.com/godzil/InsideJob}}\
\
Forked from original version by Adam Preble:\
{\field{\*\fldinst{HYPERLINK "http://adampreble.net"}}{\fldrslt http://adampreble.net}}\
{\field{\*\fldinst{HYPERLINK "http://github.com/preble/InsideJob"}}{\fldrslt http://github.com/preble/InsideJob}}\
\

View File

@ -1,2 +1,5 @@
/* Localized versions of Info.plist keys */
"No world loaded." = "No world loaded.";
"No world exists in that slot." = "No world exists in that slot.";
"Dismiss" = "Dismiss";
"Please create a new single player world in this slot using Minecraft and try again." = "Please create a new single player world in this slot using Minecraft and try again.";

File diff suppressed because it is too large Load Diff

View File

@ -4,6 +4,8 @@
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleDocumentTypes</key>
<array/>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
@ -17,11 +19,15 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0.2</string>
<string>1.0.2-gdz</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
<array/>
<key>CFBundleVersion</key>
<string>5</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.utilities</string>
<key>LSMinimumSystemVersion</key>
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
<key>NSHumanReadableCopyright</key>
@ -30,5 +36,11 @@
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>NSServices</key>
<array/>
<key>UTExportedTypeDeclarations</key>
<array/>
<key>UTImportedTypeDeclarations</key>
<array/>
</dict>
</plist>

View File

@ -74,6 +74,8 @@
66BCFE61125FCEC6005A23F4 /* DataValuesV110Transparent.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = DataValuesV110Transparent.png; sourceTree = "<group>"; };
8D1107310486CEB800E47090 /* InsideJob-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "InsideJob-Info.plist"; sourceTree = "<group>"; };
8D1107320486CEB800E47090 /* Inside Job.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Inside Job.app"; sourceTree = BUILT_PRODUCTS_DIR; };
D13FDB481322757D00D318D1 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file; name = fr; path = fr.lproj/InfoPlist.strings; sourceTree = "<group>"; };
D13FDB491322782100D318D1 /* fr */ = {isa = PBXFileReference; lastKnownFileType = file; name = fr; path = fr.lproj/MainMenu.xib; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -272,6 +274,7 @@
Japanese,
French,
German,
fr,
);
mainGroup = 29B97314FDCFA39411CA2CEA /* InsideJob */;
projectDirPath = "";
@ -327,6 +330,7 @@
isa = PBXVariantGroup;
children = (
089C165DFE840E0CC02AAC07 /* English */,
D13FDB481322757D00D318D1 /* fr */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
@ -335,6 +339,7 @@
isa = PBXVariantGroup;
children = (
1DDD58150DA1D0A300B32029 /* English */,
D13FDB491322782100D318D1 /* fr */,
);
name = MainMenu.xib;
sourceTree = "<group>";

View File

@ -204,5 +204,6 @@
353,Sugar
354,Cake
355,Bed
356,Redstone Repeater
2256,Gold Record
2257,Green Record
Can't render this file because it has a wrong number of fields in line 35.

View File

@ -5,6 +5,7 @@
![Inside Job Screenshot](http://adampreble.net/images/InsideJob.png)
Inside Job was written in early October 2010 by [Adam Preble](http://adampreble.net).
Opening SMP world folder added by Godzil [Manoel Trapier](http://www.godzil.net).
Features include:
@ -33,6 +34,14 @@ After changing your inventory you will need to save the currently open world usi
### Release Notes
#### 1.0.2-gdz - March 5, 2011
- Major changes on world internal selection, we no longuer use World Index as ID, but the world path. We currently still have "slots" on the interface, but it should be changed soon to use a popup button with the list of worlds.
- Now we have separated level.dat form player.dat for beeing SMP friendly.
- Start to use externalised resources string to be more easy to translate the app.
- Add missing Redstone repeater
- Forked from official version
#### 1.0.2 - February 25, 2011
- Inside Job presently only supports worlds named "World1" thru "World5". Support for worlds with other names will be added in a future release.

View File

@ -0,0 +1,5 @@
/* Localized versions of Info.plist keys */
"No world loaded." = "Aucun monde chargé.";
"No world exists in that slot." = "Aucun mode dans ce slot";
"Dismiss" = "Annuler";
"Please create a new single player world in this slot using Minecraft and try again." = "Veuillez creer un monde en mode un joueur utilisant ce slot dans Minecraft, et essayez a nouveau.";

2719
fr.lproj/MainMenu.xib Normal file

File diff suppressed because it is too large Load Diff