Skip to main content

Channel State

Overview

Channel state allows you to store and manage custom data within channels, similar to player state. This feature enables implementing complex multiplayer mechanics such as:

  • Clans with shared banks - shared resources management
  • Tournaments with prize pools - collective prize distribution
  • Raids and boss battles - shared health pools and progress tracking
  • Guild systems - collective achievements and resources
  • Collaborative events - shared objectives and rewards
tip

Channel state is perfect for implementing collaborative gameplay mechanics where multiple players need to share and modify the same data

Channel Fields Configuration

When creating or editing a channel template, you can configure custom fields before the restrictions group:

Field Types

Field TypeDescriptionUse Cases
StringText valuesPlayer names, descriptions, status messages
BooleanTrue/false valuesFeature toggles, completion flags
NumberNumeric valuesHealth points, scores, quantities

Field Settings

PropertyDescriptionUse Cases
EnumerationPredefined optionsDifficulty levels, game modes
Min-MaxNumeric values with limitsHealth pools, resource caps

Access Control

For field access, you can configure access permissions for different user roles:

  • Owner - Channel creator/administrator
  • Member - Regular channel participants
  • Guest - Players who haven't joined the channel

Available Permissions

  • Allow setting channel variables - Can modify field values
  • Allow adding to channel variables - Can increment numeric values
  • Allow subtracting from channel variables - Can decrement numeric values

SDK Methods

Fetching Channel State

const channel = await gp.channels.fetchChannel({ id: 123 });

channel.state; // All channel values
// Example
console.log(channel.state.gold);

channel.fields; // All channel field definitions

Setting Values

const { success, value } = await gp.channels.setValue({
channelId: 123,
key: 'gold',
value: 123,
});

Adding Values

const { success, value } = await gp.channels.addValue({
channelId: 123,
key: 'gold',
value: 100,
});

Event Subscriptions

// Subscribe to value changes
gp.channels.on('event:changeValue', ({ channelId, key, value }) => {
console.log(`Channel ${channelId}: ${key} changed to ${value}`);
});

// Subscribe to successful operations
gp.channels.on('setValue', ({ channelId, key, value }) => {
console.log(`Successfully set ${key} to ${value} in channel ${channelId}`);
});

// Subscribe to failed operations
gp.channels.on('error:setValue', (error) => {
console.log('Failed to set value:', error);
});

Server-Side Validation

When values are changed on the server, GamePush does the following:

  1. Access validation - Check user permissions
  2. Min/Max limits - Enforce field constraints if enabled
  3. Value updates - Apply the changes
  4. Event broadcasting - Send changeValue event to all channel members
  5. Size limits - IMPORTANT! field values are limited to 64KB

Implementation Examples

1. Clan with Shared Bank

Create a clan channel with a shared bank system where members can contribute gold and only the owner can withdraw.

Channel Template Setup

  1. Create a channel template for clans
  2. Add a Number field named bank
  3. Set permissions:
    • Members: Allow adding to channel variables
    • Owner: Allow subtracting from channel variables

Implementation

// Player contributes 100 gold to clan bank
const contributeGold = async (amount) => {
// Add to clan bank
await gp.channels.addValue({
channelId: clanChannelId,
key: 'bank',
value: amount,
});

// Subtract from player's gold
await gp.player.add('gold', -amount);
};

// Owner withdraws gold from clan bank
const withdrawGold = async (amount) => {
// Subtract from clan bank
await gp.channels.addValue({
channelId: clanChannelId,
key: 'bank',
value: -amount,
});

// Add to owner's gold
await gp.player.add('gold', amount);
};

// Listen for bank changes
gp.channels.on('event:changeValue', ({ channelId, key, value }) => {
if (key === 'bank') {
updateBankDisplay(value);
}
});

2. Tournament with Prize Pool

Create tournaments where players contribute entry fees and winners share the prize pool.

Channel Template Setup

  1. Create a tournament channel template
  2. Add a Number field named prizeAmount
  3. Set permissions:
    • Members and Owner: Allow adding to channel variables

Implementation

// Player joins tournament (pays entry fee)
const joinTournament = async () => {
const entryFee = 100;

// Add to prize pool
await gp.channels.addValue({
channelId: tournamentChannelId,
key: "prizeAmount",
value: entryFee
});

// Subtract entry fee from player
await gp.player.add('gold', -entryFee);
};

// Tournament ends - distribute prizes to top 5 players
const distributePrizes = async (winners) => {
const channel = await gp.channels.fetchChannel({ id: tournamentChannelId });
const totalPrize = channel.state.prizeAmount;
const prizePerWinner = totalPrize / winners.length;

// Work through logic to understand that player won a prize
const isMyPlayerInTop = true;
// Award prize
for (isMyPlayerInTop) {
await gp.player.add('gold', prizePerWinner);
}

// Leave the channel
gp.channels.leave({ channelId: tournamentChannelId });
};

// Listen for prize pool updates
gp.channels.on('event:changeValue', ({ channelId, key, value }) => {
if (key === 'prizeAmount') {
updatePrizeDisplay(value);
}
});

3. Raid Boss Battle

Create raid channels where players fight a boss with shared health pool.

Channel Template Setup

  1. Create a raid channel template for 5 players
  2. Add Number fields:
    • hp - Current boss health
    • maxHp - Maximum boss health
  3. Set permissions:
    • Members and Owner: Allow subtracting from channel variables (for damage)

Implementation

// Get raid channel
const channel = await gp.channels.fetchChannel({ id: raidChannelId });

// Update boss HP value
gp.channels.on('event:changeValue', ({ channelId, key, value }) => {
// Only for our channel
if (channel.id !== channelId) {
return;
}

// Keep state up to date
channel.state[key] = value;

if (key === 'hp') {
updateBossHealthDisplay(value);
}
});

// Player attacks boss
const attackBoss = async (damage) => {
const { success, value } = await gp.channels.addValue({
channelId: raidChannelId,
key: 'hp',
value: -damage,
});

if (success) {
const currentHp = channel.state.hp;
const maxHp = channel.state.maxHp;

// Notify about boss damage in chat (optional)
await gp.channels.sendMessage({
channelId: raidChannelId,
text: `${gp.player.name} deals ${damage} damage! HP: ${currentHp}/${maxHp}`,
});

// Check if boss is defeated
if (currentHp <= 0) {
await defeatBoss();
}
}
};

// Boss defeated
const defeatBoss = async () => {
// If owner - notify everyone about raid completion
if (channel.ownerId === gp.player.id) {
await gp.channels.sendMessage({
channelId: raidChannelId,
text: '🎉 Boss defeated! Rewards distributed!',
});
}

// Give reward to player
const reward = 1000;
await gp.player.add('gold', reward);

// Leave the channel
await gp.channels.leave({ channelId: raidChannelId });
};

Best Practices

  1. Design field permissions carefully - Ensure only authorized users can modify critical values
  2. Use min/max constraints - Prevent unrealistic values (e.g., negative health)
  3. Implement proper error handling - Check operation success before proceeding
  4. Monitor channel events - Use event listeners to update UI and game state
  5. Consider data size - Keep field values under 64KB limit
  6. Test thoroughly - Verify permissions and constraints work as expected
tip

Channel state is a powerful feature that opens up many possibilities for collaborative gameplay. Start with simple implementations and gradually add complexity as needed.

Error Handling

When working with channel state, you may encounter various errors. Below is a list of possible errors and their meanings:

Error CodeDescription
fields_not_foundChannel template fields are not configured or not found
channel_not_foundThe specified channel does not exist or has been deleted
value_not_numberAttempted to perform numeric operations on a non-numeric field
channel_state_not_foundChannel state data is not available or corrupted
key_not_foundThe specified field key does not exist in the channel
internal_errorServer-side error occurred during the operation
value_already_maxAttempted to increase a value that is already at maximum limit
value_already_minAttempted to decrease a value that is already at minimum limit
value_too_lowThe provided value is below the minimum allowed limit
value_too_highThe provided value is above the maximum allowed limit
value_too_largeThe provided value exceeds the 64KB size limit
invalid_field_typeThe operation is not compatible with the field type

Basic Errors

These errors are common across all channel operations:

Error CodeDescription
player_not_foundThe player making the request is not found
project_not_foundThe game project is not found or inactive
origin_not_allowedThe request origin is not allowed for this project
player_bannedThe player is banned and cannot perform this action
internal_errorAn unexpected server error occurred