Skip to content

Commit

Permalink
[DOC] add ScriptEngine API description in russian
Browse files Browse the repository at this point in the history
  • Loading branch information
Insineer committed Sep 11, 2019
1 parent dc9537f commit 9de983c
Show file tree
Hide file tree
Showing 2 changed files with 286 additions and 1 deletion.
2 changes: 1 addition & 1 deletion CI/appveyor/appveyor-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ after_build:
- set BIN_FOLDER_SUFFIX=%platform%
- if "%BIN_FOLDER_SUFFIX%"=="x86" (set BIN_FOLDER_SUFFIX=Win32)

- 7z a "OSS13-%platform%-%appveyor_build_version%.zip" "%APPVEYOR_BUILD_FOLDER%\bin\Release-%BIN_FOLDER_SUFFIX%\OSS13 Client.exe" "%APPVEYOR_BUILD_FOLDER%\bin\Release-%BIN_FOLDER_SUFFIX%\OSS13 Server.exe" "C:\Tools\vcpkg\installed\%platform%-windows\bin\python37.dll" Resources -ir!GameLogic\*.py Arialuni.ttf LICENSE README.md UsersDB
- 7z a "OSS13-%platform%-%appveyor_build_version%.zip" "%APPVEYOR_BUILD_FOLDER%\bin\Release-%BIN_FOLDER_SUFFIX%\OSS13 Client.exe" "%APPVEYOR_BUILD_FOLDER%\bin\Release-%BIN_FOLDER_SUFFIX%\OSS13 Server.exe" "C:\Tools\vcpkg\installed\%platform%-windows\bin\python37.dll" Documentation Resources -ir!GameLogic\*.py Arialuni.ttf LICENSE README.md UsersDB

artifacts:
- path: "OSS13-$(platform)-%appveyor_build_version%.zip"
Expand Down
285 changes: 285 additions & 0 deletions Documentation/ScriptEngine API [russian].txt
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() // сбросить сет

0 comments on commit 9de983c

Please sign in to comment.