NamedBinaryTag-Format (Minecraft) lesen/schreiben

Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Neue Antwort erstellen

das wurgel

Betreff: NamedBinaryTag-Format (Minecraft) lesen/schreiben

BeitragSa, März 12, 2011 19:28
Antworten mit Zitat
Benutzer-Profile anzeigen
NBT ist ein Tag-basiertes Datei-Format zum Speichern von Daten verschiedener Typen. Die Daten können beliebig untergliedert werden. Das Format wird von Minecraft für die Speicherstände benutzt.

Was man mit dem Modul machen kann:
Man kann das Format für eigene Programme benutzen oder einen Speicherstandeditor für Minecraft schreiben.

Formatsbeschreibung: http://www.minecraft.net/docs/NBT.txt

Tags:
Jedes Tag ist namentlich markiert und kann über seinen Namen gefunden werden.
  • Byte, Short, Integer, Float, Double: Speichert numerischen Wert
  • ByteArray: Ein Array aus Bytes
  • String: Ein String beliebiger Länge
  • List: Eine Liste vordefinierter Länge, die weitere Tags enthält. Alle enthaltenen Tags sind des selben Typs und namenlos.
  • Compound: Enthält beliebig viele weitere Tags. Am Anfang jeder NBT-Datei ist ein Compound, der alle Daten enthält.


Beispiel für den Aufbau einer NBT-Datei:
Zitat:
Code: [AUSKLAPPEN]
   TAG_Compound("Level"): 11 entries
   {
      TAG_Short("shortTest"): 32767
      TAG_Long("longTest"): 9223372036854775807
      TAG_Float("floatTest"): 0.49823147
      TAG_String("stringTest"): HELLO WORLD THIS IS A TEST STRING ÅÄÖ!
      TAG_Int("intTest"): 2147483647
      TAG_Compound("nested compound test"): 2 entries
      {
         TAG_Compound("ham"): 2 entries
         {
            TAG_String("name"): Hampus
            TAG_Float("value"): 0.75
         }
         TAG_Compound("egg"): 2 entries
         {
            TAG_String("name"): Eggbert
            TAG_Float("value"): 0.5
         }
      }
      TAG_List("listTest (long)"): 5 entries of type TAG_Long
      {
         TAG_Long: 11
         TAG_Long: 12
         TAG_Long: 13
         TAG_Long: 14
         TAG_Long: 15
      }
      TAG_Byte("byteTest"): 127
      TAG_List("listTest (compound)"): 2 entries of type TAG_Compound
      {
         TAG_Compound: 2 entries
         {
            TAG_String("name"): Compound tag #0
            TAG_Long("created-on"): 1264099775885
         }
         TAG_Compound: 2 entries
         {
            TAG_String("name"): Compound tag #1
            TAG_Long("created-on"): 1264099775885
         }
      }
      TAG_Byte_Array("byteArrayTest (the first 1000 values of (n*n*255+n*7)%100, starting with n=0 (0, 62, 34, 16, 8, ...))"): [1000 bytes]
      TAG_Double("doubleTest"): 0.4931287132182315
   }


Modulaufbau:
BlitzMax: [AUSKLAPPEN]

+ReadStructure:TNamedBinaryTag_Compound(stream:TStream) 'Liest eine NBT-Struktur aus Stream aus
+WriteStructure(stream:TStream, comp:TNamedBinaryTag_Compound) 'Schreibt eine NBT-Struktur in Stream rein

Type TNamedBinaryTag_[Byte / Short / Integer / Long / Float / Double] Extends TNamedBinaryTag
-value:[Byte / Short / Int / Long / Float / Double]

Type TNamedBinaryTag_ByteArray Extends TNamedBinaryTag
-bytes:Byte[]

Type TNamedBinaryTag_String Extends TNamedBinaryTag
-text:String

Type TNamedBinaryTag_List Extends TNamedBinaryTag
-tags:TNamedBinaryTag[] 'Alle desselben Typs

Type TNamedBinaryTag_[Byte / Short / Integer / Long / Float / Double / ByteArray / String / List / Compound]List Extends TNamedBinaryTag_List
Field tags:TNamedBinaryTag_[Byte / Short / Integer / Long / Float / Double / ByteArray / String / List / Compound] 'Zeigt auf gleiches Array wie Oberklasse

Type TNamedBinaryTag_Compound
-tags:TNamedBinaryTag[]

-find:TNamedBinaryTag(name$, case_sensitive@=False) ' Sucht ein Tag mit dem ensprechenden Namen heraus
-find[Byte / Short / Integer / Long / Float / Double / ByteArray / String / List / Compound]:TNamedBinaryTag_*(name$, case_sensitive@=False) ' Sucht ein *-Tag mit dem ensprechenden Namen heraus
-find[Byte / Short / Integer / Long / Float / Double / ByteArray / String / List / Compound]List:TNamedBinaryTag_*(name$, case_sensitive@=False) ' Sucht ein *List-Tag mit dem ensprechenden Namen heraus


Download: https://www.blitzforum.de/upload/file.php?id=10400

Nützliches:
Da die NBT-Files von Minecraft GZipped sind könnten diese beiden Funktionen zusammen mit gzip hilfreich sein:
BlitzMax: [AUSKLAPPEN]
Function ReadGZippedFile:TStream(File$)
If Not File.Contains("~q") And File.Contains(" ") Then File="~q"+File+"~q"

Local proc:TProcess = TProcess.Create("gzip -f -c -d " + File,0)
Local s@[]

While proc.Status()<>Null 'Or proc.pipe.ReadAvail()
While proc.pipe.ReadAvail()
s :+ [Byte(proc.pipe.ReadByte())]
Wend
Delay 10
Wend

While proc.pipe.ReadAvail()
s :+ [Byte(proc.pipe.ReadByte())]
Wend

Return CreateBankStream( CreateStaticBank(s, s.length) )
End Function


Function GZipFile(srcfile$, dstfile$)
Local dstfiletmp$=dstfile

While FileType(dstfiletmp)
dstfiletmp=dstfile+MilliSecs()
Wend

Local dst:TStream=WriteFile(dstfiletmp)

If Not srcfile.Contains("~q") And srcfile.Contains(" ") Then srcfile="~q"+srcfile+"~q"

Local proc:TProcess = TProcess.Create("gzip -f -c " + srcfile,0)

While proc.Status()<>Null 'Or proc.pipe.ReadAvail()
While proc.pipe.ReadAvail()
WriteByte dst, proc.pipe.ReadByte()
Wend
Delay 10
Wend
While proc.pipe.ReadAvail()
WriteByte dst, proc.pipe.ReadByte()
Wend

CloseFile dst

If dstfiletmp<>dstfile Then
DeleteFile dstfile
RenameFile dstfiletmp, dstfile
EndIf
End Function


Beispielprogramm:
Macht den Spieler in Minecraft wieder Lebendig:
BlitzMax: [AUSKLAPPEN]
SuperStrict

Import wurgel.namedbinarytag


Local filename$=RequestFile("level.dat Öffnen", "Minecraft level.dat:dat")

Local stream:TStream=ReadGZippedFile(filename)

Local comp:TNamedBinaryTag_Compound = TNamedBinaryTag.ReadStructure(stream)

Local health:TNamedBinaryTag_Short = comp.findCompound("data").findCompound("player").findShort("health")

Print health.value

health.value=20

Local file:TStream=WriteFile(filename)

TNamedBinaryTag.WriteStructure(file, comp)

CloseFile file

GZipFile(filename, filename)

End

Function ReadGZippedFile:TStream(File$)
If Not File.Contains("~q") And File.Contains(" ") Then File="~q"+File+"~q"

Local proc:TProcess = TProcess.Create("gzip -f -c -d " + File,0)
Local s@[]

While proc.Status()<>Null 'Or proc.pipe.ReadAvail()
While proc.pipe.ReadAvail()
s :+ [Byte(proc.pipe.ReadByte())]
Wend
Delay 10
Wend

While proc.pipe.ReadAvail()
s :+ [Byte(proc.pipe.ReadByte())]
Wend

Return CreateBankStream( CreateStaticBank(s, s.length) )
End Function


Function GZipFile(srcfile$, dstfile$)
Local dstfiletmp$=dstfile

While FileType(dstfiletmp)
dstfiletmp=dstfile+MilliSecs()
Wend

Local dst:TStream=WriteFile(dstfiletmp)

If Not srcfile.Contains("~q") And srcfile.Contains(" ") Then srcfile="~q"+srcfile+"~q"

Local proc:TProcess = TProcess.Create("gzip -f -c " + srcfile,0)

While proc.Status()<>Null 'Or proc.pipe.ReadAvail()
While proc.pipe.ReadAvail()
WriteByte dst, proc.pipe.ReadByte()
Wend
Delay 10
Wend
While proc.pipe.ReadAvail()
WriteByte dst, proc.pipe.ReadByte()
Wend

CloseFile dst

If dstfiletmp<>dstfile Then
DeleteFile dstfile
RenameFile dstfiletmp, dstfile
EndIf
End Function
1 ist ungefähr 3

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group