diff --git a/config.json b/config.json index 977a68948..2c688ec51 100644 --- a/config.json +++ b/config.json @@ -16,6 +16,7 @@ "FestaEvent": 0, "TournamentEvent": 0, "MezFesEvent": true, + "DisableMailItems": true, "SaveDumps": { "Enabled": true, "OutputDir": "savedata" diff --git a/config/config.go b/config/config.go index 5d6c65838..e4f916321 100644 --- a/config/config.go +++ b/config/config.go @@ -36,6 +36,7 @@ type DevModeOptions struct { FestaEvent int // Hunter's Festa event status TournamentEvent int // VS Tournament event status MezFesEvent bool // MezFes status + DisableMailItems bool // Hack to prevent english versions of MHF from crashing SaveDumps SaveDumpOptions } diff --git a/network/mhfpacket/msg_mhf_oprt_mail.go b/network/mhfpacket/msg_mhf_oprt_mail.go index 5da66f115..2c9e06828 100644 --- a/network/mhfpacket/msg_mhf_oprt_mail.go +++ b/network/mhfpacket/msg_mhf_oprt_mail.go @@ -1,20 +1,20 @@ package mhfpacket import ( - "errors" + "errors" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) type OperateMailOperation uint8 const ( - OPERATE_MAIL_DELETE = 0x01 - OPERATE_MAIL_LOCK = 0x02 - OPERATE_MAIL_UNLOCK = 0x03 - OPERATE_MAIL_ACQUIRE_ITEM = 0x05 + OPERATE_MAIL_DELETE = 0x01 + OPERATE_MAIL_LOCK = 0x02 + OPERATE_MAIL_UNLOCK = 0x03 + OPERATE_MAIL_ACQUIRE_ITEM = 0x05 ) // MsgMhfOprtMail represents the MSG_MHF_OPRT_MAIL @@ -23,10 +23,10 @@ type MsgMhfOprtMail struct { AccIndex uint8 Index uint8 Operation OperateMailOperation - Unk0 uint8 - Data []byte - Amount uint16 - ItemID uint16 + Unk0 uint8 + Data []byte + Amount uint16 + ItemID uint16 } // Opcode returns the ID associated with this packet type. @@ -40,12 +40,11 @@ func (m *MsgMhfOprtMail) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientCon m.AccIndex = bf.ReadUint8() m.Index = bf.ReadUint8() m.Operation = OperateMailOperation(bf.ReadUint8()) - m.Unk0 = bf.ReadUint8() - switch m.Operation { - case OPERATE_MAIL_ACQUIRE_ITEM: - m.Amount = bf.ReadUint16() - m.ItemID = bf.ReadUint16() - } + m.Unk0 = bf.ReadUint8() + if m.Operation == OPERATE_MAIL_ACQUIRE_ITEM { + m.Amount = bf.ReadUint16() + m.ItemID = bf.ReadUint16() + } return nil } diff --git a/network/mhfpacket/msg_mhf_send_mail.go b/network/mhfpacket/msg_mhf_send_mail.go index f6f7c9460..e0f34ba54 100644 --- a/network/mhfpacket/msg_mhf_send_mail.go +++ b/network/mhfpacket/msg_mhf_send_mail.go @@ -1,23 +1,24 @@ package mhfpacket import ( - "errors" + "errors" + "erupe-ce/common/stringsupport" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) // MsgMhfSendMail represents the MSG_MHF_SEND_MAIL type MsgMhfSendMail struct { - AckHandle uint32 - RecipientID uint32 - SubjectLength uint16 - BodyLength uint16 - Quantity uint32 - ItemID uint16 - Subject []byte - Body []byte + AckHandle uint32 + RecipientID uint32 + SubjectLength uint16 + BodyLength uint16 + Quantity uint32 + ItemID uint16 + Subject string + Body string } // Opcode returns the ID associated with this packet type. @@ -27,15 +28,15 @@ func (m *MsgMhfSendMail) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfSendMail) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { - m.AckHandle = bf.ReadUint32() - m.RecipientID = bf.ReadUint32() - m.SubjectLength = bf.ReadUint16() - m.BodyLength = bf.ReadUint16() - m.Quantity = bf.ReadUint32() - m.ItemID = bf.ReadUint16() - m.Subject = bf.ReadNullTerminatedBytes() - m.Body = bf.ReadNullTerminatedBytes() - return nil + m.AckHandle = bf.ReadUint32() + m.RecipientID = bf.ReadUint32() + m.SubjectLength = bf.ReadUint16() + m.BodyLength = bf.ReadUint16() + m.Quantity = bf.ReadUint32() + m.ItemID = bf.ReadUint16() + m.Subject = stringsupport.SJISToUTF8(bf.ReadNullTerminatedBytes()) + m.Body = stringsupport.SJISToUTF8(bf.ReadNullTerminatedBytes()) + return nil } // Build builds a binary packet from the current data. diff --git a/server/channelserver/handlers_mail.go b/server/channelserver/handlers_mail.go index ac6d5dcae..1e060b245 100644 --- a/server/channelserver/handlers_mail.go +++ b/server/channelserver/handlers_mail.go @@ -2,6 +2,7 @@ package channelserver import ( "database/sql" + "erupe-ce/common/stringsupport" "time" "erupe-ce/common/byteframe" @@ -275,7 +276,7 @@ func handleMsgMhfReadMail(s *Session, p mhfpacket.MHFPacket) { bf := byteframe.NewByteFrame() - body := s.clientContext.StrConv.MustEncode(mail.Body) + body := stringsupport.UTF8ToSJIS(mail.Body) bf.WriteNullTerminatedBytes(body) doAckBufSucceed(s, pkt.AckHandle, bf.Data()) @@ -307,13 +308,11 @@ func handleMsgMhfListMail(s *Session, p mhfpacket.MHFPacket) { s.mailAccIndex++ itemAttached := m.AttachedItemID != 0 - subject := s.clientContext.StrConv.MustEncode(m.Subject) - sender := s.clientContext.StrConv.MustEncode(m.SenderName) msg.WriteUint32(m.SenderID) msg.WriteUint32(uint32(m.CreatedAt.Unix())) - msg.WriteUint8(uint8(accIndex)) + msg.WriteUint8(accIndex) msg.WriteUint8(uint8(i)) flags := uint8(0x00) @@ -329,8 +328,15 @@ func handleMsgMhfListMail(s *Session, p mhfpacket.MHFPacket) { // System message, hides ID // flags |= 0x04 - if m.AttachedItemReceived { - flags |= 0x08 + // Workaround until EN mail items are patched + if s.server.erupeConfig.DevMode && s.server.erupeConfig.DevModeOptions.DisableMailItems { + if itemAttached { + flags |= 0x08 + } + } else { + if m.AttachedItemReceived { + flags |= 0x08 + } } if m.IsGuildInvite { @@ -339,11 +345,10 @@ func handleMsgMhfListMail(s *Session, p mhfpacket.MHFPacket) { msg.WriteUint8(flags) msg.WriteBool(itemAttached) - msg.WriteUint8(uint8(len(subject) + 1)) - msg.WriteUint8(uint8(len(sender) + 1)) - msg.WriteNullTerminatedBytes(subject) - msg.WriteNullTerminatedBytes(sender) - + msg.WriteUint8(16) + msg.WriteUint8(21) + msg.WriteBytes(stringsupport.PaddedString(m.Subject, 16, true)) + msg.WriteBytes(stringsupport.PaddedString(m.SenderName, 21, true)) if itemAttached { msg.WriteUint16(m.AttachedItemAmount) msg.WriteUint16(m.AttachedItemID) @@ -358,34 +363,22 @@ func handleMsgMhfOprtMail(s *Session, p mhfpacket.MHFPacket) { mail, err := GetMailByID(s, s.mailList[pkt.AccIndex]) if err != nil { - doAckSimpleFail(s, pkt.AckHandle, nil) panic(err) } - switch mhfpacket.OperateMailOperation(pkt.Operation) { + + switch pkt.Operation { case mhfpacket.OPERATE_MAIL_DELETE: err = mail.MarkDeleted(s) - if err != nil { - doAckSimpleFail(s, pkt.AckHandle, nil) - 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: err = mail.MarkAcquired(s) - if err != nil { - doAckSimpleFail(s, pkt.AckHandle, nil) - panic(err) - } + } + + if err != nil { + panic(err) } doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))