Mail reads the player’s mailbox and parcel locker, sends letters and packages to the player, and tells you when mail arrives. A letter goes to the mailbox and a package goes to the parcel locker.
Mail read the mailbox, send mail, and hear when it arrives
Call Inbox(kind) to read the mailbox or the locker, and SendItem, SendMoney or SendBundle to send mail to the player.
public static class Mail
{
public static event Action<MailReceivedArgs> Received;
public static event Action<MailReceivedArgs> PackageReceived;
public static event Action<MailSentArgs> Sent;
public static bool IsAvailable { get; }
public static List<MailInfo> Inbox(MailKind kind);
public static bool SendItem(string mailName, int itemId, int count, MailKind kind);
public static bool SendMoney(string mailName, MoneyCurrency currency, float amount, MailKind kind);
public static bool SendBundle(string mailName, IList<MailLine> lines, MailKind kind, int delayMinutes);
public static List<PendingMail> Pending();
}
| Method | Returns | What it does |
|---|---|---|
Inbox(kind) | List<MailInfo> | The mail that has arrived and is waiting. |
SendItem(mailName, itemId, count, kind) | bool | Sends the player an item. |
SendMoney(mailName, currency, amount, kind) | bool | Sends the player money. |
SendBundle(mailName, lines, kind, delayMinutes) | bool | Sends several items in one mail. |
Pending() | List<PendingMail> | The player’s mail that is still on its way. |
| Property | Type | What it means |
|---|---|---|
IsAvailable | bool | false when the mail events could not be set up. |
| Event | Gives you | When it fires |
|---|---|---|
Received | MailReceivedArgs | A letter arrived. args.Name is the letter name and args.Kind is Letter. |
PackageReceived | MailReceivedArgs | A package arrived. args.Name is the package name and args.Kind is Package. |
Sent | MailSentArgs | The game sent mail out into the world. |
MailInfo one piece of mail waiting in the mailbox or locker
Mail.Inbox returns these for each letter or package waiting. Name is the subject, and ItemId, Count, Oc and Rm say what is inside.
public sealed class MailInfo
{
public string Name { get; }
public MailKind Kind { get; }
public int ItemId { get; }
public int Count { get; }
public int Oc { get; }
public float Rm { get; }
public bool IsNote { get; }
public string Body { get; }
public string Sender { get; }
}
| Property | Type | What it means |
|---|---|---|
Name | string | The name the game shows for the mail, used as the subject. |
Kind | MailKind | Letter or package. |
ItemId | int | The item inside. 0 when the mail holds no item. |
Count | int | How many of the item. |
Oc | int | The OC inside. 0 when there is none. |
Rm | float | The RM inside. |
IsNote | bool | true when the letter carries a note (text). |
Body | string | The note’s text. "" when it is not a note. |
Sender | string | Who an email note is from. "" when there is none. |
MailKind where a piece of mail goes
Inbox, the send calls and MailInfo.Kind take one of these. Letter goes to the mailbox and Package to the parcel locker.
public enum MailKind
{
Letter = 0,
Package = 1
}
| Value | Meaning |
|---|---|
Letter | A letter, delivered to the mailbox. |
Package | A package, delivered to the parcel locker. |
MailLine one line of a bundle
SendBundle takes a list of these, one for each line of the bundle.
public sealed class MailLine
{
public int ItemId;
public int Count;
}
| Property | Type | What it means |
|---|---|---|
ItemId | int | The item. It must be above 1. |
Count | int | How many. It must be 1 to 1000. |
MailSentArgs what you get when the game sends mail into the world
Sent gives you one of these when the game sends mail out into the world.
public sealed class MailSentArgs
{
public string Name { get; }
public int ReceiverNpcId { get; }
public int ItemId { get; }
public int Count { get; }
}
| Property | Type | What it means |
|---|---|---|
Name | string | The mail’s name. |
ReceiverNpcId | int | The NPC it is for. 0 when it has no NPC receiver. |
ItemId | int | The item inside. 0 when the mail holds no item. |
Count | int | How many of the item. |
PendingMail one piece of mail still on its way to the player
Mail.Pending() lists the mail still on its way to the player, with SecondsLeft until each one arrives.
public sealed class PendingMail
{
public string Name { get; }
public MailKind Kind { get; }
public int SecondsLeft { get; }
}
| Property | Type | What it means |
|---|---|---|
Name | string | The mail’s name. |
Kind | MailKind | Letter or package. |
SecondsLeft | int | Seconds until it arrives. |
Things to know
Inboxlists the mail that has arrived and is still waiting. That is the letters in the mailbox or the packages in the parcel locker. It does not list mail that is still on its way, and the game clears the list when the player takes the mail. To read only letters with text, keep the ones whereIsNoteistrue. (the game clears the list inMailbox.TakeMail.)IsNote,BodyandSenderread a letter’s note. A letter that carries a note hasIsNoteset totrueandBodyset to the text.Senderis who an email note is from, and is""for any other note. Letters with an item or money, and other letters, haveIsNoteset tofalseand an emptyBodyandSender. (a note letter is the game’sNoteMail, andSenderis thefromof the note when the note is an email asset.)SendItemandSendMoneysend mail to the player, and the game’s mail delay applies. The mail may arrive later, as game mail does. A letter goes to the mailbox and a package to the parcel locker. (they use the game’sMailController.SendMailwithTarget.Player(letter) orTarget.PlayerParcelLocker(package).)SendItem,SendMoneyandSendBundlemake items or money out of nothing, so use them for rewards.- A package also makes the game send a “Parcel Notification” letter, so
Receivedfires for it too. ReceivedandPackageReceivedfire when mail is delivered, whether at once or after the delay.- When a save loads, the game replays the letters and packages it has stored. The framework ignores that replay, but only for the names that were in the save’s received lists when the load finished, one game notification for each stored name.
- Everything else is passed on, so a letter or package that the framework or the game delivers while the save is loading is reported. (they forward the game’s
MailController.MailReceivedandPackageReceived. The game replays two frames afterMailController.OnLoadingGamereads the save (MailController.DelayedOnLoaded).) SendBundlesends several items as one letter or one package. UseMailKind.Letterfor the player’s mailbox orMailKind.Packagefor the parcel locker.- The game’s own timer, in game time, delivers a bundle that has a delay. The game’s default delay is not used.
Pendinglists the player’s letters and packages that are still on their way. It does not list mail for NPCs.SecondsLeftis the timer’s seconds remaining. How often the game updates that number has not been confirmed.Senttells you when the game sends mail out into the world. The game raises it for every mail sent to the world side: a drop into a player’s mailbox, and scene mail senders set to the world.Sentis not raised for the player’s own letters and packages, soSendItem,SendMoneyandSendBundlenever raise it. A mail with a delay raises it when the game’s timer ends, not when the mailbox drops it. (it forwards the game’sMailController.MailSentforTarget.World:Mailbox.InsertMailand scene mail senders whosemailTargetisWorld(logic_mail_sender,logic_mail_bundle_sender). A delayed mail raises it fromTimerSendMailWorld.)Sentonly says that the mail was delivered to the world side. It does not say whether anything claimed the letter, and the order of handlers compared with the game’s own listeners is not defined.
Limits
SendItemandSendBundlerefuse a count outside 1 to 1000 and an item id of 1 or less. If the inventory is full, the game drops a large count into the world.SendBundlechecks each line likeSendItem, and you need at least one line.delayMinutesmust be 1 to 525600.SendBundlereturnsfalsewhile the game is saving or loading, the same asSendItem.Pendingonly reads, so it always works.Sentdoes not fire while a save is loading. A mail the old session sent that arrives during a load is dropped on purpose, not passed into the new save.- A delayed mail can fire at any game time, so a handler that writes money, items or quests must check
SaveData.Busyfirst.ReceiverNpcIdis0when the mail has no receiver, andItemIdandCountare0for money or other mail that holds no item.