Skip to main content

CharacterHub

WebSocket hub for character operations. All operations verify that the character belongs to the authenticated user.

Endpoint: /characterHub

Authorization: All methods require authentication ([Authorize])

Methods

GetCharacter

Get character details.

public async Task<Character> GetCharacter(Guid characterId, string seasonId)

Parameters:

NameTypeDescription
characterIdGuidCharacter ID
seasonIdstringSeason the character belongs to

Returns: Character

{
characterId: string;
accountId: string;
seasonId: string;
name: string;
level: number;
experience: number;
restrictions: CharacterRestrictions;
stats: Record<string, number>;
challengeProgress: ChallengeProgress[];
isDead: boolean;
isMigrated: boolean;
createdAt: string;
diedAt?: string;
migratedAt?: string;
}

Errors:

  • "Character does not belong to this account." - Ownership verification failed

AddExperience

Add experience to a character.

public async Task<Character> AddExperience(Guid characterId, string seasonId, long amount)

Parameters:

NameTypeDescription
characterIdGuidCharacter ID
seasonIdstringSeason ID
amountlongExperience to add (≥ 0)

Returns: Updated Character with new XP and potentially new level.


SetStat

Set a character stat value.

public async Task<Character> SetStat(Guid characterId, string seasonId, string statName, int value)

Parameters:

NameTypeDescription
characterIdGuidCharacter ID
seasonIdstringSeason ID
statNamestringStat name (e.g., "strength", "dexterity")
valueintNew stat value

GetChallengeProgress

Get challenge progress for a character.

public async Task<IReadOnlyList<ChallengeProgress>> GetChallengeProgress(
Guid characterId,
string seasonId)

Returns: ChallengeProgress[]

{
challengeId: string;
progress: number;
completed: boolean;
}

UpdateChallengeProgress

Update challenge progress for a character.

public async Task UpdateChallengeProgress(
Guid characterId,
string seasonId,
string challengeId,
int progress)

Die

Kill a character. For Hardcore characters, triggers migration to the permanent league.

public async Task<DieResult> Die(Guid characterId, string seasonId)

Returns: DieResult

{
character: Character;
migrated: boolean; // true if character moved to permanent league
}

Behavior:

  • Marks character as dead (isDead = true)
  • For Hardcore characters: Migrates to permanent league and updates season reference
  • For Non-Hardcore: Just marks as dead (can be resurrected if game supports it)

GetHistory

Get character history - chronological list of significant events.

public async Task<IReadOnlyList<CharacterHistoryEntry>> GetHistory(
Guid characterId,
string seasonId)

Returns: CharacterHistoryEntry[]

{
eventType: string; // "Created", "Died", "Migrated", etc.
timestamp: string; // ISO 8601
details?: string;
}

Character Lifecycle

Ownership Verification

Every method verifies the character belongs to the caller:

public async Task<Character> GetCharacter(Guid characterId, string seasonId)
{
await VerifyCharacterOwnershipAsync(characterId); // Throws if not owner
// ... proceed with operation
}

The verification:

  1. Gets all character IDs from AccountGrain.GetCharactersAsync()
  2. Checks if the requested character ID is in the list
  3. Throws HubException if not found