Универсальные 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
. Проверка будет вызвана только на сервере.
Либо делайте свои пакеты с дополнительной проверкой корректности данных.