Skip to main content
Version: 2.0

Универсальные Capability


Система Capability

Вы решили добавить игроку шкалу маны или добавить всем мобам новый параметр деньги или какие-либо другие данные? Для этого HollowCore предоставляет систему Capability с автоматическим сохранением и синхронизацией данных.



Создание Capability

Создание Capability

Наследуйтесь от класса CapalilityInstance() и добавьте какой-либо сериализуемый параметр (с аннотацией @Serializable или наследуемый от ru.hollowhorizon.hc.client.utils.nbt.INBTSerializable).

Так же добавьте аннотацию @HollowCapabilityV2 с параметрами объекта, к которому Capability будет привязана ко всем объектам, наследованным от указанного. Доступные варианты: Entity, Player, BlockEntity и Level. Также вы можете создать интерфейс и указать его в качестве цели, тогда все объекты, реализующие данный интерфейс, будут иметь эту Capability.

Пример
@HollowCapabilityV2(Entity::class)
class MoneyCapability : CapabilityInstance() {
var money: Int by syncable(0) // Синхронизируемый параметр типа Int, все примитивные типы тоже сериализуемы
}

Синхронизируемые списки

Синхронизируемые списки

Создайте делегат при помощи syncableList<>(), тогда при изменении содержимого списка - он автоматически будет изменён и у клиента.

Пример
@HollowCapabilityV2(Entity::class)
class DataCapability : CapabilityInstance() {
var dataList by syncableList<String>()
}

Синхронизируемые Map<>()

Синхронизируемые списки

Создайте делегат при помощи syncableMap<K, V>(), где K - ключ, а V - значение, тогда при изменении содержимого списка - он автоматически будет изменён и у клиента.

Пример
@HollowCapabilityV2(Entity::class)
class DataCapability : CapabilityInstance() {
var dataList by syncableMap<Int, String>()
}
Примечание

Параметр K рекомендуется использовать только, как примитивный тип, если это возможно. Кроме того, все объекты рекомендуется делать одного типа, т.е. - использовать syncableMap<Number, Tag>() - не стоит, это может привести к багам и вылетам.



Использование Capability

Использование Capability

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

Пример
fun example(entity: Entity) {
val capability = entity[MoneyCapability::class]

val money: Int = capability.money // Получение значения

capability.money = -100 // Изменение значения
}


Как изменить серверное значение будучи на клиенте?

Защита и способ решения

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

Но вы можете добавить метод для проверки на игрока (Например только для модераторов сервера), для этого переопределите внутри Capability метод canAcceptFromClient(player: Player): Boolean. Проверка будет вызвана только на сервере. Либо делайте свои пакеты с дополнительной проверкой корректности данных.