diff --git a/3ds/add_friendship_by_pid.go b/3ds/add_friendship_by_pid.go new file mode 100644 index 0000000..d4d1ce5 --- /dev/null +++ b/3ds/add_friendship_by_pid.go @@ -0,0 +1,79 @@ +package friends_3ds + +import ( + database_3ds "github.com/PretendoNetwork/friends-secure/database/3ds" + "github.com/PretendoNetwork/friends-secure/globals" + nex "github.com/PretendoNetwork/nex-go" + nexproto "github.com/PretendoNetwork/nex-protocols-go" +) + +func AddFriendshipByPrincipalID(err error, client *nex.Client, callID uint32, lfc uint64, pid uint32) { + friendRelationship := database_3ds.SaveFriendship(client.PID(), pid) + + connectedUser := globals.ConnectedUsers[pid] + if connectedUser != nil { + go sendFriendshipCompletedNotification(connectedUser.Client, pid, client.PID()) + } + + rmcResponseStream := nex.NewStreamOut(globals.NEXServer) + + rmcResponseStream.WriteStructure(friendRelationship) + + rmcResponseBody := rmcResponseStream.Bytes() + + rmcResponse := nex.NewRMCResponse(nexproto.Friends3DSProtocolID, callID) + rmcResponse.SetSuccess(nexproto.Friends3DSMethodAddFriendByPrincipalID, rmcResponseBody) + + rmcResponseBytes := rmcResponse.Bytes() + + responsePacket, _ := nex.NewPacketV0(client, nil) + + responsePacket.SetVersion(0) + responsePacket.SetSource(0xA1) + responsePacket.SetDestination(0xAF) + responsePacket.SetType(nex.DataPacket) + responsePacket.SetPayload(rmcResponseBytes) + + responsePacket.AddFlag(nex.FlagNeedsAck) + responsePacket.AddFlag(nex.FlagReliable) + + globals.NEXServer.Send(responsePacket) +} + +func sendFriendshipCompletedNotification(client *nex.Client, friendPID uint32, senderPID uint32) { + notificationEvent := nexproto.NewNintendoNotificationEventGeneral() + notificationEvent.U32Param = 0 + notificationEvent.U64Param1 = 0 + notificationEvent.U64Param2 = uint64(friendPID) + + eventObject := nexproto.NewNintendoNotificationEvent() + eventObject.Type = 7 + eventObject.SenderPID = senderPID + eventObject.DataHolder = nex.NewDataHolder() + eventObject.DataHolder.SetTypeName("NintendoNotificationEventGeneral") + eventObject.DataHolder.SetObjectData(notificationEvent) + + stream := nex.NewStreamOut(globals.NEXServer) + eventObjectBytes := eventObject.Bytes(stream) + + rmcRequest := nex.NewRMCRequest() + rmcRequest.SetProtocolID(nexproto.NintendoNotificationsProtocolID) + rmcRequest.SetCallID(3810693103) + rmcRequest.SetMethodID(nexproto.NintendoNotificationsMethodProcessNintendoNotificationEvent1) + rmcRequest.SetParameters(eventObjectBytes) + + rmcRequestBytes := rmcRequest.Bytes() + + requestPacket, _ := nex.NewPacketV0(client, nil) + + requestPacket.SetVersion(0) + requestPacket.SetSource(0xA1) + requestPacket.SetDestination(0xAF) + requestPacket.SetType(nex.DataPacket) + requestPacket.SetPayload(rmcRequestBytes) + + requestPacket.AddFlag(nex.FlagNeedsAck) + requestPacket.AddFlag(nex.FlagReliable) + + globals.NEXServer.Send(requestPacket) +} diff --git a/3ds/get_all_friends.go b/3ds/get_all_friends.go new file mode 100644 index 0000000..aa6bf33 --- /dev/null +++ b/3ds/get_all_friends.go @@ -0,0 +1,36 @@ +package friends_3ds + +import ( + database_3ds "github.com/PretendoNetwork/friends-secure/database/3ds" + "github.com/PretendoNetwork/friends-secure/globals" + nex "github.com/PretendoNetwork/nex-go" + nexproto "github.com/PretendoNetwork/nex-protocols-go" +) + +func GetAllFriends(err error, client *nex.Client, callID uint32) { + friendRelationships := database_3ds.GetUserFriends(client.PID()) + + rmcResponseStream := nex.NewStreamOut(globals.NEXServer) + + rmcResponseStream.WriteListStructure(friendRelationships) + + rmcResponseBody := rmcResponseStream.Bytes() + + rmcResponse := nex.NewRMCResponse(nexproto.Friends3DSProtocolID, callID) + rmcResponse.SetSuccess(nexproto.Friends3DSMethodGetAllFriends, rmcResponseBody) + + rmcResponseBytes := rmcResponse.Bytes() + + responsePacket, _ := nex.NewPacketV0(client, nil) + + responsePacket.SetVersion(0) + responsePacket.SetSource(0xA1) + responsePacket.SetDestination(0xAF) + responsePacket.SetType(nex.DataPacket) + responsePacket.SetPayload(rmcResponseBytes) + + responsePacket.AddFlag(nex.FlagNeedsAck) + responsePacket.AddFlag(nex.FlagReliable) + + globals.NEXServer.Send(responsePacket) +} diff --git a/3ds/get_friend_mii.go b/3ds/get_friend_mii.go new file mode 100644 index 0000000..ec44540 --- /dev/null +++ b/3ds/get_friend_mii.go @@ -0,0 +1,36 @@ +package friends_3ds + +import ( + database_3ds "github.com/PretendoNetwork/friends-secure/database/3ds" + "github.com/PretendoNetwork/friends-secure/globals" + nex "github.com/PretendoNetwork/nex-go" + nexproto "github.com/PretendoNetwork/nex-protocols-go" +) + +func GetFriendMii(err error, client *nex.Client, callID uint32, pids []uint32) { + miiList := database_3ds.GetFriendMiis(pids) + + rmcResponseStream := nex.NewStreamOut(globals.NEXServer) + + rmcResponseStream.WriteListStructure(miiList) + + rmcResponseBody := rmcResponseStream.Bytes() + + rmcResponse := nex.NewRMCResponse(nexproto.Friends3DSProtocolID, callID) + rmcResponse.SetSuccess(nexproto.Friends3DSMethodGetFriendMii, rmcResponseBody) + + rmcResponseBytes := rmcResponse.Bytes() + + responsePacket, _ := nex.NewPacketV0(client, nil) + + responsePacket.SetVersion(0) + responsePacket.SetSource(0xA1) + responsePacket.SetDestination(0xAF) + responsePacket.SetType(nex.DataPacket) + responsePacket.SetPayload(rmcResponseBytes) + + responsePacket.AddFlag(nex.FlagNeedsAck) + responsePacket.AddFlag(nex.FlagReliable) + + globals.NEXServer.Send(responsePacket) +} diff --git a/3ds/get_friend_persistent_info.go b/3ds/get_friend_persistent_info.go new file mode 100644 index 0000000..59f3821 --- /dev/null +++ b/3ds/get_friend_persistent_info.go @@ -0,0 +1,36 @@ +package friends_3ds + +import ( + database_3ds "github.com/PretendoNetwork/friends-secure/database/3ds" + "github.com/PretendoNetwork/friends-secure/globals" + nex "github.com/PretendoNetwork/nex-go" + nexproto "github.com/PretendoNetwork/nex-protocols-go" +) + +func GetFriendPersistentInfo(err error, client *nex.Client, callID uint32, pids []uint32) { + infoList := database_3ds.GetFriendPersistentInfos(client.PID(), pids) + + rmcResponseStream := nex.NewStreamOut(globals.NEXServer) + + rmcResponseStream.WriteListStructure(infoList) + + rmcResponseBody := rmcResponseStream.Bytes() + + rmcResponse := nex.NewRMCResponse(nexproto.Friends3DSProtocolID, callID) + rmcResponse.SetSuccess(nexproto.Friends3DSMethodGetFriendPersistentInfo, rmcResponseBody) + + rmcResponseBytes := rmcResponse.Bytes() + + responsePacket, _ := nex.NewPacketV0(client, nil) + + responsePacket.SetVersion(0) + responsePacket.SetSource(0xA1) + responsePacket.SetDestination(0xAF) + responsePacket.SetType(nex.DataPacket) + responsePacket.SetPayload(rmcResponseBytes) + + responsePacket.AddFlag(nex.FlagNeedsAck) + responsePacket.AddFlag(nex.FlagReliable) + + globals.NEXServer.Send(responsePacket) +} diff --git a/3ds/get_friend_presence.go b/3ds/get_friend_presence.go new file mode 100644 index 0000000..730f139 --- /dev/null +++ b/3ds/get_friend_presence.go @@ -0,0 +1,47 @@ +package friends_3ds + +import ( + "github.com/PretendoNetwork/friends-secure/globals" + nex "github.com/PretendoNetwork/nex-go" + nexproto "github.com/PretendoNetwork/nex-protocols-go" +) + +func GetFriendPresence(err error, client *nex.Client, callID uint32, pids []uint32) { + presenceList := make([]*nexproto.FriendPresence, 0) + + for i := 0; i < len(pids); i++ { + connectedUser := globals.ConnectedUsers[pids[i]] + + if connectedUser != nil && connectedUser.Presence != nil { + friendPresence := nexproto.NewFriendPresence() + friendPresence.PID = pids[i] + friendPresence.Presence = globals.ConnectedUsers[pids[i]].Presence + + presenceList = append(presenceList, friendPresence) + } + } + + rmcResponseStream := nex.NewStreamOut(globals.NEXServer) + + rmcResponseStream.WriteListStructure(presenceList) + + rmcResponseBody := rmcResponseStream.Bytes() + + rmcResponse := nex.NewRMCResponse(nexproto.Friends3DSProtocolID, callID) + rmcResponse.SetSuccess(nexproto.Friends3DSMethodGetFriendPresence, rmcResponseBody) + + rmcResponseBytes := rmcResponse.Bytes() + + responsePacket, _ := nex.NewPacketV0(client, nil) + + responsePacket.SetVersion(0) + responsePacket.SetSource(0xA1) + responsePacket.SetDestination(0xAF) + responsePacket.SetType(nex.DataPacket) + responsePacket.SetPayload(rmcResponseBytes) + + responsePacket.AddFlag(nex.FlagNeedsAck) + responsePacket.AddFlag(nex.FlagReliable) + + globals.NEXServer.Send(responsePacket) +} diff --git a/3ds/get_pid_by_lfc.go b/3ds/get_pid_by_lfc.go new file mode 100644 index 0000000..2006a74 --- /dev/null +++ b/3ds/get_pid_by_lfc.go @@ -0,0 +1,29 @@ +package friends_3ds + +import ( + "github.com/PretendoNetwork/friends-secure/globals" + nex "github.com/PretendoNetwork/nex-go" + nexproto "github.com/PretendoNetwork/nex-protocols-go" +) + +func GetPrincipalIDByLocalFriendCode(err error, client *nex.Client, callID uint32, lfc uint64, lfcList []uint64) { + // Drop this request entirely, waiting for gRPC to retrieve PID from account server + + rmcResponse := nex.NewRMCResponse(nexproto.Friends3DSProtocolID, callID) + rmcResponse.SetSuccess(nexproto.Friends3DSMethodGetPrincipalIDByLocalFriendCode, nil) + + rmcResponseBytes := rmcResponse.Bytes() + + responsePacket, _ := nex.NewPacketV0(client, nil) + + responsePacket.SetVersion(0) + responsePacket.SetSource(0xA1) + responsePacket.SetDestination(0xAF) + responsePacket.SetType(nex.DataPacket) + responsePacket.SetPayload(rmcResponseBytes) + + responsePacket.AddFlag(nex.FlagNeedsAck) + responsePacket.AddFlag(nex.FlagReliable) + + globals.NEXServer.Send(responsePacket) +} diff --git a/3ds/notifications.go b/3ds/notifications.go new file mode 100644 index 0000000..36359ef --- /dev/null +++ b/3ds/notifications.go @@ -0,0 +1,57 @@ +package friends_3ds + +import ( + database_3ds "github.com/PretendoNetwork/friends-secure/database/3ds" + "github.com/PretendoNetwork/friends-secure/globals" + nex "github.com/PretendoNetwork/nex-go" + nexproto "github.com/PretendoNetwork/nex-protocols-go" +) + +// Notifications that are used in other files with no main file + +func SendUserWentOfflineNotificationsGlobally(client *nex.Client) { + friendsList := database_3ds.GetUserFriends(client.PID()) + + for i := 0; i < len(friendsList); i++ { + SendUserWentOfflineNotification(client, friendsList[i].PID) + } +} + +func SendUserWentOfflineNotification(client *nex.Client, pid uint32) { + notificationEvent := nexproto.NewNintendoNotificationEventGeneral() + + eventObject := nexproto.NewNintendoNotificationEvent() + eventObject.Type = 10 + eventObject.SenderPID = client.PID() + eventObject.DataHolder = nex.NewDataHolder() + eventObject.DataHolder.SetTypeName("NintendoNotificationEventGeneral") + eventObject.DataHolder.SetObjectData(notificationEvent) + + stream := nex.NewStreamOut(globals.NEXServer) + eventObjectBytes := eventObject.Bytes(stream) + + rmcRequest := nex.NewRMCRequest() + rmcRequest.SetProtocolID(nexproto.NintendoNotificationsProtocolID) + rmcRequest.SetCallID(3810693103) + rmcRequest.SetMethodID(nexproto.NintendoNotificationsMethodProcessNintendoNotificationEvent1) + rmcRequest.SetParameters(eventObjectBytes) + + rmcRequestBytes := rmcRequest.Bytes() + + connectedUser := globals.ConnectedUsers[pid] + + if connectedUser != nil { + requestPacket, _ := nex.NewPacketV0(connectedUser.Client, nil) + + requestPacket.SetVersion(0) + requestPacket.SetSource(0xA1) + requestPacket.SetDestination(0xAF) + requestPacket.SetType(nex.DataPacket) + requestPacket.SetPayload(rmcRequestBytes) + + requestPacket.AddFlag(nex.FlagNeedsAck) + requestPacket.AddFlag(nex.FlagReliable) + + globals.NEXServer.Send(requestPacket) + } +} diff --git a/3ds/remove_friend_by_lfc.go b/3ds/remove_friend_by_lfc.go new file mode 100644 index 0000000..70f7abc --- /dev/null +++ b/3ds/remove_friend_by_lfc.go @@ -0,0 +1,29 @@ +package friends_3ds + +import ( + "github.com/PretendoNetwork/friends-secure/globals" + nex "github.com/PretendoNetwork/nex-go" + nexproto "github.com/PretendoNetwork/nex-protocols-go" +) + +func RemoveFriendByLocalFriendCode(err error, client *nex.Client, callID uint32, friendLFC uint64) { + // Drop this request entirely, waiting for gRPC to retrieve PID from account server + + rmcResponse := nex.NewRMCResponse(nexproto.Friends3DSProtocolID, callID) + rmcResponse.SetSuccess(nexproto.Friends3DSMethodRemoveFriendByLocalFriendCode, nil) + + rmcResponseBytes := rmcResponse.Bytes() + + responsePacket, _ := nex.NewPacketV0(client, nil) + + responsePacket.SetVersion(0) + responsePacket.SetSource(0xA1) + responsePacket.SetDestination(0xAF) + responsePacket.SetType(nex.DataPacket) + responsePacket.SetPayload(rmcResponseBytes) + + responsePacket.AddFlag(nex.FlagNeedsAck) + responsePacket.AddFlag(nex.FlagReliable) + + globals.NEXServer.Send(responsePacket) +} diff --git a/3ds/remove_friend_by_pid.go b/3ds/remove_friend_by_pid.go new file mode 100644 index 0000000..1498a64 --- /dev/null +++ b/3ds/remove_friend_by_pid.go @@ -0,0 +1,31 @@ +package friends_3ds + +import ( + database_3ds "github.com/PretendoNetwork/friends-secure/database/3ds" + "github.com/PretendoNetwork/friends-secure/globals" + nex "github.com/PretendoNetwork/nex-go" + nexproto "github.com/PretendoNetwork/nex-protocols-go" +) + +func RemoveFriendByPrincipalID(err error, client *nex.Client, callID uint32, pid uint32) { + go SendUserWentOfflineNotification(client, pid) + database_3ds.RemoveFriendship(client.PID(), pid) + + rmcResponse := nex.NewRMCResponse(nexproto.Friends3DSProtocolID, callID) + rmcResponse.SetSuccess(nexproto.Friends3DSMethodRemoveFriendByPrincipalID, nil) + + rmcResponseBytes := rmcResponse.Bytes() + + responsePacket, _ := nex.NewPacketV0(client, nil) + + responsePacket.SetVersion(0) + responsePacket.SetSource(0xA1) + responsePacket.SetDestination(0xAF) + responsePacket.SetType(nex.DataPacket) + responsePacket.SetPayload(rmcResponseBytes) + + responsePacket.AddFlag(nex.FlagNeedsAck) + responsePacket.AddFlag(nex.FlagReliable) + + globals.NEXServer.Send(responsePacket) +} diff --git a/3ds/sync_friend.go b/3ds/sync_friend.go index 60b9c0a..b5b8b3b 100644 --- a/3ds/sync_friend.go +++ b/3ds/sync_friend.go @@ -1,17 +1,39 @@ package friends_3ds import ( + database_3ds "github.com/PretendoNetwork/friends-secure/database/3ds" "github.com/PretendoNetwork/friends-secure/globals" nex "github.com/PretendoNetwork/nex-go" nexproto "github.com/PretendoNetwork/nex-protocols-go" + "golang.org/x/exp/slices" ) -func SyncFriend(err error, client *nex.Client, callID uint32, unknown1 uint64, pids []uint32, unknown3 []uint64) { - // TODO: Do something with this +func SyncFriend(err error, client *nex.Client, callID uint32, lfc uint64, pids []uint32, lfcList []uint64) { + friendRelationships := database_3ds.GetUserFriends(client.PID()) + + for i := 0; i < len(friendRelationships); i++ { + if !slices.Contains(pids, friendRelationships[i].PID) { + database_3ds.RemoveFriendship(client.PID(), friendRelationships[i].PID) + } + } + + for i := 0; i < len(pids); i++ { + if !isPIDInRelationships(friendRelationships, pids[i]) { + friendRelationship := database_3ds.SaveFriendship(client.PID(), pids[i]) + + friendRelationships = append(friendRelationships, friendRelationship) + + // Alert the other side, in case they weren't able to get our presence data + connectedUser := globals.ConnectedUsers[pids[i]] + if connectedUser != nil { + go sendFriendshipCompletedNotification(connectedUser.Client, pids[i], client.PID()) + } + } + } rmcResponseStream := nex.NewStreamOut(globals.NEXServer) - rmcResponseStream.WriteUInt32LE(0) // List length 0 + rmcResponseStream.WriteListStructure(friendRelationships) rmcResponseBody := rmcResponseStream.Bytes() @@ -33,3 +55,12 @@ func SyncFriend(err error, client *nex.Client, callID uint32, unknown1 uint64, p globals.NEXServer.Send(responsePacket) } + +func isPIDInRelationships(relationships []*nexproto.FriendRelationship, pid uint32) bool { + for i := range relationships { + if relationships[i].PID == pid { + return true + } + } + return false +} diff --git a/3ds/update_comment.go b/3ds/update_comment.go index a1a3452..09b822c 100644 --- a/3ds/update_comment.go +++ b/3ds/update_comment.go @@ -1,13 +1,15 @@ package friends_3ds import ( + database_3ds "github.com/PretendoNetwork/friends-secure/database/3ds" "github.com/PretendoNetwork/friends-secure/globals" nex "github.com/PretendoNetwork/nex-go" nexproto "github.com/PretendoNetwork/nex-protocols-go" ) func UpdateComment(err error, client *nex.Client, callID uint32, comment string) { - // TODO: Do something with this + go sendCommentUpdateNotification(client, comment) + database_3ds.UpdateUserComment(client.PID(), comment) rmcResponse := nex.NewRMCResponse(nexproto.Friends3DSProtocolID, callID) rmcResponse.SetSuccess(nexproto.Friends3DSMethodUpdateComment, nil) @@ -27,3 +29,48 @@ func UpdateComment(err error, client *nex.Client, callID uint32, comment string) globals.NEXServer.Send(responsePacket) } + +func sendCommentUpdateNotification(client *nex.Client, comment string) { + notificationEvent := nexproto.NewNintendoNotificationEventGeneral() + notificationEvent.StrParam = comment + + eventObject := nexproto.NewNintendoNotificationEvent() + eventObject.Type = 3 + eventObject.SenderPID = client.PID() + eventObject.DataHolder = nex.NewDataHolder() + eventObject.DataHolder.SetTypeName("NintendoNotificationEventGeneral") + eventObject.DataHolder.SetObjectData(notificationEvent) + + stream := nex.NewStreamOut(globals.NEXServer) + eventObjectBytes := eventObject.Bytes(stream) + + rmcRequest := nex.NewRMCRequest() + rmcRequest.SetProtocolID(nexproto.NintendoNotificationsProtocolID) + rmcRequest.SetCallID(3810693103) + rmcRequest.SetMethodID(nexproto.NintendoNotificationsMethodProcessNintendoNotificationEvent1) + rmcRequest.SetParameters(eventObjectBytes) + + rmcRequestBytes := rmcRequest.Bytes() + + friendsList := database_3ds.GetUserFriends(client.PID()) + + for i := 0; i < len(friendsList); i++ { + + connectedUser := globals.ConnectedUsers[friendsList[i].PID] + + if connectedUser != nil { + requestPacket, _ := nex.NewPacketV0(connectedUser.Client, nil) + + requestPacket.SetVersion(0) + requestPacket.SetSource(0xA1) + requestPacket.SetDestination(0xAF) + requestPacket.SetType(nex.DataPacket) + requestPacket.SetPayload(rmcRequestBytes) + + requestPacket.AddFlag(nex.FlagNeedsAck) + requestPacket.AddFlag(nex.FlagReliable) + + globals.NEXServer.Send(requestPacket) + } + } +} diff --git a/3ds/update_favorite_game_key.go b/3ds/update_favorite_game_key.go index 83d3fd3..20c52de 100644 --- a/3ds/update_favorite_game_key.go +++ b/3ds/update_favorite_game_key.go @@ -1,13 +1,15 @@ package friends_3ds import ( + database_3ds "github.com/PretendoNetwork/friends-secure/database/3ds" "github.com/PretendoNetwork/friends-secure/globals" nex "github.com/PretendoNetwork/nex-go" nexproto "github.com/PretendoNetwork/nex-protocols-go" ) func UpdateFavoriteGameKey(err error, client *nex.Client, callID uint32, gameKey *nexproto.GameKey) { - // TODO: Do something with this + go sendFavoriteUpdateNotification(client, gameKey) + database_3ds.UpdateUserFavoriteGame(client.PID(), gameKey) rmcResponse := nex.NewRMCResponse(nexproto.Friends3DSProtocolID, callID) rmcResponse.SetSuccess(nexproto.Friends3DSMethodUpdateFavoriteGameKey, nil) @@ -27,3 +29,45 @@ func UpdateFavoriteGameKey(err error, client *nex.Client, callID uint32, gameKey globals.NEXServer.Send(responsePacket) } + +func sendFavoriteUpdateNotification(client *nex.Client, gameKey *nexproto.GameKey) { + eventObject := nexproto.NewNintendoNotificationEvent() + eventObject.Type = 2 + eventObject.SenderPID = client.PID() + eventObject.DataHolder = nex.NewDataHolder() + eventObject.DataHolder.SetTypeName("GameKey") + eventObject.DataHolder.SetObjectData(gameKey) + + stream := nex.NewStreamOut(globals.NEXServer) + eventObjectBytes := eventObject.Bytes(stream) + + rmcRequest := nex.NewRMCRequest() + rmcRequest.SetProtocolID(nexproto.NintendoNotificationsProtocolID) + rmcRequest.SetCallID(3810693103) + rmcRequest.SetMethodID(nexproto.NintendoNotificationsMethodProcessNintendoNotificationEvent1) + rmcRequest.SetParameters(eventObjectBytes) + + rmcRequestBytes := rmcRequest.Bytes() + + friendsList := database_3ds.GetUserFriends(client.PID()) + + for i := 0; i < len(friendsList); i++ { + + connectedUser := globals.ConnectedUsers[friendsList[i].PID] + + if connectedUser != nil { + requestPacket, _ := nex.NewPacketV0(connectedUser.Client, nil) + + requestPacket.SetVersion(0) + requestPacket.SetSource(0xA1) + requestPacket.SetDestination(0xAF) + requestPacket.SetType(nex.DataPacket) + requestPacket.SetPayload(rmcRequestBytes) + + requestPacket.AddFlag(nex.FlagNeedsAck) + requestPacket.AddFlag(nex.FlagReliable) + + globals.NEXServer.Send(requestPacket) + } + } +} diff --git a/3ds/update_mii.go b/3ds/update_mii.go index 04c7701..7ab280d 100644 --- a/3ds/update_mii.go +++ b/3ds/update_mii.go @@ -1,13 +1,15 @@ package friends_3ds import ( + database_3ds "github.com/PretendoNetwork/friends-secure/database/3ds" "github.com/PretendoNetwork/friends-secure/globals" nex "github.com/PretendoNetwork/nex-go" nexproto "github.com/PretendoNetwork/nex-protocols-go" ) func UpdateMii(err error, client *nex.Client, callID uint32, mii *nexproto.Mii) { - // TODO: Do something with this + go sendMiiUpdateNotification(client) + database_3ds.UpdateUserMii(client.PID(), mii) rmcResponse := nex.NewRMCResponse(nexproto.Friends3DSProtocolID, callID) rmcResponse.SetSuccess(nexproto.Friends3DSMethodUpdateMii, nil) @@ -27,3 +29,47 @@ func UpdateMii(err error, client *nex.Client, callID uint32, mii *nexproto.Mii) globals.NEXServer.Send(responsePacket) } + +func sendMiiUpdateNotification(client *nex.Client) { + notificationEvent := nexproto.NewNintendoNotificationEventGeneral() + + eventObject := nexproto.NewNintendoNotificationEvent() + eventObject.Type = 5 + eventObject.SenderPID = client.PID() + eventObject.DataHolder = nex.NewDataHolder() + eventObject.DataHolder.SetTypeName("NintendoNotificationEventGeneral") + eventObject.DataHolder.SetObjectData(notificationEvent) + + stream := nex.NewStreamOut(globals.NEXServer) + eventObjectBytes := eventObject.Bytes(stream) + + rmcRequest := nex.NewRMCRequest() + rmcRequest.SetProtocolID(nexproto.NintendoNotificationsProtocolID) + rmcRequest.SetCallID(3810693103) + rmcRequest.SetMethodID(nexproto.NintendoNotificationsMethodProcessNintendoNotificationEvent1) + rmcRequest.SetParameters(eventObjectBytes) + + rmcRequestBytes := rmcRequest.Bytes() + + friendsList := database_3ds.GetUserFriends(client.PID()) + + for i := 0; i < len(friendsList); i++ { + + connectedUser := globals.ConnectedUsers[friendsList[i].PID] + + if connectedUser != nil { + requestPacket, _ := nex.NewPacketV0(connectedUser.Client, nil) + + requestPacket.SetVersion(0) + requestPacket.SetSource(0xA1) + requestPacket.SetDestination(0xAF) + requestPacket.SetType(nex.DataPacket) + requestPacket.SetPayload(rmcRequestBytes) + + requestPacket.AddFlag(nex.FlagNeedsAck) + requestPacket.AddFlag(nex.FlagReliable) + + globals.NEXServer.Send(requestPacket) + } + } +} diff --git a/3ds/update_preferences.go b/3ds/update_preferences.go new file mode 100644 index 0000000..f6030aa --- /dev/null +++ b/3ds/update_preferences.go @@ -0,0 +1,40 @@ +package friends_3ds + +import ( + database_3ds "github.com/PretendoNetwork/friends-secure/database/3ds" + "github.com/PretendoNetwork/friends-secure/globals" + nex "github.com/PretendoNetwork/nex-go" + nexproto "github.com/PretendoNetwork/nex-protocols-go" +) + +func UpdatePreferences(err error, client *nex.Client, callID uint32, showOnline bool, showCurrentGame bool, showPlayedGame bool) { + if !showCurrentGame { + emptyPresence := nexproto.NewNintendoPresence() + emptyPresence.GameKey = nexproto.NewGameKey() + emptyPresence.ChangedFlags = 4294967295 // FF FF FF FF, All flags + sendPresenceUpdateNotification(client, emptyPresence) + } + if !showOnline { + SendUserWentOfflineNotificationsGlobally(client) + } + + database_3ds.UpdateUserPreferences(client.PID(), showOnline, showCurrentGame) + + rmcResponse := nex.NewRMCResponse(nexproto.Friends3DSProtocolID, callID) + rmcResponse.SetSuccess(nexproto.Friends3DSMethodUpdatePreference, nil) + + rmcResponseBytes := rmcResponse.Bytes() + + responsePacket, _ := nex.NewPacketV0(client, nil) + + responsePacket.SetVersion(0) + responsePacket.SetSource(0xA1) + responsePacket.SetDestination(0xAF) + responsePacket.SetType(nex.DataPacket) + responsePacket.SetPayload(rmcResponseBytes) + + responsePacket.AddFlag(nex.FlagNeedsAck) + responsePacket.AddFlag(nex.FlagReliable) + + globals.NEXServer.Send(responsePacket) +} diff --git a/3ds/update_presence.go b/3ds/update_presence.go index cee979d..f00a5e2 100644 --- a/3ds/update_presence.go +++ b/3ds/update_presence.go @@ -1,13 +1,24 @@ package friends_3ds import ( + database_3ds "github.com/PretendoNetwork/friends-secure/database/3ds" "github.com/PretendoNetwork/friends-secure/globals" nex "github.com/PretendoNetwork/nex-go" nexproto "github.com/PretendoNetwork/nex-protocols-go" ) -func UpdatePresence(err error, client *nex.Client, callID uint32, presence *nexproto.NintendoPresence, unknown bool) { - // TODO: Do something with this +func UpdatePresence(err error, client *nex.Client, callID uint32, presence *nexproto.NintendoPresence, showGame bool) { + currentPresence := presence + + // Send an entirely empty status, with every flag set to update + if !showGame { + currentPresence = nexproto.NewNintendoPresence() + currentPresence.GameKey = nexproto.NewGameKey() + currentPresence.ChangedFlags = 4294967295 // FF FF FF FF, All flags + } + + go sendPresenceUpdateNotification(client, currentPresence) + globals.ConnectedUsers[client.PID()].Presence = currentPresence rmcResponse := nex.NewRMCResponse(nexproto.Friends3DSProtocolID, callID) rmcResponse.SetSuccess(nexproto.Friends3DSMethodUpdatePresence, nil) @@ -27,3 +38,46 @@ func UpdatePresence(err error, client *nex.Client, callID uint32, presence *nexp globals.NEXServer.Send(responsePacket) } + +func sendPresenceUpdateNotification(client *nex.Client, presence *nexproto.NintendoPresence) { + eventObject := nexproto.NewNintendoNotificationEvent() + eventObject.Type = 1 + eventObject.SenderPID = client.PID() + eventObject.DataHolder = nex.NewDataHolder() + eventObject.DataHolder.SetTypeName("NintendoPresence") + eventObject.DataHolder.SetObjectData(presence) + + stream := nex.NewStreamOut(globals.NEXServer) + eventObjectBytes := eventObject.Bytes(stream) + + rmcRequest := nex.NewRMCRequest() + rmcRequest.SetProtocolID(nexproto.NintendoNotificationsProtocolID) + rmcRequest.SetCallID(3810693103) + rmcRequest.SetMethodID(nexproto.NintendoNotificationsMethodProcessNintendoNotificationEvent1) + rmcRequest.SetParameters(eventObjectBytes) + + rmcRequestBytes := rmcRequest.Bytes() + + friendsList := database_3ds.GetUserFriends(client.PID()) + + for i := 0; i < len(friendsList); i++ { + + connectedUser := globals.ConnectedUsers[friendsList[i].PID] + + if connectedUser != nil { + + requestPacket, _ := nex.NewPacketV0(connectedUser.Client, nil) + + requestPacket.SetVersion(0) + requestPacket.SetSource(0xA1) + requestPacket.SetDestination(0xAF) + requestPacket.SetType(nex.DataPacket) + requestPacket.SetPayload(rmcRequestBytes) + + requestPacket.AddFlag(nex.FlagNeedsAck) + requestPacket.AddFlag(nex.FlagReliable) + + globals.NEXServer.Send(requestPacket) + } + } +} diff --git a/3ds/update_profile.go b/3ds/update_profile.go index c26fa05..7aac872 100644 --- a/3ds/update_profile.go +++ b/3ds/update_profile.go @@ -1,13 +1,14 @@ package friends_3ds import ( + database_3ds "github.com/PretendoNetwork/friends-secure/database/3ds" "github.com/PretendoNetwork/friends-secure/globals" nex "github.com/PretendoNetwork/nex-go" nexproto "github.com/PretendoNetwork/nex-protocols-go" ) func UpdateProfile(err error, client *nex.Client, callID uint32, profileData *nexproto.MyProfile) { - // TODO: Do something with this + database_3ds.UpdateUserProfile(client.PID(), profileData) rmcResponse := nex.NewRMCResponse(nexproto.Friends3DSProtocolID, callID) rmcResponse.SetSuccess(nexproto.Friends3DSMethodUpdateProfile, nil)