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 } }
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, }) } } } }