Skip to main content
πŸŽ‰οΈ WEB Games Market Conference πŸ‘Ύ September 18, 2025 | details

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', ({ channelId, key, value }) => {
console.log(`Failed to set ${key} to ${value} in channel ${channelId}`);
});

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.set('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.set('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.set('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.set('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.set('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