技能是如何运转的?
属性是什么?
技能是一个自定义的物品属性。同一属性在不同的物品上可以有不同的变化。例如,耐久属性允许您为一个物品定义一个自定义的耐久,但并不是所有拥有耐久机制的物品都有相同的耐久
耐久机制的工作原理是将物品的耐久存储在它的metadatas中,并使用耐久度条来显示它的自定义耐久度,而不是它的真正耐久度
那么如果每个项目的属性都不一样,我是不是每次都要重写一个不同的耐久呢?
当然,为此Oraxen允许你为每个属性关联一个ItemModifier列表。ItemModifier是Function,它基本上是一小段代码,包含了当一个物品由服务器通过其配置生成时要对其进行的修改。例如对于耐久机制,我使用了一个 itemModifier,它可以将用户选择的耐久存储在物品的 metadatas 中
复制 item -> item . setCustomTag (NAMESPACED_KEY ,
PersistentDataType . INTEGER , section . getInt ( "value" ))
让我们创建我们的第一个属性
在本教程中,我将以耐久机制为例(因为它非常简单易懂),但你可以按照本教程来创建你想要的机制
第一步:创建我们的属性类
从创建一个继承自Mechanical的类开始,如果使用intelliJ,则应该得到如下所示:
复制 class DurabilityMechanic extends Mechanic {
public DurabilityMechanic ( MechanicFactory mechanicFactory ,
ConfigurationSection section ,
Function < ItemBuilder , ItemBuilder >... modifiers) {
super(mechanicFactory , section , modifiers);
}
}
Mechanic构造函数需要三个参数:
复制 - 创建属性的实例
- 用于配置属性的部分
- 项目修饰
我希望我的属性文件的每个变化都有不同的耐久,所以我将阅读属性文件的配置并存储值
属性配置部分的外观:
复制 class DurabilityMechanic extends Mechanic {
private int itemDurability;
public DurabilityMechanic ( MechanicFactory mechanicFactory ,
ConfigurationSection section) {
/* We give:
- an instance of the Factory which created the mechanic
- the section used to configure the mechanic
- the item modifier(s)
*/
super(mechanicFactory , section , item ->
item . setCustomTag (NAMESPACED_KEY ,
PersistentDataType . INTEGER , section . getInt ( "value" )));
this . itemDurability = section . getInt ( "value" );
}
public int getItemMaxDurability () {
return itemDurability;
}
}
所以现在我们有了一个DurabilityMechanic类,它能够适应任何项目,它将调用我们的DurabilityModifier类来告诉Oraxen在创建它们之前要做哪些修改(这里我们只是在条目中添加一个包含所需新耐久的数据)
第二步:创建属性功能类
和之前一样,使用你的ide功能自动创建一个扩展MechanicFactory的类
复制 class DurabilityMechanicFactory extends MechanicFactory {
public DurabilityMechanicFactory ( ConfigurationSection section) {
super(section);
}
@ Override
public Mechanic parse ( ConfigurationSection itemMechanicConfiguration) {
return null ;
}
}
我们重写解析方法来创建一个新的属性(通过之前创建的DurabilityMechanic类)。我们还想告诉Oraxen这个属性已经成功实现了,可以使用addToImplemented方法加载,所以我们的类现在看起来是这样的
复制 public class DurabilityMechanicFactory extends MechanicFactory {
public DurabilityMechanicFactory ( ConfigurationSection section) {
super(section);
}
@ Override
public Mechanic parse ( ConfigurationSection itemMechanicConfiguration) {
Mechanic mechanic = new DurabilityMechanic( this , itemMechanicConfiguration) ;
addToImplemented(mechanic) ;
return mechanic;
}
}
第三步:添加我们的功能(事件)
在我的例子中,我只需要使用一个事件来玩耐久,我会创建一个DurabilityMechanicsManager类来实现Listener,以获得一个干净整洁的代码,但我可以直接在DurabilityMechanicFactory中完成。我告诉Bukkit,当建成后,哪个类管理事件
复制 public class DurabilityMechanicFactory extends MechanicFactory {
public DurabilityMechanicFactory ( ConfigurationSection section) {
super(section);
MechanicsManager . registerListeners ( OraxenPlugin . get () ,
new DurabilityMechanicsManager( this ) );
}
@ Override
public Mechanic parse ( ConfigurationSection itemMechanicConfiguration) {
Mechanic mechanic = new DurabilityMechanic( this , itemMechanicConfiguration) ;
addToImplemented(mechanic) ;
return mechanic;
}
}
为了根据插件管理的真实耐久计算物品上显示的耐久,我使用了一些简单的数学方法:
bukkitDamage等于bukkitMaxDurability减 realMaxDurability除realDurability乘bukkitMaxDurability
所以这就是我的DurabilityMechanicsManager类:
复制 class DurabilityMechanicsManager implements Listener {
private DurabilityMechanicFactory factory;
public DurabilityMechanicsManager ( DurabilityMechanicFactory factory) {
this . factory = factory;
}
@ EventHandler (priority = EventPriority . HIGH , ignoreCancelled = true )
private void onItemDamaged ( PlayerItemDamageEvent event) {
ItemStack item = event . getItem ();
String itemID = OraxenItems . getIdByItem (item);
if ( factory . isNotImplementedIn (itemID))
return ;
DurabilityMechanic durabilityMechanic =
(DurabilityMechanic) factory . getMechanic (itemID);
ItemMeta itemMeta = item . getItemMeta ();
PersistentDataContainer persistentDataContainer =
itemMeta . getPersistentDataContainer ();
int realDurabilityLeft = persistentDataContainer
. get ( DurabilityMechanic . NAMESPACED_KEY , PersistentDataType . INTEGER )
- event . getDamage ();
if (realDurabilityLeft > 0 ) {
double realMaxDurability =
//because int rounded values suck
durabilityMechanic . getItemMaxDurability ();
persistentDataContainer . set ( DurabilityMechanic . NAMESPACED_KEY ,
PersistentDataType . INTEGER , realDurabilityLeft);
((Damageable) itemMeta) . setDamage (( int ) ( item . getType ()
. getMaxDurability () - realDurabilityLeft
/ realMaxDurability * item . getType () . getMaxDurability ()));
item . setItemMeta (itemMeta);
} else {
item . setAmount ( 0 );
}
}
}
最后一步:注册你的属性
只需在加载插件时调用这一行(例如在你的onEnable方法中)
复制 MechanicsManager . registerMechanicFactory ( "durability" ,
DurabilityMechanicFactory . class );
结论
为了正确创建新的属性,建议将其代码分为三部分:
在MechanicsManager类中加入您自己的功能(也可以选择)
由于有了ItemModifier,您可以使用您的机制修改项目:
复制 item -> item . setCustomTag (NAMESPACED_KEY ,
PersistentDataType . INTEGER , section . getInt ( "value" ))
也可以使用类似的方法修改材质包:
复制 ResourcePack . addModifiers (packFolder -> { /* your modifications
最后注册你的技能!
总结一下教程,这里是耐久机制的完整源码