From 9de983c01f442c52c39d9464b4b80c961f15244d Mon Sep 17 00:00:00 2001 From: Insineer Date: Wed, 11 Sep 2019 06:33:57 +0300 Subject: [PATCH] [DOC] add ScriptEngine API description in russian --- CI/appveyor/appveyor-release.yml | 2 +- Documentation/ScriptEngine API [russian].txt | 285 +++++++++++++++++++ 2 files changed, 286 insertions(+), 1 deletion(-) create mode 100644 Documentation/ScriptEngine API [russian].txt diff --git a/CI/appveyor/appveyor-release.yml b/CI/appveyor/appveyor-release.yml index f3c0124..6fa32d7 100644 --- a/CI/appveyor/appveyor-release.yml +++ b/CI/appveyor/appveyor-release.yml @@ -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" diff --git a/Documentation/ScriptEngine API [russian].txt b/Documentation/ScriptEngine API [russian].txt new file mode 100644 index 0000000..6231fb1 --- /dev/null +++ b/Documentation/ScriptEngine API [russian].txt @@ -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() // сбросить сет +