• 欢迎来到Minecraft插件百科!
  • 对百科编辑一脸懵逼?帮助:快速入门带您快速熟悉百科编辑!
  • 因近日遭受攻击,百科现已限制编辑,有意编辑请加入插件百科企鹅群:223812289

Citizens/API:修订间差异

来自Minecraft插件百科
跳转到导航 跳转到搜索
无编辑摘要
 
(未显示同一用户的5个中间版本)
第14行: 第14行:
'''开发版下载地址:''' [http://ci.citizensnpcs.co/job/CitizensAPI/ Jenkins]
'''开发版下载地址:''' [http://ci.citizensnpcs.co/job/CitizensAPI/ Jenkins]


'''Documentation:''' [http://jd.citizensnpcs.co/ JavaDocs]
'''文档:''' [http://jd.citizensnpcs.co/ JavaDocs]


'''源码:''' [https://github.com/CitizensDev/CitizensAPI Github]
'''源码:''' [https://github.com/CitizensDev/CitizensAPI Github]
第20行: 第20行:
</div>
</div>
</div>
</div>
 
{{FNavBox}}
Citizens拥有广泛的API来让你制作与npc相关的插件或给npc添加新的角色特性。 确认你使用的是最新版的CitizensAPI来兼容最新版的Citizens.
Citizens拥有广泛的API来让你制作与npc相关的插件或给npc添加新的角色特性。 确认你使用的是最新版的CitizensAPI来兼容最新版的Citizens.


第41行: 第41行:
</pre>
</pre>


and this dependency:
和这个:
<pre>
<pre>
     <dependency>
     <dependency>
第52行: 第52行:
</pre>
</pre>


And replace <code>VERSION</code> with the current version of Citizens (check the filenames at http://ci.citizensnpcs.co/job/Citizens2/ for current version ID), formatted like <code>2.0.23-SNAPSHOT</code> (but with the version numbers changed to the relevant version).
并把 <code>VERSION</code>改为当前版本的Citizens (可以在 http://ci.citizensnpcs.co/job/Citizens2/ 看到Citizens版本号 ID), 比如 <code>2.0.23-SNAPSHOT</code> (but with the version numbers changed to the relevant version).


Note that for most purposes, it's best to link <code>citizens</code> rather than the API project, as many useful classes and utilities are not in the API. The main Citizens project ''includes'' the API and adds more options.
在大多数情况下,最好链接 <code>citizens</code> 而不是 API 项目, 因为很多有用的 classes 和 utilities不在API内. Citizens的项目 ''包括'' API和添加的更多选项.


==Hooking Into Citizens==
==关联Citizens==
Hooking into Citizens is as simple as creating a basic plugin and adding the line
关联Citizens和创建一个普通的插件一样简单,只需添加
depend: [Citizens] into your plugin.yml. From here, a common basic entry point is the CitizensAPI class. This gives you access to the NPCRegistry for NPC lookup, as well as the TraitFactory which allows trait registration. If Citizens is not loaded, all CitizensAPI.* methods will return null.
depend: [Citizens] 到你的 plugin.yml 内即可. From here, a common basic entry point is the CitizensAPI class. 这给予你 NPCRegistry for NPC lookup, as well as the TraitFactory which allows trait registration. If Citizens is not loaded, all CitizensAPI.* methods will return null.


== 创建一个 NPC ==
== 创建一个 NPC ==
创建npc最简单的方法就是使用 NPCRegistry。这个东西管理npc的存储和创建 which manages the storage and creation of NPCs. 默认的registry由CitizensAPI.getNPCRegistry() 给予, 并且你可以创建一个新的and you can create new ones with different storage methods by calling other CitizensAPI methods. A Player NPC with name "fullwall" could then be created like this:
创建npc最简单的方法就是使用 NPCRegistry 这个东西来管理npc的存储和创建 . 默认的registry由CitizensAPI.getNPCRegistry() 给予, 并且你可以用不同的存储方式来创建一个新的NPC. 一个玩家类型的名为"fullwall"的NPC可以这一创建:
  NPC npc = CitizensAPI.getNPCRegistry().createNPC(EntityType.PLAYER, "fullwall");
  NPC npc = CitizensAPI.getNPCRegistry().createNPC(EntityType.PLAYER, "fullwall");


== 检测实体是否是NPC ==
== 检测实体是否是NPC ==
Citizens NPCs will have the "NPC" metadata set to true.
Citizens的 NPC拥有设置为true的 "NPC"元数据.
Eg.
示例:
  boolean isCitizensNPC = entity.hasMetadata("NPC");
  boolean isCitizensNPC = entity.hasMetadata("NPC");


==Creating a Trait==
==创建特性==
Traits are persistent, attachable objects that are linked to an NPC and provide specific functionality. This can be anything from a full-blown dynamic villager AI to a simple talking trait.
特征是链接到NPC并提供特定功能的持久、可附加的板块。 这可以是任何东西,可以是带有动态AI会进行简单谈话的村民特性.


If using Maven, Citizens' Maven repo is available at http://repo.citizensnpcs.co
如果使用Maven, Citizens的Maven repo 可以在 http://repo.citizensnpcs.co 找到


To register a trait, we use the '''TraitFactory''' class. This controls registration for your custom traits.
想要注册一个特性,你可以使用 '''TraitFactory''' class. 这个东西可以控制特性的注册.
{{codebox|height=300px|width=100%|Example registration and simple trait|<pre>
{{codebox|height=300px|width=100%|注册示例和简易特性|<pre>
//This is your trait that will be applied to a npc using the /trait mytraitname command. Each NPC gets its own instance of this class.
//这个特性可以应用于NPC,输入 /trait [我的特性名] 即可应用. 每个NPC gets its own instance of this class.
//the Trait class has a reference to the attached NPC class through the protected field 'npc' or getNPC().
//这个特性class has a reference to the attached NPC class through the protected field 'npc' or getNPC().
//The Trait class also implements Listener so you can add EventHandlers directly to your trait.
//这个特性class也实现了监听器的功能所以你可以直接把EventHandlers添加到你的特性插件里 .
@TraitName("mytraitname") // convenience annotation in recent CitizensAPI versions for specifying trait name
@TraitName("mytraitname") // 最好取简单点的名字来方便注释
public class MyTrait extends Trait {
public class MyTrait extends Trait {
public MyTrait() {
public MyTrait() {
super("mytraitname");
super("我的特性名");
plugin = JavaPlugin.getPlugin(MyPlugin.class);
plugin = JavaPlugin.getPlugin(MyPlugin.class);
}
}
第90行: 第90行:
boolean SomeSetting = false;
boolean SomeSetting = false;
          
          
         // see the 'Persistence API' section
         // 查看'Persistence API' 部分
         @Persist("mysettingname") boolean automaticallyPersistedSetting = false;
         @Persist("mysettingname") boolean automaticallyPersistedSetting = false;


// Here you should load up any values you have previously saved (optional).  
// 你可以在这里加载你之前保存的数值 (可选).  
         // This does NOT get called when applying the trait for the first time, only loading onto an existing npc at server start.
         // 在第一次应用特性时不会使用这个, 只会在已服务器存在的NPC上加载.
         // This is called AFTER onAttach so you can load defaults in onAttach and they will be overridden here.
         // 这叫做 AFTER onAttach so you can load defaults in onAttach and they will be overridden here.
         // This is called BEFORE onSpawn, npc.getBukkitEntity() will return null.
         // This is called BEFORE onSpawn, npc.getBukkitEntity() will return null.
public void load(DataKey key) {
public void load(DataKey key) {
第171行: 第171行:
</pre>
</pre>
}}
}}
===Dos and Don'ts===
===使用须知===
'''{{color|green|white|DO}}'''
'''{{color1|green|white|DO}}'''
* Check npc.isSpawned() before using npc.getBukkitEntity()
* 在使用 npc.getBukkitEntity() 之前检查 npc.isSpawned()  
* Check npc.isSpawned() before using npc.getNavigator()
* 在使用 npc.getNavigator() 之前检查 npc.isSpawned()
* Create a separate singleton Listener class if you expect there to be many instances of this trait running. This may help performance with frequently called events.
*如果希望这个特性运行多个实例,请创建单独的单例监听器class.这可以让 called 事件更高效.
* Honor npc.data().get(NPC.DEFAULT_PROTECTED_METADATA) If this is true the NPC should be 'invulnerable' to normal damaging effects.
* Honor npc.data().get(NPC.DEFAULT_PROTECTED_METADATA) 如果这个为true,NPC 会变得'无敌',无法受到普通攻击的伤害 .
* use CitizensAPI.getNPCRegistry().isNPC() to check if an entity is a NPC. Real players and player-type NPCs will both return true for instanceof Player.
* CitizensAPI.getNPCRegistry().isNPC() 来检查实体是否为NPC. 真正的玩家和玩家类型的NPC都会return true for instanceof Player.
'''{{color|red|white|DON'T}}'''
'''{{color1|red|whi1e|DON'T}}'''
* Attempt to access npc.getBukkitEntity() from within traits until onSpawn() has been called or npc.isSpawned() returns true.
* 不要尝试从特性内获取 npc.getBukkitEntity() ,直到onSpawn() called npc.isSpawned() returns true.
* Change anything in npc.getNavigator.getDefaultParams() unless you're sure you want a global change. Use the localParams() instead ''after'' setting a navigation target.
* 不要改变npc.getNavigator.getDefaultParams() 里的任何东西,除非你想要彻底改变插件.使用 localParams() 而不是 ''after'' 来设置导航目标.
* Assume a NPC is a player-type. Mob types have some important differences.
* 不要假设NPC的类型为玩家.怪物类型有很大的区别.


===Download an example===
===下载一个示例===
This is a link to a an example trait. It is similar to the code above, with some additional code for better handling commands, default configuration, and a plugin.yml
通过这个链接你可以下载到一个插件示例. 和上面的代码一样, 但这会有一些更好的代码来处理指令、默认配置和plugin.yml.
*[https://github.com/jrbudda/Citizens2/downloads Download it here]
*[https://github.com/jrbudda/Citizens2/downloads 点击下载]
You will need to build against [http://ci.citizensnpcs.co/job/CitizensAPI/ CitizensAPI.jar],[http://ci.citizensnpcs.co/job/Citizens2/ Citizens.jar] (although this is not always required),  and [http://dl.bukkit.org/downloads/bukkit/ Bukkit.jar].
你需要基于 [http://ci.citizensnpcs.co/job/CitizensAPI/ CitizensAPI.jar][http://ci.citizensnpcs.co/job/Citizens2/ Citizens.jar][http://dl.bukkit.org/downloads/bukkit/ Bukkit.jar].来构造插件


==NPC Events==
==NPC事件==
Citizens implements its own Listeners and will call new NPC-specific versions of many common events. This saves Trait developers the trouble of finding their npcs from the normal event entities. The event object these events provide are just like their Bukkit counterparts with the addition of the getNPC() method.
Citizens 执行自己的监听器并call new NPC-specific versions of many common events. 这避免了特性开发者从正常事件实体中查找npc的麻烦. The event object these events provide are just like their Bukkit counterparts with the addition of the getNPC() method.
Citizens currently provides the following:
Citizens提供以下事件:
*EntityTargetNPCEvent
*EntityTargetNPCEvent
*NPCChatEvent
*NPCChatEvent
第212行: 第212行:
*PlayerCreateNPCEvent
*PlayerCreateNPCEvent


See the [[http://jd.citizensnpcs.co/ Javadocs]] for details.
详情查看 [[http://jd.citizensnpcs.co/ Javadocs]]


==Using the AI API==
==使用 AI API==
The AI API of Citizens can be broken down into two parts - ''GoalController'' and ''Navigator''.
AI API 可分为两部分: - ''目标控制器''''导航器''.


A ''Goal'' is a repeatable, abstract unit of work that can be performed by an NPC. It can be registered with a GoalController with a priority (higher is more important). The highest priority goal which can be executed will be prioritised. NPC contains getDefaultGoalController() for this purpose.
一个''目标'' 可以重复, abstract unit of work that can be performed by an NPC. It can be registered with a GoalController with a priority (higher is more important). The highest priority goal which can be executed will be prioritised. NPC contains getDefaultGoalController() for this purpose.


The GoalSelector allows a great deal of flexibility within goal implementations. It allows firstly the dynamic selection of sub-goals and the concurrent execution of many sub-goals, and can stop execution at any time.
目标选择器可以使目标更加灵活.首先它可以动态选择子目标并同时执行多个目标,并且可以随时停止.


In recent versions of CitizensAPI the "Behavior" class is introduced which allows a behavior tree-based AI approach that is backwards compatible with Goals and GoalControllers.
最近的CitizensAPI版本里,  "Behavior" class is introduced which allows a behavior tree-based AI approach that is backwards compatible with Goals and GoalControllers.


{{codebox|height=300px|width=100%|Example|<pre lang="java5">
{{codebox|height=300px|width=100%|Example|<pre lang="java5">
  public class MyGoal implements Goal {
  public class MyGoal implements Goal {
     private Object state;
     private Object state;
     private GoalSelector selector; // the current selector
     private GoalSelector selector; // 当前选择器
     public void reset() {
     public void reset() {
         state = null;
         state = null;
         // this method can be called at any time - tear down any state
         // 这种方式可以被多次called - tear down any state
     }
     }
     public void run() {
     public void run() {
第261行: 第261行:
The pathfinding range of the Navigator is the maximum range it will search when attempting to find a path to the target. This is usually set by the server admin. The speed modifier of the Navigator is the % modified movement speed of the NPC while moving to the target.
The pathfinding range of the Navigator is the maximum range it will search when attempting to find a path to the target. This is usually set by the server admin. The speed modifier of the Navigator is the % modified movement speed of the NPC while moving to the target.


==Using the Persistence API==
==使用永久API==
Sometimes, traits can store a lot of simple variables such as primitives, Strings, Locations, and others. Saving/loading them via the trait API can be a little bit of overkill.
有时候, 特性可以存储大量的变量,比如primitives, Strings, 地点和其他.通过特性的API保存/加载这些东西可能有点困难.


Citizens 2.0.4+ provides a simple Persistence API to automatically save and load these variables using DataKeys. The key to this API is the @Persist annotation. Sample code is provided below.
Citizens 2.0.4+提供了简易的永久API使用DataKeys来自动保存和加载这些变量.这个API的key是 @Persist annotation. 示例代码如下.
{{codebox|height=300px|width=100%|Example|<pre lang="java5">
{{codebox|height=300px|width=100%|Example|<pre lang="java5">
  public class MyTrait extends Trait {
  public class MyTrait extends Trait {
第304行: 第304行:
</pre>}}
</pre>}}


==See Also==
==查看==
[[Characters]]
[[Characters]]


{{NavBox}}
{{NavBox}}
[[Category:Usage]]
[[Category:Usage]]

2018年11月25日 (日) 07:42的最新版本

最新正式版下载地址: Jenkins

开发版下载地址: Jenkins

文档: JavaDocs

源码: Github

快捷导航
用法 安装  · 常见疑问  · 指令  · 编辑器  · 兼容性  · API
配置 数据存储  · 权限  · 限制  · 经济  · 翻译
角色 Denizen  · 哨兵  · 冒险家  · 炼金术士  · 铁匠  · DtlTraders  · 任务  · 建筑者  · 快递员  · HyperMerchant
工具 / 信息 下载  · 1.2 版本文件转换器  · IRC聊天室

Citizens拥有广泛的API来让你制作与npc相关的插件或给npc添加新的角色特性。 确认你使用的是最新版的CitizensAPI来兼容最新版的Citizens.

你可以在这里找到Javadocs:http://jd.citizensnpcs.co

如果你在使用 API的过程中遇到了问题 请在github 进行反馈 https://github.com/CitizensDev/Citizens2/issues 或者在Discord反馈:https://discord.gg/Q6pZGSR


正确链接Java

Citizens和大多数的Java项目一样是用的Maven构造而成的。你构造关联citizens的插件也应该用Maven。

在你的 pom.xml (Maven 项目)文件内, 你可以使用这个 repository:

    <repository>
        <id>everything</id>
        <url>http://repo.citizensnpcs.co/</url>
    </repository>

和这个:

    <dependency>
        <groupId>net.citizensnpcs</groupId>
        <artifactId>citizens</artifactId>
        <version>VERSION</version>
        <type>jar</type>
        <scope>provided</scope>
    </dependency>

并把 VERSION改为当前版本的Citizens (可以在 http://ci.citizensnpcs.co/job/Citizens2/ 看到Citizens版本号 ID), 比如 2.0.23-SNAPSHOT (but with the version numbers changed to the relevant version).

在大多数情况下,最好链接 citizens 而不是 API 项目, 因为很多有用的 classes 和 utilities不在API内. Citizens的项目 包括 API和添加的更多选项.

关联Citizens

关联Citizens和创建一个普通的插件一样简单,只需添加 depend: [Citizens] 到你的 plugin.yml 内即可. From here, a common basic entry point is the CitizensAPI class. 这给予你 NPCRegistry for NPC lookup, as well as the TraitFactory which allows trait registration. If Citizens is not loaded, all CitizensAPI.* methods will return null.

创建一个 NPC

创建npc最简单的方法就是使用 NPCRegistry 这个东西来管理npc的存储和创建 . 默认的registry由CitizensAPI.getNPCRegistry() 给予, 并且你可以用不同的存储方式来创建一个新的NPC. 一个玩家类型的名为"fullwall"的NPC可以这一创建:

NPC npc = CitizensAPI.getNPCRegistry().createNPC(EntityType.PLAYER, "fullwall");

检测实体是否是NPC

Citizens的 NPC拥有设置为true的 "NPC"元数据. 示例:

boolean isCitizensNPC = entity.hasMetadata("NPC");

创建特性

特征是链接到NPC并提供特定功能的持久、可附加的板块。 这可以是任何东西,可以是带有动态AI会进行简单谈话的村民特性.

如果使用Maven, Citizens的Maven repo 可以在 http://repo.citizensnpcs.co 找到

想要注册一个特性,你可以使用 TraitFactory class. 这个东西可以控制特性的注册.

Code: 注册示例和简易特性
//这个特性可以应用于NPC,输入 /trait [我的特性名] 即可应用. 每个NPC gets its own instance of this class.
//这个特性class has a reference to the attached NPC class through the protected field 'npc' or getNPC().
//这个特性class也实现了监听器的功能所以你可以直接把EventHandlers添加到你的特性插件里 .
@TraitName("mytraitname") // 最好取简单点的名字来方便注释
public class MyTrait extends Trait {
	public MyTrait() {
		super("我的特性名");
		plugin = JavaPlugin.getPlugin(MyPlugin.class);
	}

	MyPlugin plugin = null;

	boolean SomeSetting = false;
        
        // 查看'Persistence API' 部分
        @Persist("mysettingname") boolean automaticallyPersistedSetting = false;

	// 你可以在这里加载你之前保存的数值 (可选). 
        // 在第一次应用特性时不会使用这个, 只会在已服务器存在的NPC上加载.
        // 这叫做 AFTER onAttach so you can load defaults in onAttach and they will be overridden here.
        // This is called BEFORE onSpawn, npc.getBukkitEntity() will return null.
	public void load(DataKey key) {
		SomeSetting = key.getBoolean("SomeSetting", false);
	}

	// Save settings for this NPC (optional). These values will be persisted to the Citizens saves file
	public void save(DataKey key) {
		key.setBoolean("SomeSetting",SomeSetting);
	}

        // An example event handler. All traits will be registered automatically as Bukkit Listeners.
	@EventHandler
	public void click(net.citizensnpcs.api.event.NPCClickEvent event){
		//Handle a click on a NPC. The event has a getNPC() method. 
		//Be sure to check event.getNPC() == this.getNPC() so you only handle clicks on this NPC!
		
	}
      
        // Called every tick
        @Override
        public void run() {
        }

	//Run code when your trait is attached to a NPC. 
        //This is called BEFORE onSpawn, so npc.getBukkitEntity() will return null
        //This would be a good place to load configurable defaults for new NPCs.
	@Override
	public void onAttach() {
		plugin.getServer().getLogger().info(npc.getName() + "has been assigned MyTrait!");
	}

        // Run code when the NPC is despawned. This is called before the entity actually despawns so npc.getBukkitEntity() is still valid.
	@Override
	public void onDespawn() {
        }

	//Run code when the NPC is spawned. Note that npc.getBukkitEntity() will be null until this method is called.
        //This is called AFTER onAttach and AFTER Load when the server is started.
	@Override
	public void onSpawn() {

	}

        //run code when the NPC is removed. Use this to tear down any repeating tasks.
	@Override
	public void onRemove() {
        }

}

//This is your bukkit plugin class. Use it to hook your trait into Citizens and handle any commands.
public class MyPlugin extends org.bukkit.plugin.java.JavaPlugin {

	public void onEnable() {
	
	//check if Citizens is present and enabled.

		if(getServer().getPluginManager().getPlugin("Citizens") == null || getServer().getPluginManager().getPlugin("Citizens").isEnabled() == false) {
			getLogger().log(Level.SEVERE, "Citizens 2.0 not found or not enabled");
			getServer().getPluginManager().disablePlugin(this);	
			return;
		}	

		//Register your trait with Citizens.        
		net.citizensnpcs.api.CitizensAPI.getTraitFactory().registerTrait(net.citizensnpcs.api.trait.TraitInfo.create(MyTrait.class));	
	}

	@Override
	public boolean onCommand(CommandSender sender, Command cmd, String cmdLabel, String[] inargs) {
		//handle commands for /myplugin 
	}
}

使用须知

DO

  • 在使用 npc.getBukkitEntity() 之前检查 npc.isSpawned()
  • 在使用 npc.getNavigator() 之前检查 npc.isSpawned()
  • 如果希望这个特性运行多个实例,请创建单独的单例监听器class.这可以让 called 事件更高效.
  • Honor npc.data().get(NPC.DEFAULT_PROTECTED_METADATA) 如果这个为true,NPC 会变得'无敌',无法受到普通攻击的伤害 .
  • 用 CitizensAPI.getNPCRegistry().isNPC() 来检查实体是否为NPC. 真正的玩家和玩家类型的NPC都会return true for instanceof Player.

DON'T

  • 不要尝试从特性内获取 npc.getBukkitEntity() ,直到onSpawn() 被 called 或 npc.isSpawned() returns true.
  • 不要改变npc.getNavigator.getDefaultParams() 里的任何东西,除非你想要彻底改变插件.使用 localParams() 而不是 after 来设置导航目标.
  • 不要假设NPC的类型为玩家.怪物类型有很大的区别.

下载一个示例

通过这个链接你可以下载到一个插件示例. 和上面的代码一样, 但这会有一些更好的代码来处理指令、默认配置和plugin.yml.

你需要基于 CitizensAPI.jarCitizens.jarBukkit.jar.来构造插件

NPC事件

Citizens 执行自己的监听器并call new NPC-specific versions of many common events. 这避免了特性开发者从正常事件实体中查找npc的麻烦. The event object these events provide are just like their Bukkit counterparts with the addition of the getNPC() method. Citizens提供以下事件:

  • EntityTargetNPCEvent
  • NPCChatEvent
  • NPCClickEvent
  • NPCCollisionEvent
  • NPCCombustByBlockEvent
  • NPCCombustByEntityEvent
  • NPCCombustEvent
  • NPCDamageByBlockEvent
  • NPCDamageByEntityEvent
  • NPCDamageEvent
  • NPCDeathEvent
  • NPCDespawnEvent
  • NPCEvent
  • NPCLeftClickEvent
  • NPCPushEvent
  • NPCRemoveEvent
  • NPCRightClickEvent
  • NPCSelectEvent
  • NPCSpawnEvent
  • PlayerCreateNPCEvent

详情查看 [Javadocs]

使用 AI API

AI API 可分为两部分: - 目标控制器导航器.

一个目标 可以重复, abstract unit of work that can be performed by an NPC. It can be registered with a GoalController with a priority (higher is more important). The highest priority goal which can be executed will be prioritised. NPC contains getDefaultGoalController() for this purpose.

目标选择器可以使目标更加灵活.首先它可以动态选择子目标并同时执行多个目标,并且可以随时停止.

最近的CitizensAPI版本里, "Behavior" class is introduced which allows a behavior tree-based AI approach that is backwards compatible with Goals and GoalControllers.


Code: Example
 public class MyGoal implements Goal {
     private Object state;
     private GoalSelector selector; // 当前选择器
     public void reset() {
         state = null;
         // 这种方式可以被多次called - tear down any state
     }
     public void run() {
         if(!npcIsCool()) {
             selector.finish(); // stops execution
         } else if (npcIsAwesome()){
             selector.select(new AwesomeGoal()); // this switches execution to AwesomeGoal and stops execution of this goal.
         } else if (npcNeedsCool()) {
             selector.selectAdditional(new AccumulateCoolGoal()); // AccumulateCoolGoal executes concurrently to this goal.
         }
     }
     public boolean shouldExecute(GoalSelector selector) {
         if (npcIsCool()) {
             this.selector = selector;
             return true;
         }
         return false;
     }
 }

The second concept is the Navigator. This controls the pathfinding aspects of the NPC. The Navigator can have one target at a time, and will call events to notify of completion/cancellation:

  • NavigationBeginEvent
  • NavigationCancelEvent
  • NavigationCompleteEvent
  • NavigationEvent
  • NavigationReplaceEvent

The pathfinding range of the Navigator is the maximum range it will search when attempting to find a path to the target. This is usually set by the server admin. The speed modifier of the Navigator is the % modified movement speed of the NPC while moving to the target.

使用永久API

有时候, 特性可以存储大量的变量,比如primitives, Strings, 地点和其他.通过特性的API保存/加载这些东西可能有点困难.

Citizens 2.0.4+提供了简易的永久API使用DataKeys来自动保存和加载这些变量.这个API的key是 @Persist annotation. 示例代码如下.

Code: Example
 public class MyTrait extends Trait {
     // logic omitted.

    @Persist boolean myVariable = false; // the default value of @Persist saves the value under the field name (in this case, 'myVariable').
    
    @Persist("newkey") int intVariable = 11; // this saves the value under 'newkey'. The default value of the variable has been set to 11 - this will be used when loading if the key doesn't exist.

    @Persist(value="newkey", required=true) String required; // if the value under 'newkey' doesn't exist, then the trait will fail to load.
 }

More advanced use of the API can be found in the @DelegatePersistence annotation. This allows complex types such as Locations to be saved and loaded with finer grained control. These types can be given default delegates by calling PersistenceLoader#registerPersistDelegate(Persister) - Location has a built in Persister for convenience.


Code: Example
 public class MyTrait extends Trait {
     // logic omitted.

    @Persist 
    @DelegatePersistence(ExplicitComplexTypePersister.class) // explicit delegation
    ComplexType myComplexType;

    @Persist ComplexType implicitComplexType; // implicit delegation
    static {
        PersistenceLoader.registerPersistDelegate(ImplicitComplexTypePersister.class);
    }
 }
 
 public class ExplicitComplexTypePersister implements Persister {
     public Object create(DataKey root) {
         return new ComplexType(root.getInteger("complexstructures"));
     }
     public void save(Object instance, DataKey root) {
         ComplexType real = (ComplexType) instance; // guaranteed cast - will always succeed.
         root.setInteger("complexstructures", real.getComplexStructure());
     }
 }

查看

Characters