Monster Gifts (Grant IDs)
When an NPC hands the player a monster -- the starter in the lab, a gift on a route, a fossil revived -- a single-player game simply adds it to the roster. An online game cannot do that: a client that can give itself any monster is a client that can give itself a legendary. In MCE Online the server mints the gift, and the client only asks for it.
Available in Pro and Source tiers.
How a Gift Works Online
The node behind every gift is GiveMonsters (CommandGraph, Monsters category). The starter and the "NPC gift" are the same node, so there is one mechanism for both.
- The player talks to the NPC and the graph reaches the
GiveMonstersnode. - Online, the node does not add the monster. It asks the server through
OnlineCommandBridge.RequestGiveMonsterAsync(grantId, ...), naming the site by itsGrantId. - The server looks the site up in its own data (
monster_grant_data) and mints the species, level and amount it has on record. Whatever species a client sends in the request is ignored and logged. - The server records that this character has claimed this site (
monster_grant_claims, keyed by character and grant id), so a gift can be taken once per character: an NPC you can talk to again is not a monster factory. - The client receives the minted monster and shows it with the same dialogs the offline path uses.
If the server does not grant it, the node grants nothing locally -- doing so would reopen the self-gift hole -- and shows a "grant failed" dialog. Offline, nothing changes at all.
The GrantId
Every gift site needs its own GrantId: an opaque string stored on the GiveMonsters node (it is hidden in the Inspector; you do not type it). The server rejects an empty id by name (grantId is required), so a site with no id gives no gift online -- it fails closed.
The ids are:
- Per site, not per node type. Two nodes that were copied from each other share the node's authoring GUID but give different things; the stamped id is the node's GUID plus a short hash of where the node lives (the asset's GUID and the property path), so each site is distinct.
- Stable. The hash uses the asset's GUID, not its path, so moving or renaming the file does not change it.
- Opaque. An id has no
#,/or file extension, so the node can always pronounce it at runtime. - Never overwritten. Stamping only fills ids that are empty. An id that already exists, and therefore the server's seed for it, never changes.
Stamping and Exporting (the Editor Side)
MonsterGrantSeedExporter (in the MCE.Online.Editor assembly) does the two jobs:
- It scans the prefabs and the scenes of the project for
GiveMonstersnodes. Scenes are first filtered by text (a scene is only opened when its YAML contains the node's class mark), so scanning does not open every scene. - With stamping on, it fills the missing
GrantIds, and it writes the seed:SeedData/monster-grant-seed.json(what each site gives) andSeedData/monster-grant-seed.report.txt(the sites seen and the ones skipped, with the reason).
The exporter entry points:
| Entry | Use |
|---|---|
MonsterGrantSeedExporter.Export(folder) | Stamp the missing ids, then write the seed and the report |
MonsterGrantSeedExporter.Scan(stampMissingIds, persist) | Scan; optionally stamp, optionally save to disk. Scan() alone reads and writes nothing |
BatchExporters.ExportMonsterGrants | Batchmode: -executeMethod OpenMon.MCE.Online.Editor.BatchExporters.ExportMonsterGrants |
Sending the seed to the server is server-to-server, like the rest of the seeds: the mce_monster_grant_seed RPC rejects any call that carries a user session and needs the runtime HTTP key (see Species Seeding for why that key never goes inside Unity).
GiveMonsters hands out one fixed gift (or a random one). The node that offers a choice -- GiveMonstersBasedOnChosenItem, as the fossil reviver does -- is exported with choice: true: the server derives the item that the chosen option costs from the index the player picked, so a client cannot revive the expensive fossil by claiming it spent the cheap one.
Imported Games
A game imported from a cartridge or an Essentials project is full of gift nodes: the three starters of the lab, the Pokémon of an NPC, a fossil. The importers do the stamping for you.
After the NPC importers (HeartGold / SoulSilver, FireRed) finish, GrantsEnLoImportado.Estampar() runs the exporter's scan with stamping and persistence on -- if the online layer is part of the project; without it there is nothing to stamp. It then checks its own work with an independent count: it reads every scene under Assets/ImportedGames and counts empty GrantId values, including the ones a scene stores as an override of a prefab instance (the starter of the lab is exactly that). If any is left it throws, so an import never finishes "successfully" while leaving gifts the server would reject:
[Importador] GrantId de los regalos: estampados=3 yaEstaban=0 quedanSinId=0
(estampados: stamped now; yaEstaban: already had an id; quedanSinId: still empty, must be 0.)
Afterwards, export the gift seed (above) and send it to the server. Like the other seed RPCs, mce_monster_grant_seed refuses any call that carries a user session: only a server-to-server call with the runtime HTTP key can write it.
Reference
| Type | Where | Role |
|---|---|---|
GiveMonsters | OpenMon.MCE.Actors.CommandGraph.Monsters | The node; carries GrantId and asks the server when online |
OnlineCommandBridge.RequestGiveMonsterAsync | MCE.Online.Runtime | The request (grantId, optional choice index) |
MonsterGrantSeedExporter | OpenMon.MCE.Online.Editor | Scan, stamp and export the seed |
GrantsEnLoImportado | OpenMon.MCE.EssentialsImporter.Editor | Stamps and verifies the ids after an import |
mce_monster_grant_seed | Nakama RPC | Server-to-server: stores the sites |