
Security News
Axios Supply Chain Attack Reaches OpenAI macOS Signing Pipeline, Forces Certificate Rotation
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.
astra-engine
Advanced tools
astra-engine - игровой веб-движок, написанный на NodeJS и использующий модуль socket.io
npm install astra-engine
Запуск сервера на TypeScript:
import SocketIO from "socket.io";
import { AstraEngine, Lobby, Player } from "astra-engine";
// Наследуемся от базового класса лобби
class GameLobby extends Lobby {
// Метод вызывается когда команда прилетает от игрока в данном лобби
onCommand(player: Player, action: string, payload: any) {
// Если экшен команды "ping"
if(action === "ping") {
// Определяем задержку между игроком и сервером, которая является разницей во времени между ними
const ping = Date.now() - payload;
// И посылаем игроку задержку (пинг)
this.command(player, "pong", ping);
}
}
}
// Создаём сервер (может быть любым фреймворком, поддерживающим socket.io)
const io = SocketIO(3000);
// И экземпляр движка, передавая созданный socket.io сервер и класс лобби, используемый по умолчанию
const engine = new AstraEngine(io, GameLobby);
Подключение клиента на JavaScript:
// EventEmitter не обязателен, но очень полезен для упрощения обработки команд
const { EventEmitter } = require("events");
const SocketIO = require("socket.io-client");
// Создаём экземпляр EventEmitter'а
const server = new EventEmitter();
// Привязываем к нему все обрабатываемые команды
server
// Когда игрок подключился (после аунтентификации)
.on("player.connected", ({ playerId }) => {
// Берём playerId из данных, пришедших от сервера (пейлода)
console.log(`player with id ${playerId} connected!`);
// И отправляем команду подсоединения к лобби, т.к. после подключения мы можем это сделать
io.emit("command", "lobby.join");
})
// Когда мы подключились к лобби - мы можем отправлять команды непосредственно в него
.on("lobby.joined", ({ playerId, lobbyId }) => {
// Выводим, что мы подключились в лобби
console.log(`player with id ${playerId} connected to lobby with id ${lobbyId}`);
// И, с интервалом в 500 мс, посылаем текущие время серверу
setInterval(() => io.emit("command", "ping", Date.now()), 500);
})
// Когда же сервер отвечает нам командой "pong"
.on("pong", ping => {
// Мы выводим пинг, полученный из аргумента, являющимся пришедшими данными от движка
console.log("pong!", `ping: ${ping} ms`)
})
// Создаём соединение, передавая в query строку username, являющейся ключём аутентификации в данный момент
// (поддержка токенов пока не реализована)
const io = SocketIO("http://localhost:3000", { query: { username: "1337player" } });
// И враппим данные о команде в наш эмиттер
io.on("command", (action, payload) => server.emit(action, payload));
У каждого лобби существует два типа объекта состояния:
lobbyState, глобальное, единое для всех игроковplayerState, уникальное для каждого игрокаОба состояния можно менять и изменения отправлять клиентам, обмениваясь данными и синхронизируя их. Например, существует игра, цель которой нажмать на кнопку и получать очки, тогда лобби будет создано следующим образом:
class GameLobby extends Lobby {
createPlayerState = () => ({ score: 0 })
onCommand(player: Player, action: string) {
if(action !== "player.score") return;
const ps = this.getPlayerState(player);
const changes = ps.modify(s => ({ score: s.score + 1 })).apply();
this.command(player, "player.score", changes);
}
}
Суть проста - функция createPlayerState возвращает объект, определяющий начальное состояние каждого подключенного в лобби игрока. Если она не объявлена, то состоянию присваивается пустой объект {}.
Метод onCommand вызывается при команде, не имеющей отношения к отношения к системному взаимодействию с лобби, посылаемой игроком находящимся в данный момент в лобби. Например, игрок, посылая команду game.ping, отправит её именно в то лобби, в котором он находится в данный момент и метод onCommand вызовется, передав игрока первым аргументом player. Вторым и третьим аргументами выступают наименование команды action и дополнительные данные payload, которые игрок мог передать. Если их нет - обработчику прилетает пустой объект {}.
В методе проверяется, является ли обрабатываемая команда player.score:
if(action !== "player.score") return;
В ином случае, обработка команды завершается. Метод базового класса Lobby именуемый getPlayerState позволяет получить состояние любого игрока, находящегося (или находившегося когда-либо) в этом лобби. Для этого первым аргументом передаётся ссылка на экземпляр игрока player, в ответ возвращается экземпляр класса SyncState, позволяющий манипулировать данными состояния.
const ps = this.getPlayerState(player);
Следующим шагом необходимо изменить состояние игрока, добавив ему очки. Данная операция осуществляется методом modify в объекте состояния. В его аргумент передаётся функция, в аргументах которой находятся:
state, текущее состояние;changes, все совершённые изменения над этим состоянием после использования modify;Методом modify возвращается экземпляр объекта изменений, которые можно сохранить и получить, выполнив метод apply, возвращающий объект изменений, совершённых над состоянием.
const changes = ps.modify(s => ({ score: s.score + 1 })).apply();
Изменения необходимо отправить клиенту и для этой цели используется метод базового класса Lobby именуемый command, имеющий следующие аргументы:
player, игрок, который должен получить данные;action, команда, которая придёт игроку с этими данными;payload, Сам объект данных, отправляемый игроку;Прописав метод:
this.command(player, "player.score", changes);
После вышеперечисленных операций игрок получит ответ с изменившимся состоянием, новым количеством очков, что и требовалось сделать.
yarn test
FAQs
game web-engine
The npm package astra-engine receives a total of 36 weekly downloads. As such, astra-engine popularity was classified as not popular.
We found that astra-engine demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.

Security News
Open source is under attack because of how much value it creates. It has been the foundation of every major software innovation for the last three decades. This is not the time to walk away from it.

Security News
Socket CEO Feross Aboukhadijeh breaks down how North Korea hijacked Axios and what it means for the future of software supply chain security.