-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[DOC] add ScriptEngine API description in russian
- Loading branch information
Showing
2 changed files
with
286 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,285 @@ | ||
|
||
API скриптового движка Open Space Station 13 | ||
/* черновая версия */ | ||
|
||
Как все работает: | ||
|
||
Сначала движок запускает сервер, подбирает ресурсы, запускает скриптовый движок, генерирует мир и стартует. | ||
Карта генерируется питоном. Движок для этого вызывает функцию FillMap из файла Map. | ||
|
||
Мир начинает жить, но игроки этого не увидят пока не подключатся. На подключении игрока движок вызывает в скриптах функцию OnPlayerJoined из файла EngineHook. | ||
В этой функции можно настроить место появления игрока, создать ему персонажа и т.д. Пока персонаж создается движком, но это скоро изменится. | ||
|
||
Далее движок периодически обновляет мир. Мир - это объекты, которые расположены по карте в своих тайлах. | ||
У каждого объекта каждый такт ровно один раз вызывается метод Update. Также движок вызывает различные методы объектов в зависимости от инпута игрока: | ||
Move, InteractBy и т.д. | ||
|
||
Все объекты строятся на двух логиках: наследование и компоненты. Все что укладывается в логику наследования, должно реализовываться через нее, например: | ||
Object -> Item (Небольшой предмет) -> Gun -> Taser. | ||
Какая-то дополнительная логика, которая вылазит за пределы иерархии (например, светиться или жрать энергию может почти что угодно), реализуется с помощью компонент. | ||
У каждого объекта есть список компонент, их можно получать из объекта по типу и добавлять их ему. Сейчас есть только одна компонента - Control, но в будущем появится много других. | ||
|
||
Все объекты реализуются только в скриптах. Большая часть компонент реализуется тоже в скриптах, но в случае компонент есть возможность создания на стороне движка, чтобы повысить производительность. | ||
|
||
|
||
Точки передачи управления (колбеки, которые вызывает движок): | ||
|
||
Модуль Map: FillMap() | ||
Модуль EngineHook: OnPlayerJoined() | ||
// more soon | ||
|
||
|
||
// * * * * * | ||
// | ||
// Модуль Engine_Server | ||
// | ||
// * * * * * | ||
|
||
Server | ||
Поля readonly: | ||
RM // Менеджер ресурсов | ||
GServer // глобальная переменная, единственный способ получить объект типа Server | ||
|
||
|
||
Game | ||
Поля readonly: | ||
world // игровой мир | ||
GGame // глобальная переменная, экземпляр игры | ||
|
||
|
||
Player(наследован от VerbsHolder) | ||
Поля readonly: | ||
ckey(string) | ||
Поля read/write: | ||
control // Control, компонента, которая прикреплена к некому объекту. С помощью нее игрок управляет объектом. Мб None. | ||
Функции: | ||
IsConnected() -> bool // True, если игрок онлайн. False, если отключился. Игроки удаляются только на рестарте, при переподключении получаем того же игрока. | ||
|
||
|
||
ResourceManager | ||
Функции: | ||
GetIcon(string title, ItemSpriteState state) -> Icon // возвращает иконку по названию спрайта и его состоянию | ||
|
||
|
||
Icon | ||
пока ничего нет тут, просто объект | ||
|
||
// Состояние спрайта. Примеры конфигурации спрайтов смотри в уже существующих .json ресурсов. | ||
ItemSpriteState(enumeration) | ||
ItemSpriteState.DEFAULT // файл icon.png | ||
ItemSpriteState.ON_MOB // файл icon.mob.png | ||
ItemSpriteState.IN_HAND_LEFT // файл icon.lhand.png | ||
ItemSpriteState.IN_HAND_RIGHT // файл icon.rhand.png | ||
|
||
|
||
|
||
// * * * * * | ||
// | ||
// Модуль Engine_World | ||
// | ||
// * * * * * | ||
|
||
World | ||
Функции: | ||
GetObjectById(int) -> Object // возвращает объект по его id. У каждого объекта уникальный id. | ||
GetMap() -> Map // возвращает карту. Пока в мире только одна карта, но будет больше. | ||
|
||
|
||
// Карта игрового мира, состоит из клеток (Tile) | ||
Map | ||
Поля readonly: | ||
size(Vec3i) // размеры карты | ||
Функции: | ||
GetTile(Vec3i) -> Tile // получить Tile по координатам | ||
|
||
|
||
// Клетка игрового мира | ||
Tile | ||
Поля readonly: | ||
x, y, z (int) | ||
pos(Vec3i) // Vec3i(x, y, z) | ||
map(Map) | ||
Функции: | ||
IsDense(DirectionSet) -> bool // True, если в тайле есть объект, через который нельзя пройти по одному из заданных направлений | ||
IsSpace() -> bool // True, если в тайле космос (нет пола и стены) | ||
GetDenseObject(DirectionSet) -> Object // Возвращает первый объект, который мешает проходу по одному из заданных направлений или null, если такого нет | ||
|
||
// Игровой объект | ||
Object | ||
Поля: | ||
name(string) - название объекта | ||
sprite(string) - id спрайта (строка) | ||
layer(int) - слой отрисовки объекта (от 0 до 100). Чем выше, тем позже рисуется | ||
density(bool) - игнорирует ли объект жесткие препятствия (объекты с параметром solidity) | ||
solidity(DirectionSet) - жесткие направления (какие направления блокируются объектом) | ||
invisibility(int) - невидимость объекта (в бинарном представлении каждый бит - отдельный тип невидимости) | ||
tile(Tile) - тайл, в котором находится объект. Может быть null | ||
position(Vec2i) - координаты объекта. {-1, -1}, если объект не расположен на карте | ||
speed(Vec2f) - физическая скорость объекта, тайлы в секунду | ||
moveSpeed(float) - скорость объекта при движении (когда он сам движется), тайлы в секунду | ||
isFloor(bool) | ||
isWall(bool) | ||
|
||
Функции: | ||
AddVerb(string id, function() action) - добавить действие объекту (можно запихать аргументом любую функцию без аргументов) | ||
Update(duration timeDelta) - вызывается каждый такт обновления мира движком | ||
InteractedBy(Object) - вызывается, когда вызвано взаимодействие с объектом другим объектом (щелкнули по объекту: в аргументе то, что было в руке или сама рука) | ||
|
||
IsCloseTo(Object) - проверяет, находится ли объект рядом с тем, который передан в аргументе | ||
Move(Vec2i) - передвинуть объект в заданном направлении. Все компоненты вектора должны быть == 1 ({1, 0}, {1, 1} например) | ||
MoveZ(int) - передвинуть вверх/вниз, аргумент от -1 до 1 | ||
|
||
AddComponent(string) // добавить компонент по его типу, который задается строкой | ||
GetComponent(string) -> Component // получить компонент | ||
|
||
AddObject(Object) - добавить объект в содержимое объекта | ||
RemoveObject(Object) - удалить объект из содержимого объекта | ||
|
||
SetSpriteState(ItemSpriteState) - поменять состояние спрайтов | ||
PlayAnimation(string id, function callback) - проиграть анимацию по её id(строка), после чего вызвать функцию callback | ||
|
||
Delete() - удалить объект | ||
|
||
_updateIcons() - функция вызывается когда нужно нарисовать иконки. В ней можно вызвать _pushToIcons, чтобы добавить дополнительную иконку | ||
_pushToIcons(Icon) - добавляет иконку в вектор иконок, которые будут использованы для отрисовки объекта. | ||
sprite объекта отрисуется автоматически самым первым, а добавленные спрайты рисуются по порядку добавления | ||
|
||
// Единственный легальный способ создать объект | ||
CreateObject(string) -> Object // создает и возвращает объект по его пути. Пример: ghost = CreateObject("Objects.Creatures.Ghost"), чтобы создать Ghost. | ||
// Название файла скриптов и создаваемого объекта должны совпадать (временное ограничение) | ||
|
||
|
||
// Компоненты объекта. Кирпичик будущей Entity Component System. К объектам будут крепиться КОМПОНЕНТЫ, которые могут определяться и в питоне, и в плюсах. | ||
// В будущем будет инфраструктура, чтобы определять их в питоне, но пока не уверен, что это получится сделать. | ||
Component | ||
Функции: | ||
Update(duration timeDelta) // вызывается каждый такт обновления мира движком | ||
GetOwner() -> Object // возвращает объект, который содержит в себе эту компоненту | ||
|
||
|
||
// Единственная реализованная пока компонента - компонента управления. Сейчас она дается игроку, который с помощью нее управляет персонажем: | ||
// Игрок -> Логика клиента -> Network -> Прием пакета сервером -> Player -> Control -> Character | ||
// В будущем с помощью этой компоненты персонажами также сможет управлять ИИ. | ||
Control(наследуется от Component) | ||
Поля: | ||
seeInvisibleAbility(int) // способность видеть невидимое. Каждый битовый флаг указывает на возможность видеть конкретную невидимость | ||
// P.S. Не помню, почему это тут. По идее, оно должно быть в существе или еще где. | ||
|
||
Функции: | ||
GetAndDropMoveOrder() -> Vec2i // возвращает приказ, полученный от игрока, на то, в каком направлении двигаться | ||
GetAndDropMoveZOrder() -> int // приказ двигаться по Z-уровням | ||
GetAndDropClickedObject() -> Object // возвращает объект, по которому кликнул игрок (None, если игрок никуда не кликал) | ||
|
||
|
||
// UI, который связан с управляемым существом. Хранится у компоненты Control. Отвечает за те кнопочки, которые рисуются поверх тайлгрида. | ||
ControlUI | ||
Поля: | ||
// read only | ||
resolution(Vec2i) // размеры TileGrid у игрока. Это значение ни к чему не привязано и может меняться, у игрока потом скейлится. | ||
// На момент написания 15*32 x 15*32. На клиенте увеличивается так, чтобы занимать весь TileGrid. | ||
center(Vec2i) - resolution пополам, просто для удобства | ||
iconSize(Vec2i) - размеры одного элемента. Скорее всего это поле будет изменено в будущем. Сейчас 32 x 32. | ||
|
||
Функции: | ||
UpdateElement(ControlUIElement) // Создаем элемент и пихаем в ControlUI с помощью этой функции | ||
RemoveElement(string) // удаляем элемент по id | ||
|
||
|
||
// Элемент ControlUI. Его нужно создавать на стороне питона и отдавать ControlUI. Можно хранить на него указатель и обновлять по мере необходимости. | ||
ControlUIElement | ||
Конструктор: | ||
ControlUIElement() - создает пустой контрол | ||
|
||
Поля: | ||
// read/write | ||
id(string) // уникальный идентификатор контрола. Задав уже существующий, можно переписать старый контрол, который есть в ControlUI, новым. | ||
position(vec2i) // координаты контрола на экране игрока. Размеры окна и самого контрола можно взять у ControlUI. | ||
|
||
Функции: | ||
RegisterCallback(void function()) // регистрирует функцию без аргументов, которая будет вызвана при нажатии по элементу UI | ||
AddIcon(string) // нарисовать спрайт поверх уже заданных, аргумент - название спрайта | ||
PopIcon() // удалить самый верхний спрайт (последний добавленный) | ||
ClearIcons() // удалить все спрайты | ||
|
||
|
||
// Класс, от которого наследуется плеер. Позволяет добавлять действия без параметров, которые можно будет вызвать из консоли. | ||
// Пример: | ||
// def MyAction(player): | ||
// print(player.ckey + " called MyAction") | ||
// | ||
// где-то в другом коде, например, в конструкторе Player пишем: | ||
// ... | ||
// self.AddVerb("MyAction", MyAction) | ||
// ... | ||
// | ||
// Запускаем сервер + клиент, в консоли на клиенте пишем: "Player.MyAction". Вызывается действие. "Player" - это название, с которым был зарегистрирован VerbsHolder. Пока регистрировать в скриптах нельзя. | ||
// Из интересного, можно вбить Atmos.ToggleOverlay и увидеть номера газовых локалей :) | ||
VerbsHolder | ||
Функции: | ||
AddVerb(string, function(Player)) // добавить действие, которое будет вызываться командой "string". Действие - это функция, которая принимает единственный аргумент - Player. | ||
|
||
|
||
// * * * * * | ||
// | ||
// Модуль Engine_Geometry | ||
// | ||
// * * * * * | ||
|
||
Векторы: | ||
Vec2i, Vec2f, Vec3i, Vec3f - вектора целых чисел и | ||
чисел с плавающей точкой с двумя или тремя компонентами | ||
|
||
Конктрукторы: | ||
Vec2i() | ||
Vec3i() | ||
Vec2i(x, y) | ||
Vec3i(Vec2i xy, z) // первый аргумент - плоский вектор, а второй - дополняющая третья координата | ||
Vec3i(x, y, z) | ||
Vec2i(s) // Всем координатам ставится одно число | ||
Vec3i(s) // x = s, y = s, z = s | ||
|
||
Поля: | ||
x, y, z - read/write | ||
|
||
Поля readonly: | ||
xy - только у 3d вектора. Возвращает 2d вектор без третьей координаты. | ||
|
||
Функции: | ||
Length() -> float | ||
Normalize() -> Vec // возвращает вектор с тем же направлением, длины 1 | ||
GetAngle() -> float // возвращает угол, на который повернут вектор в радианах | ||
GetDirection() // возвращает направление, куда направлен вектор. Может возвращать сложные направления, например (0.5, 0.5) -> Direction.NORTH_EAST | ||
Сложение | ||
Вычитание | ||
Умножение на число (int или float) | ||
Деление на число (int или float) | ||
__repr__ | ||
__bool__ - True если одна из координат != 0 | ||
|
||
Direction(enumeration) | ||
Direction.NONE | ||
Direction.SOUTH | ||
Direction.WEST | ||
Direction.NORTH | ||
Direction.EAST | ||
Direction.SOUTH_WEST | ||
Direction.NORTH_WEST | ||
Direction.NORTH_EAST | ||
Direction.SOUTH_EAST | ||
Direction.CENTER | ||
|
||
DirectionToVect(Direction) -> Vec2i // возвращает вектор с координатами 0, +1 или -1, направленный согласно заданному направлению | ||
InvertDirection(Direction) -> Direction // возвращает зеркальное направление | ||
|
||
// Набор направлений. Например, используется чтобы указать, что тонкая стенка не пускает только на север. Составные направления разбиваются на составляющие. | ||
DirectionSet | ||
Конструкторы: | ||
DirectionSet() | ||
|
||
Функции: | ||
Add([Directions]) // добавить список Direction в сет | ||
Remove([Directions]) // удалить список Direction из сета | ||
IsExistsOne([Directions]) -> bool // True, если хотя бы одно из направлений есть в сете | ||
AreExistAll([Directions]) -> bool // True, если все направления есть в сете | ||
Reset() // сбросить сет | ||
|