| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- package gen7
- import (
- "bytes"
- "encoding/binary"
- "fmt"
- "strings"
- "unicode/utf16"
- p "github.com/ajswis/go-pkparse-server/pokemon"
- )
- // Parse accepts a raw pokemon (byte slice) and either returns a Pokemon struct
- // with all applicable fields populated or an error depicting the reason for
- // failure.
- func Parse(rawPokemon p.RawPokemon) (*p.Pokemon, error) {
- if l := len(rawPokemon); l < 232 {
- return nil, fmt.Errorf("Invalid length for generation 7 pokemon: %d bytes", l)
- }
- var pkmn p.Pokemon
- pkmn.RawPokemon = &rawPokemon
- pkmn.EncryptionConstant = binary.LittleEndian.Uint32(rawPokemon[0x00:0x08])
- pkmn.PokedexNumber = binary.LittleEndian.Uint16(rawPokemon[0x08:0x0a])
- pkmn.HeldItemID = binary.LittleEndian.Uint16(rawPokemon[0x0a:0x0c])
- pkmn.TrainerID = binary.LittleEndian.Uint16(rawPokemon[0x0c:0x0e])
- pkmn.SecretID = binary.LittleEndian.Uint16(rawPokemon[0x0e:0x10])
- pkmn.FullTrainerID = binary.LittleEndian.Uint32(rawPokemon[0x0c:0x10])
- pkmn.Experience = binary.LittleEndian.Uint32(rawPokemon[0x10:0x15])
- pkmn.AbilityID = rawPokemon[0x14]
- pkmn.AbilityNum = rawPokemon[0x14]
- pkmn.PID = binary.LittleEndian.Uint32(rawPokemon[0x18:0x1c])
- pkmn.NatureID = rawPokemon[0x1c]
- genderByte := rawPokemon[0x1d]
- pkmn.FatefulEncounter = (genderByte & 0x01) == 1
- if (genderByte & 0x02) == 0x02 {
- pkmn.Gender = "F"
- } else if (genderByte & 0x04) == 0x04 {
- pkmn.Gender = ""
- } else {
- pkmn.Gender = "M"
- }
- pkmn.FormID = genderByte >> 3
- pkmn.HPEV = rawPokemon[0x1e]
- pkmn.AtkEV = rawPokemon[0x1f]
- pkmn.DefEV = rawPokemon[0x20]
- pkmn.SpeEV = rawPokemon[0x21]
- pkmn.SpAtkEV = rawPokemon[0x22]
- pkmn.SpDefEV = rawPokemon[0x23]
- pokerusByte := rawPokemon[0x2b]
- pkmn.PokerusDuration = pokerusByte & 15
- pkmn.PokerusStrain = pokerusByte >> 4
- pkmn.RawNickname = rawPokemon[0x40:0x58]
- pkmn.Nickname = binaryToUTF16leString(pkmn.RawNickname)
- pkmn.Move1ID = binary.LittleEndian.Uint16(rawPokemon[0x5a:0x5c])
- pkmn.Move2ID = binary.LittleEndian.Uint16(rawPokemon[0x5c:0x5e])
- pkmn.Move3ID = binary.LittleEndian.Uint16(rawPokemon[0x5e:0x60])
- pkmn.Move4ID = binary.LittleEndian.Uint16(rawPokemon[0x60:0x62])
- pkmn.Move1PP = rawPokemon[0x62]
- pkmn.Move2PP = rawPokemon[0x63]
- pkmn.Move3PP = rawPokemon[0x64]
- pkmn.Move4PP = rawPokemon[0x65]
- pkmn.Move1PPUsed = rawPokemon[0x66]
- pkmn.Move2PPUsed = rawPokemon[0x67]
- pkmn.Move3PPUsed = rawPokemon[0x68]
- pkmn.Move4PPUsed = rawPokemon[0x69]
- pkmn.EggMove1ID = binary.LittleEndian.Uint16(rawPokemon[0x6a:0x6c])
- pkmn.EggMove2ID = binary.LittleEndian.Uint16(rawPokemon[0x6c:0x6e])
- pkmn.EggMove3ID = binary.LittleEndian.Uint16(rawPokemon[0x6e:0x70])
- pkmn.EggMove4ID = binary.LittleEndian.Uint16(rawPokemon[0x70:0x72])
- ivBytes := binary.LittleEndian.Uint32(rawPokemon[0x74:0x78])
- pkmn.HPIV = ivBytes & 0x1f
- pkmn.AtkIV = ivBytes >> 5 & 0x1f
- pkmn.DefIV = ivBytes >> 10 & 0x1f
- pkmn.SpeIV = ivBytes >> 15 & 0x1f
- pkmn.SpAtkIV = ivBytes >> 20 & 0x1f
- pkmn.SpDefIV = ivBytes >> 25 & 0x1f
- pkmn.IsEgg = ((ivBytes >> 30) % 2) == 1
- pkmn.IsNicknamed = ((ivBytes >> 31) % 2) == 1
- return &pkmn, nil
- }
- func binaryToUTF16leString(b []byte) string {
- r := bytes.NewReader(b)
- u16 := make([]uint16, len(b)/2)
- binary.Read(r, binary.LittleEndian, &u16)
- runes := utf16.Decode(u16)
- s := strings.Split(string(runes), "\u0000")[0]
- return s
- }
|