Skip to content

Latest commit

 

History

History
320 lines (223 loc) · 21.6 KB

HollowEngine.md

File metadata and controls

320 lines (223 loc) · 21.6 KB

Здесь описано всё, что я буду разрабатывать в ближайшее время, а также различные мои мысли насчёт разработки.

Организация ресурсов

  • HollowEngine : Корневая папка
    • .cache
      • scripts
      • server-resources
    • resources : ресурсы
      • blocks
      • cutscenes
      • entities
      • items
      • guis
      • models | клиент
      • recipes
      • sounds | клиент
      • textures | клиент
      • world
        • biomes
        • chunkgen
        • dimensions
        • structures
    • scripts : исходники
      • libraries : библиотеки

Скриптовой Движок

События

Вообще критически важно написать обфускатор скриптов, тогда всякие из этих дополнений можно реализовывать через расширяемые функции.

Абстракция для мира

interface IWorld {
    fun placeBlock(block: IPos, facing: FacingType, nbt: INBT? = null, playSound: Boolean = true)

	fun destroyBlock(block: IPos, playSound: Boolean)
	
	fun useBlock([x, y z], item: IItem)
	
	fun getOrSpawnStructure(name: String): IStructure

	fun placeStructure(name: String, [x, y z], facing, animation)

	fun changeWeather(weather: WeatherType = RAIN)

	fun setTime(time: Long)
}

enum BuildAnimation {
	NONE, DELAY, FROM_GROUND, FROM_CEILING
}

метод: executeClient("path to script") - запускает скрипт на клиенте, например открыть gui или настройки. — возвращает переменную для получения статуса или остановки скрипта. Например можно запустить скрипт и дождаться его завершения.

Метод forceComplete(path: String) - принудительное завершиение скрипта

Также стоит добавить аннотацию @file:StartOnFirstJoin() и возможность запускать конкретный скрипт. Это очень важно в случаях, когда есть несколько глобальных веток прохождения

Задачи NPC

//типы: looped, single, async
npc.loopedTask {
    async(
    { movement.go(team) },
    { look.at(team, lockY=true) }
    )
    //задачи типа attack это по сути те же singleTask, основанные на tickable задачах
    attack(team)
    if(npc.hp<npc.maxHp/2) {
        movement.avoid(team)
    }
    tickable { tick ->
        return true;
    }
}

npc.lockHitbox = true

npc.configure {
	texture = "..." //сменить текстуру, прям щас
	animations[Animations.WALK] = AnimationManager.get(npc, "file", "name")
}

npc play AnimationManager.get(npc, "file", "name")
} //может проиграть кастомную анимацию, но лучше все анимации подготовить заранее и ассинхронно

val cancelableTask = npc.loopedTask {
	look.at(team)
}

cancelableTask.cancel()

val task = async(
	timeout=5f
) {
//Ассинхронный запуск
}

task.isComlete()
task.cancel()
task.isError()

Виды скриптов

Миксины

Пример:

@file:Mixin(SomeObject::class)

@shadow val f: SomeClass

@Inject(...)
fun someMethod(player): SomeClass {
	val rep = player.team.fraction["test"].reputation

    return rep>10
}

Также стоит сделать возможность включать/выключать их через другие скрипты и интерфейс, например захотел какой-нибудь разработчик отключить агр у враждебных мобов при определённом уровне фракции и сделал себе миксин для этого.

Main-скрипт

Запускается при запуске игры, можно написать почти что угодно.

Пример file_name.main.kts:

val ITEMS = DeferredRegisterer.create(...)

ITEMS.register(...)

Достаточно полезная вещь, особенно для всяких библиотек.

Оба скрипта выше имеют аннотацию @file:Side(CLIENT/SERVER) она позволяет запускать скрипт только со стороны клиента или сервера.

Библиотеки

Здесь описаны несколько опциональных библиотек, для более удобного создания особых скриптов, т.к. те же фракции или компанионы нужны далеко не во всех проектах.

[Fractions]

StoryTeam.fractions - возвращает StoryFractions - обьект хранящий всё о фракциях.

StoryFractions.get("name") - возвращает фракцию с именем

из Фракции можно получить или изменить репутацию, а также указать доп. NBT, чтобы хранить что-то важное насчёт фракции. Фракция имеет кодовое название и обычное (переводимое)

[Companions]

Компанионы, это NPC, которых можно брать с собой в команду, они могут помогать в битвах, добыче и прочих мелочах, также тут есть доп. API для создания кастомных задач.

пара примеров:

class Companion {
    val name
    val reputation
    val nbt
    private val options
}

//получает определённого компаниона
val companion = Companions.getOrCreate("name")

//Добавляет новую возможность в меню компаниона, например защищать территорию рядом
companion.makeOption("menu.guard_task", this::someTask)

Companions.GLOBAL.add(companion, npc)

team.hasCompanion("name")

[ResumeLib]

Библиооека, добавляющая сохраняемые задания, например:

StagedTask(
{
//действие 1
},
{
//действие 2
}
//и т.д.
)
//nbt сохраняется в формате "addon.resume_lib.event_name.[номер]": текущий номер 

Эффекты

Эффектов пока 2 вида: шейдеры и партиклы:

val spawner = ParticleSpawner(level, "particles/test.json")

spawner.enable()
spawner.disable()
spawner.play(2f) //2 секунды

val shader = ShaderSpawner("shaders/test.hc")

//То, к чему прикрепляется шейдер будет определяться в редакторе, это скорее просто "выключатель", который может его включить и выключить

shader.configure {
    uniforms["pos"] = [1, 2, 3]
}

shader.enable() //disable/play

Игровой контент

Редактор Сущностей

Редактор Сущностей представляет собой окно размером 90% от экрана поделённое на 2 части, в правой предпросмотр персонажа, его можно повертеть, посмотреть хитбокс, сравнить размеры с игроком, в левой части вкладки с настройками.

Вкладок планируется 5.

  1. Модель. Здесь указывается путь к файлу модели, текстурам и начальная трансформация модели, т.е. можно немного её сдвинуть, увеличить или повернуть, если при экспорте модели кто-то немного накосячил.
  2. Анимации. В этой вкладке можно указать анимации (ходьба, бег, ожидание) и опционально - эмоции (радость, страх, гнев и т.п.), они в основном для нпс, их можно указать просто как статичную позу, так и полноценную анимацию. Сами анимации будут обрабатываться автоматически, условно если NPC падает, запускается анимация падения, если умирает, то анимация смерти и т.п. А эмоции можно легко указать в скриптах, чтобы не указывать каждый раз полный путь к ним, что не особо удобно.
  3. Параметры. Тут можно будет настроить саму Сущность: аттрибуты (здоровье, атака, скорость и т.п.), имя, размер хитбокса и прочие мелочи.
  4. Рендеринг. Тут настраивается всё что связано с рендером и оптимизацией: игнорировать освещение (как глаза эндермена например, которые всегда светятся), односторонние текстуры (иногда текстуры видны только с 1 стороны, например чтобы сделать эффект "ауры" используют простой шар, но с текстурой, где видна только внутренняя часть), полупрозрачные текстуры (например если моб - призрак, сквозь которого можно смотреть, по умолчанию отключено для оптимизации, подумайте почему это вызывает нагрузку), сглаживание нормалей (делает модель более гладкой, не меняя количество вершин, можете загуглить, но не подавитесь линейной алгеброй!)
  5. Оружие и броня. Тут настраивается отображение предметов и брони - можно указать к какой кости модели прикрепить обьект и при необходимости сдвинуть его относительно кости. Также можно полностью отключить отображение брони и оружия. В будущем можно будет указать отдельную модель брони.

Редактор Предметов

Структуры

Виды структур: простая и пазловая. (Хотелось бы ещё сделать "биомную" структуру, как в TF напрмер) Пазловая состоит из простых, т.е. спавнится "ядро", от него идут развилки и так определённое количество раз (можно сделать случайный предпросмотр)

После указания файла можно настроить как она будет спавнится вот условия, их можно комбинировать [и, или]:

  1. в воздухе, в земле, на поверхности
  2. ниже или выше определённого y
  3. измерение
  4. шанс спавна на чанк / одиночный вызов
  5. скрипт (для кастомных условий и настроек спавна)

Для пазловой будут несколько доп. условий, например:

  1. сдвиг относительно предыдущего элемента + случайный сдиг в пределе [x1, x2]
  2. тропа/тоннель - например отдельный блок или специальная под-структура

и в завершении можно настроить всякие мелочи, типа заполнения воздухом или игнорирования замены.

Также бонусом было бы не плохо добавить процедурные "Декораторы", можно даже скриптовые, например:

  1. Стены на границах, например для крепости
  2. сталактиты и сталагмиты для подземных структур
  3. всякие цветы на полянах в структуре
IPlacedStructure.blockPos - позиция
IPlacedStructure.facing - направление (север, юг и т.п.)
IPlacedStructure.blockAt([блок относительно структуры с учётом поворота])

interface IPlaceableStructure {
    void placeAt(position, facing)
    void spawn(world)
}

world.structures.getOrSpawn(name): IPlacedStructure

Настройки Мира/Локации

Позволяет настроить скайбокс, туман, всякие шейдерные эффекты, также стоит сделать удобный редактор мира на подобии MCEdit. Если получится, то было бы не плохо загружать целые карты (на определённые координаты в мире или относительно структуры) из блендера, но тут проблема скорее в коллизиях и оптимизации, ибо те части карты, что мы не видим должны буть отброшены, а не рендерится, а опыта в подобном не только у меня нет, но и ни у одного мододела в мире :(

Редактор интерфейса

Редактор представляет собой интерфейс, где можно на пкм добавлять на экран различные виджеты, например: картинка, слот, инвентарь, хотбар, меню с вкладками, моб, текст, поле ввода, слайдер, чекбокс, скроллбар, Orgin (для нодовых структур). Нажимая по виджетам пкм можно добавить на них ещё виджеты. Слева на панели можно настраивать содержимое, также, зажав ctrl, при перемещении виджета он будет центрироваться при приближении к центру.

HTML интерфейс

В папке HollowEngine/resources/guis/могут лежать страницы, их можно открыть командой и они автоматически обновляются.

Также было бы интересно при запуске сервера открывать клиентам доступ к данным гуишкам напрямую к серверу, чтобы он сам отслеживал все нажатия и введённые данные, это позволит избежать некоторых уязвимостей

Катсцены

[типы кадров]

Кадр представляет собой отрезок на временной шкале, например есть 2 точки, одна на 0с, вторая на 3,5с, кадр хранит информацию о том, что и как нужно сделать за этот отрезок времени. Разные кадры можно применять лишь на разные элементы, например кадр экрана можно применить лишь на камеру.

  • Кадры перемещения - кадр, хранящий начальное и конечное положение моба в пространстве, а также направление его взгляда и поворот тела.
  • Кадры анимации - гибридный кадр, хранящий начальную и конечную позу. Кадры анимации полностью оверрайдят предыдущее положение модели, но при необходимости можно наложить модификатор <Тип Анимации>.
  • Кадры звука - хранят информацию о звуке/музыке, которая будет играть, есть несколько настроек: (скорость звука/повтор) - если длина кадра больше длины аудио, Fade In/Out - плавное включение/выключение звука, громкость, сам звук можно указать как путь или ссылку.
  • Кадры перехода - позволяет настроить плавный переход из позы конца предыдущего кадра в позу начала следующего, можно добавить исключительно между 2 кадрами анимации. Крайне удобно при переходе от шаблонной анимации к "новой".
  • Кадры записи <игрок> - записывает перемещение игрока и применяет к npc + в параметрах можно отключить не нужное: перемещение, поворот, анимации модельки. Перемещение это список векторов, поворот, это повороты тела и головы, а анимация - это текущий статус игрока (IDLE, WALK, RUN, SIT...)
  • Кадры записи <поиск пути> - записывает перемещение, как если бы NPC шёл от точки к точке, как обычный моб.
  • Кадры экрана - позволяет настроить всё, что на экране, например: скрыть хотбар, добавить надпись или оверлей.
  • Кадры инвентаря - позволяет настроить оружие и броню NPC

[модификаторы кадров]

  • Модификатор <Интерполяция> - позволяет выполнять действия с ускорением, а не равномерно. Работает на весь кадр.
  • Модификатор <Аудио> - позволяет запускать звуки в начале кадра, удобно для озвучки например, если длина звука меньше кадра, то звук останавливается, удобно тем, что можно делать синхронизацию разговоров или звуковой эффект.
  • Модификатор <Скрипт> - запускает указанный файл, в файле можно указать что делать в начале/конце кадра или обрабатывать каждый тик кадра.
  • Модификатор <Сплайн> - несколько кадров (имеет эффект от 3 шт) можно объединить в сплайн, например чтобы моб или камера двигались не от точки к точке по прямым, а плавно. Накладывается на кадр перемещения.
  • Модификатор <Тип Анимации> - позволяет указать вид анимации:
    • полная перезапись прошлой позы
    • дополнение прошлой позы (например если до начала анимации рука была повёрнута на 10 градусов, а в анимации она повёрнута на 20 градусов, то общий поворот будет равен 30)
    • среднее арифметическое. Используется для многослойных анимаций, например когда персонаж идёт и говорит одновременно.

Работа с таймлайном — Нажав пкм на таймлайне можно выбрать в списке определённый кадр и настроить его, также он автоматически создаётся, если сделать что-то с моделью на экране (передвинуть, повернуть, анимировать), тогда создаются кадры по соответвенному действию, их также можно настроить, например создав кадр анимации можно выбрать 2 режима: шаблоная анимация и новая анимация, в новой нужно самому анимировать, а в шаблонной просто выбрать готовую анимацию NPC или его эмоцию, которые настраивались при создании сущности, также этот режим позволяет либо растянуть анимацию на всё время кадра, либо зациклить. Вообще по умолчанию видно 3 слоя, в каждом могут быть любые кадры, а самих слоёв бесконечное множество. переключаются вертикальными стрелками в интерфейсе.