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