implement mail locking

This commit is contained in:
wishu
2022-06-08 10:52:56 +10:00
parent c8cdff1163
commit 356e498389
2 changed files with 64 additions and 23 deletions

View File

@@ -12,12 +12,14 @@ type OperateMailOperation uint8
const ( const (
OPERATE_MAIL_DELETE = 0x01 OPERATE_MAIL_DELETE = 0x01
OPERATE_MAIL_LOCK = 0x02
OPERATE_MAIL_UNLOCK = 0x03
OPERATE_MAIL_ACQUIRE_ITEM = 0x05 OPERATE_MAIL_ACQUIRE_ITEM = 0x05
) )
// MsgMhfOprtMail represents the MSG_MHF_OPRT_MAIL // MsgMhfOprtMail represents the MSG_MHF_OPRT_MAIL
type MsgMhfOprtMail struct { type MsgMhfOprtMail struct {
AckHandle uint32 AckHandle uint32
AccIndex uint8 AccIndex uint8
Index uint8 Index uint8
Operation OperateMailOperation Operation OperateMailOperation
@@ -34,7 +36,7 @@ func (m *MsgMhfOprtMail) Opcode() network.PacketID {
// Parse parses the packet from binary // Parse parses the packet from binary
func (m *MsgMhfOprtMail) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { func (m *MsgMhfOprtMail) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
m.AckHandle = bf.ReadUint32() m.AckHandle = bf.ReadUint32()
m.AccIndex = bf.ReadUint8() m.AccIndex = bf.ReadUint8()
m.Index = bf.ReadUint8() m.Index = bf.ReadUint8()
m.Operation = OperateMailOperation(bf.ReadUint8()) m.Operation = OperateMailOperation(bf.ReadUint8())

View File

@@ -4,7 +4,6 @@ import (
"database/sql" "database/sql"
"time" "time"
"github.com/Solenataris/Erupe/common/stringsupport"
"github.com/Solenataris/Erupe/network/binpacket" "github.com/Solenataris/Erupe/network/binpacket"
"github.com/Solenataris/Erupe/network/mhfpacket" "github.com/Solenataris/Erupe/network/mhfpacket"
"github.com/Andoryuuta/byteframe" "github.com/Andoryuuta/byteframe"
@@ -19,9 +18,10 @@ type Mail struct {
Body string `db:"body"` Body string `db:"body"`
Read bool `db:"read"` Read bool `db:"read"`
Deleted bool `db:"deleted"` Deleted bool `db:"deleted"`
Locked bool `db:"locked"`
AttachedItemReceived bool `db:"attached_item_received"` AttachedItemReceived bool `db:"attached_item_received"`
AttachedItemID *uint16 `db:"attached_item"` AttachedItemID uint16 `db:"attached_item"`
AttachedItemAmount int16 `db:"attached_item_amount"` AttachedItemAmount uint16 `db:"attached_item_amount"`
CreatedAt time.Time `db:"created_at"` CreatedAt time.Time `db:"created_at"`
IsGuildInvite bool `db:"is_guild_invite"` IsGuildInvite bool `db:"is_guild_invite"`
SenderName string `db:"sender_name"` SenderName string `db:"sender_name"`
@@ -49,8 +49,8 @@ func (m *Mail) Send(s *Session, transaction *sql.Tx) error {
zap.Uint32("recipientID", m.RecipientID), zap.Uint32("recipientID", m.RecipientID),
zap.String("subject", m.Subject), zap.String("subject", m.Subject),
zap.String("body", m.Body), zap.String("body", m.Body),
zap.Uint16p("itemID", m.AttachedItemID), zap.Uint16("itemID", m.AttachedItemID),
zap.Int16("itemAmount", m.AttachedItemAmount), zap.Uint16("itemAmount", m.AttachedItemAmount),
zap.Bool("isGuildInvite", m.IsGuildInvite), zap.Bool("isGuildInvite", m.IsGuildInvite),
) )
return err return err
@@ -110,6 +110,23 @@ func (m *Mail) MarkAcquired(s *Session) error {
return nil return nil
} }
func (m *Mail) MarkLocked(s *Session, locked bool) error {
_, err := s.server.db.Exec(`
UPDATE mail SET locked = $1 WHERE id = $2
`, locked, m.ID)
if err != nil {
s.logger.Error(
"failed to mark mail as locked",
zap.Error(err),
zap.Int("mailID", m.ID),
)
return err
}
return nil
}
func GetMailListForCharacter(s *Session, charID uint32) ([]Mail, error) { func GetMailListForCharacter(s *Session, charID uint32) ([]Mail, error) {
rows, err := s.server.db.Queryx(` rows, err := s.server.db.Queryx(`
SELECT SELECT
@@ -124,6 +141,7 @@ func GetMailListForCharacter(s *Session, charID uint32) ([]Mail, error) {
m.created_at, m.created_at,
m.is_guild_invite, m.is_guild_invite,
m.deleted, m.deleted,
m.locked,
c.name as sender_name c.name as sender_name
FROM mail m FROM mail m
JOIN characters c ON c.id = m.sender_id JOIN characters c ON c.id = m.sender_id
@@ -171,6 +189,7 @@ func GetMailByID(s *Session, ID int) (*Mail, error) {
m.created_at, m.created_at,
m.is_guild_invite, m.is_guild_invite,
m.deleted, m.deleted,
m.locked,
c.name as sender_name c.name as sender_name
FROM mail m FROM mail m
JOIN characters c ON c.id = m.sender_id JOIN characters c ON c.id = m.sender_id
@@ -255,8 +274,9 @@ func handleMsgMhfReadMail(s *Session, p mhfpacket.MHFPacket) {
_ = mail.MarkRead(s) _ = mail.MarkRead(s)
bf := byteframe.NewByteFrame() bf := byteframe.NewByteFrame()
bodyBytes, _ := stringsupport.ConvertUTF8ToShiftJIS(mail.Body)
bf.WriteNullTerminatedBytes(bodyBytes) body := s.clientContext.StrConv.MustEncode(mail.Body)
bf.WriteNullTerminatedBytes(body)
doAckBufSucceed(s, pkt.AckHandle, bf.Data()) doAckBufSucceed(s, pkt.AckHandle, bf.Data())
} }
@@ -286,9 +306,10 @@ func handleMsgMhfListMail(s *Session, p mhfpacket.MHFPacket) {
s.mailList[accIndex] = m.ID s.mailList[accIndex] = m.ID
s.mailAccIndex++ s.mailAccIndex++
itemAttached := m.AttachedItemID != nil
subjectBytes, _ := stringsupport.ConvertUTF8ToShiftJIS(m.Subject) itemAttached := m.AttachedItemID != 0
senderNameBytes, _ := stringsupport.ConvertUTF8ToShiftJIS(m.SenderName) subject := s.clientContext.StrConv.MustEncode(m.Subject)
sender := s.clientContext.StrConv.MustEncode(m.SenderName)
msg.WriteUint32(m.SenderID) msg.WriteUint32(m.SenderID)
msg.WriteUint32(uint32(m.CreatedAt.Unix())) msg.WriteUint32(uint32(m.CreatedAt.Unix()))
@@ -302,28 +323,34 @@ func handleMsgMhfListMail(s *Session, p mhfpacket.MHFPacket) {
flags |= 0x01 flags |= 0x01
} }
if m.Locked {
flags |= 0x02
}
// System message, hides ID
// flags |= 0x04
// Mitigate game crash
flags |= 0x08
if m.AttachedItemReceived { if m.AttachedItemReceived {
flags |= 0x08 // flags |= 0x08
} }
if m.IsGuildInvite { if m.IsGuildInvite {
// Guild Invite
flags |= 0x10 flags |= 0x10
// System message?
flags |= 0x04
} }
msg.WriteUint8(flags) msg.WriteUint8(flags)
msg.WriteBool(itemAttached) msg.WriteBool(itemAttached)
msg.WriteUint8(uint8(len(subjectBytes)+1)) msg.WriteUint8(uint8(len(subject)+1))
msg.WriteUint8(uint8(len(senderNameBytes)+1)) msg.WriteUint8(uint8(len(sender)+1))
msg.WriteNullTerminatedBytes(subjectBytes) msg.WriteNullTerminatedBytes(subject)
msg.WriteNullTerminatedBytes(senderNameBytes) msg.WriteNullTerminatedBytes(sender)
// TODO: The game will crash if it attempts to receive items
if itemAttached { if itemAttached {
msg.WriteInt16(m.AttachedItemAmount) msg.WriteUint16(m.AttachedItemAmount)
msg.WriteUint16(*m.AttachedItemID) msg.WriteUint16(m.AttachedItemID)
} }
} }
@@ -347,6 +374,18 @@ func handleMsgMhfOprtMail(s *Session, p mhfpacket.MHFPacket) {
doAckSimpleFail(s, pkt.AckHandle, nil) doAckSimpleFail(s, pkt.AckHandle, nil)
panic(err) panic(err)
} }
case mhfpacket.OPERATE_MAIL_LOCK:
err = mail.MarkLocked(s, true)
if err != nil {
doAckSimpleFail(s, pkt.AckHandle, nil)
panic(err)
}
case mhfpacket.OPERATE_MAIL_UNLOCK:
err = mail.MarkLocked(s, false)
if err != nil {
doAckSimpleFail(s, pkt.AckHandle, nil)
panic(err)
}
case mhfpacket.OPERATE_MAIL_ACQUIRE_ITEM: case mhfpacket.OPERATE_MAIL_ACQUIRE_ITEM:
err = mail.MarkAcquired(s) err = mail.MarkAcquired(s)
if err != nil { if err != nil {