Progress snapshot.
This commit is contained in:
parent
fa54a6c0ff
commit
1132d91503
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
build
|
||||
*.perspectivev3
|
||||
*.pbxuser
|
||||
*.pbxuser
|
||||
tmp
|
||||
File diff suppressed because it is too large
Load Diff
@ -8,6 +8,14 @@
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
// See: http://www.minecraftwiki.net/wiki/Data_values
|
||||
#define IJInventorySlotQuickFirst (0)
|
||||
#define IJInventorySlotQuickLast (8)
|
||||
#define IJInventorySlotNormalFirst (9)
|
||||
#define IJInventorySlotNormalLast (35)
|
||||
#define IJInventorySlotArmorLast (103) // head
|
||||
#define IJInventorySlotArmorFirst (100) // feet
|
||||
|
||||
|
||||
@interface IJInventoryItem : NSObject {
|
||||
uint16_t itemId;
|
||||
@ -20,4 +28,10 @@
|
||||
@property (nonatomic, assign) uint8_t count;
|
||||
@property (nonatomic, assign) uint8_t slot;
|
||||
|
||||
@property (nonatomic, readonly) NSString *itemName;
|
||||
|
||||
+ (id)emptyItemWithSlot:(uint8_t)slot;
|
||||
|
||||
+ (NSDictionary *)itemIdLookup;
|
||||
|
||||
@end
|
||||
|
||||
@ -13,4 +13,41 @@
|
||||
|
||||
@synthesize itemId, slot, damage, count;
|
||||
|
||||
+ (id)emptyItemWithSlot:(uint8_t)slot
|
||||
{
|
||||
IJInventoryItem *obj = [[[[self class] alloc] init] autorelease];
|
||||
obj.slot = slot;
|
||||
return obj;
|
||||
}
|
||||
|
||||
- (NSString *)itemName
|
||||
{
|
||||
NSString *name = [[IJInventoryItem itemIdLookup] objectForKey:[NSNumber numberWithShort:self.itemId]];
|
||||
if (name)
|
||||
return name;
|
||||
else
|
||||
return [NSString stringWithFormat:@"%d", self.itemId];
|
||||
}
|
||||
|
||||
+ (NSDictionary *)itemIdLookup
|
||||
{
|
||||
static NSDictionary *lookup = nil;
|
||||
if (!lookup)
|
||||
{
|
||||
NSError *error = nil;
|
||||
NSString *lines = [NSString stringWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"Items" withExtension:@"csv"]
|
||||
encoding:NSUTF8StringEncoding
|
||||
error:&error];
|
||||
NSMutableDictionary *building = [NSMutableDictionary dictionary];
|
||||
[lines enumerateLinesUsingBlock:^(NSString *line, BOOL *stop) {
|
||||
NSArray *components = [line componentsSeparatedByString:@","];
|
||||
NSNumber *itemId = [NSNumber numberWithShort:[[components objectAtIndex:0] intValue]];
|
||||
NSString *name = [components objectAtIndex:1];
|
||||
[building setObject:name forKey:itemId];
|
||||
}];
|
||||
lookup = [[NSDictionary alloc] initWithDictionary:building];
|
||||
}
|
||||
return lookup;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@ -8,9 +8,27 @@
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@class IJMinecraftLevel;
|
||||
|
||||
@interface IJInventoryWindowController : NSWindowController {
|
||||
|
||||
IJMinecraftLevel *level;
|
||||
NSArray *inventory;
|
||||
|
||||
NSOutlineView *outlineView;
|
||||
NSPopUpButton *worldPopup;
|
||||
|
||||
NSArray *rootItems;
|
||||
NSMutableArray *armorItem;
|
||||
NSMutableArray *quickItem;
|
||||
NSMutableArray *inventoryItem;
|
||||
|
||||
BOOL dirty;
|
||||
int64_t sessionLockValue;
|
||||
}
|
||||
|
||||
@property (nonatomic, assign) IBOutlet NSOutlineView *outlineView;
|
||||
@property (nonatomic, assign) IBOutlet NSPopUpButton *worldPopup;
|
||||
|
||||
- (IBAction)worldSelectionChanged:(id)sender;
|
||||
|
||||
@end
|
||||
|
||||
@ -7,24 +7,288 @@
|
||||
//
|
||||
|
||||
#import "IJInventoryWindowController.h"
|
||||
|
||||
#import "IJMinecraftLevel.h"
|
||||
#import "IJInventoryItem.h"
|
||||
#import "IJItemPickerWindowController.h"
|
||||
|
||||
@implementation IJInventoryWindowController
|
||||
|
||||
@synthesize outlineView;
|
||||
@synthesize worldPopup;
|
||||
|
||||
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
|
||||
|
||||
- (void)awakeFromNib
|
||||
{
|
||||
return 0;
|
||||
armorItem = [NSMutableArray array];
|
||||
quickItem = [NSMutableArray array];
|
||||
inventoryItem = [NSMutableArray array];
|
||||
rootItems = [[NSArray alloc] initWithObjects:armorItem, quickItem, inventoryItem, nil];
|
||||
|
||||
[self worldSelectionChanged:nil];
|
||||
|
||||
[outlineView expandItem:nil expandChildren:YES];
|
||||
}
|
||||
- (void)dealloc
|
||||
{
|
||||
[inventory release];
|
||||
[rootItems release];
|
||||
[level release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark World Selection
|
||||
|
||||
- (void)loadWorldAtIndex:(int)worldIndex
|
||||
{
|
||||
[armorItem removeAllObjects];
|
||||
[quickItem removeAllObjects];
|
||||
[inventoryItem removeAllObjects];
|
||||
|
||||
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];
|
||||
|
||||
NSData *fileData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:levelPath]];
|
||||
|
||||
if (!fileData)
|
||||
{
|
||||
// Error loading
|
||||
[outlineView reloadData];
|
||||
NSBeginCriticalAlertSheet(@"Error loading world.", @"Dismiss", nil, nil, self.window, nil, nil, nil, nil, @"InsideJob was unable to load the level at %@.", levelPath);
|
||||
return;
|
||||
}
|
||||
|
||||
[level release];
|
||||
level = [[IJMinecraftLevel nbtContainerWithData:fileData] retain];
|
||||
inventory = [[level inventory] retain];
|
||||
|
||||
// Add placeholder inventory items:
|
||||
|
||||
for (int i = 0; i < IJInventorySlotQuickLast + 1 - IJInventorySlotQuickFirst; i++)
|
||||
[quickItem addObject:[IJInventoryItem emptyItemWithSlot:IJInventorySlotQuickFirst + i]];
|
||||
|
||||
for (int i = 0; i < IJInventorySlotNormalLast + 1 - IJInventorySlotNormalFirst; i++)
|
||||
[inventoryItem addObject:[IJInventoryItem emptyItemWithSlot:IJInventorySlotNormalFirst + i]];
|
||||
|
||||
for (int i = 0; i < IJInventorySlotArmorLast + 1 - IJInventorySlotArmorFirst; i++)
|
||||
[armorItem addObject:[IJInventoryItem emptyItemWithSlot:IJInventorySlotArmorFirst + i]];
|
||||
|
||||
|
||||
// Overwrite the placeholders with actual inventory:
|
||||
|
||||
for (IJInventoryItem *item in inventory)
|
||||
{
|
||||
if (IJInventorySlotQuickFirst <= item.slot && item.slot <= IJInventorySlotQuickLast)
|
||||
{
|
||||
[quickItem replaceObjectAtIndex:item.slot - IJInventorySlotQuickFirst withObject:item];
|
||||
}
|
||||
else if (IJInventorySlotNormalFirst <= item.slot && item.slot <= IJInventorySlotNormalLast)
|
||||
{
|
||||
[inventoryItem replaceObjectAtIndex:item.slot - IJInventorySlotNormalFirst withObject:item];
|
||||
}
|
||||
else if (IJInventorySlotArmorFirst <= item.slot && item.slot <= IJInventorySlotArmorLast)
|
||||
{
|
||||
[armorItem replaceObjectAtIndex:item.slot - IJInventorySlotArmorFirst withObject:item];
|
||||
}
|
||||
}
|
||||
|
||||
[outlineView reloadData];
|
||||
}
|
||||
|
||||
- (void)saveToWorldAtIndex:(int)worldIndex
|
||||
{
|
||||
if (![IJMinecraftLevel checkSessionLockAtIndex:worldIndex 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];
|
||||
|
||||
NSMutableArray *newInventory = [NSMutableArray array];
|
||||
|
||||
for (NSArray *items in rootItems)
|
||||
{
|
||||
for (IJInventoryItem *item in items)
|
||||
{
|
||||
if (item.count > 0 && item.itemId > 0)
|
||||
[newInventory addObject:item];
|
||||
}
|
||||
}
|
||||
|
||||
[level setInventory:newInventory];
|
||||
|
||||
NSString *backupPath = [levelPath stringByAppendingPathExtension:@".insidejobbackup"];
|
||||
|
||||
BOOL success;
|
||||
NSError *error = nil;
|
||||
success = [[NSFileManager defaultManager] removeItemAtPath:backupPath error:&error];
|
||||
success = [[NSFileManager defaultManager] copyItemAtPath:levelPath
|
||||
toPath:backupPath
|
||||
error:&error];
|
||||
if (!success)
|
||||
{
|
||||
NSBeginCriticalAlertSheet(@"An error occurred while saving.", @"Dismiss", nil, nil, self.window, nil, nil, nil, nil, @"Inside Job was unable to create a backup of the existing level file.");
|
||||
return;
|
||||
}
|
||||
|
||||
[[level writeData] writeToURL:[NSURL fileURLWithPath:levelPath] atomically:NO];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Actions
|
||||
|
||||
- (IBAction)worldSelectionChanged:(id)sender
|
||||
{
|
||||
int worldIndex = [[worldPopup selectedItem] tag];
|
||||
[self loadWorldAtIndex:worldIndex];
|
||||
}
|
||||
|
||||
- (void)saveDocument:(id)sender
|
||||
{
|
||||
int worldIndex = [[worldPopup selectedItem] tag];
|
||||
[self saveToWorldAtIndex:worldIndex];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Inventory Outline View
|
||||
|
||||
- (id)outlineView:(NSOutlineView *)theOutlineView child:(NSInteger)index ofItem:(id)item
|
||||
{
|
||||
if (item == nil)
|
||||
{
|
||||
return [rootItems objectAtIndex:index];
|
||||
}
|
||||
else
|
||||
{
|
||||
return [item objectAtIndex:index];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView *)theOutlineView isItemExpandable:(id)item
|
||||
{
|
||||
return item == nil || [rootItems containsObject:item];
|
||||
}
|
||||
|
||||
- (NSInteger)outlineView:(NSOutlineView *)theOutlineView numberOfChildrenOfItem:(id)item
|
||||
{
|
||||
if (item == nil)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
else if ([rootItems containsObject:item])
|
||||
{
|
||||
return [(NSArray *)item count];
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
- (id)outlineView:(NSOutlineView *)theOutlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
|
||||
{
|
||||
if ([rootItems containsObject:item])
|
||||
{
|
||||
if ([tableColumn.identifier isEqual:@"slot"])
|
||||
{
|
||||
if (item == armorItem)
|
||||
return @"Armor";
|
||||
else if (item == quickItem)
|
||||
return @"Quick Inventory";
|
||||
else if (item == inventoryItem)
|
||||
return @"Inventory";
|
||||
}
|
||||
else
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
IJInventoryItem *invItem = item;
|
||||
|
||||
if ([tableColumn.identifier isEqual:@"slot"])
|
||||
{
|
||||
return [NSString stringWithFormat:@"%d", invItem.slot];
|
||||
}
|
||||
else if ([tableColumn.identifier isEqual:@"id"])
|
||||
{
|
||||
if (invItem.itemId)
|
||||
return [NSNumber numberWithShort:invItem.itemId];
|
||||
else
|
||||
return nil;
|
||||
}
|
||||
else if ([tableColumn.identifier isEqual:@"item"])
|
||||
{
|
||||
if (invItem.itemId)
|
||||
return invItem.itemName;
|
||||
else
|
||||
return @"";
|
||||
}
|
||||
else if ([tableColumn.identifier isEqual:@"count"])
|
||||
{
|
||||
if (invItem.count)
|
||||
return [NSNumber numberWithUnsignedChar:invItem.count];
|
||||
else
|
||||
return nil;
|
||||
}
|
||||
else if ([tableColumn.identifier isEqual:@"damage"])
|
||||
{
|
||||
if (invItem.damage)
|
||||
return [NSNumber numberWithShort:invItem.damage];
|
||||
else
|
||||
return nil;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)tableView:(NSTableView *)tableView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
|
||||
- (void)outlineView:(NSOutlineView *)theOutlineView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
|
||||
{
|
||||
|
||||
IJInventoryItem *invItem = item;
|
||||
if ([tableColumn.identifier isEqual:@"id"])
|
||||
{
|
||||
invItem.itemId = [object shortValue];
|
||||
}
|
||||
else if ([tableColumn.identifier isEqual:@"count"])
|
||||
{
|
||||
invItem.count = [object unsignedCharValue];
|
||||
if (invItem.count > 64)
|
||||
invItem.count = 64;
|
||||
}
|
||||
else if ([tableColumn.identifier isEqual:@"damage"])
|
||||
{
|
||||
invItem.damage = [object shortValue];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView *)theOutlineView shouldEditTableColumn:(NSTableColumn *)tableColumn item:(id)item
|
||||
{
|
||||
if ([rootItems containsObject:item])
|
||||
return NO;
|
||||
else if ([tableColumn.identifier isEqual:@"item"])
|
||||
{
|
||||
IJInventoryItem *invItem = item;
|
||||
[[IJItemPickerWindowController sharedController] showPickerWithInitialItemId:invItem.itemId completionBlock:^(uint16_t itemId) {
|
||||
invItem.itemId = itemId;
|
||||
[outlineView reloadItem:item];
|
||||
}];
|
||||
return NO;
|
||||
}
|
||||
else
|
||||
{
|
||||
return [tableColumn.identifier isEqual:@"slot"] == NO;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
27
IJItemPickerWindowController.h
Normal file
27
IJItemPickerWindowController.h
Normal file
@ -0,0 +1,27 @@
|
||||
//
|
||||
// IJItemPickerWindowController.h
|
||||
// InsideJob
|
||||
//
|
||||
// Created by Adam Preble on 10/7/10.
|
||||
// Copyright 2010 Adam Preble. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
|
||||
@interface IJItemPickerWindowController : NSWindowController {
|
||||
void(^completionBlock)(uint16_t itemId);
|
||||
NSTableView *tableView;
|
||||
NSArray *allItemIds;
|
||||
NSArray *filteredItemIds;
|
||||
}
|
||||
@property (nonatomic, assign) IBOutlet NSTableView *tableView;
|
||||
|
||||
+ (IJItemPickerWindowController *)sharedController;
|
||||
|
||||
- (void)showPickerWithInitialItemId:(uint16_t)initialItemId completionBlock:(void(^)(uint16_t itemId))block;
|
||||
|
||||
- (IBAction)itemActivated:(id)sender;
|
||||
- (IBAction)updateFilter:(id)sender;
|
||||
|
||||
@end
|
||||
113
IJItemPickerWindowController.m
Normal file
113
IJItemPickerWindowController.m
Normal file
@ -0,0 +1,113 @@
|
||||
//
|
||||
// IJItemPickerWindowController.m
|
||||
// InsideJob
|
||||
//
|
||||
// Created by Adam Preble on 10/7/10.
|
||||
// Copyright 2010 Adam Preble. All rights reserved.
|
||||
//
|
||||
|
||||
#import "IJItemPickerWindowController.h"
|
||||
#import "IJInventoryItem.h"
|
||||
|
||||
@implementation IJItemPickerWindowController
|
||||
|
||||
@synthesize tableView;
|
||||
|
||||
+ (IJItemPickerWindowController *)sharedController
|
||||
{
|
||||
static IJItemPickerWindowController *globalSharedController = nil;
|
||||
if (!globalSharedController)
|
||||
{
|
||||
globalSharedController = [[IJItemPickerWindowController alloc] initWithWindowNibName:@"ItemPicker"];
|
||||
}
|
||||
return globalSharedController;
|
||||
}
|
||||
|
||||
- (void)awakeFromNib
|
||||
{
|
||||
[tableView setTarget:self];
|
||||
[tableView setDoubleAction:@selector(itemActivated:)];
|
||||
|
||||
NSArray *keys = [[IJInventoryItem itemIdLookup] allKeys];
|
||||
keys = [keys sortedArrayUsingSelector:@selector(compare:)];
|
||||
allItemIds = [[NSArray alloc] initWithArray:keys];
|
||||
filteredItemIds = [allItemIds retain];
|
||||
}
|
||||
|
||||
- (void)showPickerWithInitialItemId:(uint16_t)initialItemId completionBlock:(void(^)(uint16_t itemId))theBlock
|
||||
{
|
||||
[self showWindow:nil];
|
||||
|
||||
[completionBlock autorelease];
|
||||
completionBlock = [theBlock copy];
|
||||
|
||||
NSUInteger row = [filteredItemIds indexOfObject:[NSNumber numberWithShort:initialItemId]];
|
||||
if (row != NSNotFound)
|
||||
{
|
||||
[tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO];
|
||||
[tableView scrollRowToVisible:row];
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction)updateFilter:(id)sender
|
||||
{
|
||||
NSString *filterString = [sender stringValue];
|
||||
|
||||
if (filterString.length == 0)
|
||||
{
|
||||
[filteredItemIds autorelease];
|
||||
filteredItemIds = [allItemIds retain];
|
||||
[tableView reloadData];
|
||||
return;
|
||||
}
|
||||
|
||||
NSMutableArray *results = [NSMutableArray array];
|
||||
|
||||
for (NSNumber *itemId in allItemIds)
|
||||
{
|
||||
NSString *name = [[IJInventoryItem itemIdLookup] objectForKey:itemId];
|
||||
NSRange range = [name rangeOfString:filterString options:NSCaseInsensitiveSearch];
|
||||
if (range.location != NSNotFound)
|
||||
[results addObject:itemId];
|
||||
}
|
||||
|
||||
[filteredItemIds autorelease];
|
||||
filteredItemIds = [results retain];
|
||||
[tableView reloadData];
|
||||
}
|
||||
|
||||
- (IBAction)itemActivated:(id)sender
|
||||
{
|
||||
NSUInteger row = [tableView selectedRow];
|
||||
uint16_t itemId = [[filteredItemIds objectAtIndex:row] shortValue];
|
||||
|
||||
[[self window] orderOut:nil];
|
||||
|
||||
completionBlock(itemId);
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark NSTableViewDataSource
|
||||
|
||||
- (NSInteger)numberOfRowsInTableView:(NSTableView *)theTableView
|
||||
{
|
||||
return filteredItemIds.count;
|
||||
}
|
||||
- (id)tableView:(NSTableView *)theTableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
|
||||
{
|
||||
// TODO: Change this, because the row will not correspond once we support sorting.
|
||||
NSNumber *itemId = [filteredItemIds objectAtIndex:row];
|
||||
|
||||
if ([tableColumn.identifier isEqual:@"itemId"])
|
||||
return [itemId stringValue];
|
||||
|
||||
NSString *name = [[IJInventoryItem itemIdLookup] objectForKey:itemId];
|
||||
return name;
|
||||
}
|
||||
|
||||
- (void)windowDidResignKey:(NSNotification *)notification
|
||||
{
|
||||
[[self window] orderOut:nil];
|
||||
}
|
||||
|
||||
@end
|
||||
@ -15,4 +15,12 @@
|
||||
|
||||
@property (nonatomic, copy) NSArray *inventory; // Array of IJInventoryItem objects.
|
||||
|
||||
+ (NSString *)pathForWorldAtIndex:(int)worldIndex;
|
||||
+ (NSString *)pathForLevelDatAtIndex:(int)worldIndex;
|
||||
+ (NSString *)pathForSessionLockAtIndex:(int)worldIndex;
|
||||
|
||||
+ (int64_t)writeToSessionLockAtIndex:(int)worldIndex;
|
||||
+ (BOOL)checkSessionLockAtIndex:(int)worldIndex value:(int64_t)checkValue;
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@ -69,4 +69,70 @@
|
||||
inventoryList.children = newChildren;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Helpers
|
||||
|
||||
+ (NSString *)pathForWorldAtIndex:(int)worldIndex
|
||||
{
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
|
||||
NSString *path = [paths objectAtIndex:0];
|
||||
path = [path stringByAppendingPathComponent:@"minecraft"];
|
||||
path = [path stringByAppendingPathComponent:@"saves"];
|
||||
path = [path stringByAppendingPathComponent:[NSString stringWithFormat:@"World%d", worldIndex]];
|
||||
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"];
|
||||
}
|
||||
|
||||
|
||||
|
||||
+ (NSData *)dataWithInt64:(int64_t)v
|
||||
{
|
||||
NSMutableData *data = [NSMutableData data];
|
||||
uint32_t v0 = htonl(v >> 32);
|
||||
uint32_t v1 = htonl(v);
|
||||
[data appendBytes:&v0 length:4];
|
||||
[data appendBytes:&v1 length:4];
|
||||
return data;
|
||||
}
|
||||
+ (int64_t)int64FromData:(NSData *)data
|
||||
{
|
||||
uint8_t *bytes = (uint8_t *)[data bytes];
|
||||
uint64_t n = ntohl(*((uint32_t *)(bytes + 0)));
|
||||
n <<= 32;
|
||||
n += ntohl(*((uint32_t *)(bytes + 4)));
|
||||
return n;
|
||||
}
|
||||
|
||||
+ (int64_t)writeToSessionLockAtIndex:(int)worldIndex
|
||||
{
|
||||
NSString *path = [IJMinecraftLevel pathForSessionLockAtIndex:worldIndex];
|
||||
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
|
||||
{
|
||||
NSString *path = [IJMinecraftLevel pathForSessionLockAtIndex:worldIndex];
|
||||
NSData *data = [NSData dataWithContentsOfFile:path];
|
||||
|
||||
int64_t milliseconds = [IJMinecraftLevel int64FromData:data];
|
||||
return checkValue == milliseconds;
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@ -15,6 +15,9 @@
|
||||
668B27AF125D8EFD0060BF71 /* IJMinecraftLevel.m in Sources */ = {isa = PBXBuildFile; fileRef = 668B27AE125D8EFD0060BF71 /* IJMinecraftLevel.m */; };
|
||||
668B27B2125D8F8E0060BF71 /* IJInventoryItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 668B27B1125D8F8E0060BF71 /* IJInventoryItem.m */; };
|
||||
668B27F2125D963F0060BF71 /* IJInventoryWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 668B27F1125D963F0060BF71 /* IJInventoryWindowController.m */; };
|
||||
668B290F125E40560060BF71 /* Items.csv in Resources */ = {isa = PBXBuildFile; fileRef = 668B28D8125E370A0060BF71 /* Items.csv */; };
|
||||
668B2979125E5DD40060BF71 /* IJItemPickerWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 668B2978125E5DD40060BF71 /* IJItemPickerWindowController.m */; };
|
||||
668B297C125E5DF00060BF71 /* ItemPicker.xib in Resources */ = {isa = PBXBuildFile; fileRef = 668B297B125E5DF00060BF71 /* ItemPicker.xib */; };
|
||||
8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; };
|
||||
8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; };
|
||||
8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
|
||||
@ -42,6 +45,10 @@
|
||||
668B27B1125D8F8E0060BF71 /* IJInventoryItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJInventoryItem.m; sourceTree = "<group>"; };
|
||||
668B27F0125D963F0060BF71 /* IJInventoryWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJInventoryWindowController.h; sourceTree = "<group>"; };
|
||||
668B27F1125D963F0060BF71 /* IJInventoryWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJInventoryWindowController.m; sourceTree = "<group>"; };
|
||||
668B28D8125E370A0060BF71 /* Items.csv */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Items.csv; sourceTree = "<group>"; };
|
||||
668B2977125E5DD40060BF71 /* IJItemPickerWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJItemPickerWindowController.h; sourceTree = "<group>"; };
|
||||
668B2978125E5DD40060BF71 /* IJItemPickerWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJItemPickerWindowController.m; sourceTree = "<group>"; };
|
||||
668B297B125E5DF00060BF71 /* ItemPicker.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ItemPicker.xib; sourceTree = "<group>"; };
|
||||
8D1107310486CEB800E47090 /* InsideJob-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "InsideJob-Info.plist"; sourceTree = "<group>"; };
|
||||
8D1107320486CEB800E47090 /* InsideJob.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = InsideJob.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
@ -125,6 +132,8 @@
|
||||
8D1107310486CEB800E47090 /* InsideJob-Info.plist */,
|
||||
089C165CFE840E0CC02AAC07 /* InfoPlist.strings */,
|
||||
1DDD58140DA1D0A300B32029 /* MainMenu.xib */,
|
||||
668B297B125E5DF00060BF71 /* ItemPicker.xib */,
|
||||
668B28D8125E370A0060BF71 /* Items.csv */,
|
||||
);
|
||||
name = Resources;
|
||||
sourceTree = "<group>";
|
||||
@ -165,6 +174,8 @@
|
||||
children = (
|
||||
668B27F0125D963F0060BF71 /* IJInventoryWindowController.h */,
|
||||
668B27F1125D963F0060BF71 /* IJInventoryWindowController.m */,
|
||||
668B2977125E5DD40060BF71 /* IJItemPickerWindowController.h */,
|
||||
668B2978125E5DD40060BF71 /* IJItemPickerWindowController.m */,
|
||||
);
|
||||
name = Interface;
|
||||
sourceTree = "<group>";
|
||||
@ -224,6 +235,8 @@
|
||||
files = (
|
||||
8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */,
|
||||
1DDD58160DA1D0A300B32029 /* MainMenu.xib in Resources */,
|
||||
668B290F125E40560060BF71 /* Items.csv in Resources */,
|
||||
668B297C125E5DF00060BF71 /* ItemPicker.xib in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -241,6 +254,7 @@
|
||||
668B27AF125D8EFD0060BF71 /* IJMinecraftLevel.m in Sources */,
|
||||
668B27B2125D8F8E0060BF71 /* IJInventoryItem.m in Sources */,
|
||||
668B27F2125D963F0060BF71 /* IJInventoryWindowController.m in Sources */,
|
||||
668B2979125E5DD40060BF71 /* IJItemPickerWindowController.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
||||
1108
ItemPicker.xib
Normal file
1108
ItemPicker.xib
Normal file
File diff suppressed because it is too large
Load Diff
163
Items.csv
Normal file
163
Items.csv
Normal file
@ -0,0 +1,163 @@
|
||||
1,Stone
|
||||
2,Grass
|
||||
3,Dirt
|
||||
4,Cobblestone
|
||||
5,Wood
|
||||
6,Sapling
|
||||
7,Bedrock
|
||||
8,Water
|
||||
9,Stationary Water
|
||||
10,Lava
|
||||
11,Stationary Lava
|
||||
12,Sand
|
||||
13,Gravel
|
||||
14,Gold Ore
|
||||
15,Iron Ore
|
||||
16,Coal Ore
|
||||
17,Log
|
||||
18,Leaves
|
||||
19,Sponge
|
||||
20,Glass
|
||||
35,White Cloth
|
||||
37,Yellow Flower
|
||||
38,Red Rose
|
||||
39,Brown Mushroom
|
||||
40,Red Mushroom
|
||||
41,Gold Block
|
||||
42,Iron Block
|
||||
43,Double Step
|
||||
44,Step
|
||||
45,Brick
|
||||
46,TNT
|
||||
47,Bookcase
|
||||
48,Mossy Cobblestone
|
||||
49,Obsidian
|
||||
50,Torch
|
||||
51,Fire
|
||||
52,Mob Spawner
|
||||
53,Wooden Stairs
|
||||
54,Chest
|
||||
55,Redstone Wire
|
||||
56,Diamond Ore
|
||||
57,Diamond Block
|
||||
58,Workbench
|
||||
59,Crops
|
||||
60,Soil
|
||||
61,Furnace
|
||||
62,Burning Furnace
|
||||
63,Sign Post
|
||||
64,Wooden Door
|
||||
65,Ladder
|
||||
66,Minecart Tracks
|
||||
67,Cobblestone Stairs
|
||||
68,Wall Sign
|
||||
69,Lever
|
||||
70,Stone Pressure Plate
|
||||
71,Iron Door
|
||||
72,Wooden Pressure Plate
|
||||
73,Redstone Ore
|
||||
74,Glowing Redstone Ore
|
||||
75,Redstone Torch (Off)
|
||||
76,Redstone Torch (On)
|
||||
77,Stone Button
|
||||
78,Snow
|
||||
79,Ice
|
||||
80,Snow Block
|
||||
81,Cactus
|
||||
82,Clay
|
||||
83,Reed
|
||||
84,Jukebox
|
||||
85,Fence
|
||||
256,Iron Spade
|
||||
257,Iron Pickaxe
|
||||
258,Iron Axe
|
||||
259,Flint and Steel
|
||||
260,Apple
|
||||
261,Bow
|
||||
262,Arrow
|
||||
263,Coal
|
||||
264,Diamond
|
||||
265,Iron Ingot
|
||||
266,Gold Ingot
|
||||
267,Iron Sword
|
||||
268,Wooden Sword
|
||||
269,Wooden Spade
|
||||
270,Wooden Pickaxe
|
||||
271,Woord Axe
|
||||
272,Stone Sword
|
||||
273,Stone Spade
|
||||
274,Stone Pickaxe
|
||||
275,Stone Axe
|
||||
276,Diamond Sword
|
||||
277,Diamond Spade
|
||||
278,Diamond Pickaxe
|
||||
279,Diamond Axe
|
||||
280,Stick
|
||||
281,Bowl
|
||||
282,Mushroom Soup
|
||||
283,Gold Sword
|
||||
284,Gold Spade
|
||||
285,Gold Pickaxe
|
||||
286,Gold Axe
|
||||
287,String
|
||||
288,Feather
|
||||
289,Gunpowder
|
||||
290,Wooden Hoe
|
||||
291,Stone Hoe
|
||||
292,Iron Hoe
|
||||
293,Diamond Hoe
|
||||
294,Gold Hoe
|
||||
295,Seeds
|
||||
296,Wheat
|
||||
297,Bread
|
||||
298,Leather Helmet
|
||||
299,Leather Chestplate
|
||||
300,Leather Pants
|
||||
301,Leather Boots
|
||||
302,Chainmail Helmet
|
||||
303,Chainmail Chestplate
|
||||
304,Chainmail Pants
|
||||
305,Chainmail Boots
|
||||
306,Iron Helmet
|
||||
307,Iron Chestplate
|
||||
308,Iron Pants
|
||||
309,Iron Boots
|
||||
310,Diamond Helmet
|
||||
311,Diamond Chestplate
|
||||
312,Diamond Pants
|
||||
313,Diamond Boots
|
||||
314,Gold Helmet
|
||||
315,Gold Chestplate
|
||||
316,Gold Pants
|
||||
317,Gold Boots
|
||||
318,Flint
|
||||
319,Pork
|
||||
320,Grilled Pork
|
||||
321,Paintings
|
||||
322,Golden Apple
|
||||
323,Sign
|
||||
324,Wooden Door
|
||||
325,Bucket
|
||||
326,Water Bucket
|
||||
327,Lava Bucket
|
||||
328,Mine Cart
|
||||
329,Saddle
|
||||
330,Iron Door
|
||||
331,Redstone
|
||||
332,Snowball
|
||||
333,Boat
|
||||
334,Leather
|
||||
335,Milk Bucket
|
||||
336,Clay Brick
|
||||
337,Clay Balls
|
||||
338,Reed
|
||||
339,Paper
|
||||
340,Book
|
||||
341,Slime Ball
|
||||
342,Storage Minecart
|
||||
343,Powered Minecart
|
||||
344,Egg
|
||||
345,Compass
|
||||
346,Fishing Rod
|
||||
2256,Gold Record
|
||||
2257,Green Record
|
||||
|
Loading…
x
Reference in New Issue
Block a user