Entwickler-Ecke
Dateizugriff - Noob sucht Hilfe: Wie speichern Spiele oder Programme Datein
Nano-Ware - Sa 19.03.11 17:23
Titel: Noob sucht Hilfe: Wie speichern Spiele oder Programme Datein
Hey,
mir ist jetzt schon öfters aufgefallen, dass wenn ich ein gespeichertes Spiel oder die ein oder andere Programmdatei im Editor öffne, dass ich dort nur auf total sinnlose zeichen stoße statt auf gehoffte Ini oder Xml Struktur. Was ich mich jetzt frage ist, wie solche Dateien generiert werden und ob ich die Möglichkeit habe herauszufinden wie ich an die Dateien komme:
Z.B. bei dem Spiel Minecraft: Es wird in einem Ordner das Spiel in der Datei level.dat gespeichert. In der Datei befinden sich "nur" die Koordinaten aller Objekte und die Objekte + Anzahl die ich im Inventar habe. Trotzdem ist diese Datei sehr komisch.
Wie kann ich sowas auslesen. Geht mal wirklich davon aus, dass ich echt garkeine Ahnung hab, was binäres schreiben von Dateien betrifft auch total zutrifft.
Danke
Achja meistens bringen mir Erklärungen die direkt darauf bezogen sind, mehr als irgendwelche Links!
Moderiert von
Christian S.: Topic aus Off Topic verschoben am Sa 19.03.2011 um 17:39
Gausi - Sa 19.03.11 17:49
Naja, im grunde sind ja alle Dateien "binäre Dateien". Es gibt halt nur einige, da sehen die Nullen und Einsen wie Buchstaben aus. ;-)
Ob man nun einen String wie "x = 23" reinschreibt, oder direkt die 23 so, wie sie auch im Speicher steht, ist dem Computer ja egal.
Sowas regelt man am einfachsten mit FileStreams. Wenn man z.B. zwischen durch auch mal Strings reinschreiben will, sollte man vorher die Länge in den Stream schreiben. Kleines Beispiel:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33:
| procedure TForm1.Button1Click(Sender: TObject); var fs: TFileStream; aString: AnsiString; aInteger: Integer; begin fs := TFileStream.Create('test.tst', fmCreate or fmOpenReadWrite); try aString := 'Hallo Welt'; aInteger := length(aString); fs.Write(aInteger, SizeOf(aInteger)); fs.Write(aString[1], aInteger); finally fs.Free; end; end;
procedure TForm1.Button2Click(Sender: TObject); var fs: TFileStream; aString: AnsiString; aInteger: Integer; begin fs := TFileStream.Create('test.tst', fmOpenRead); try fs.Read(aInteger, SizeOf(aInteger)); Setlength(aString, aInteger); fs.Read(aString[1], aInteger); showmessage(aString); finally fs.Free; end; end; |
ALF - Sa 19.03.11 17:49
Meist werden solche saves als Record gespeichert. Da gabs hier mal nen paar Threads dazu.
Vorteil, man kann nicht so schnell manipulieren :wink: weil halt binär.
Nachteil, wenn man es ebend will :dance2:
Meist macht man sich die Mühe mit einen HexEditor. Vergleicht Sav1 mit sav2, um zu sehen wo sich was ändert! zb Rucksack. Habe 1 element drin. Save, sichere Datei. Finde diese Element nochmal und nehem es auf. Save. Nun vergleiche beide Saves mit einen Exeditor.
So kenn ich es noch aus uralten Zeiten.
ALf
Nano-Ware - Sa 19.03.11 18:03
Ich hab das mim Hex Editor versucht. Wenn ich nur von einem Item im Inventar die Anzahl um 1 runterschraube ändert sich so ziemlich die GANZE Datei... Ich bin am verzweifeln -.-
Gausi - Sa 19.03.11 18:08
Dann sind die Daten da evtl. verschlüsselt gespeichert, damit pöhse Cheater da nicht so einfach drin rumhäcken können. ;-)
Nano-Ware - Sa 19.03.11 18:11
Es gibt aber schon 1. ein Programm, dass das Inventar füllen kann und 2. ist das Programm in Java geschrieben...
jaenicke - Sa 19.03.11 18:12
Dann schau dir doch davon einfach den Quelltext an. Wenn du Glück hast, ist der nicht obfuscated. ;-)
Nano-Ware - Sa 19.03.11 18:18
Ich hab im Internet gefunden, dass die Datei GZipped ist? Wie kann man die denn in Delphi GUnzippen?
jaenicke - Sa 19.03.11 18:28
Ich denke einmal am einfachsten mit den Indy-Komponenten, die sind ja eh mit Delphi gleich installiert.
Nano-Ware - Sa 19.03.11 18:30
Und mit welcher und wie?
jaenicke - Sa 19.03.11 18:45
So viele Möglichkeiten gibts da ja nicht, hab kurz geschaut, wie wäre es mit TIdCompressorZLib.DecompressGZipStream?
elundril - Sa 19.03.11 18:51
Wenn du nur bei dem spiel jetzt nachschauen willst wie das gespeichert ist, kannst du auch unter linux die datei entpacken, oder mit 7zip. Können soweit ich weiß beide die GZip-Kompression.
lg elundril
Gerd Kayser - Sa 19.03.11 18:51
Beim Lesen / Schreiben von binären Dateien kann es aber noch einige Fallstricke geben. Zum Beispiel Big oder Little Endian, Verwendung von MJD (modifiziertes Julianisches Datum) usw.
JungerIslaender - So 20.03.11 11:47
Nano-Ware hat folgendes geschrieben : |
Ich hab das mim Hex Editor versucht. Wenn ich nur von einem Item im Inventar die Anzahl um 1 runterschraube ändert sich so ziemlich die GANZE Datei... Ich bin am verzweifeln -.- |
Naja und ich möchte behaupten das es dir in Minecraft nicht gelingt zwei identische speicherstände anzulegen, die sich nur in der Anzahl eines Items unterscheiden. Es wird ja noch viel mehr gespeichert als nur die Itemzahl, nämlich Uhrzeit, position Blickrichtung usw...
Es ist allerdings möglich die Anzahl der Items per Cheatengine zu verändern. D.h. das müsste dann simultan ja auch mit Delphi machar sein. LG JungerIslaender
Nano-Ware - So 20.03.11 11:50
Ich wüsste nicht wie das per Cheatengine gehen sollte habs ja schon versucht. Nur mir gehts ja auch nicht darum.. das könnte ich ja ich will ja lernen was es mit den Dateien auf sich hat!
Martok - Mo 21.03.11 17:40
Wie wäre es dann mit Dokumentation lesen? NBT ist ein sehr gut dokumentiertes Format...
http://www.minecraft.net/docs/NBT.txt
http://www.minecraftwiki.net/wiki/Alpha_Level_Format#level.dat_Format
Allerdings ist das nicht so ganz einfach eine funktionierene ZLib dafür zu finden. Ich benutze dafür eine "ZLibEx" von "base2 technologies" und einen eigenen Stream, weil GZip keinen Dateinamen verwendet, aber der ZDecompressionStream eigentlich einen sehen will; deswegen über-seek-e ich den einfach:
Lizenz: WTFPL
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:
| unit GZip;
interface
uses Classes, ZLibEx;
type TGZDecompressionStream = class(TZDecompressionStream) public constructor Create(source: TStream); end;
implementation
constructor TGZDecompressionStream.Create(source: TStream); begin Source.Position:= 10; inherited Create(Source, -15); end;
end. |
EDIT: Was natürlich quatsch ist hier: nur die Maps sind komprimiert, und in 1.3 ja dann auch anders als dieser Code lesen würde. Für die level.dat brauchst du nichts zum dekomprimieren.
Nano-Ware - Mo 21.03.11 23:40
Ehm ich hab das Spiel ja auf dem PC ich hkönnte bei bedarf eine level.dat hochladen.. Naja also wenn ich die Datei einfach mal frech mit WinRAR entpacke ist der Text bis auf 5-6 Buchstaben lesbar...
Martok - Mo 21.03.11 23:46
Könnte ich auch *g*
War da grade auf dem falschen Dampfer. Natürlich ist eine .dat immer komprimiert. Da drin ist dann das NBT, für das man den Auslese-Code mit etwas aufwand direkt runterschreiben kann - die Doku ist halt direkt für Entwickler geschrieben ;)
Aber stimmt, Winrar erkennt das verwendete GZip z.B. direkt. Nur halt keiner der üblichen DecompressionStream-Klassen, daher der Aufwand.
Woran scheiterts denn?
Nano-Ware - Di 22.03.11 19:55
weil es dekomprimiert so aussieht :
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| Data Time ’ LastPlayed .Þ3¼_ Player SleepTimer Motion ? [€#äÞà¿´Â\)¿ô +7Ö OnGround HurtTime Health Dimension Air, Inventory id B Damage Count Slot id¸ Damage Count Slot id Y Damage Count, Slot id\ Damage Count Slot id 5 Damage Count; Slot id | Damage Count? Slot id9 Damage Count Slotd id8 Damage Count Slote id7 Damage Count Slotf id6 Damage Count Slotg Pos @Uà"~˜Ú@Z'®€ @BBæÄ‹p AttackTime Sleeping Fireÿì FallDistance Rotation Å¿…A½™… Score DeathTime SpawnX SpawnY @ LevelName Marka SpawnZ SizeOnDisk >0 RandomSeed i«Q version J¼ |
FrEaKY - So 27.03.11 19:07
Und wo ist das Problem? Du hast doch nicht erwartet, dass es wie ein Word-Dokument aussieht?
Anscheinend werden die Werte als Record gespeichert... dann solltest du sie mit einem Record auch wieder lesen können, sofern du das Format richtig rausliest.
Martok - So 27.03.11 20:11
Nicht direkt ein Record, eher ein allgmeiner Baum von Key-Value Paaren. Quasi so eine Art binäres, typisiertes XML. Wie genau das funktioniert, hab ich oben verlinkt.
Diesen kann man dann z.B. auch wieder als solchen darstellen:
Das ist z.B. eine level.dat aus MC 1.1 von mir.
Aber mal kurze Rückfrage: ist das jetzt ein allgemeiner Thread oder ein Minecraft-Thread? Eventuell wäre dann nämlich ein Teil abzutrennen.
Nano-Ware - So 27.03.11 22:52
Also ich bin bei diesem Thema leider total unterbelichtet. Martok, kannst du vielleicht dein Projekt hochladen? Ich möchte sowieso das ganze nur machen um langsam zu verstehen, wie das funktioniert, ich werde keinen einzigen Teil deines Codes verwenden nur mir fehlt der Ansatz.
Und nein es ist kein Minecraftspiel. Mir geht es hier generell ums Datenspeichern und ich wollte mich an das Beispiel von Minecraft ranwagen.
Danke schonmal Martok das sieht nämlich so aus wie ich mir das vorgestellt hab (:
Lg
jaenicke - So 27.03.11 23:08
Nano-Ware hat folgendes geschrieben : |
Mir geht es hier generell ums Datenspeichern und ich wollte mich an das Beispiel von Minecraft ranwagen. |
Nun ja, es hat niemand gesagt, dass das dort eine optimale Variante der Datenspeicherung ist. Das heißt, wenn es dir darum geht eigene Daten in einer Datei zu speichern und wie sowas funktioniert, würde ich jetzt nicht einfach irgendwelche Dateien anschauen. ;-)
Nano-Ware - So 27.03.11 23:47
Irgendwo muss man mal anfangen.. ich fang bei MC an und schau dann mal weiter :P
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!