Пример #1
0
func (cc *GameConnection) HandleNewConnection() {
	defer func() {
		delete(cc.Server.PlayerConnections, cc.Player.Uuid)
		cc.EntityServer = nil
	}()

	cc.Server.PlayerConnections[cc.Player.Uuid] = make(chan *protocol.Packet, 256)
	cc.Player.EntityId = int64(len(cc.Server.PlayerConnections)+1) + cc.Server.Offset
	cc.Player.HeadY = 105
	cc.Player.FeetY = 105 - 1.62
	cc.Player.OnGround = true

	var err error
	cc.EntityServer, err = cc.Server.FindEntityServer(cc.Player)
	if err != nil {
		log.Printf("Failed to connect to entity server: %s", err)
		protocol.WriteNewPacket(cc.ConnEncrypted, protocol.PreAuthKickID, protocol.CreateJsonMessage("Failed to connect to entity server!", ""))
		return
	}
	cc.EntityServer.SendMessage(&protobuf.PlayerAction{
		Player: cc.Player,
		Action: protobuf.PlayerAction_JOIN,
	})

	var x, z int64
	for x = -8; x < 8; x++ {
		for z = -8; z < 8; z++ {
			conn, err := cc.Server.Cluster.ChunkConnection(x, z, cc.Server)
			if err != nil {
				log.Printf("Failed to connect to chunk server (%d, %d): %s", x, z, err)
				protocol.WriteNewPacket(cc.ConnEncrypted, protocol.PreAuthKickID, protocol.CreateJsonMessage("Failed to connect to chunk server!", ""))
				return
			}
			conn.SendMessage(&protobuf.ChunkRequest{
				X:    x,
				Z:    z,
				Uuid: cc.Player.Uuid,
			})
		}
	}

	protocol.WriteNewPacket(cc.ConnEncrypted, protocol.LoginSuccessID, cc.Player.Uuid, cc.Player.Username)
	protocol.WriteNewPacket(cc.ConnEncrypted, protocol.JoinGameID, int32(cc.Player.EntityId), uint8(1), byte(0), uint8(1), uint8(cc.Server.Size), "default")
	protocol.WriteNewPacket(cc.ConnEncrypted, protocol.SpawnPositionID, int32(0), int32(128), int32(0))
	protocol.WriteNewPacket(cc.ConnEncrypted, protocol.PlayerAbilitiesID, byte(1), float32(0.05), float32(0.1))
	protocol.WriteNewPacket(cc.ConnEncrypted, protocol.PlayerPositionAndLookID, cc.Player.X, cc.Player.HeadY, cc.Player.Z, cc.Player.Yaw, cc.Player.Pitch, cc.Player.OnGround)

	go cc.Server.DrainPlayerConnections(cc)
	cc.HandleEncryptedConnection()
}
Пример #2
0
func (cc *GameConnection) HandleAuth() {
	defer func() {
		delete(cc.Server.Clients, cc)
		cc.Conn.Close()
	}()
	remoteAddr := cc.Conn.RemoteAddr().String()

	state := 0
	verifyToken := make([]byte, 0)
	for {
		cc.Conn.SetReadDeadline(time.Now().Add(time.Second * 10))
		id, buf, err := protocol.ReadPacket(cc.Conn)
		if err != nil {
			err2, ok := err.(net.Error)
			if ok && err2.Timeout() {
				log.Printf("Timeout handling connection (%s): %s", remoteAddr, err2.Error())
			}
			return
		} else {
			switch id {
			case 0x00: // Handshake, Status Request, Login start
				if state == 1 {
					log.Printf("Server pinged from: %s", remoteAddr)

					protocol.WriteNewPacket(cc.Conn, protocol.StatusResponseID, cc.Server.GetMinecraftStatus())
				} else if state == 2 {
					cc.Player.Username, _ = protocol.ReadString(buf, 0)
					log.Printf("Got connection from %s", cc.Player.Username)
					defer log.Printf("Connection closed for %s", cc.Player.Username)

					pubKey := cc.Server.keyPair.Serialize()
					verifyToken = protocol.GenerateKey(16)
					protocol.WriteNewPacket(cc.Conn, protocol.EncryptionRequestID, "", int16(len(pubKey)), pubKey, int16(len(verifyToken)), verifyToken)
				} else {
					_, n := protocol.ReadVarint(buf, 0) // version
					_, n = protocol.ReadString(buf, n)  // address
					_, n = protocol.ReadShort(buf, n)   // port

					nextstate, n := protocol.ReadVarint(buf, n)
					state = int(nextstate)
				}
			case 0x01: // Encryption Response, Ping Request
				if state == 2 {
					secretLen, n := protocol.ReadShort(buf, 0)
					secretEncrypted, n := protocol.ReadBytes(buf, n, secretLen)
					tokenLen, n := protocol.ReadShort(buf, n)
					tokenEncrypted, n := protocol.ReadBytes(buf, n, tokenLen)

					verifyToken2, err := protocol.DecryptRSABytes(tokenEncrypted, cc.Server.keyPair)
					if err != nil {
						log.Printf("Error decrypting RSA token: %s", err.Error())
						return
					} else if !bytes.Equal(verifyToken, verifyToken2) {
						log.Printf("Error: verification token did not match!")
						return
					}
					sharedSecret, err := protocol.DecryptRSABytes(secretEncrypted, cc.Server.keyPair)
					if err != nil {
						log.Printf("Error decrypting RSA secret: %s", err.Error())
						return
					}

					cc.ConnEncrypted, err = protocol.NewAESConn(cc.Conn, sharedSecret)
					if err != nil {
						log.Printf("Error creating AES connection: %s", err.Error())
					}

					cc.Player.Uuid, err = protocol.CheckAuth(cc.Player.Username, "", cc.Server.keyPair, sharedSecret)
					if err != nil {
						log.Printf("Failed to verify username %s: %s", cc.Player.Username, err)
						protocol.WriteNewPacket(cc.ConnEncrypted, protocol.PreAuthKickID, protocol.CreateJsonMessage("Failed to verify username!", ""))
						return
					}

					// protocol.WriteNewPacket(cc.ConnEncrypted, protocol.PreAuthKickID, protocol.CreateJsonMessage("Server will bbl", "blue"))
					cc.HandleNewConnection()
					return
				} else {
					time, _ := protocol.ReadLong(buf, 0)
					//fmt.Printf("Ping: %d\n", time)
					protocol.WriteNewPacket(cc.Conn, protocol.PingResponseID, time)
					return
				}
			default:
				log.Printf("Unknown Packet (state:%d): 0x%X : %s", state, id, hex.Dump(buf))
				return
			}
		}
	}
}
Пример #3
0
func (s *Server) HandleMessage(message interface{}, conn *network.InternalConnection) {
	switch req := message.(type) {
	case *protobuf.ChatMessage:
		player := s.Players[req.Uuid]
		message := protocol.CreateJsonMessage("<"+player.Username+"> "+req.Message, "")
		log.Printf("Chat: %s", message.Message)
		for uuid, p := range s.Players {
			p.Conn.SendMessage(&protobuf.ChatMessage{
				Message: message.String(),
				Uuid:    uuid,
			})
		}
	case *protobuf.BlockUpdate:
		for uuid, p := range s.Players {
			p.Conn.SendMessage(&protobuf.BlockUpdate{
				X:             req.X,
				Y:             req.Y,
				Z:             req.Z,
				BlockId:       req.BlockId,
				BlockMetadata: req.BlockMetadata,
				Uuid:          uuid,
			})
		}
	case *protobuf.PlayerAction:
		player, action := req.GetPlayer(), req.GetAction()
		switch action {
		case protobuf.PlayerAction_JOIN:
			s.Players[player.Uuid] = &PlayerEntity{
				Player: protobuf.Player{
					Uuid:     player.Uuid,
					Username: player.Username,
					EntityId: player.EntityId,
					X:        0,
					HeadY:    105,
					FeetY:    105 - 1.62,
					Z:        0,
				},
				LastX: 0,
				LastY: 105 - 1.62,
				LastZ: 0,
				Conn:  conn,
			}

			log.Printf("Player joined (%d): %s", player.EntityId, player.Username)

			cx, cz := world.ChunkCoordsToNode(0, 0)
			for ix := cx; ix >= cx-world.ChunkWidthPerNode; ix -= world.ChunkWidthPerNode {
				for iz := cz; iz >= cz-world.ChunkWidthPerNode; iz -= world.ChunkWidthPerNode {
					conn, err := s.Cluster.ChunkConnection(ix, iz, s)
					if err != nil {
						log.Printf("Chunk subscription error (%d, %d): %s", ix, iz, err)
						continue
					}
					conn.SendMessage(&protobuf.Subscription{
						Subscribe: true,
					})
				}
			}

			for uuid, p := range s.Players {
				p.Conn.SendMessage(&protobuf.PlayerAction{
					Player: &s.Players[player.Uuid].Player,
					Action: protobuf.PlayerAction_JOIN,
					Uuid:   uuid,
				})
				if uuid != player.Uuid {
					conn.SendMessage(&protobuf.PlayerAction{
						Player: &p.Player,
						Action: protobuf.PlayerAction_JOIN,
						Uuid:   player.Uuid,
					})
				}
			}
		case protobuf.PlayerAction_MOVE_ABSOLUTE:
			responseType := protobuf.PlayerAction_MOVE_RELATIVE

			tmp := s.Players[player.Uuid]
			if req.Flags&1 == 1 {
				if math.Abs(player.X-tmp.LastX) > 3 ||
					math.Abs(player.FeetY-tmp.LastY) > 3 ||
					math.Abs(player.Z-tmp.LastZ) > 3 {
					responseType = protobuf.PlayerAction_MOVE_ABSOLUTE
					tmp.LastX = player.X
					tmp.LastY = player.FeetY
					tmp.LastZ = player.Z
				}
			}

			for uuid, p := range s.Players {
				if uuid != player.Uuid {
					sendPlayer := protobuf.Player{
						Uuid:     player.Uuid,
						EntityId: tmp.EntityId,
					}
					if responseType == protobuf.PlayerAction_MOVE_ABSOLUTE {
						sendPlayer.X = player.X
						sendPlayer.HeadY = player.HeadY
						sendPlayer.FeetY = player.FeetY
						sendPlayer.Z = player.Z
					} else if req.Flags&1 == 1 {
						sendPlayer.X = player.X - tmp.X
						sendPlayer.FeetY = player.FeetY - tmp.FeetY
						sendPlayer.Z = player.Z - tmp.Z
					}
					if req.Flags&2 == 2 {
						sendPlayer.Pitch = player.Pitch
						sendPlayer.Yaw = player.Yaw
					}
					p.Conn.SendMessage(&protobuf.PlayerAction{
						Player: &sendPlayer,
						Action: responseType,
						Uuid:   uuid,
						Flags:  req.Flags,
					})
				}
			}

			if req.Flags&1 == 1 {
				tmp.X = player.X
				tmp.HeadY = player.HeadY
				tmp.FeetY = player.FeetY
				tmp.Z = player.Z
			}
			if req.Flags&2 == 2 {
				tmp.Pitch = player.Pitch
				tmp.Yaw = player.Yaw
			}
		case protobuf.PlayerAction_LEAVE:
			tmp := s.Players[player.Uuid]
			delete(s.Players, player.Uuid)

			log.Printf("Player left: %s", tmp.Username)

			for uuid, p := range s.Players {
				sendPlayer := protobuf.Player{
					Uuid:     player.Uuid,
					Username: tmp.Username,
					EntityId: tmp.EntityId,
				}
				p.Conn.SendMessage(&protobuf.PlayerAction{
					Player: &sendPlayer,
					Action: protobuf.PlayerAction_LEAVE,
					Uuid:   uuid,
				})
			}
		}
	}
}
Пример #4
0
func (s *Server) HandleMessage(message interface{}, conn *network.InternalConnection) {
	switch msg := message.(type) {
	case *protobuf.ChunkResponse:
		s.PlayerConnections[msg.Uuid] <- protocol.CreatePacket(protocol.MapChunkBulkID, int16(1), int32(len(msg.Data)), true, msg.Data, int32(msg.X), int32(msg.Z), uint16(0xFFFF), uint16(0))
	case *protobuf.ChatMessage:
		s.PlayerConnections[msg.Uuid] <- protocol.CreatePacket(protocol.ChatMessageID, msg.Message)
	case *protobuf.BlockUpdate:
		log.Printf("Sending block update to: %s", msg.Uuid)
		s.PlayerConnections[msg.Uuid] <- protocol.CreatePacket(protocol.BlockChangeID, int32(msg.X), uint8(msg.Y), int32(msg.Z), protocol.Varint{uint64(msg.BlockId)}, uint8(msg.BlockMetadata))
	case *protobuf.PlayerAction:
		switch msg.Action {
		case protobuf.PlayerAction_JOIN:
			s.PlayerConnections[msg.Uuid] <- protocol.CreatePacket(protocol.PlayerListItemID, msg.Player.Username, true, int16(0))
			s.PlayerConnections[msg.Uuid] <- protocol.CreatePacket(protocol.ChatMessageID, protocol.CreateJsonMessage(msg.Player.Username+" joined the game", "yellow"))
			if msg.Uuid != msg.Player.Uuid {
				meta := protocol.NewMetadata(
					protocol.AbsorptionHeartsID, float32(0),
					protocol.OnFireID, false,
					protocol.UnknownBitFieldID, byte(0),
					protocol.AirID, uint16(0x012c),
					protocol.ScoreID, uint32(0),
					protocol.HealthID, float32(20),
					protocol.PotionColorID, int32(0),
					protocol.AmbientPotionID, byte(0),
					protocol.ArrowCountID, byte(0),
				)

				s.PlayerConnections[msg.Uuid] <- protocol.CreatePacket(protocol.SpawnPlayerID,
					protocol.Varint{uint64(msg.Player.EntityId)},
					msg.Player.Uuid,
					msg.Player.Username,
					protocol.Varint{0},
					int32(msg.Player.X*32),
					int32(msg.Player.FeetY*32),
					int32(msg.Player.Z*32),
					byte(msg.Player.Yaw*256/2/math.Pi),
					byte(msg.Player.Pitch*256/2/math.Pi),
					int16(0),
					meta,
				)
				s.PlayerConnections[msg.Uuid] <- protocol.CreatePacket(protocol.EntityMetadataID,
					int32(msg.Player.EntityId),
					meta,
				)
				s.PlayerConnections[msg.Uuid] <- protocol.CreatePacket(protocol.EntityPropertiesID,
					int32(msg.Player.EntityId),
					int32(2),
					"generic.maxHealth", float64(20), int16(0),
					"generic.movementSpeed", float64(0.1), int16(0),
				)
				s.PlayerConnections[msg.Uuid] <- protocol.CreatePacket(protocol.EntityTeleportID,
					int32(msg.Player.EntityId),
					int32(msg.Player.X*32),
					int32(msg.Player.FeetY*32),
					int32(msg.Player.Z*32),
					byte(msg.Player.Yaw*256/360),
					byte(msg.Player.Pitch*256/360),
				)
			}
		case protobuf.PlayerAction_MOVE_RELATIVE:
			if msg.Flags == 1 {
				s.PlayerConnections[msg.Uuid] <- protocol.CreatePacket(protocol.EntityRelativeMoveID,
					int32(msg.Player.EntityId),
					byte(msg.Player.X*32),
					byte(msg.Player.FeetY*32),
					byte(msg.Player.Z*32),
				)
			} else if msg.Flags == 2 {
				s.PlayerConnections[msg.Uuid] <- protocol.CreatePacket(protocol.EntityLookID,
					int32(msg.Player.EntityId),
					byte(msg.Player.Yaw*256/360),
					byte(msg.Player.Pitch*256/360),
				)
			} else if msg.Flags == 3 {
				s.PlayerConnections[msg.Uuid] <- protocol.CreatePacket(protocol.EntityLookAndMoveID,
					int32(msg.Player.EntityId),
					byte(msg.Player.X*32),
					byte(msg.Player.FeetY*32),
					byte(msg.Player.Z*32),
					byte(msg.Player.Yaw*256/360),
					byte(msg.Player.Pitch*256/360),
				)
			}
			if msg.Flags&2 == 2 {
				s.PlayerConnections[msg.Uuid] <- protocol.CreatePacket(protocol.EntityHeadLookID, int32(msg.Player.EntityId), byte(msg.Player.Yaw*256/360))
			}
		case protobuf.PlayerAction_MOVE_ABSOLUTE:
			s.PlayerConnections[msg.Uuid] <- protocol.CreatePacket(protocol.EntityTeleportID,
				int32(msg.Player.EntityId),
				int32(msg.Player.X*32),
				int32(msg.Player.FeetY*32),
				int32(msg.Player.Z*32),
				byte(msg.Player.Yaw*256/360),
				byte(msg.Player.Pitch*256/360),
			)
			s.PlayerConnections[msg.Uuid] <- protocol.CreatePacket(protocol.EntityHeadLookID, int32(msg.Player.EntityId), byte(msg.Player.Yaw*256/360))
		case protobuf.PlayerAction_LEAVE:
			s.PlayerConnections[msg.Uuid] <- protocol.CreatePacket(protocol.DestroyEntitiesID, byte(1), int32(msg.Player.EntityId))
			s.PlayerConnections[msg.Uuid] <- protocol.CreatePacket(protocol.PlayerListItemID, msg.Player.Username, false, int16(0))
			s.PlayerConnections[msg.Uuid] <- protocol.CreatePacket(protocol.ChatMessageID, protocol.CreateJsonMessage(msg.Player.Username+" left the game", "yellow"))
		}
	}
}