enumerate friends list across characters

This commit is contained in:
wish
2022-07-17 03:10:45 +10:00
parent 70b5fe4eb7
commit cd26a96dfd
5 changed files with 95 additions and 26 deletions

View File

@@ -1,6 +1,8 @@
package stringsupport package stringsupport
import ( import (
"strings"
"strconv"
"bytes" "bytes"
"io/ioutil" "io/ioutil"
@@ -114,6 +116,35 @@ func PaddedString(x string, size uint, t bool) []byte {
return out return out
} }
func CSVAdd(csv string, v int) string {
if len(csv) == 0 {
return strconv.Itoa(v)
}
return csv + "," + strconv.Itoa(v)
}
func CSVRemove(csv string, v int) string {
s := strings.Split(csv, ",")
for i, e := range s {
if e == strconv.Itoa(v) {
s[i] = s[len(s) - 1]
s = s[:len(s) - 1]
}
}
return strings.Join(s, ",")
}
func CSVContains(csv string, v int) bool {
s := strings.Split(csv, ",")
for i := 0; i < len(s); i++ {
j, _ := strconv.ParseInt(s[i], 10, 64)
if int(j) == v {
return true
}
}
return false
}
// ConvertUTF8ToShiftJIS converts a UTF8 string to a Shift-JIS []byte. // ConvertUTF8ToShiftJIS converts a UTF8 string to a Shift-JIS []byte.
func ConvertUTF8ToShiftJIS(text string) ([]byte, error) { func ConvertUTF8ToShiftJIS(text string) ([]byte, error) {
r := bytes.NewBuffer([]byte(text)) r := bytes.NewBuffer([]byte(text))

View File

@@ -9,7 +9,13 @@ import (
) )
// MsgMhfOprMember represents the MSG_MHF_OPR_MEMBER // MsgMhfOprMember represents the MSG_MHF_OPR_MEMBER
type MsgMhfOprMember struct{} type MsgMhfOprMember struct {
AckHandle uint32
Blacklist bool
Operation bool
Unk uint16
CharID uint32
}
// Opcode returns the ID associated with this packet type. // Opcode returns the ID associated with this packet type.
func (m *MsgMhfOprMember) Opcode() network.PacketID { func (m *MsgMhfOprMember) Opcode() network.PacketID {
@@ -18,7 +24,12 @@ func (m *MsgMhfOprMember) Opcode() network.PacketID {
// Parse parses the packet from binary // Parse parses the packet from binary
func (m *MsgMhfOprMember) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { func (m *MsgMhfOprMember) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
return errors.New("NOT IMPLEMENTED") m.AckHandle = bf.ReadUint32()
m.Blacklist = bf.ReadBool()
m.Operation = bf.ReadBool()
m.Unk = bf.ReadUint16()
m.CharID = bf.ReadUint32()
return nil
} }
// Build builds a binary packet from the current data. // Build builds a binary packet from the current data.

View File

@@ -1,6 +1,7 @@
package channelserver package channelserver
import ( import (
"erupe-ce/common/stringsupport"
"erupe-ce/network/mhfpacket" "erupe-ce/network/mhfpacket"
"erupe-ce/common/byteframe" "erupe-ce/common/byteframe"
"go.uber.org/zap" "go.uber.org/zap"
@@ -60,8 +61,26 @@ func handleMsgMhfListMember(s *Session, p mhfpacket.MHFPacket) {
} }
func handleMsgMhfOprMember(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfOprMember(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfListMember) pkt := p.(*mhfpacket.MsgMhfOprMember)
// TODO: add targetid(uint32) to charid(uint32)'s database under new field var csv string
if pkt.Blacklist {
if pkt.Operation {
// remove from blacklist
} else {
// add to blacklist
}
} else { // Friendlist
err := s.server.db.QueryRow("SELECT friends FROM characters WHERE id=$1", s.charID).Scan(&csv)
if err != nil {
panic(err)
}
if pkt.Operation {
csv = stringsupport.CSVRemove(csv, int(pkt.CharID))
} else {
csv = stringsupport.CSVAdd(csv, int(pkt.CharID))
}
_, _ = s.server.db.Exec("UPDATE characters SET friends=$1 WHERE id=$2", csv, s.charID)
}
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
} }

View File

@@ -88,7 +88,7 @@ type character struct {
func (s *Server) getCharactersForUser(uid int) ([]character, error) { func (s *Server) getCharactersForUser(uid int) ([]character, error) {
characters := []character{} characters := []character{}
err := s.db.Select(&characters, "SELECT id, is_female, is_new_character, name, unk_desc_string, hrp, gr, weapon_type, last_login FROM characters WHERE user_id = $1 AND deleted = false ORDER BY last_login DESC", uid) err := s.db.Select(&characters, "SELECT id, is_female, is_new_character, name, unk_desc_string, hrp, gr, weapon_type, last_login FROM characters WHERE user_id = $1 AND deleted = false", uid)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -96,28 +96,36 @@ func (s *Server) getCharactersForUser(uid int) ([]character, error) {
} }
type members struct { type members struct {
CID uint32 // Local character ID
ID uint32 `db:"id"` ID uint32 `db:"id"`
Name string `db:"name"` Name string `db:"name"`
} }
func (s *Server) getFriendsForCharacter(cid uint32) ([]members, error) { func (s *Server) getFriendsForCharacters(chars []character) ([]members, error) {
friends := []members{} friends := make([]members, 0)
var friendsCSV string for _, char := range chars {
err := s.db.QueryRow("SELECT friends FROM characters WHERE id=$1", cid).Scan(&friendsCSV) friendsCSV := ""
friendsSlice := strings.Split(friendsCSV, ",") err := s.db.QueryRow("SELECT friends FROM characters WHERE id=$1", char.ID).Scan(&friendsCSV)
if friendsSlice[0] == "" { friendsSlice := strings.Split(friendsCSV, ",")
return nil, nil friendQuery := "SELECT id, name FROM characters WHERE id="
} for i := 0; i < len(friendsSlice); i++ {
friendQuery := "SELECT id, name FROM characters WHERE id=" friendQuery += friendsSlice[i]
for i := 0; i < len(friendsSlice); i++ { if i + 1 != len(friendsSlice) {
friendQuery += friendsSlice[i] friendQuery += " OR id="
if i + 1 != len(friendsSlice) { }
friendQuery += " OR id="
} }
charFriends := []members{}
err = s.db.Select(&charFriends, friendQuery)
if err != nil {
continue
}
for i, _ := range charFriends {
charFriends[i].CID = char.ID
}
friends = append(friends, charFriends...)
} }
err = s.db.Select(&friends, friendQuery) if len(friends) > 255 { // Uint8
if err != nil { friends = friends[:255]
return nil, err
} }
return friends, nil return friends, nil
} }

View File

@@ -75,13 +75,13 @@ func (s *Session) makeSignInResp(uid int) []byte {
bf.WriteUint16(0) // Unk bf.WriteUint16(0) // Unk
} }
friends, err := s.server.getFriendsForCharacter(lastPlayed) friends, err := s.server.getFriendsForCharacters(chars)
if err != nil || friends == nil { if err != nil || len(friends) == 0 {
bf.WriteUint8(0) bf.WriteUint8(0)
} else { } else {
bf.WriteUint8(uint8(len(friends))) bf.WriteUint8(uint8(len(friends)))
for _, friend := range friends { for _, friend := range friends {
bf.WriteUint32(lastPlayed) bf.WriteUint32(friend.CID)
bf.WriteUint32(friend.ID) bf.WriteUint32(friend.ID)
ps.Uint8(bf, friend.Name, true) ps.Uint8(bf, friend.Name, true)
} }