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
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 Type | Description | Use Cases |
---|---|---|
String | Text values | Player names, descriptions, status messages |
Boolean | True/false values | Feature toggles, completion flags |
Number | Numeric values | Health points, scores, quantities |
Field Settings
Property | Description | Use Cases |
---|---|---|
Enumeration | Predefined options | Difficulty levels, game modes |
Min-Max | Numeric values with limits | Health 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:
- Access validation - Check user permissions
- Min/Max limits - Enforce field constraints if enabled
- Value updates - Apply the changes
- Event broadcasting - Send
changeValue
event to all channel members - 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
- Create a channel template for clans
- Add a Number field named
bank
- 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
- Create a tournament channel template
- Add a Number field named
prizeAmount
- 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
- Create a raid channel template for 5 players
- Add Number fields:
hp
- Current boss healthmaxHp
- Maximum boss health
- 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
- Design field permissions carefully - Ensure only authorized users can modify critical values
- Use min/max constraints - Prevent unrealistic values (e.g., negative health)
- Implement proper error handling - Check operation success before proceeding
- Monitor channel events - Use event listeners to update UI and game state
- Consider data size - Keep field values under 64KB limit
- Test thoroughly - Verify permissions and constraints work as expected
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 Code | Description |
---|---|
fields_not_found | Channel template fields are not configured or not found |
channel_not_found | The specified channel does not exist or has been deleted |
value_not_number | Attempted to perform numeric operations on a non-numeric field |
channel_state_not_found | Channel state data is not available or corrupted |
key_not_found | The specified field key does not exist in the channel |
internal_error | Server-side error occurred during the operation |
value_already_max | Attempted to increase a value that is already at maximum limit |
value_already_min | Attempted to decrease a value that is already at minimum limit |
value_too_low | The provided value is below the minimum allowed limit |
value_too_high | The provided value is above the maximum allowed limit |
value_too_large | The provided value exceeds the 64KB size limit |
invalid_field_type | The operation is not compatible with the field type |
Basic Errors
These errors are common across all channel operations:
Error Code | Description |
---|---|
player_not_found | The player making the request is not found |
project_not_found | The game project is not found or inactive |
origin_not_allowed | The request origin is not allowed for this project |
player_banned | The player is banned and cannot perform this action |
internal_error | An unexpected server error occurred |