Custom Ticketing Flow
Custom ticketing flows are only supported if you have source code access. You can see how to purchase it here.
This ticketing "mode" enables powerful setups where the backend decides where to place the player based on their PlayerCharacter data. Clients simply call Join Custom (URedwoodClientGameSubsystem::JoinCustom(bTransferWholeParty, Regions, OnUpdate)), and your backend code decides whether to put them into matchmaking or a queue, and for what.
Example Scenario
Here is an example flow for an MMORPG.
- If the Character hasn't finished the tutorial yet, put them in
matchmakingfor a tutorial profile - If the Character has finished the tutorial but has no last location, put them in the
queuein the starting zone for the overworld proxy - If the Character level >= 5 and the date is between December 1 and December 31, place them in a special holidays proxy/zone
- If the Character was in a dungeon/player housing last, put them in
matchmakingfor that dungeon/player housing profile - Otherwise, put the Character in their last known location/proxy/zone
Setup
-
Make a new file at
packages/realm-frontend/src/routes/player/custom/custom.tswith the contents:import { CustomPlayerJoinData, CustomTicketingFunction } from ".";
import { PlayerCharacter } from "@redwoodmmo/realm-db";
import { RealmFrontendManager } from "../../../realm-frontend-manager";
import { Logger } from "@redwoodmmo/common";
const flow: CustomTicketingFunction = async (
manager: RealmFrontendManager,
character: PlayerCharacter
): Promise<CustomPlayerJoinData> => {
throw new Error("Custom module not implemented yet");
};
export default flow; -
You can safely commit this new
custom.tsin your fork of the backend repo without worrying about future conflicts -
Don't modify
packages/realm-frontend/src/routes/player/custom/default.ts(it loads yourcustom.tsautomatically if it exists) -
In the new
custom.ts, replace the contents of theflowfunction as you see fit; you have access to the entirePlayerCharacter(including all of its data fields) and the Realm Frontend'smanager(e.g.manager.dbfor the realm database) -
You can throw an error with
throw new Error("Message")and "Message" will be sent as the error to the user -
Call Join Custom from the UE plugin
The Return Value
Your function returns a CustomPlayerJoinData object (defined in packages/realm-frontend/src/routes/player/custom/index.ts), which is one of these shapes:
// Put the player into matchmaking for a game profile
{
type: "matchmaking",
profileId: "dungeon",
}
// Queue the player into a zone, at a named spawn point (an ARedwoodZoneSpawn's SpawnName)
{
type: "queue",
profileId: "overworld",
proxyId: "cm1ol7o270001xhxi5z3d7fw2", // optional; defaults to the first active proxy with the profileId
zoneName: "town",
spawnName: "default",
}
// Queue the player into a zone, at a specific transform
{
type: "queue",
profileId: "overworld",
zoneName: "town",
transform: {
location: { x: 0, y: 0, z: 100 },
rotation: { x: 0, y: 0, z: 90 },
controlRotation: { x: 0, y: 0, z: 90 },
},
}
For matchmaking, the regions the client passed to Join Custom (with their pings) are used, just like Join Matchmaking. For queuing, the client's bTransferWholeParty input is respected, and if you don't return a proxyId, the first active (not ended) proxy using profileId is used (or the player gets the error ... there are no available proxies with that profile.).
The spawnName and transform fields of a queue decision aren't applied yet; players spawn using the normal rules (their last location in that zone, then the zone's default Zone Spawn).
A character's last known location is stored in its redwoodData.lastLocation (proxyId, zoneName, and either a transform or a spawnName), which is handy for the "put them back where they were" case.