diff --git a/server/client.go b/server/client.go index c93efb8..f3cfae5 100644 --- a/server/client.go +++ b/server/client.go @@ -90,7 +90,12 @@ type SessionClient struct { system string // do not compare directly; use isPrivatedTo - private, singleplayer bool + private bool + // 1 = hide everybody but party members and friends + // 2 = hide everybody (singleplayer) + // 4 = hide friends + // 8 = hide party members + privateHideType int hideLocation bool partyId int @@ -172,9 +177,37 @@ func (c *SessionClient) disconnect() { writeLog(c.uuid, "sess", "disconnect", 200) } +func (c *SessionClient) isSingleplayer() bool { + hideAll := 2 + // hide strangers, friends, and party members + hideAllImplicit := 1 | 4 | 8 + return (c.privateHideType & hideAll) != 0 || + (c.privateHideType & hideAllImplicit) == hideAllImplicit +} + func (c *SessionClient) isPrivatedTo(other *SessionClient) bool { - return (c.private || other.private) && ((c.singleplayer || other.singleplayer) || - (other.partyId == 0 || c.partyId != other.partyId) && !c.onlineFriends[other.uuid]) + if !c.private && !other.private { + return false + } + + const hideStrangers = 1 + const hideAll = 2 + const hideFriends = 4 + const hideParty = 8 + + privateHideType := c.privateHideType | other.privateHideType + + if (privateHideType & hideAll) != 0 { + return true + } + + areFriends := c.onlineFriends[other.uuid] + arePartyMembers := other.partyId != 0 && c.partyId == other.partyId + areStrangers := !areFriends && !arePartyMembers + + return (areStrangers && (privateHideType & hideStrangers) != 0) || + (areFriends && (privateHideType & hideFriends) != 0) || + (arePartyMembers && (privateHideType & hideParty) != 0) } func (c *SessionClient) isBlockedWith(other *SessionClient) bool { diff --git a/server/friends.go b/server/friends.go index 6b78b4b..69ce4d3 100644 --- a/server/friends.go +++ b/server/friends.go @@ -119,7 +119,7 @@ func getPlayerFriendData(uuid string) (playerFriends []*PlayerFriend, err error) playerFriend.Badge = client.badge playerFriend.Medals = client.medals - if client.roomC != nil && !(client.hideLocation && client.singleplayer) { + if client.roomC != nil && !(client.hideLocation && client.isSingleplayer()) { playerFriend.MapId = client.roomC.mapId playerFriend.PrevMapId = client.roomC.prevMapId playerFriend.PrevLocations = client.roomC.prevLocations diff --git a/server/handlers.go b/server/handlers.go index 4b4c746..e75ea2e 100644 --- a/server/handlers.go +++ b/server/handlers.go @@ -1334,8 +1334,13 @@ func (c *SessionClient) handlePr(msg []string) error { return errors.New("segment count mismatch") } - c.singleplayer = msg[1] == "2" - c.private = c.singleplayer || msg[1] == "1" + privateHideType, err := strconv.Atoi(msg[1]) + if err != nil { + return err + } + + c.privateHideType = privateHideType + c.private = privateHideType != 0 return nil } diff --git a/server/party.go b/server/party.go index b7bf6de..a209b3b 100644 --- a/server/party.go +++ b/server/party.go @@ -133,13 +133,13 @@ func getPartyData(partyId int) (*Party, error) { member.Badge = client.badge member.Medals = client.medals - if client.roomC != nil && !(client.hideLocation && client.singleplayer) { + if client.roomC != nil && !(client.hideLocation && client.isSingleplayer()) { member.MapId = client.roomC.mapId member.PrevMapId = client.roomC.prevMapId member.PrevLocations = client.roomC.prevLocations member.X = client.roomC.x member.Y = client.roomC.y - } else if client.roomC != nil && (client.hideLocation && client.singleplayer) { + } else if client.roomC != nil && (client.hideLocation && client.isSingleplayer()) { member.MapId = "0000" member.PrevMapId = "0000" member.PrevLocations = ""