[LIB] [1.7] Remote entities - Next generation NPC library [No support]

Discussion in 'Resources' started by kumpelblase2, Nov 10, 2012.

Thread Status:
Not open for further replies.
  1. Remote Entities

    Hey everyone!

    After about two weeks of work, I managed to finish my NPC library. It was made with the idea of being able to modify the entities in any possible way. So I started from scratch, made my plans and now I'm here with the first version. It's only compatible with 1.6.2, not with any other version (see earlier releases for other version compatibility).

    So what is it capable of?
    - Use any entity as a npc
    - Customize speed
    - Change and create own goals/desires
    - Cross-plugin interactivity
    - Make your own behaviors

    What do I need as a developer?
    Either: download it (see link at the end) and add it just like you'd do with craftbukkit/bukkit.
    Or (using maven):
    Show Spoiler

    and maven will do the rest (don't forget to update the version!).
    You can also use this url when you also want to get the snapshots:

    What do users of my plugin need?
    They also need the plugin, just like Vault. See 'download' below.

    Alright, so how do I get started?
    First, add the plugin to your (soft)dependencies in your plugin.yml:
    depend: [RemoteEntities]
    Now lets get into the code:
    1. public void onEnable()
    2. {
    3. //First we need an instance of the manager, which keeps track of your entities
    4. EntityManager manager = RemoteEntities.createManager(this);
    5. //Using the manager we create a new Zombie npc at the spawn location, but we won't setup the standard desires/goals
    6. RemoteEntity entity = manager.createEntity(RemoteEntity.Zombie, Bukkit.getWorld("world").getSpawnLocation(), false);
    7. //We don't want him to move so we make him stationary
    8. entity.setStationary(true);
    9. //Now we want him to look at the nearest player. This desire has a priority of 1 (the higher the better).
    10. //Since we don't have any other desires 1 is totally fine.
    11. //Note that when you have more than one desire with the same priority, both could get executed, but they'd need a different type (e.g. looking and moving)
    12. //This does not get executed all the time. It might just get executed but he might take a break for 2 seconds after that. It's random.
    13. entity.getMind().addMovementDesire(new DesireLookAtNearest(entity, Player.class, 8F), 1);
    14. //When a player interacts with him, we want him to tell something to the player.
    15. //I make an anonymous class here, but you can create a whole new class if you want to
    16. //but it needs to extend InteractBehaviour
    17. entity.getMind().addBehaviour(new InteractBehaviour(entity)
    18. {
    19. @Override
    20. public void onInteract(Player inPlayer)
    21. {
    22. inPlayer.sendMessage("Hello " + inPlayer.getName() + "!");
    23. }
    24. });
    25. }

    So let me explain things further:
    - EntityManager: The entity manager creates, removes and generally keeps track of all your entities.

    - RemoteEntity: This is the base instance of the entity. Each entity has a specific subclass (e.g. RemoteZombie) which might enables more functionality for the entity (e.g. let a creeper explode).

    - Mind: Yes, entities do have a mind in my library. The mind essentially controls or executes every action of the entity. Like which desire gets executed, should a behavior get fired. Moreover, it contains all the features of the entity.

    - Desire: A desire is something that the entity wants to do. For example, a zombie wants to attack the nearest player (DesireAttackNearest). You can create your own ones or just build on top of the existing ones. (Preset desires see this)

    - Behavior: Behaviors control what an entity should do on a specific event, when a player touches them for instance. Again, you can create your own ones here.

    - Features: Giving a zombie a taming feature would allow you to use the zombie as a pet. So features give you functionality that's normally not available for the entity. (Preset features see this)

    That seems interesting. Where can I find javadocs or something like that?
    JavaDocs can be found: HERE
    Source is available: HERE
    Jenkins: HERE

    Still having questions?
    Then go ahead and ask! I haven't covered everything here, so it's totally ok to ask.

    Last words
    Alright, I'm not the best writer so I hope I wrote everything as clear as possible. Like I said, feel free to ask if something isn't clear enough.
    When you have a suggestion, you shouldn't wait and just tell me, it won't hurt you.

    Version 1.7

    Version 1.7:
    - Updated to minecraft 1.6.2
        - Updated desire logic
        - Added horse
        - Use attributes for speed
    - Added event for touching and pushing an entity
    - Added event for creating (not spawning) and entity
    - Added ability to change pathfinding range
    - Added serialization for features and behaviors
    - Added trading feature (see examples)
    - Added ability to add a speed modifier to an entity
    - Added error prevention with incompatible minecraft versions by disabling
    - Javadoc updates
    - Fix DesireMoveToLocation not finishing sometimes
    - Changed desires so they can be created without an entity and could be reapplied to a different entity
    - Vectors will now get released when they aren't used anymore.
    - createNamedEntity will now create an entity with a custom name when it's not a human entity
    - Fixed some spawning issues, including players
    - When using DesireWanderAroundArea, the entity will now also try to move back into the area when it went outside
    - Pigmen will now use the default desires of zombies
    - Internal changes and updates
    Version 1.6:
    - Updated to minecraft 1.5.2 .
    - Added ability to fix head yaw.
    - Added ability to get default desires for entities.
    - Added ability to save entities automatically when all get despawned.
    - Added custom pathfinding, but it is not in use yet and thus not even documented
    - Changed how types of desires work. They are now represented by an enum which makes it easier to understand.
    - Some internal cleanup and changes.
    - Fixed DesireKillTarget and DesireAttackOnCollide not working properly.
    - Fixed not calling onAdd and onRemove for behaviors.
    - Fixed DamageBehavior.
    - Fixed default size of RemoteInventoryFeature.
    - Fixed issue in DesireFollowTamer.
    - Fixed not applying default desires sometimes.
    - Fixed not despawning entities when RemoteEntities gets disabled.
    - Fixed a concurrent exception when working with OneTimeDesires.
    - Fixed IgnoreSerialization annotation.
    - Fixed some serialization issues.
    Version 1.5.1:
    - Fixed some desire types
    - Fixed default desires for cave spider
    - Updated wrong desire logics (These were a lot)
    Version 1.5:
    - Entity will now have a metadatavalue representing the remote entity
    - Renamed and moved some internal classes such as DesireSelector and PathfinderGoalSelectorHelper
    - Changed action desires to target desires
    - Fixed serialization in some classes
    - Added  ability to override attacking mechanics in some desires
    - Added base for OneTimeDesires
    - Updated to 1.5.1
    - Added events for starting and stopping desires
    - Small other additions
    Version 1.4:
    - Added an api for implementing persistence
    - getActionDesires() and getMovementDesires() now returns a list of desire items so you can also get the priority
    - Fixed npe when settings using custom max health in createentitycontext
    - Fixed issues with copyInventory
    - Changed desire constructors to also accept bukkit classes. You won't notice this right away because it will still work like the way it used to but with the addition that you can also pass in common bukkit classes.
    - Enhanced entity spawning and respawning while loading/unloading chunks.
    - Fixed createEntityFromExisting not setting up default desires
    - Updated with (craft)bukkit -> 1.4.7
    Version 1.3:
    - Updated for Craftbukkit 1.4.5-R1.0.
    - Removed EntityEquipment feature.
    - Hopefully fixed concurrent exception.
    - Throwing some exceptions when using Remoteentities when it's not enabled.
    Version 1.2:
    - Updated with 1.4.5
    - Fixed melee
    - Fixed many NPEs
    - No longer interferes with other plugins using the entity type enum
    - Fixed standard goals for mushroom entity
    - Fixed entities not getting respawned on chunck reload
    - Fixed RemoteEntityInteractEvent not getting fired
    - Added new way for creating entities
    Version 1.1.1:
    - Fixed some entities not updating their mind
    Version 1.1:
    - Fixed NPEs crashing the server
    - Fixed some issues with custom entity types
    - Fixed many entities ignoring stationary and push status
    Version 1.0:
    - First release
    Plugins/Servers using it
    Mineblown.com (the main reason why I created it.)

    That's it,
    have fun!
  2. Offline


    Very cool! Great job, as far as I can see. ;)
    I'll try this some time.
    I love the customization you can add using the behaviors and desires!
  3. Offline


    Does this not work with Java JRE7 and higher? I get an error in the EnumChange class: Access restriction: The type ReflectionFactory is not accessible due to restriction on required library C:\Program Files\Java\jre7\lib\rt.jar
  4. are you using the compiled jar or do you include the whole library in your project?
  5. Offline


    I'm pretty new to the whole plugin thing so I'll tell you exactly what I did:
    Downloaded the source from Github, added the 'de' folder as a library for my project package and refactored so all the package names were correct (it autonamed them to com.jordair.xxx)
    The onEnable method wasn't running because I had a different main class so I changed some things.
    Set eclipse to use Java JRE6 instead of 7 and the error I posted above disappeared.

    Obviously, I don't really know what I'm doing. Could you explain how to import this as a library?
  6. Offline


    Finally finished, awesome! *Instantly downloads*

    Oh, I couldn't download it with Maven because I copy-pasted it, and apparently the link is https://https:// (that's what you provided).

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
    Last edited by a moderator: May 29, 2016
  7. That's what I assumed.
    Alright, so here's what you should've done:
    1. download the jar (pretty much at the end of my post. or use this link)
    2. in eclipse go to the java build path and add the jar as an external jar, just like you did with the bukkit jar.
    3. when using your plugin on the server you need to put the remote entities jar in the same folder (i.e. plugin folder)

    I'll alway provide a jar, so you don't need to build it yourself. It also prevents errors from appearing.

    P.S.: You said, that you're new to plugins so I assumed you might be new to programing and hence not familiar with maven. If that's wrong, I'm sorry and please tell me as it's a lot easier with maven.

    haha, nice :p

    I'll fix it. Thanks.
  8. Offline


    Up and running now!

    Thanks a lot, this is great :) One small issue though...
    InventoryFeature inv = new RemoteInventoryFeature(e);
    throws an IllegalArgumentException.

    I'm assuming this is because you initialize the InventoryFeature inventory as a CHEST type (length 27) while PLAYER inventories are 36 slots, thus resulting in an error.

    New to programming I am not, never have I heard of Maven though but I might give it a try :)

    I went into your RemoteInventoryFeature class and changed your inventory initializer to this:
    this.m_inventory = Bukkit.getServer().createInventory((InventoryHolder)inEntity.getHandle(), InventoryType.PLAYER);
    and all problems were solved:)

    Another question for you:

    How do I implement the event handling? It doesn't seem to work like standard bukkit events (using the EventHandler annotation) and I can't quite figure out how to get a RemoteEntity DeathEvent.

    Sorry about asking so many questions but how can I also add the knockback effect upon damage to the RemotePlayer?

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
    Last edited by a moderator: May 29, 2016
  9. Thanks for bringing this issue up! I won't change only that line, but I'll make it so that you can change it to your liking even more.

    There's no separate event for that. Just use the bukkit entity death event and check if the entity is a remote entity with the manager.

    For me it already gets knocked back :confused:
  10. Offline


    It's possible I have a conflict with my plugin :S.

    Just so I'm sure, when the RemoteEntity dies, it gets despawned, correct? Is there a way to catch the despawn event?
  11. Yep, there's a custom event: http://docs.infinityblade.de/remote...ties/api/events/RemoteEntityDespawnEvent.html

    By the way: Please don't tell me that ender dragons don't work as expected. They might work fine or might not. They drove me crazy already in the past and I tried fixing the issues, but some might still be there.

    Also, when you think that something needs to be added or should be changed in some way, feel free to make a ticked/pr on github, it would help making this library even better.

    First snapshot is already up (1.1-SNAPSHOT as maven version). You can get it here. Note: Snapshots will be updated very often. I won't post them here, otherwise I would spam this too much, but final version will still get posted.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
    Last edited by a moderator: May 29, 2016
  12. Offline


    Unsure of the exact cause but it seems that something is now making my screen flash as if I'm teleporting randomly around the map... I'll look into it
  13. Tutorial:
    Registering your own entity:
    Let's assume you want to have your own zombie entity for whatever reason. What you'd do is first create a subclass of RemoteZombie and/or RemoteZombieEntity, lets call them NewRemoteZombie and NewRemoteZombieEntity. You won't need both in most cases, though.
    Now we have two options: Replace or add them.
    What's the difference? When you replace 'Zombie' then your classes get used, even when other plugins spawn them. When you add them, you can spawn them separate from the original zombies.
    There are two methods in the RemoteEntityType that lets you achieve this:
    addType(String inName, Class<? extends EntityLiving> inEntityClass, Class<? extends RemoteEntity> inRemoteClass, boolean isNamed)
    replaceType(String inName, Class<? extends EntityLiving> inEntityClass, Class<? extends RemoteEntity> inRemoteClass, boolean isNamed)
    so in our case:
    RemoteEntityType.addType("NewZombie", NewRemoteZombieEntity.class, NewRemoteZombie.class, false);
    RemoteEntityType.replaceType("Zombie", NewRemoteZombieEntity.class, NewRemoteZombie.class, false);
    Note: when you add them, you can't use them statically like you do normally with enums, you need to use valueOf(<name>); as I reflect them into the enum.
  14. Offline


    Wow this looks great! Amazing work!
  15. Offline


  16. it should, yeah
  17. Offline


    This looks like a great library. Does the createEntity method invoke the CreatureSpawnEvent? I'm trying to add Zombies to the EntityManager as they spawn, but I'm getting errors and it crashes the server. I may have misunderstood how to use the library though.

    public void onEntitySpawn(CreatureSpawnEvent event) {
                    RemoteEntity zomb = craft.EntityManager.createRemoteEntityFromExisting(event.getEntity());
  18. It should throw an event yeah. Try to check if the spawned entity is not an instance of RemoteEntityHandle. If that's the case, you can continue your code.
  19. Offline


    A dumb question; If I create a new Skeleton it basically inherits all of the skeletons standard behavior, correct? So if I wanted it to wear a chain helmet and hold a fire charge in its hand I could just spawn my new RemoteEntity and apply equipment, correct?
  20. Depends on how you create it. There are two methods for creating an entity.
    createEntity(RemoteEntityType type, Location location);
    createEntity(RemoteEntityType type, Location location, boolean goals);
    when you use the first one, it will just create the entity and won't add the behavior. Using the second one with 'true' at the end would setup those behaviors.
  21. Offline


    That is beyond sexy; you've just saved me hours of programming!

    How would one iterate just through the new skeletons? Nevermind ... getAllEntites returns a list and I can iter through that.
  22. Good to hear that :)

    I have said "Cross-plugin interactivity" in my first post but didn't really explain it. So I'm gonna do that now.
    (Assuming that all plugins create their manager normally) You can access other plugin's entity manager, hence also all their entities and so on. How you can do that? It's pretty easy:
    EntityManager manager = RemoteEntities.getManagerOfPlugin("PluginName");
    You might want to check if the plugin actually has a manager (hasManagerOfPlugin(<name>)).
    Since you now have the manager you can get all it's entities and such.
    Have fun!
  23. Offline


    Gah, I can't get this to work. :(

    You wouldn't have a simple dummy plugin that uses this and works, would you? :)
  24. I'll probably put up some examples every once in awhile here: https://github.com/kumpelblase2/Remote-Entities/tree/master/examples
    There's one already which I just uploaded. When you still have problems feel free to ask.
    phondeux likes this.
  25. Offline


    Still getting the nullpointer exception causing the server to crash.

        public void onEntitySpawn(CreatureSpawnEvent event) {
            if (event.getEntityType().equals(EntityType.PLAYER))
            if (event.getEntityType().equals(EntityType.ZOMBIE)) {
                    if(!craft.EntityManager.isRemoteEntity(event.getEntity())) {
    Using above, the nullpointer seems to be "this.getRemoteEntity().getMind().tick();" (RemoteZombieEntity line 114), am I meant to set a mind somehow?


    Edit: Still getting the same error even after setting a mind, following your example
        public void onEntitySpawn(CreatureSpawnEvent event) {
            if (event.getEntityType().equals(EntityType.PLAYER))
            if (event.getEntityType().equals(EntityType.ZOMBIE)) {
                    if(!craft.EntityManager.isRemoteEntity(event.getEntity())) {
                        RemoteEntity zomb = craft.EntityManager.createRemoteEntityFromExisting(event.getEntity());
                        zomb.getMind().addMovementDesire(new DesireWanderAround(zomb),                       zomb.getMind().getHighestMovementPriority() + 1);
  26. Alright, I'll look into that and check if I can reproduce it.
  27. Offline


    That was perfect, thank you!

    So I am creating a skeleton and I want it equipped with a fire charge in hand or just fire. I did the following;
    public void onEntitySpawn(CreatureSpawnEvent event) {
        if (event.getEntity() instanceof Skeleton) {
            RemoteEntity entity = parent.skManager.createNamedEntity(RemoteEntityType.Skeleton, event.getLocation(), "SkelWizard");
            EquipmentFeature feature = new RemoteEquipmentFeature(entity);
            feature.getEquipment().setItemInHand(new ItemStack(385,1));
    However I get the following exception in my console on spawn events;
    09:21:06 [SEVERE] Could not pass event CreatureSpawnEvent to SkeletonKing v1.0
            at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:341)
            at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:62)
            at org.bukkit.plugin.SimplePluginManager.fireEvent(SimplePluginManager.java:477)
            at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:462)
            at org.bukkit.craftbukkit.event.CraftEventFactory.callCreatureSpawnEvent(CraftEven
            at net.minecraft.server.World.addEntity(World.java:872)
            at net.minecraft.server.SpawnerCreature.spawnEntities(SpawnerCreature.java:158)
            at net.minecraft.server.WorldServer.doTick(WorldServer.java:154)
            at net.minecraft.server.MinecraftServer.r(MinecraftServer.java:565)
            at net.minecraft.server.DedicatedServer.r(DedicatedServer.java:215)
            at net.minecraft.server.MinecraftServer.q(MinecraftServer.java:495)
            at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:428)
            at net.minecraft.server.ThreadServerApplication.run(SourceFile:818)
    Caused by: java.lang.NullPointerException
            at de.kumpelblase2.remoteentities.api.features.RemoteEquipmentFeature.loadEquipmen
            at de.kumpelblase2.remoteentities.api.features.RemoteEquipmentFeature.<init>(Remot
            at com.java.phondeux.skeletonking.SKEntityListener.onEntitySpawn(SKEntityListener.
            at sun.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.ja
            at java.lang.reflect.Method.invoke(Method.java:601)
            at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:339)
            ... 12 more
    Any idea why?
  28. You try to spawn a non-nameable entity (you can only name players!) as a named entity. That won't work. I'll change it that it'll spawn the non-named entity instead, but for now, use createEntity().

    confuserr : As far as I can tell, I only had a similar error when using spawner eggs, normal spawns work totally fine. Did you do something special?

    Since I fixed some things on my webserver I'll move the maven repo onto it as well. New urls are:
    Have fun!

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
    Last edited by a moderator: May 29, 2016
  29. Offline


    Nope, not unless there's another plugin interfering. The only "special" thing I do is change majority of mobs/animals to zombies but that shouldn't cause a Null Pointer on the getMind() within the remoteentities plugin should it? Is it because im using createRemoteEntityFromExisting?
  30. Offline


    Great work, I change from NPC Lib to your Lib soon ;)
Thread Status:
Not open for further replies.

Share This Page