diff --git a/src/main/java/emu/grasscutter/game/GenshinPlayer.java b/src/main/java/emu/grasscutter/game/GenshinPlayer.java index 16f321a0e..16b45b9b8 100644 --- a/src/main/java/emu/grasscutter/game/GenshinPlayer.java +++ b/src/main/java/emu/grasscutter/game/GenshinPlayer.java @@ -1,5 +1,8 @@ package emu.grasscutter.game; +import java.time.Instant; +import java.util.*; + import dev.morphia.annotations.*; import emu.grasscutter.GenshinConstants; import emu.grasscutter.Grasscutter; @@ -588,8 +591,9 @@ public class GenshinPlayer { Mail message = getMailById(mailId); if(message != null) { - this.mail.remove(message); - this.save(); + int index = getMailIndex(message); + message.expireTime = (int) Instant.now().getEpochSecond(); // Just set the mail as expired for now. I don't want to implement a counter specifically for an account... + this.replaceMailByIndex(index, message); return true; } @@ -604,9 +608,10 @@ public class GenshinPlayer { return this.mail.indexOf(message); } - public boolean replaceMailByIndex(int mailId, Mail message) { - if(getMailById(mailId) != null) { - this.mail.set(mailId, message); + public boolean replaceMailByIndex(int index, Mail message) { + if(getMailById(index) != null) { + this.mail.set(index, message); + this.save(); return true; } else { return false; diff --git a/src/main/java/emu/grasscutter/game/Mail.java b/src/main/java/emu/grasscutter/game/Mail.java index 1ace4610f..67a592a33 100644 --- a/src/main/java/emu/grasscutter/game/Mail.java +++ b/src/main/java/emu/grasscutter/game/Mail.java @@ -25,14 +25,14 @@ public class Mail { itemList = new ArrayList<>(); sendTime = 0; expireTime = 0; - importance = 1; + importance = 0; // Starred mail, 0 = No star, 1 = Star. isRead = true; isAttachmentGot = true; - stateValue = 1; + stateValue = 1; // Different mailboxes, 1 = Default, 3 = Gift-box. } public Mail(MailContent mailContent, List itemList, long expireTime) { - this(mailContent, itemList, expireTime, 1); + this(mailContent, itemList, expireTime, 0); } public Mail(MailContent mailContent, List itemList, long expireTime, int importance) { @@ -90,19 +90,24 @@ public class Mail { public static class MailItem { public int itemId; public int itemCount; + public int itemLevel; public MailItem() { this.itemId = 11101; this.itemCount = 1; + this.itemLevel = 1; } public MailItem(int itemId) { this(itemId, 1); } - public MailItem(int itemId, int itemCount) { + public MailItem(int itemId, int itemCount) { this(itemId, itemCount, 1); } + + public MailItem(int itemId, int itemCount, int itemLevel) { this.itemId = itemId; this.itemCount = itemCount; + this.itemLevel = itemLevel; } } } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerDelMailReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerDelMailReq.java new file mode 100644 index 000000000..4c6473996 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerDelMailReq.java @@ -0,0 +1,21 @@ +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.DelMailReqOuterClass; +import emu.grasscutter.net.proto.DeleteFriendReqOuterClass; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketDelMailRsp; + +@Opcodes(PacketOpcodes.DelMailReq) +public class HandlerDelMailReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + DelMailReqOuterClass.DelMailReq req = DelMailReqOuterClass.DelMailReq.parseFrom(payload); + + session.send(new PacketDelMailRsp(session.getPlayer(), req.getMailIdListList())); + } + +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketDelMailRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketDelMailRsp.java new file mode 100644 index 000000000..6a11521a5 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketDelMailRsp.java @@ -0,0 +1,29 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.GenshinPlayer; +import emu.grasscutter.net.packet.GenshinPacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.DelMailRspOuterClass.DelMailRsp; + +import java.util.ArrayList; +import java.util.List; + +public class PacketDelMailRsp extends GenshinPacket { + + public PacketDelMailRsp(GenshinPlayer player, List toDeleteIds) { + super(PacketOpcodes.DelMailRsp); + + DelMailRsp.Builder proto = DelMailRsp.newBuilder(); + + List deletedIds = new ArrayList<>(); + + for(int mailId : toDeleteIds) { + if(player.deleteMail(mailId)) { + deletedIds.add(mailId); + } + } + + this.setData(proto.build()); + player.getSession().send(new PacketMailChangeNotify(player, null, deletedIds)); + } +} \ No newline at end of file diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetAllMailRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetAllMailRsp.java index b8a36e1bf..756b6f347 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetAllMailRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetAllMailRsp.java @@ -12,6 +12,7 @@ import emu.grasscutter.net.proto.MailDataOuterClass.MailData; import emu.grasscutter.net.proto.MailItemOuterClass; import emu.grasscutter.net.proto.MailTextContentOuterClass.MailTextContent; +import java.time.Instant; import java.util.ArrayList; import java.util.Base64; import java.util.List; @@ -38,41 +39,45 @@ public class PacketGetAllMailRsp extends GenshinPacket { List mailDataList = new ArrayList(); for (Mail message : player.getAllMail()) { - if(message.stateValue == 1) { //Make sure it isn't a gift - MailTextContent.Builder mailTextContent = MailTextContent.newBuilder(); - mailTextContent.setTitle(message.mailContent.title); - mailTextContent.setContent(message.mailContent.content); - mailTextContent.setSender(message.mailContent.sender); + if(message.stateValue == 1) { // Make sure it isn't a gift + if (message.expireTime < Instant.now().getEpochSecond()) { // Make sure the message isn't expired (The game won't show expired mail, but I don't want to send unnecessary information). + if(mailDataList.size() <= 1000) { // Make sure that there isn't over 1000 messages in the mailbox. (idk what will happen if there is but the game probably won't like it.) + MailTextContent.Builder mailTextContent = MailTextContent.newBuilder(); + mailTextContent.setTitle(message.mailContent.title); + mailTextContent.setContent(message.mailContent.content); + mailTextContent.setSender(message.mailContent.sender); - List mailItems = new ArrayList<>(); + List mailItems = new ArrayList<>(); - for (Mail.MailItem item : message.itemList) { - MailItemOuterClass.MailItem.Builder mailItem = MailItemOuterClass.MailItem.newBuilder(); - ItemParamOuterClass.ItemParam.Builder itemParam = ItemParamOuterClass.ItemParam.newBuilder(); - itemParam.setItemId(item.itemId); - itemParam.setCount(item.itemCount); - mailItem.setItemParam(itemParam.build()); + for (Mail.MailItem item : message.itemList) { + MailItemOuterClass.MailItem.Builder mailItem = MailItemOuterClass.MailItem.newBuilder(); + ItemParamOuterClass.ItemParam.Builder itemParam = ItemParamOuterClass.ItemParam.newBuilder(); + itemParam.setItemId(item.itemId); + itemParam.setCount(item.itemCount); + mailItem.setItemParam(itemParam.build()); - mailItems.add(mailItem.build()); + mailItems.add(mailItem.build()); + } + + MailDataOuterClass.MailData.Builder mailData = MailDataOuterClass.MailData.newBuilder(); + mailData.setMailId(message._id); + mailData.setMailTextContent(mailTextContent.build()); + mailData.addAllItemList(mailItems); + mailData.setSendTime((int) message.sendTime); + mailData.setExpireTime((int) message.expireTime); + mailData.setImportance(message.importance); + mailData.setIsRead(message.isRead); + mailData.setIsAttachmentGot(message.isAttachmentGot); + mailData.setStateValue(1); + + mailDataList.add(mailData.build()); + } } - - MailDataOuterClass.MailData.Builder mailData = MailDataOuterClass.MailData.newBuilder(); - mailData.setMailId(message._id); - mailData.setMailTextContent(mailTextContent.build()); - mailData.addAllItemList(mailItems); - mailData.setSendTime((int) message.sendTime); - mailData.setExpireTime((int) message.expireTime); - mailData.setImportance(message.importance); - mailData.setIsRead(message.isRead); - mailData.setIsAttachmentGot(message.isAttachmentGot); - mailData.setStateValue(1); - - mailDataList.add(mailData.build()); } } proto.addAllMailList(mailDataList); - proto.setIsTruncated(false); // When enabled this will send a notification to the user that their inbox is full when opening the mailbox. + proto.setIsTruncated(mailDataList.size() <= 1000 ? false : true); // When enabled this will send a notification to the user telling them their inbox is full and they should delete old messages when opening the mailbox. this.setData(proto.build()); } else { diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketGetMailItemRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketGetMailItemRsp.java index a31c6c2db..79f0072ae 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketGetMailItemRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketGetMailItemRsp.java @@ -1,6 +1,5 @@ package emu.grasscutter.server.packet.send; -import emu.grasscutter.Grasscutter; import emu.grasscutter.data.GenshinData; import emu.grasscutter.game.GenshinPlayer; import emu.grasscutter.game.Mail; @@ -10,8 +9,6 @@ import emu.grasscutter.net.packet.GenshinPacket; import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.proto.EquipParamOuterClass; import emu.grasscutter.net.proto.GetMailItemRspOuterClass.GetMailItemRsp; -import emu.grasscutter.net.proto.ItemParamOuterClass; -import emu.grasscutter.net.proto.MailItemOuterClass; import java.util.ArrayList; import java.util.List; @@ -22,9 +19,6 @@ public class PacketGetMailItemRsp extends GenshinPacket { public PacketGetMailItemRsp(GenshinPlayer player, List mailList) { super(PacketOpcodes.GetMailItemRsp); - //I'm assuming that this is to receive the attachments on the message. - // TODO: This. - List claimedMessages = new ArrayList<>(); List claimedItems = new ArrayList<>(); @@ -34,13 +28,7 @@ public class PacketGetMailItemRsp extends GenshinPacket { Mail message = player.getMailById(mailId); int messageIndex = player.getMailIndex(message); - message.isAttachmentGot = true; - claimedMessages.add(message); - - player.replaceMailByIndex(messageIndex, message); - for(Mail.MailItem mailItem : message.itemList) { - //TODO: Actually give the item EquipParamOuterClass.EquipParam.Builder item = EquipParamOuterClass.EquipParam.newBuilder(); item.setItemId(mailItem.itemId); item.setItemNum(mailItem.itemCount); @@ -51,14 +39,17 @@ public class PacketGetMailItemRsp extends GenshinPacket { player.getInventory().addItem(genshinItem); player.sendPacket(new PacketItemAddHintNotify(genshinItem, ActionReason.MailAttachment)); } + + message.isAttachmentGot = true; + claimedMessages.add(message); + + player.replaceMailByIndex(messageIndex, message); } proto.addAllMailIdList(claimedMessages.stream().map(Mail::getId).collect(Collectors.toList())); proto.addAllItemList(claimedItems); - player.save(); - Grasscutter.getLogger().info(Grasscutter.getDispatchServer().getGsonFactory().toJson(proto.build())); this.setData(proto.build()); - player.getSession().send(new PacketMailChangeNotify(player, claimedMessages)); + player.getSession().send(new PacketMailChangeNotify(player, claimedMessages)); // For some reason you have to also send the MailChangeNotify packet } } diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketMailChangeNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketMailChangeNotify.java index ee07f06b7..fe8437fdd 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketMailChangeNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketMailChangeNotify.java @@ -18,44 +18,52 @@ public class PacketMailChangeNotify extends GenshinPacket { } public PacketMailChangeNotify(GenshinPlayer player, List mailList) { + this(player, mailList, null); + } + + public PacketMailChangeNotify(GenshinPlayer player, List mailList, List delMailIdList) { super(PacketOpcodes.MailChangeNotify); MailChangeNotifyOuterClass.MailChangeNotify.Builder proto = MailChangeNotifyOuterClass.MailChangeNotify.newBuilder(); - for(Mail message : mailList) { - MailTextContentOuterClass.MailTextContent.Builder mailTextContent = MailTextContentOuterClass.MailTextContent.newBuilder(); - mailTextContent.setTitle(message.mailContent.title); - mailTextContent.setContent(message.mailContent.content); - mailTextContent.setSender(message.mailContent.sender); + if (mailList != null) { + for (Mail message : mailList) { + MailTextContentOuterClass.MailTextContent.Builder mailTextContent = MailTextContentOuterClass.MailTextContent.newBuilder(); + mailTextContent.setTitle(message.mailContent.title); + mailTextContent.setContent(message.mailContent.content); + mailTextContent.setSender(message.mailContent.sender); - List mailItems = new ArrayList(); + List mailItems = new ArrayList(); - for(Mail.MailItem item : message.itemList) { - MailItemOuterClass.MailItem.Builder mailItem = MailItemOuterClass.MailItem.newBuilder(); - ItemParamOuterClass.ItemParam.Builder itemParam = ItemParamOuterClass.ItemParam.newBuilder(); - itemParam.setItemId(item.itemId); - itemParam.setCount(item.itemCount); - mailItem.setItemParam(itemParam.build()); + for (Mail.MailItem item : message.itemList) { + MailItemOuterClass.MailItem.Builder mailItem = MailItemOuterClass.MailItem.newBuilder(); + ItemParamOuterClass.ItemParam.Builder itemParam = ItemParamOuterClass.ItemParam.newBuilder(); + itemParam.setItemId(item.itemId); + itemParam.setCount(item.itemCount); + mailItem.setItemParam(itemParam.build()); - mailItems.add(mailItem.build()); + mailItems.add(mailItem.build()); + } + + MailDataOuterClass.MailData.Builder mailData = MailDataOuterClass.MailData.newBuilder(); + mailData.setMailId(message._id); + mailData.setMailTextContent(mailTextContent.build()); + mailData.addAllItemList(mailItems); + mailData.setSendTime((int) message.sendTime); + mailData.setExpireTime((int) message.expireTime); + mailData.setImportance(message.importance); + mailData.setIsRead(message.isRead); + mailData.setIsAttachmentGot(message.isAttachmentGot); + mailData.setStateValue(message.stateValue); + + proto.addMailList(mailData.build()); } - - MailDataOuterClass.MailData.Builder mailData = MailDataOuterClass.MailData.newBuilder(); - mailData.setMailId(message._id); - mailData.setMailTextContent(mailTextContent.build()); - mailData.addAllItemList(mailItems); - mailData.setSendTime((int)message.sendTime); - mailData.setExpireTime((int)message.expireTime); - mailData.setImportance(message.importance); - mailData.setIsRead(message.isRead); - mailData.setIsAttachmentGot(message.isAttachmentGot); - mailData.setStateValue(message.stateValue); - - proto.addMailList(mailData.build()); - - Grasscutter.getLogger().info(Grasscutter.getDispatchServer().getGsonFactory().toJson(proto.build())); - - this.setData(proto.build()); } + + if(delMailIdList != null) { + proto.addAllDelMailIdList(delMailIdList); + } + + this.setData(proto.build()); } } \ No newline at end of file