func (handler) PlayerListInfo(p *protocol.PlayerInfo) { playerList := Client.playerList.info for _, pl := range p.Players { if _, ok := playerList[pl.UUID]; (!ok && p.Action != 0) || (ok && p.Action == 0) { continue } switch p.Action { case 0: // Add i := &playerInfo{ name: pl.Name, uuid: pl.UUID, displayName: pl.DisplayName, gameMode: gameMode(pl.GameMode), ping: int(pl.Ping), } for _, prop := range pl.Properties { if prop.Name == "textures" { if !prop.IsSigned { Client.network.SignalClose(errors.New("Missing signature from textures")) return } data, err := base64.StdEncoding.DecodeString(prop.Value) if err != nil { Client.network.SignalClose(err) continue } sig, err := base64.StdEncoding.DecodeString(prop.Signature) if err != nil { Client.network.SignalClose(err) continue } if err := verifySkinSignature([]byte(prop.Value), sig); err != nil { Client.network.SignalClose(err) return } var blob skinBlob err = json.Unmarshal(data, &blob) if err != nil { Client.network.SignalClose(err) continue } url := blob.Textures.Skin.Url if strings.HasPrefix(url, "http://textures.minecraft.net/texture/") { i.skinHash = url[len("http://textures.minecraft.net/texture/"):] render.RefSkin(i.skinHash) i.skin = render.Skin(i.skinHash) } url = blob.Textures.Cape.Url if strings.HasPrefix(url, "http://textures.minecraft.net/texture/") { i.capeHash = url[len("http://textures.minecraft.net/texture/"):] render.RefSkin(i.capeHash) i.cape = render.Skin(i.capeHash) } } } if i.skin == nil { i.skin = render.GetTexture("entity/steve") } i.skin = render.RelativeTexture(i.skin, 64, 64) playerList[pl.UUID] = i // Special case for self if !Client.entityAdded && i.uuid == Client.entity.UUID() { Client.entities.container.AddEntity(Client.entity) Client.entityAdded = true } case 1: // Update gamemode playerList[pl.UUID].gameMode = gameMode(pl.GameMode) case 2: // Update ping playerList[pl.UUID].ping = int(pl.Ping) case 3: // Update display name playerList[pl.UUID].displayName = pl.DisplayName case 4: // Remove i := playerList[pl.UUID] if i.skinHash != "" { render.FreeSkin(i.skinHash) } delete(playerList, pl.UUID) } } }
func (s *skullComponent) Deserilize(tag *nbt.Compound) { t, ok := tag.Items["SkullType"].(int8) if !ok { return } s.SkullType = skullType(t) rot, ok := tag.Items["Rot"].(int8) if !ok { return } s.Rotation = int(rot) if s.SkullType != skullPlayer { s.free() s.create() return } owner, ok := tag.Items["Owner"].(*nbt.Compound) if !ok { return } props, ok := owner.Items["Properties"].(*nbt.Compound) if !ok { return } tex, ok := props.Items["textures"].(*nbt.List) if !ok || tex.Type != nbt.TagCompound || len(tex.Elements) < 1 { return } texP := tex.Elements[0].(*nbt.Compound) value := texP.Items["Value"].(string) sigV, hasSig := texP.Items["Signature"].(string) data, err := base64.StdEncoding.DecodeString(value) if err != nil { return } if hasSig { sig, err := base64.StdEncoding.DecodeString(sigV) if err != nil { return } if err := verifySkinSignature([]byte(value), sig); err != nil { return } } var blob skinBlob err = json.Unmarshal(data, &blob) if err != nil { return } url := blob.Textures.Skin.Url // We can only handle textures from textures.minecraft.net currently, // luckily these are the only ones we really see in practice and // mojang seemed to have blocked other urls if strings.HasPrefix(url, "http://textures.minecraft.net/texture/") { s.free() s.Owner = url[len("http://textures.minecraft.net/texture/"):] render.RefSkin(s.Owner) s.OwnerSkin = render.Skin(s.Owner) s.create() } }