예제 #1
0
파일: server.go 프로젝트: frustra/fracture
func (s *Server) HandleMessage(message interface{}, conn *network.InternalConnection) {
	switch req := message.(type) {
	case *protobuf.Subscription:
		if req.Subscribe {
			log.Printf("Got subscription from (%d, %d): %s", s.OffsetX, s.OffsetZ, conn)
			s.Listeners[conn] = true
		} else {
			delete(s.Listeners, conn)
		}
	case *protobuf.ChunkRequest:
		chunk := s.GetChunk(req.X, req.Z)

		res := &protobuf.ChunkResponse{
			X:    req.X,
			Z:    req.Z,
			Uuid: req.Uuid,
		}

		if chunk != nil {
			res.Data = chunk.MarshallCompressed()
		} else {
			res.Data = make([]byte, 0)
		}

		conn.SendMessage(res)
	case *protobuf.BlockUpdate:
		s.blockUpdateChannel <- req
	}
}
예제 #2
0
파일: server.go 프로젝트: frustra/fracture
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,
				})
			}
		}
	}
}