diff --git a/IJInventoryItem.h b/IJInventoryItem.h new file mode 100644 index 0000000..b239551 --- /dev/null +++ b/IJInventoryItem.h @@ -0,0 +1,23 @@ +// +// IJInventoryItem.h +// InsideJob +// +// Created by Adam Preble on 10/7/10. +// Copyright 2010 Adam Preble. All rights reserved. +// + +#import + + +@interface IJInventoryItem : NSObject { + uint16_t itemId; + uint16_t damage; + uint8_t count; + uint8_t slot; +} +@property (nonatomic, assign) uint16_t itemId; +@property (nonatomic, assign) uint16_t damage; +@property (nonatomic, assign) uint8_t count; +@property (nonatomic, assign) uint8_t slot; + +@end diff --git a/IJInventoryItem.m b/IJInventoryItem.m new file mode 100644 index 0000000..d1fd1fb --- /dev/null +++ b/IJInventoryItem.m @@ -0,0 +1,16 @@ +// +// IJInventoryItem.m +// InsideJob +// +// Created by Adam Preble on 10/7/10. +// Copyright 2010 Adam Preble. All rights reserved. +// + +#import "IJInventoryItem.h" + + +@implementation IJInventoryItem + +@synthesize itemId, slot, damage, count; + +@end diff --git a/IJMinecraftLevel.h b/IJMinecraftLevel.h new file mode 100644 index 0000000..5e1e25f --- /dev/null +++ b/IJMinecraftLevel.h @@ -0,0 +1,18 @@ +// +// IJMinecraftLevel.h +// InsideJob +// +// Created by Adam Preble on 10/7/10. +// Copyright 2010 Adam Preble. All rights reserved. +// + +#import +#import "NBTContainer.h" + +@interface IJMinecraftLevel : NBTContainer { + +} + +@property (nonatomic, copy) NSArray *inventory; // Array of IJInventoryItem objects. + +@end diff --git a/IJMinecraftLevel.m b/IJMinecraftLevel.m new file mode 100644 index 0000000..0bb632c --- /dev/null +++ b/IJMinecraftLevel.m @@ -0,0 +1,72 @@ +// +// IJMinecraftLevel.m +// InsideJob +// +// Created by Adam Preble on 10/7/10. +// Copyright 2010 Adam Preble. All rights reserved. +// + +#import "IJMinecraftLevel.h" +#import "IJInventoryItem.h" + +@implementation IJMinecraftLevel + +- (NBTContainer *)containerWithName:(NSString *)theName inArray:(NSArray *)array +{ + for (NBTContainer *container in array) + { + if ([container.name isEqual:theName]) + return container; + } + return nil; +} + +- (NBTContainer *)inventoryList +{ + // Inventory is found in: + // - compound "Data" + // - compound "Player" + // - list "Inventory" + // * + NBTContainer *dataCompound = [self childNamed:@"Data"]; + NBTContainer *playerCompound = [dataCompound childNamed:@"Player"]; + NBTContainer *inventoryList = [playerCompound childNamed:@"Inventory"]; + // TODO: Check for error conditions here. + return inventoryList; +} + +- (NSArray *)inventory +{ + NSMutableArray *output = [NSMutableArray array]; + 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]; + invItem.slot = [[self containerWithName:@"Slot" inArray:listItems].numberValue unsignedCharValue]; + [output addObject:invItem]; + [invItem release]; + } + return output; +} + +- (void)setInventory:(NSArray *)newInventory +{ + NSMutableArray *newChildren = [NSMutableArray array]; + NBTContainer *inventoryList = [self inventoryList]; + for (IJInventoryItem *invItem in newInventory) + { + NSArray *listItems = [NSArray arrayWithObjects: + [NBTContainer containerWithName:@"id" type:NBTTypeShort numberValue:[NSNumber numberWithShort:invItem.itemId]], + [NBTContainer containerWithName:@"Damage" type:NBTTypeShort numberValue:[NSNumber numberWithShort:invItem.damage]], + [NBTContainer containerWithName:@"Count" type:NBTTypeByte numberValue:[NSNumber numberWithShort:invItem.count]], + [NBTContainer containerWithName:@"Slot" type:NBTTypeByte numberValue:[NSNumber numberWithShort:invItem.slot]], + nil]; + [newChildren addObject:listItems]; + } + inventoryList.children = newChildren; +} + +@end diff --git a/InsideJob.xcodeproj/project.pbxproj b/InsideJob.xcodeproj/project.pbxproj index c7f2b17..bb5884f 100644 --- a/InsideJob.xcodeproj/project.pbxproj +++ b/InsideJob.xcodeproj/project.pbxproj @@ -12,6 +12,8 @@ 668B2556125D5A3E0060BF71 /* NBTContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = 668B2555125D5A3E0060BF71 /* NBTContainer.m */; }; 668B255C125D5BCA0060BF71 /* NSData+CocoaDevAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 668B255B125D5BCA0060BF71 /* NSData+CocoaDevAdditions.m */; }; 668B2560125D5C1C0060BF71 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 668B255F125D5C1C0060BF71 /* libz.dylib */; }; + 668B27AF125D8EFD0060BF71 /* IJMinecraftLevel.m in Sources */ = {isa = PBXBuildFile; fileRef = 668B27AE125D8EFD0060BF71 /* IJMinecraftLevel.m */; }; + 668B27B2125D8F8E0060BF71 /* IJInventoryItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 668B27B1125D8F8E0060BF71 /* IJInventoryItem.m */; }; 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 */; }; @@ -33,6 +35,10 @@ 668B255A125D5BCA0060BF71 /* NSData+CocoaDevAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+CocoaDevAdditions.h"; sourceTree = ""; }; 668B255B125D5BCA0060BF71 /* NSData+CocoaDevAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+CocoaDevAdditions.m"; sourceTree = ""; }; 668B255F125D5C1C0060BF71 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; }; + 668B27AD125D8EFD0060BF71 /* IJMinecraftLevel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJMinecraftLevel.h; sourceTree = ""; }; + 668B27AE125D8EFD0060BF71 /* IJMinecraftLevel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJMinecraftLevel.m; sourceTree = ""; }; + 668B27B0125D8F8E0060BF71 /* IJInventoryItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IJInventoryItem.h; sourceTree = ""; }; + 668B27B1125D8F8E0060BF71 /* IJInventoryItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IJInventoryItem.m; sourceTree = ""; }; 8D1107310486CEB800E47090 /* InsideJob-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "InsideJob-Info.plist"; sourceTree = ""; }; 8D1107320486CEB800E47090 /* InsideJob.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = InsideJob.app; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -131,6 +137,10 @@ 668B2551125D59BF0060BF71 /* Model */ = { isa = PBXGroup; children = ( + 668B27AD125D8EFD0060BF71 /* IJMinecraftLevel.h */, + 668B27AE125D8EFD0060BF71 /* IJMinecraftLevel.m */, + 668B27B0125D8F8E0060BF71 /* IJInventoryItem.h */, + 668B27B1125D8F8E0060BF71 /* IJInventoryItem.m */, 668B2554125D5A3E0060BF71 /* NBTContainer.h */, 668B2555125D5A3E0060BF71 /* NBTContainer.m */, ); @@ -215,6 +225,8 @@ 256AC3DA0F4B6AC300CF3369 /* InsideJobAppDelegate.m in Sources */, 668B2556125D5A3E0060BF71 /* NBTContainer.m in Sources */, 668B255C125D5BCA0060BF71 /* NSData+CocoaDevAdditions.m in Sources */, + 668B27AF125D8EFD0060BF71 /* IJMinecraftLevel.m in Sources */, + 668B27B2125D8F8E0060BF71 /* IJInventoryItem.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/InsideJobAppDelegate.m b/InsideJobAppDelegate.m index 46240e7..2f6fffe 100644 --- a/InsideJobAppDelegate.m +++ b/InsideJobAppDelegate.m @@ -8,6 +8,7 @@ #import "InsideJobAppDelegate.h" #import "NBTContainer.h" +#import "IJMinecraftLevel.h" @implementation InsideJobAppDelegate @@ -16,8 +17,12 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { // Insert code here to initialize your application - NSData *fileData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:@"../../level.dat"]]; - NBTContainer *nbtFile = [NBTContainer nbtContainerWithData:fileData]; + NSData *fileData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:@"../../world5-level.dat"]]; + IJMinecraftLevel *level = [IJMinecraftLevel nbtContainerWithData:fileData]; + [level inventory]; + +// NSData *newData = [level writeData]; +// [newData writeToURL:[NSURL fileURLWithPath:@"../../output.nbt"] atomically:NO]; } @end diff --git a/NBTContainer.h b/NBTContainer.h index 4741be3..dec8940 100644 --- a/NBTContainer.h +++ b/NBTContainer.h @@ -37,7 +37,9 @@ typedef enum { @property (nonatomic, retain) NSNumber *numberValue; @property (nonatomic, assign) NBTType listType; ++ (NBTContainer *)containerWithName:(NSString *)theName type:(NBTType)theType numberValue:(NSNumber *)theNumber; + (id)nbtContainerWithData:(NSData *)data; - (void)readFromData:(NSData *)data; - (NSData *)writeData; +- (NBTContainer *)childNamed:(NSString *)theName; @end diff --git a/NBTContainer.m b/NBTContainer.m index f8893a9..0b54997 100644 --- a/NBTContainer.m +++ b/NBTContainer.m @@ -51,6 +51,15 @@ [super dealloc]; } ++ (NBTContainer *)containerWithName:(NSString *)theName type:(NBTType)theType numberValue:(NSNumber *)theNumber +{ + NBTContainer *cont = [[[NBTContainer alloc] init] autorelease]; + cont.name = theName; + cont.type = theType; + cont.numberValue = theNumber; + return cont; +} + + (id)nbtContainerWithData:(NSData *)data; { @@ -74,6 +83,24 @@ return [[self data] gzipDeflate]; } +- (NBTContainer *)childNamed:(NSString *)theName +{ + if (self.type != NBTTypeCompound) + { + NSLog(@"ERROR: Cannot find children inside a non-compound NBTContainer."); + return nil; + } + for (NBTContainer *container in self.children) + { + if ([container.name isEqual:theName]) + return container; + } + return nil; +} + +#pragma mark - +#pragma mark Private I/O API + - (void)populateWithBytes:(const uint8_t *)bytes offset:(uint32_t *)offsetPointer { uint32_t offset = *offsetPointer;