D2S ist ein binärer Parser, der in Go geschrieben wurde, mit .d2s -Dateien analysiert werden. Dies ist das binäre Format, mit dem das Spiel Diablo II alle Informationen über einen bestimmten Charakter speichert.
Dieses Paket wurde für einen privaten Server von Diablo II namens Slash Diablo erstellt, um eine Army für alle Zeichen auf dem Server zu erstellen. Wo jeder zu einem bestimmten Zeitpunkt alles über einen bestimmten Charakter sehen konnte. Hier sind einige Beispiele.
$ go get github.com/nokka/d2s package main
import (
"fmt"
"log"
"os"
"github.com/nokka/d2s"
)
func main () {
path := "nokka.d2s"
file , err := os . Open ( path )
if err != nil {
log . Fatal ( "Error while opening .d2s file" , err )
}
defer file . Close ()
char , err := d2s . Parse ( file )
if err != nil {
log . Fatal ( err )
}
// Prints character name and class.
fmt . Println ( char . Header . Name )
fmt . Println ( char . Header . Class )
} Der Header ist 765 byte -lange Strukturen, die die meisten Charakter -Meta -Daten enthalten.
| Offset | Bytes | Beschreibung |
|---|---|---|
| 0 | 4 | Kennung |
| 4 | 4 | Version ID |
| 8 | 4 | Dateigröße |
| 12 | 4 | Überprüfung |
| 16 | 4 | Aktive Waffe |
| 20 | 16 | Charaktername |
| 36 | 1 | Charakterstatus |
| 37 | 1 | Charakter -Fortschritt |
| 38 | 2 | Unbekannt |
| 40 | 1 | Charakterklasse |
| 41 | 2 | Unbekannt |
| 43 | 1 | Charakterebene |
| 44 | 4 | Unbekannt |
| 48 | 4 | Zuletzt gespielt |
| 52 | 4 | Unbekannt |
| 56 | 64 | Zugewiesene Fähigkeiten |
| 120 | 4 | Linksmaustaste Skill ID ID |
| 124 | 4 | Rechte Maustaste Skill ID ID |
| 128 | 4 | Links -Tausch -Maustaste Skill ID ID |
| 132 | 4 | Recht |
| 136 | 32 | Zeichenmenü Erscheinungsbild |
| 168 | 3 | Schwierigkeit |
| 171 | 4 | Karte ID |
| 175 | 2 | Unbekannt |
| 177 | 2 | Söldner tot |
| 179 | 4 | Söldner -ID |
| 183 | 2 | Mercenary Name ID |
| 185 | 2 | Söldnertyp |
| 187 | 4 | Söldnererfahrung |
| 191 | 144 | Unbekannt |
| 335 | 298 | Quests |
| 633 | 81 | Wegpunkte |
| 714 | 51 | NPC -Einführungen |
Charakternamen werden als [16]byte gestaltet, das den Namen und einen Buchstaben pro byte enthält. Der Name kann 16 Zeichen lang sein, und ein kürzerer Name hat den Namen von 0x00 hinter dem Namen gepolstert, bis wir 16 bytes erreichen.
- oder _ . Der Charakterstatus ist ein byte , in dem je nach Status des Charakters verschiedene Bits festgelegt werden. Sie haben sie immer noch nicht alle herausgefunden, aber hier sind die wichtigsten.
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|---|
| ? | Leiter | Erweiterung | ? | Gestorben | Hardcore | ? | ? |
Noch nicht implementiert.
Der Wert wird jedes Mal inkrementiert, wenn Sie einen Act -Chef töten.
| Wert | Standard | Hardcore |
|---|---|---|
| 0-3 | - - | - - |
| 4-7 | Sir/Dame | Graf/Countess |
| 8-11 | Herr/Dame | Herzog/Herzogin |
| 12 | Baron/Baronin | König/Königin |
| Wert | Erweiterung | Expansion Hardcore |
|---|---|---|
| 0-3 | - - | - - |
| 5-8 | Tötung | Zerstörer |
| 10-13 | Champion | Eroberer |
| 15 | Patriarch/Matriarch | Wächter |
Die Charakterklasse ist ein byte , in dem verschiedene Werte eine Klasse darstellen.
| Klasse | Wert |
|---|---|
| Amazonas | 0x00 |
| Zauberin | 0x01 |
| Nekromant | 0x02 |
| Paladin | 0x03 |
| Barbar | 0x04 |
| Druide | 0x05 |
| Attentäter | 0x06 |
Last gespielt wird als unit32 UNIX TIMESTAMP, z. B. 1495882861 .
Zugewiesenen Fertigkeitsabschnitt ist eine Reihe von 16 Skill -IDs, jeweils eine 4 byte -Ganzzahl (UINT32). Wenn keine Fähigkeit zugewiesen wird, beträgt der Wert 0x00 .
Die Quests Struct ist 298 byte -Abschnitt, der alle Quests im Spiel beschreibt, aber auch Daten über das ACT -Reisen und die NPC -Einführungen enthält. Jede Quest ist 2 byte lang.
| Offset | Bytes | Inhalt |
|---|---|---|
| 335 | 4 | Umwerben! |
| 339 | 6 | Unbekannt |
Eine Quest ist 2 byte lang, ich habe eine allgemeine quest erstellt, die die wichtigsten Daten einer Quest enthält, wenn sie abgeschlossen ist oder nicht. Jede Quest hat je nach verschiedenen Meilensteinen der Quest viele einzigartige Bits. Zum Beispiel, wenn Sie den Widerstand aus dem Quest "Gefängnis von Eis" konsumiert haben oder nicht.
| Bisschen | Beschreibung |
|---|---|
| 0 | Quest fertiggestellt |
Das Gefängnis von Ice ist die einzige Suche, die ich mir umgesetzt habe, weil ich wissen musste, ob der Charakter Widerstände aus der Schriftrolle erhöht haben oder nicht.
| Bisschen | Beschreibung |
|---|---|
| 0 | Quest fertiggestellt |
| 7 | Konsumatistik |
Diese Struktur wiederholt sich dreimal selbst, einmal für Normale, Albtraum und Hölle. Der Versatz ist der Offset in die Queststruktur.
| Offset | Bytes | Beschreibung |
|---|---|---|
| 0 | 2 | Setzen Sie auf 1 , wenn Sie in Akt I in Warriv eingeführt wurden. |
| 2 | [6]quest | Alle sechs Quests für Akt I. |
| 14 | 2 | Setzen Sie auf 1 , wenn Sie zu Akt II gereist sind. |
| 16 | 2 | Set auf 1 , wenn Sie Jerhyn vorgestellt wurden. |
| 18 | [6]quest | Alle sechs Quests für Akt II. |
| 30 | 2 | Setzen Sie auf 1 , wenn Sie zu Akt III gereist sind. |
| 32 | 2 | Setzen Sie auf 1 , wenn Sie in Hratli eingeführt wurden. |
| 34 | [6]quest | Alle sechs Quests für Akt III. |
| 46 | 2 | Setzen Sie auf 1 , wenn Sie in Akt IV gereist sind. |
| 48 | 2 | Setzen Sie auf 1 , wenn Sie in Akt IV vorgestellt wurden. (was Sie haben, wenn Sie gereist sind) |
| 50 | [6]quest | Akt IV hat nur 3 Quests, so dass die Struktur hier 6 leere Bytes hat. |
| 62 | 2 | Setzen Sie auf 1 , wenn Sie zu Akt V gereist sind. |
| 64 | 2 | Scheint auf 1 zu sein, nachdem Terrors Ende abgeschlossen und mit Cain in Akt IV gesprochen wurde. |
| 66 | 4 | Scheint eine Art Polsterung zu sein. |
| 70 | [6]quest | Alle sechs Quests für Akt V. |
| 82 | 14 | Eine Art Polsterung nach all den Questdaten. |
Nicht implementiert
Nicht implementiert
Nach dem Header ist der Abschnitt Attribute, in diesem Abschnittslayout besteht aus einer Array von 9 bit -Attribut -ID, gefolgt von einem n bit -Länge -Attributwert. Der Abschnitt wird mit einem 9 bit -Wert von 0x1ff beendet. Es ist erwähnenswert, dass diese Felder bitter umgekehrt sind. Grundsätzlich, wenn Sie die Bits 00100111 finden, werden sie in 11100100 umgekehrt.
| AUSWEIS | Attribut |
|---|---|
| 0 | Stärke |
| 1 | Energie |
| 2 | Geschicklichkeit |
| 3 | Vitalität |
| 4 | Unbenutzte Statistiken |
| 5 | Unbenutzte Fähigkeiten |
| 6 | Aktuelle HP |
| 7 | Max HP |
| 8 | Aktuelles Mana |
| 9 | Max Mana |
| 10 | Aktuelle Ausdauer |
| 11 | Max -Ausdauer |
| 12 | Ebene |
| 13 | Erfahrung |
| 14 | Gold |
| 15 | Gold aufbewahrt |
| Bitlänge | Attribut |
|---|---|
| 10 | Stärke |
| 10 | Energie |
| 10 | Geschicklichkeit |
| 10 | Vitalität |
| 10 | Unbenutzte Statistiken |
| 8 | Unbenutzte Fähigkeiten |
| 21 | Aktuelle HP |
| 21 | Max HP |
| 21 | Aktuelles Mana |
| 21 | Max Mana |
| 21 | Aktuelle Ausdauer |
| 21 | Max -Ausdauer |
| 7 | Ebene |
| 32 | Erfahrung |
| 25 | Gold |
| 25 | Gold aufbewahrt |
for {
// 1. read 9 bits id. (reverse them)
// 2. if the id is 0x1ff, terminate the loop
// 3. read bit length from attribute map for that id.
// 4. read bit length nr of bits.
} Fertigkeiten sind ein 32 byte -Abschnitt mit einem 2 byte -Header mit dem Wert, if und 30 byte der Skilldaten. Jede Klasse verfügt über 30 Fähigkeiten, sodass jede Fertigkeit jeweils 1 byte erhält. Der schwierige Teil der Skill -Mapping besteht darin, dass jede Klasse einen anderen Versatz in der Skill -Karte hat, in der ihre klassenspezifischen Fähigkeiten beginnen, und dann 30 Indizes in die Karte einfließen. So hat Assassin beispielsweise einen Versatz von 251 . Dies bedeutet, dass Assassin -Fähigkeiten zwischen den Indizes von 251 und 281 liegen, was genau 30 Indizes beträgt.
| Typ | Bytes | Wert |
|---|---|---|
| Kopfball | 2 | if |
| Fähigkeiten | 30 | [30] Geschicklichkeit |
| Klasse | Offset |
|---|---|
| Amazonas | 6 |
| Zauberin | 36 |
| Nekromant | 66 |
| Paladin | 96 |
| Barbar | 126 |
| Druide | 221 |
| Attentäter | 251 |
Dies ist bei weitem der schwierigste Teil zu lesen. Der Abschnitt mit den Elementen beginnt mit einem 4 byte -Header, der den Wert JM enthält, und einen uint16 -Wert, der das Element zählt, das Ihr Zeichen derzeit hat. Ausgestattet, Inventar, Versteck, Würfel und Gürtel enthalten.
Die Byte -Länge des Abschnitts ist unbekannt, bevor es in seiner Gesamtheit gelesen wird, da die Bitlänge jedes Elements je nach Qualität, Anzahl der Steckdosen und magischen Attribute variiert, die sie besitzt.
Jedes Element folgt jedoch einem bestimmten Muster, nämlich:
Jedes Element beginnt mit 111 Bit einfachen Daten, die alle Elemente enthalten. Dies sind Informationen wie der Artikeltyp, wenn er so gesteuert ist, Position wie ausgestattet oder so weiter.
Jedes Element hat auch einen Booleschen namens SimpleItem , der 1 Bit lang ist. Wenn dieser auf 1 gesetzt ist, enthält das Element keine Bits und das nächste Element startet.
Wenn der Artikel keine einfachen Elemente ist, bedeutet dies, dass er nach den ersten 111 Bits Tonnen von Daten enthält. Einige Beispiele hierfür sind das Seltenheit, das magische Suffix, das magische Affix, wenn es sich um ein Runeword, personalisiert, Teil eines Satzes, klassenspezifisch und so weiter.
Last but not zuletzt, wenn das Element Listen von magischen Eigenschaften enthält, je nachdem, ob es sich um ein Runeword, magisch, selten, verarbeitet, einzigartiger Teil des Sets usw. handelt.
Diese Listen ähneln dem Abschnitt Attribute, in dem wir lesen werden:
9 bit idn bits of magical properties0x1ff terminator Wenn wir den Terminator 0x1ff drücken, beginnt der nächste Artikel.
Eine magische Eigenschaft ist eine einzigartige Eigenschaft, die auf einem Artikel auftreten kann, jede Eigenschaft hat eine andere Bitlänge und die Karte ist riesig.
Dies ist die magische Eigenschaft mit ID 83 , die 2 -Bit -Felder pro 3 Bit lang enthält.
83 : {Bits: [] uint { 3 , 3 }, Name : "+{1} to {0} Skill Levels" },Alle magischen Eigenschaften werden in der Datei item.go zugeordnet.
Wenn Ihr Charakter derzeit tot ist und eine Leiche beim Betreten eines Spiels vor Ort ist, befinden sich Ihre ausgestatteten Gegenstände in dieser Artikelstruktur. Es handelt sich um einen Leiche -Header 16 bytes der den Header JM enthält, gefolgt von einer Elementanzahl ähnlich der Elementliste.
Das Lesen der Leicheelemente erfolgt genau wie der vorherige Abschnitt der Elemente.
Wenn Ihr Charakter im Erweiterungslord der Zerstörung geschaffen wird, wenn Sie 2 weitere Abschnitte enthalten.
Die Söldnerabschnitte beginnen mit einem 2 byte -Header mit dem Wert jf , und folgt von einem 4 byte -Element -Header, der die Anzahl der Elemente enthält, die der Söldner derzeit trägt. Die Elemente werden wie jede andere Elementliste gelesen.
Wenn Ihr Charakter sowohl ein Nekromanten als auch ein Erweiterungscharakter ist, beginnt dieser Abschnitt mit einem 3 byte -Header, bei dem die ersten beiden Bytes der Header kf sind, gefolgt von einem Booleschen namens hasGolem , wenn dieser Wert wahr ist, gibt es eine Elementliste mit der Länge 1, die dem Kopfzeile folgt.
Bitte beachten Sie.