Skip to content

События ​

WebGUI имеет двунаправленную систему именованных событий между сервером и страницей — прямой аналог системы событий WebView в alt:V.

Сервер → страница ​

Java API ​

java
// Отправить событие на страницу конкретного игрока
WebviewApi.emitToPage(player, "walletUpdate", "{\"balance\":1500}");

// Строка — тоже валидный JSON
WebviewApi.emitToPage(player, "serverRestart", "\"5 минут\"");

// Без данных
WebviewApi.emitToPage(player, "sessionExpired", null);

Второй аргумент — имя события. Третий — любое валидное JSON-значение: объект, массив, строка, число, boolean или null.

Получение на странице — React-хук ​

tsx
import { useWebGUIEvent } from '@webgui/client/react'

interface WalletUpdate { balance: number }

export function Wallet() {
  const [balance, setBalance] = useState(0)

  useWebGUIEvent<WalletUpdate>('walletUpdate', ({ balance }) => {
    setBalance(balance)
  })

  return <p>Баланс: {balance}</p>
}

Получение на странице — vanilla JS ​

js
// Через window.webgui.on (инжектится модом)
window.webgui.on('walletUpdate', (data) => {
  console.log('баланс:', data.balance)
})

// Или напрямую через DOM-событие
window.addEventListener('webgui:walletUpdate', (e) => {
  console.log('баланс:', e.detail.balance)
})

window.webgui.on и window.addEventListener слушают одно и то же CustomEvent('webgui:<eventName>').

Отписка ​

js
function onWalletUpdate(data) { ... }

window.webgui.on('walletUpdate', onWalletUpdate)
// позже:
window.webgui.off('walletUpdate', onWalletUpdate)

В React хук useWebGUIEvent очищает подписку автоматически при анмаунте компонента.


Страница → сервер ​

Отправка со страницы ​

Используйте window.webgui.postToGame с любым каналом, кроме встроенных (log, close):

js
window.webgui.postToGame({ channel: 'shop:buy', itemId: 'minecraft:diamond', qty: 1 })

Или через React-хук:

tsx
const post = usePostToGame()

post({ channel: 'shop:buy', itemId: 'minecraft:diamond', qty: 1 })

Полный JSON-пейлоад (включая поле channel) пересылается на сервер как C2S-пакет.

Получение на сервере — Java API ​

java
// Регистрируется один раз, например при инициализации мода
WebviewApi.onPageEvent("shop:buy", (player, rawJson) -> {
    JsonObject obj = JsonParser.parseString(rawJson).getAsJsonObject();
    String item = obj.get("itemId").getAsString();
    int qty     = obj.get("qty").getAsInt();
    giveItem(player, item, qty);
});

Получение на сервере — Fabric-событие ​

Для модов, предпочитающих Fabric event bus:

java
WebviewServerEvents.PAGE_EVENT.register((player, channel, payload) -> {
    if (!channel.equals("shop:buy")) return;
    // разобрать payload...
});

Встроенные каналы (только клиент, до сервера не доходят) ​

КаналДействие
logЛогирует сообщение в клиентский лог игры
closeЗакрывает активный GUI или HUD-оверлей

webgui:death ​

Приходит на страницу смерти, когда игрок умирает — если сервер задал deathScreenUrl.

js
window.addEventListener('webgui:death', (e) => {
  const { killer, cause, deathMessage, hardcore, canRespawn } = e.detail;

  document.querySelector('#msg').textContent = deathMessage;
  document.querySelector('#by').textContent =
    killer.type === 'environment' ? 'мир' : killer.name;

  document.querySelector('#respawn').hidden = !canRespawn;
});
ПолеТипОписание
killer.type"player" | "mob" | "environment"Кто убил. environment — падение, утопление, огонь, всё без сущности за этим.
killer.namestring | nullОтображаемое имя: ник игрока или имя моба ("Zombie" либо кастомное). Для environment — null.
killer.uuidstring | nullUUID убийцы. Для environment — null.
killer.entityTypestringRegistry-id вида minecraft:zombie. Только для мобов — у игрока тип и так "player".
causestringВанильный id типа урона: mob, player, fall, lava, …
deathMessagestringСообщение о смерти, которое показала бы ваниль, например "Steve was slain by Zombie".
hardcoreboolХардкорный ли мир.
canRespawnboolНа хардкоре false — кнопку возрождения показывать не нужно, она не сработает.

Возрождение — window.webgui.respawn(); это замена ванильной кнопки Respawn и единственный способ уйти со страницы.


Пример полного round-trip ​

Сервер — открываем магазин и пушим данные инвентаря:

java
WebviewApi.openGui(player, "https://your-site.example.com/shop");
WebviewApi.emitToPage(player, "inventoryLoad", buildInventoryJson(player));

WebviewApi.onPageEvent("shop:buy", (player, rawJson) -> {
    processShopPurchase(player, rawJson);
    // возвращаем обновлённый баланс на страницу
    WebviewApi.emitToPage(player, "walletUpdate", "{\"balance\":" + getBalance(player) + "}");
});

Страница — React-компонент:

tsx
import { useWebGUIEvent, usePostToGame } from '@webgui/client/react'

export function ShopScreen() {
  const [items, setItems] = useState([])
  const [balance, setBalance] = useState(0)
  const post = usePostToGame()

  useWebGUIEvent('inventoryLoad', setItems)
  useWebGUIEvent<{ balance: number }>('walletUpdate', ({ balance }) => setBalance(balance))

  function buy(itemId: string) {
    post({ channel: 'shop:buy', itemId, qty: 1 })
  }

  return (
    <>
      <p>Баланс: {balance}</p>
      {items.map(item => (
        <button key={item.id} onClick={() => buy(item.id)}>{item.name}</button>
      ))}
    </>
  )
}