Okay finished with cleaning up source of the nbt loader and made an object of it.
nbt.pasTNamedBinaryTag =Class(TObject)
provides methods:
LoadFromFile(filename,TGauge) //gauge to show loading progress
Loads NBTFile to self.cmp = TCompound
TCompound is a Tree structure root node consists of
tags = Dynamic Array of pointer-->NBT_Tag | last element always =end_tag
sub = Dynamic Array of pointer-->Compound | last element always =nil
parent = pointer-->Compound
To view complete datastructure you can set breakpoint to line
Showmessage(Cmp.name); at the end of procedure LoadFromFile(); and
browse it in local variables then NBT_Tag is an dynamic record which always contains
name:string;
type:byte; ->defines type of carried data
0: ();
1: (byte:byte);
2: (short:SmallInt);
3: (int:Integer);
4: (long:Int64);
5: (float:Single);
6: (dbl:Double);
7: (pba:PByteArray); pointer-->dynamic array of byte
8: (str:PString); pointer-->string
9: (pla:PNBTListArray); pointer-->dynamic array of NBTList_Tag
NBT_List_Tag is same as NBT_Tag without 9:(pla:PNBTListArray), tags in lists are not named
AddToTree(pointer-->TTreeView) Add self.cmp to Treeview
There is no support for writing data back to file, cause i dont need to, but i think its could be simply implemented in the same way writing it to tree view, but you have to mention the reversed byte order for all datatypes longer 1 byte exept string. I think
best way to change byte order is to sort the bytes in an array with element count of
designated datatype size in bytes and then set pointer-->datatype=@byteArray[0]
BlockRead(NBTFile,ba[3],1);
BlockRead(NBTFile,ba[2],1);
BlockRead(NBTFile,ba[1],1);
BlockRead(NBTFile,ba[0],1);
pfloat:=@ba[0];
float:=pfloat^;
Also there is, still, no support for gzip so you have to un-/repack files yourself,or,better, add it, and post it here
i´m to lazy to, maybe later when my levelfiles grow.further explaination:
self.cmp is the root node of the the compound tree, self.ptr is a pointer used to navigate
throuh compound tree.
Tree Navigation Example:
cPtr:=@cmp;
//set pointer to root node
if cPtr^.tags[0].typ<>0 then
for i:=0 to High(cPtr^.tags)-1 do
cptr^.tags
.typ:=x;
//acces Tags in compounds pointer points to
procedure readsub;
if cPtr.sub[0]<>nil then
for i:=0 to High(cPtr.sub)-1 do
begin
cptr:=cptr^.sub; //one level down
//do sth with tags of compound
//here you have to use an recursive call to read sub compounds of sub cmp´s of ..
readsub;
cPtr:=cPtr^.parent; //one level up
end;
end
//acces sub compounds pointer points to
Other usefull:
Convert NBT_Tag Value to string:
case Tag.typ of
1 : result:=IntToStr(Tag.byte);
2 : result:=IntToStr(Tag.short);
3 : result:=IntToStr(Tag.int);
4 : result:=IntToStr(Tag.long);
5 : Result:=FloattoStr(Tag.float);
6 : Result:=FloattoStr(Tag.dbl);
7 : Result:='['+InttoStr(Length(Tag.pba^)-1)+']';
8 : Result:=Tag.str^;
9 : begin;
Result:=' of '+IntToStr(Length(Tag.pla^)-1)+'*';
Result:=Result+getEnumName(TypeInfo(TTagName),Tag.pla^[0].typ)+': ';
for i:=0 to High(Tag.pla^)-1 do
Result:=Result+':'+ListTagValToStr(Tag.pla^[i]);
end;
NBT_Tag --> NBT_List_Tag
ListTag.Name:=tCmp.tags[i].name;
ListTag.typ:=tCmp.tags[i].typ;
case tcmp.typ of
1 : ListTag.byte := tCmp.tags[i].byte;
2 : ListTag.short := tCmp.tags[i].short;
3 : ListTag.int := tCmp.tags[i].int;
4 : ListTag.long := tCmp.tags[i].long;
5 : ListTag.float := tCmp.tags[i].float;
6 : ListTag.dbl := tCmp.tags[i].dbl;
7 : ListTag.pba := tCmp.tags[i].pba;
8 : ListTag.str := tCmp.tags[i].str;
end;
Optimization:in Read ByteArray introduce var point:Pointer;
and change:
for i:=0 to len-1 do
ba[i]:=Read_TAGByte(false);
to
point:=@ba[0];
BlockRead(NBTFile,point^,len);
point:=nil;
more then 10 times increased speed for loading levelChunk files cause they contain
several 16k or 32k lenght byte arrays
Simple gzip function:Install 7zip and copy executable to programm dir.
Create .bat file to call programm.
7z x -y -o%2 %1
Run .bat file from Program:(uses ShellApi)
RenameFile('.\biglc\'+FName,'.\biglc\'+FName+'.gz');
if (fileExists('.\biglc\uc\'+FName) <> true) then
begin
ShellExecute(0, nil, PChar('.\test.bat'),PChar('".\biglc\'+FName+'.gz" ".\biglc\uc\"'), PChar('G:\Minecraft'), SW_SHOW);
sleep(1000);
end;
AssignFile(NBTFile,'.\biglc\uc\'+FName);
to be continiued...