Example #1
0
func (n *networkManager) Connect(profile mojang.Profile, server string) {
	logLevel := networkLog.Value()
	go func() {
		var err error
		n.conn, err = protocol.Dial(server)
		if err != nil {
			n.SignalClose(err)
			return
		}
		if logLevel > 0 {
			n.conn.Logger = func(read bool, packet protocol.Packet) {
				if !read && logLevel < 2 {
					return
				}
				if logLevel < 3 {
					switch packet.(type) {
					case *protocol.ChunkData:
						return
					}
				}
				dir := "read"
				if !read {
					dir = "write"
				}
				console.Text("%s[%s] %T%+v", server, dir, packet, packet)
			}
		}

		err = n.conn.LoginToServer(profile)
		if err != nil {
			n.SignalClose(err)
			return
		}

	preLogin:
		for {
			packet, err := n.conn.ReadPacket()
			if err != nil {
				n.SignalClose(err)
				return
			}
			switch packet := packet.(type) {
			case *protocol.SetInitialCompression:
				n.conn.SetCompression(int(packet.Threshold))
			case *protocol.LoginSuccess:
				n.conn.State = protocol.Play
				break preLogin
			case *protocol.LoginDisconnect:
				n.SignalClose(errors.New(packet.Reason.String()))
				return
			default:
				n.SignalClose(fmt.Errorf("unhandled packet %T", packet))
				return
			}
		}

		first := true
		for {
			packet, err := n.conn.ReadPacket()
			if err != nil {
				n.SignalClose(err)
				return
			}
			if first {
				go n.writeHandler()
				first = false
			}

			// Handle keep alives async as there is no need to process them
			switch packet := packet.(type) {
			case *protocol.KeepAliveClientbound:
				n.Write(&protocol.KeepAliveServerbound{ID: packet.ID})
			case *protocol.SetCompression:
				n.conn.SetCompression(int(packet.Threshold))
			default:
				n.readChan <- packet
			}
		}
	}()
}
Example #2
0
func (sl *serverList) pingServer(addr string, motd, version *ui.Formatted,
	icon *ui.Image, id string, ping *ui.Image, players *ui.Text) {
	conn, err := protocol.Dial(addr)
	if err != nil {
		syncChan <- func() {
			msg := &format.TextComponent{Text: err.Error()}
			msg.Color = format.Red
			motd.Update(format.Wrap(msg))
		}
		return
	}
	defer conn.Close()
	resp, pingTime, err := conn.RequestStatus()
	syncChan <- func() {
		if err != nil {
			msg := &format.TextComponent{Text: err.Error()}
			msg.Color = format.Red
			motd.Update(format.Wrap(msg))
			return
		}
		y := 0.0
		pt := pingTime.Seconds() / 1000
		switch {
		case pt <= 75:
			y = 16 / 256.0
		case pt <= 150:
			y = 24 / 256.0
		case pt <= 225:
			y = 32 / 256.0
		case pt <= 350:
			y = 40 / 256.0
		case pt < 999:
			y = 48 / 256.0
		default:
			y = 56 / 256.0
		}
		ping.SetTextureY(y)

		if resp.Version.Protocol == protocol.SupportedProtocolVersion {
			players.SetG(255)
			players.SetB(255)
			players.Update(fmt.Sprintf("%d/%d", resp.Players.Online, resp.Players.Max))
		} else {
			players.SetG(85)
			players.SetB(85)
			players.Update(fmt.Sprintf("Out of date %d/%d", resp.Players.Online, resp.Players.Max))
		}
		txt := &format.TextComponent{Text: resp.Version.Name}
		txt.Color = format.Yellow
		ver := format.Wrap(txt)
		format.ConvertLegacy(ver)
		version.Update(ver)

		desc := resp.Description
		format.ConvertLegacy(desc)
		motd.Update(desc)

		if strings.HasPrefix(resp.Favicon, "data:image/png;base64,") {
			favicon := resp.Favicon[len("data:image/png;base64,"):]
			data, err := base64.StdEncoding.DecodeString(favicon)
			if err != nil {
				fmt.Printf("error base64 decoding favicon: %s\n", err)
				return
			}
			img, err := png.Decode(bytes.NewReader(data))
			if err != nil {
				fmt.Printf("error decoding favicon: %s\n", err)
				return
			}
			render.AddIcon(id, img)
			icon.SetTexture(render.Icon(id))
		}
	}
}