Перейти к основному содержимому
🎉️ Конференция о рынке WEB-игр 👾 18 сентября 2025 | подробности

Состояние канала

Обзор

Состояние канала позволяет хранить и управлять пользовательскими данными внутри каналов, аналогично состоянию игрока. Эта функция позволяет реализовать сложные многопользовательские механики, такие как:

  • Кланы с общим банком - управление общими ресурсами
  • Турниры с призовыми фондами - коллективное распределение призов
  • Рейды и битвы с боссами - общие пулы здоровья и отслеживание прогресса
  • Системы гильдий - коллективные достижения и ресурсы
  • Совместные события - общие цели и награды
tip

Состояние канала идеально подходит для реализации совместных игровых механик, где несколько игроков должны делиться и изменять одни и те же данные

Настройка полей канала

При создании или редактировании шаблона канала вы можете настроить пользовательские поля перед группой с ограничениями:

Типы полей

Тип поляОписаниеСлучаи использования
СтроковыеТекстовые значенияИмена игроков, описания, статусные сообщения
БулевыеЗначения true/falseПереключатели функций, флаги завершения
ЧисловыеЧисловые значенияОчки здоровья, счет, количества

Настройки полей

СвойствоОписаниеСлучаи использования
ПеречисляемыеПредопределенные вариантыУровни сложности, игровые режимы
Мин-максЧисловые значения с ограничениямиПулы здоровья, лимиты ресурсов

Контроль доступа

Для доступа к полям вы можете настроить права доступа для разных ролей пользователей:

  • Владелец - Создатель/администратор канала
  • Участник - Обычные участники канала
  • Гость - Игроки не вступившие в канал

Доступные разрешения

  • Разрешить устанавливать переменные канала - Может изменять значения полей
  • Разрешить добавлять значение к переменным канала - Может увеличивать числовые значения
  • Разрешить вычитать значение из переменных канала - Может уменьшать числовые значения

Методы SDK

Получение состояния канала

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

channel.state; // Все значения канала
// Пример
console.log(channel.state.gold);

channel.fields; // Все определения полей канала

Установка значений

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

Добавление значений

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

Подписка на события

// Подписка на изменения значений
gp.channels.on('event:changeValue', ({ channelId, key, value }) => {
console.log(`Канал ${channelId}: ${key} изменился на ${value}`);
});

// Подписка на успешные операции
gp.channels.on('setValue', ({ channelId, key, value }) => {
console.log(`Успешно установлено ${key} в ${value} в канале ${channelId}`);
});

// Подписка на неудачные операции
gp.channels.on('error:setValue', ({ channelId, key, value }) => {
console.log(`Не удалось установить ${key} в ${value} в канале ${channelId}`);
});

Серверная валидация

При изменении значений на сервере GamePush делает следующее:

  1. Валидация доступа - Проверка прав пользователя
  2. Ограничения мин/макс - Применение ограничений полей, если включено
  3. Обновление значений - Применение изменений
  4. Рассылка событий - Отправка события changeValue всем участникам канала
  5. Ограничения размера - ВАЖНО! значения полей ограничены 64КБ

Примеры реализации

1. Клан с общим банком

Создайте канал клана с системой общего банка, где участники могут вносить золото, а только владелец может снимать.

Настройка шаблона канала

  1. Создайте шаблон канала для кланов
  2. Добавьте Числовое поле с именем bank
  3. Установите права:
    • Участники: Разрешить добавлять значение к переменным канала
    • Владелец: Разрешить вычитать значение из переменных канала

Реализация

// Игрок вносит 100 золота в банк клана
const contributeGold = async (amount) => {
// Добавить в банк клана
await gp.channels.addValue({
channelId: clanChannelId,
key: 'bank',
value: amount,
});

// Вычесть из золота игрока
await gp.player.add('gold', -amount);
};

// Владелец снимает золото из банка клана
const withdrawGold = async (amount) => {
// Вычесть из банка клана
await gp.channels.addValue({
channelId: clanChannelId,
key: 'bank',
value: -amount,
});

// Добавить к золоту владельца
await gp.player.add('gold', amount);
};

// Слушать изменения банка
gp.channels.on('event:changeValue', ({ channelId, key, value }) => {
if (key === 'bank') {
updateBankDisplay(value);
}
});

2. Турнир с призовым фондом

Создайте турниры, где игроки вносят вступительные взносы, а победители делят призовой фонд.

Настройка шаблона канала

  1. Создайте шаблон канала турнира
  2. Добавьте Числовое поле с именем prizeAmount
  3. Установите права:
    • Участники и Владелец: Разрешить добавлять значение к переменным канала

Реализация

// Игрок присоединяется к турниру (платит вступительный взнос)
const joinTournament = async () => {
const entryFee = 100;

// Добавить в призовой фонд
await gp.channels.addValue({
channelId: tournamentChannelId,
key: "prizeAmount",
value: entryFee
});

// Вычесть вступительный взнос у игрока
await gp.player.add('gold', -entryFee);
};

// Турнир завершен - распределить призы топ-5 игрокам
const distributePrizes = async (winners) => {
const channel = await gp.channels.fetchChannel({ id: tournamentChannelId });
const totalPrize = channel.state.prizeAmount;
const prizePerWinner = totalPrize / winners.length;

// Проработать логику, чтобы понять, что игрок занял призовое место
const isMyPlayerInTop = true;
// Зачесть приз
for (isMyPlayerInTop) {
await gp.player.add('gold', prizePerWinner);
}

// Покидаем канал
gp.channels.leave({ channelId: tournamentChannelId });
};

// Слушать обновления призового фонда
gp.channels.on('event:changeValue', ({ channelId, key, value }) => {
if (key === 'prizeAmount') {
updatePrizeDisplay(value);
}
});

3. Рейд с боссом

Создайте каналы рейдов, где игроки сражаются с боссом с общим пулом здоровья.

Настройка шаблона канала

  1. Создайте шаблон канала рейда для 5 игроков
  2. Добавьте Числовые поля:
    • hp - Текущее здоровье босса
    • maxHp - Максимальное здоровье босса
  3. Установите права:
    • Участники и Владелец: Разрешить вычитать значение из переменных канала (для урона)

Реализация

// Получаем канал рейда
const channel = await gp.channels.fetchChannel({ id: raidChannelId });

// Обновляем значение HP босса
gp.channels.on('event:changeValue', ({ channelId, key, value }) => {
// Только для нашего канала
if (channel.id !== channelId) {
return;
}

// Держим состояние актуальным
channel.state[key] = value;

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

// Игрок атакует босса
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;

// Уведомляем о нанесении урона боссу в чат (опционально)
await gp.channels.sendMessage({
channelId: raidChannelId,
text: `${gp.player.name} получает ${damage} урона! HP: ${currentHp}/${maxHp}`,
});

// Проверить, побежден ли босс
if (currentHp <= 0) {
await defeatBoss();
}
}
};

// Босс побежден
const defeatBoss = async () => {
// Если владелец - уведомляем всех о завершении рейда
if (channel.ownerId === gp.player.id) {
await gp.channels.sendMessage({
channelId: raidChannelId,
text: '🎉 Босс побежден! Награды распределены!',
});
}

// Выдаем награду игроку
const reward = 1000;
await gp.player.add('gold', reward);

// Выходим из канала
await gp.channels.leave({ channelId: raidChannelId });
};

Лучшие практики

  1. Тщательно проектируйте права полей - Убедитесь, что только авторизованные пользователи могут изменять критические значения
  2. Используйте ограничения мин/макс - Предотвращайте нереалистичные значения (например, отрицательное здоровье)
  3. Реализуйте правильную обработку ошибок - Проверяйте успешность операции перед продолжением
  4. Отслеживайте события канала - Используйте слушатели событий для обновления UI и игрового состояния
  5. Учитывайте размер данных - Держите значения полей в пределах лимита 64КБ
  6. Тщательно тестируйте - Убедитесь, что права и ограничения работают как ожидается
tip

Состояние канала - это мощная функция, которая открывает множество возможностей для совместной игры. Начните с простых реализаций и постепенно добавляйте сложность по мере необходимости.

Обработка ошибок

При работе с состоянием канала вы можете столкнуться с различными ошибками. Ниже приведен список возможных ошибок и их значений:

Код ошибкиОписание
fields_not_foundПоля шаблона канала не настроены или не найдены
channel_not_foundУказанный канал не существует или был удален
value_not_numberПопытка выполнить числовые операции с нечисловым полем
channel_state_not_foundДанные состояния канала недоступны или повреждены
key_not_foundУказанный ключ поля не существует в канале
internal_errorПроизошла серверная ошибка во время операции
value_already_maxПопытка увеличить значение, которое уже на максимальном лимите
value_already_minПопытка уменьшить значение, которое уже на минимальном лимите
value_too_lowПредоставленное значение ниже минимально допустимого лимита
value_too_highПредоставленное значение выше максимально допустимого лимита
value_too_largeПредоставленное значение превышает лимит размера в 64КБ
invalid_field_typeОперация несовместима с типом поля

Базовые ошибки

Эти ошибки общие для всех операций с каналами:

Код ошибкиОписание
player_not_foundИгрок, делающий запрос, не найден
project_not_foundИгровой проект не найден или неактивен
origin_not_allowedИсточник запроса не разрешен для этого проекта
player_bannedИгрок заблокирован и не может выполнить это действие
internal_errorПроизошла неожиданная серверная ошибка