├── .gitignore ├── .project ├── .settings └── org.eclipse.m2e.core.prefs ├── .travis.yml ├── LICENSE ├── README.md ├── api ├── .classpath ├── .project ├── .settings │ ├── org.eclipse.jdt.core.prefs │ └── org.eclipse.m2e.core.prefs ├── pom.xml └── src │ └── main │ └── java │ └── net │ └── techcable │ └── npclib │ ├── Animation.java │ ├── HumanNPC.java │ ├── LivingNPC.java │ ├── NPC.java │ ├── NPCRegistry.java │ ├── PathNotFoundException.java │ ├── ai │ ├── AIEnvironment.java │ └── AITask.java │ ├── nms │ ├── IHumanNPCHook.java │ ├── ILivingNPCHook.java │ ├── INPCHook.java │ └── NMS.java │ └── utils │ ├── HttpUtils.java │ ├── NPCLog.java │ └── Reflection.java ├── base ├── .classpath ├── .project ├── .settings │ ├── org.eclipse.jdt.core.prefs │ └── org.eclipse.m2e.core.prefs ├── pom.xml └── src │ ├── main │ ├── java │ │ └── net │ │ │ └── techcable │ │ │ └── npclib │ │ │ ├── Metrics.java │ │ │ ├── NPCLib.java │ │ │ ├── NPCLibLoader.java │ │ │ ├── NPCMetrics.java │ │ │ ├── Plugin.java │ │ │ └── UnsupportedVersionException.java │ └── resources │ │ └── plugin.yml │ └── test │ └── java │ └── net │ └── techcable │ └── npclib │ └── NPCLibLoaderTest.java ├── citizens ├── .classpath ├── .project ├── .settings │ ├── org.eclipse.jdt.core.prefs │ └── org.eclipse.m2e.core.prefs ├── pom.xml └── src │ └── main │ └── java │ └── net │ └── techcable │ └── npclib │ └── citizens │ ├── CitizensNPC.java │ ├── CitizensNPCRegistry.java │ ├── HumanCitizensNPC.java │ ├── LivingCitizensNPC.java │ └── ai │ └── CitizensAIEnvironment.java ├── nms-v1_7_R3 ├── .classpath ├── .project ├── .settings │ ├── org.eclipse.jdt.core.prefs │ └── org.eclipse.m2e.core.prefs ├── pom.xml └── src │ └── main │ └── java │ └── net │ └── techcable │ └── npclib │ └── nms │ └── versions │ └── v1_7_R3 │ ├── HumanNPCHook.java │ ├── LivingNPCHook.java │ ├── NMS.java │ ├── NPCHook.java │ ├── ai │ └── NPCPath.java │ ├── entity │ └── EntityNPCPlayer.java │ └── network │ ├── NPCConnection.java │ ├── NPCNetworkManager.java │ ├── NullChannel.java │ └── NullSocketAddress.java ├── nms-v1_7_R4 ├── .classpath ├── .project ├── .settings │ ├── org.eclipse.jdt.core.prefs │ └── org.eclipse.m2e.core.prefs ├── pom.xml └── src │ └── main │ └── java │ └── net │ └── techcable │ └── npclib │ └── nms │ └── versions │ └── v1_7_R4 │ ├── HumanNPCHook.java │ ├── LivingNPCHook.java │ ├── NMS.java │ ├── NPCHook.java │ ├── ProtocolHack.java │ ├── ai │ └── NPCPath.java │ ├── entity │ └── EntityNPCPlayer.java │ └── network │ ├── NPCConnection.java │ ├── NPCNetworkManager.java │ ├── NullChannel.java │ └── NullSocketAddress.java ├── nms-v1_8_R1 ├── .classpath ├── .project ├── .settings │ ├── org.eclipse.jdt.core.prefs │ └── org.eclipse.m2e.core.prefs ├── pom.xml └── src │ └── main │ └── java │ └── net │ └── techcable │ └── npclib │ └── nms │ └── versions │ └── v1_8_R1 │ ├── HumanNPCHook.java │ ├── LivingNPCHook.java │ ├── NMS.java │ ├── NPCHook.java │ ├── ai │ └── NPCPath.java │ ├── entity │ └── EntityNPCPlayer.java │ └── network │ ├── NPCConnection.java │ ├── NPCNetworkManager.java │ ├── NullChannel.java │ └── NullSocketAddress.java ├── nms-v1_8_R2 ├── pom.xml └── src │ └── main │ └── java │ └── net │ └── techcable │ └── npclib │ └── nms │ └── versions │ └── v1_8_R2 │ ├── HumanNPCHook.java │ ├── LivingNPCHook.java │ ├── NMS.java │ ├── NPCHook.java │ ├── ai │ └── NPCPath.java │ ├── entity │ └── EntityNPCPlayer.java │ └── network │ ├── NPCConnection.java │ ├── NPCNetworkManager.java │ ├── NullChannel.java │ └── NullSocketAddress.java ├── nms-v1_8_R3 ├── pom.xml └── src │ └── main │ └── java │ └── net │ └── techcable │ └── npclib │ └── nms │ └── versions │ └── v1_8_R3 │ ├── HumanNPCHook.java │ ├── LivingNPCHook.java │ ├── NMS.java │ ├── NPCHook.java │ ├── ai │ └── NPCPath.java │ ├── entity │ └── EntityNPCPlayer.java │ └── network │ ├── NPCConnection.java │ ├── NPCNetworkManager.java │ ├── NullChannel.java │ └── NullSocketAddress.java ├── nms-v1_9_R1 ├── pom.xml └── src │ └── main │ └── java │ └── net │ └── techcable │ └── npclib │ └── nms │ └── versions │ └── v1_9_R1 │ ├── HumanNPCHook.java │ ├── LivingNPCHook.java │ ├── NMS.java │ ├── NPCHook.java │ ├── entity │ └── EntityNPCPlayer.java │ └── network │ ├── NPCConnection.java │ ├── NPCNetworkManager.java │ ├── NullChannel.java │ └── NullSocketAddress.java ├── nms ├── .classpath ├── .project ├── .settings │ ├── org.eclipse.jdt.core.prefs │ └── org.eclipse.m2e.core.prefs ├── pom.xml └── src │ └── main │ └── java │ └── net │ └── techcable │ └── npclib │ └── nms │ ├── NMSHumanNPC.java │ ├── NMSLivingNPC.java │ ├── NMSNPC.java │ ├── NMSRegistry.java │ └── ai │ └── NMSAIEnvironment.java └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | pom.xml.tag 3 | dependency-reduced-pom.xml 4 | pom.xml.releaseBackup 5 | pom.xml.versionsBackup 6 | pom.xml.next 7 | release.properties 8 | 9 | #Emacs 10 | *~ 11 | 12 | #IntelliJ 13 | *.iml 14 | /.idea 15 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | npclib-parent 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.m2e.core.maven2Builder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.m2e.core.maven2Nature 16 | 17 | 18 | -------------------------------------------------------------------------------- /.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Techcable 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | NPCLib [![Build Status](http://ci.techcable.net/buildStatus/icon?job=NPCLib)](http://ci.techcable.net/job/NPCLib/) 2 | ====== 3 | Easy spawning of npcs 4 | 5 | ##Supported Versions 6 | - 1.8 7 | - fake 1.8 8 | - 1.7.10 9 | - 1.7.9 10 | - 1.7.8 11 | - Citizens 12 | - Allows spawning on any version of minecraft 13 | 14 | ##Maven 15 | 16 | ###Repository 17 | ````xml 18 | 19 | techcable-repo 20 | http://repo.techcable.net/content/groups/public/ 21 | 22 | ```` 23 | ###Dependency 24 | ````xml 25 | 26 | net.techcable 27 | npclib 28 | LATEST 29 | 30 | ```` 31 | 32 | ##Usage 33 | [**Javadocs**](http://ci.techcable.net/job/NPCLib/javadoc/) 34 | 35 | Example: 36 | ````java 37 | public void spawn() { 38 | if (!NPCLib.isSupported()) return; 39 | NPCRegistry registry = NPCLib.getNPCRegistry("awesome-registry", getPlugin()); 40 | NPC npc = registry.createNPC(EntityType.PLAYER, "jack"); 41 | npc.setName("greeter"); 42 | npc.setProtected(true); //Makes invincible 43 | npc.setSkin(lookupId("Techcable")); //Gives the npc my troll skin 44 | npc.spawn(getSpawn()); //Spawns at server spawn 45 | } 46 | ```` 47 | -------------------------------------------------------------------------------- /api/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /api/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | npclib-api 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /api/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 3 | org.eclipse.jdt.core.compiler.compliance=1.7 4 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 5 | org.eclipse.jdt.core.compiler.source=1.7 6 | -------------------------------------------------------------------------------- /api/.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /api/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | net.techcable.npclib 5 | parent 6 | 2.0.0-beta2-SNAPSHOT 7 | ../pom.xml 8 | 9 | api 10 | 11 | 12 | 13 | com.mycila 14 | license-maven-plugin 15 | 2.8 16 | 17 | 18 | src/main/java/net/techcable/npclib/utils/astar 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /api/src/main/java/net/techcable/npclib/Animation.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib; 2 | 3 | import lombok.*; 4 | 5 | /** 6 | * An animation the npc can perform 7 | *

8 | * An animation is a visual-action 9 | * It may or may not correlate with a real action 10 | *

11 | */ 12 | @RequiredArgsConstructor 13 | public enum Animation { 14 | /** 15 | * Makes the npc act hurt 16 | *

17 | * Only applicable to living entities 18 | */ 19 | HURT, 20 | /** 21 | * Makes the npc lie on the ground 22 | *

23 | * Only applicable to living entities 24 | */ 25 | DEAD, 26 | 27 | // Human Animations 28 | 29 | /** 30 | * Makes the npc swing its arm 31 | *

32 | * Only applicable to human entities 33 | */ 34 | ARM_SWING(HumanNPC.class), 35 | /** 36 | * Makes the npc eat the item it is holding 37 | *

38 | * Only applicable to human entities 39 | */ 40 | EAT(HumanNPC.class), 41 | /** 42 | * A critical hit animation 43 | *

44 | * Only applicable to human entities 45 | */ 46 | CRITICAL(HumanNPC.class), 47 | /** 48 | * A 'magic' critical hit animation 49 | *

50 | * Only applicable to human entities 51 | */ 52 | MAGIC_CRITICAL(HumanNPC.class); 53 | 54 | 55 | private final Class appliesTo; 56 | 57 | /** 58 | * Get the type of npc this animation can be applied to 59 | * 60 | * @return the type of npc this animation can be applied to 61 | */ 62 | public Class getAppliesTo() { 63 | return appliesTo; 64 | } 65 | 66 | private Animation() { 67 | this(LivingNPC.class); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /api/src/main/java/net/techcable/npclib/HumanNPC.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib; 2 | 3 | import java.util.UUID; 4 | 5 | import org.bukkit.entity.Player; 6 | 7 | /** 8 | * Represents a human non player controlled nmsEntity 9 | * 10 | * @author Techcable 11 | * @version 2.0 12 | * @since 2.0 13 | */ 14 | public interface HumanNPC extends LivingNPC { 15 | 16 | /** 17 | * Return this npc's skin 18 | *

19 | * A value of null represents a steve skin 20 | * 21 | * @return this npc's skin 22 | */ 23 | public UUID getSkin(); 24 | 25 | /** 26 | * Set the npc's skin 27 | *

28 | * A value of null represents a steve skin 29 | * 30 | * @param skin the player id with the skin you want 31 | * 32 | * @throws UnsupportedOperationException if skins aren't supported 33 | */ 34 | public void setSkin(UUID skin); 35 | 36 | /** 37 | * Set the npc's skin 38 | *

39 | * A value of null represents a steve skin 40 | * 41 | * @param skin the player name with the skin you want 42 | * 43 | * @throws UnsupportedOperationException if skins aren't supported 44 | */ 45 | public void setSkin(String skin); 46 | 47 | /** 48 | * Get the nmsEntity associated with this npc 49 | * 50 | * @return the nmsEntity 51 | */ 52 | @Override 53 | public Player getEntity(); 54 | 55 | /** 56 | * Set if the npc is shown in the tab list 57 | * 58 | * @param show whether or not to show this npc in the tab list 59 | * 60 | * @throws java.lang.IllegalStateException if the npcc is not spawned 61 | */ 62 | public void setShowInTabList(boolean show); 63 | 64 | /** 65 | * Return if the npc is shown in the tab list 66 | * 67 | * @return true if the npc is shown in the tab list 68 | */ 69 | public boolean isShownInTabList(); 70 | } 71 | -------------------------------------------------------------------------------- /api/src/main/java/net/techcable/npclib/LivingNPC.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib; 2 | 3 | import org.bukkit.Location; 4 | import org.bukkit.entity.LivingEntity; 5 | 6 | /** 7 | * Represents a living non-player controlled nmsEntity 8 | * 9 | * @author Techcable 10 | * @version 2.0 11 | * @since 2.0 12 | */ 13 | public interface LivingNPC extends NPC { 14 | 15 | /** 16 | * Set the current name of the npc 17 | * 18 | * @param name the new name 19 | */ 20 | public void setName(String name); 21 | 22 | /** 23 | * Retrieve the name of this npc 24 | * 25 | * @return this npc's name 26 | */ 27 | public String getName(); 28 | 29 | /** 30 | * Get the nmsEntity associated with this npc 31 | * 32 | * @return the nmsEntity 33 | */ 34 | @Override 35 | public LivingEntity getEntity(); 36 | 37 | /** 38 | * The npc's head will look in this direction 39 | * 40 | * @param toFace the direction to look 41 | */ 42 | public void faceLocation(Location toFace); 43 | 44 | /** 45 | * Returns if the npc is an a condition to walk 46 | * 47 | * @return if the npc is an a condition to walk 48 | */ 49 | public boolean isAbleToWalk(); 50 | 51 | /** 52 | * Walk to the specified location 53 | * 54 | * @param l the location to walk to 55 | * 56 | * @throws java.lang.IllegalStateException if not in a condition to walk 57 | * @throws PathNotFoundException if the NPC could not walk to the specified location 58 | * @throws NullPointerException if the location is null 59 | */ 60 | public void walkTo(Location l) throws PathNotFoundException; 61 | 62 | /** 63 | * Play the specified animation to all clients 64 | * 65 | * @param animation the animation to play 66 | * 67 | * @throws java.lang.IllegalArgumentException if the annotation can't be played on this type of npc 68 | * @throws java.lang.IllegalStateException if the npc is not spawned 69 | * @throws java.lang.UnsupportedOperationException if this implementation doesn't support the specified animation 70 | */ 71 | public void animate(Animation animation); 72 | 73 | } 74 | -------------------------------------------------------------------------------- /api/src/main/java/net/techcable/npclib/NPC.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib; 2 | 3 | import java.util.UUID; 4 | 5 | import net.techcable.npclib.ai.AIEnvironment; 6 | import net.techcable.npclib.ai.AITask; 7 | 8 | import org.bukkit.Location; 9 | import org.bukkit.entity.Entity; 10 | 11 | /** 12 | * Represents a non player controlled nmsEntity 13 | * 14 | * @author Techcable 15 | * @version 2.0 16 | * @since 1.0 17 | */ 18 | public interface NPC { 19 | 20 | /** 21 | * Despawn this npc 22 | *

23 | * Once despawned it can not be respawned 24 | * It will be deregistered from the registry 25 | * 26 | * @return true if was able to despawn 27 | * 28 | * @throws java.lang.IllegalStateException if the npc is already despawned 29 | */ 30 | public void despawn(); 31 | 32 | /** 33 | * Get the nmsEntity associated with this npc 34 | * 35 | * @return the nmsEntity 36 | */ 37 | public Entity getEntity(); 38 | 39 | /** 40 | * Get this npc's uuid 41 | * 42 | * @return the uuid of this npc 43 | */ 44 | public UUID getUUID(); 45 | 46 | /** 47 | * Returns whether the npc is spawned 48 | * 49 | * @return true if the npc is spawned 50 | */ 51 | public boolean isSpawned(); 52 | 53 | /** 54 | * Returns whether the npc has been destroyed 55 | *

56 | * NPCs that are destroyed can never be respawned 57 | *

58 | * 59 | * @return true if the npc has been destroyed 60 | */ 61 | public boolean isDestroyed(); 62 | 63 | /** 64 | * Spawn this npc 65 | * 66 | * @param toSpawn location to spawn this npc 67 | * 68 | * @return true if the npc was able to spawn 69 | * 70 | * @throws java.lang.NullPointerException if location is null 71 | * @throws java.lang.IllegalArgumentException if already or spawned or {@link #despawn()} has been called 72 | */ 73 | public void spawn(Location toSpawn); 74 | 75 | /** 76 | * Set the protected status of this NPC 77 | * true by default 78 | * 79 | * @param protect whether or not this npc is invincible 80 | */ 81 | public void setProtected(boolean protect); 82 | 83 | /** 84 | * Check if the NPC is protected from damage 85 | * 86 | * @return The protected status of the NPC 87 | */ 88 | public boolean isProtected(); 89 | 90 | /** 91 | * Add the specified task to the npc 92 | * 93 | * @param task the task to add 94 | */ 95 | public void addTask(AITask task); 96 | 97 | /** 98 | * Get the npc's ai environment 99 | *

100 | * The ai environment manages the npc's ai 101 | *

102 | * 103 | * @return the npc's ai environment 104 | */ 105 | public AIEnvironment getAIEnvironment(); 106 | 107 | } 108 | -------------------------------------------------------------------------------- /api/src/main/java/net/techcable/npclib/NPCRegistry.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib; 2 | 3 | import java.util.UUID; 4 | 5 | import org.bukkit.entity.Entity; 6 | import org.bukkit.entity.EntityType; 7 | import org.bukkit.plugin.Plugin; 8 | 9 | import com.google.common.collect.ImmutableCollection; 10 | 11 | public interface NPCRegistry { 12 | 13 | /** 14 | * Creates a despawned human npc 15 | * 16 | * @param name the name of the npc 17 | * 18 | * @return the new npc 19 | */ 20 | public HumanNPC createHumanNPC(String name); 21 | 22 | /** 23 | * Creates a despawned human npc 24 | * 25 | * @param uuid the uuid of the new npc 26 | * @param name the name of the npc 27 | * 28 | * @return the new npc 29 | */ 30 | public HumanNPC createHumanNPC(UUID uuid, String name); 31 | 32 | /** 33 | * Creates a despawned npc of the specified type 34 | *

35 | * Human npcs are not supported by this method 36 | *

37 | * 38 | * @param name the name of the npc 39 | * @param type use 40 | * 41 | * @return the new npc 42 | * 43 | * @throws java.lang.IllegalArgumentException if the entity type isn't a living entity 44 | * @throws java.lang.UnsupportedOperationException if the entity type is unsupported 45 | */ 46 | public LivingNPC createLivingNPC(String name, EntityType type); 47 | 48 | /** 49 | * Creates a despawned npc of the specified type 50 | *

51 | * Human npcs are supported by this method 52 | *

53 | * 54 | * @param uuid the uuid of the new npcs 55 | * @param name the name of the npc 56 | * @param type the type of the npc to spawn 57 | * 58 | * @return the new npc 59 | * 60 | * @throws java.lang.IllegalArgumentException if the entity type isn't a living entity 61 | * @throws java.lang.UnsupportedOperationException if the entity type is unsupported 62 | */ 63 | public LivingNPC createLivingNPC(UUID uuid, String name, EntityType type); 64 | 65 | /** 66 | * Removes this npc from the registry 67 | * Be careful not to remove despawned npcs 68 | * 69 | * @param npc the npc to deregister 70 | * 71 | * @throws IllegalStateException if the npc is spawned 72 | */ 73 | public void deregister(NPC npc); 74 | 75 | /** 76 | * Deregisters every npc in the registry 77 | */ 78 | public void deregisterAll(); 79 | 80 | /** 81 | * Retreives the npc with the given UUID 82 | * 83 | * @param uuid the uuid to get the npc for 84 | * 85 | * @return the npc with this uuid 86 | */ 87 | public NPC getByUUID(UUID uuid); 88 | 89 | /** 90 | * Retreives a npc with the given name 91 | *

92 | *

93 | * There may be multiple npcs with a name, so this method may not return the one you want 94 | * If you want to guarentee unqiueness, use uuids 95 | * Some npcs are ignored by this method, depending on the implementation 96 | *

97 | * 98 | * @param name the name to get a npc with 99 | * 100 | * @return a npc with the given name 101 | * 102 | * @since 2.0 103 | * @deprecated there may be multiple npcs with the given name, and some npcs are ignored 104 | */ 105 | @Deprecated 106 | public NPC getByName(String name); 107 | 108 | /** 109 | * Converts an Entity to an NPC 110 | * 111 | * @param entity the npc to get as an nmsEntity 112 | * 113 | * @return the NPC that represents this nmsEntity 114 | */ 115 | public NPC getAsNPC(Entity entity); 116 | 117 | /** 118 | * Checks if the nmsEntity can be converted to an npc 119 | * 120 | * @param entity the nmsEntity to check 121 | * 122 | * @return true if the nmsEntity is an npc 123 | */ 124 | public boolean isNPC(Entity entity); 125 | 126 | /** 127 | * Retreive every npc in the registry 128 | * 129 | * @return all the npcs in the registry 130 | */ 131 | public ImmutableCollection listNpcs(); 132 | 133 | /** 134 | * Get this registry's owning plugin 135 | * 136 | * @return the registry's plugin 137 | */ 138 | public Plugin getPlugin(); 139 | 140 | } 141 | -------------------------------------------------------------------------------- /api/src/main/java/net/techcable/npclib/PathNotFoundException.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib; 2 | 3 | import org.bukkit.Location; 4 | 5 | public class PathNotFoundException extends Exception { 6 | public PathNotFoundException(Location to, Location from) { 7 | super(String.format("Could not find a path to %s, %s, %s from %s, %s, %s", to.getX(), to.getY(), to.getZ(), from.getX(), from.getY(), from.getZ())); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /api/src/main/java/net/techcable/npclib/ai/AIEnvironment.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.ai; 2 | 3 | import com.google.common.base.Preconditions; 4 | import lombok.RequiredArgsConstructor; 5 | import net.techcable.npclib.utils.NPCLog; 6 | 7 | import java.util.ArrayList; 8 | import java.util.HashSet; 9 | import java.util.List; 10 | import java.util.Set; 11 | 12 | @RequiredArgsConstructor 13 | public class AIEnvironment { 14 | private final Set tasks = new HashSet<>(); 15 | private final List callbacks = new ArrayList<>(); 16 | 17 | protected void tick() { 18 | for (final AITask task : tasks) { 19 | try { 20 | task.tick(this); 21 | } catch (Throwable t) { 22 | NPCLog.warn("AI task " + task.getClass().getSimpleName() + " threw an exception", t); 23 | } 24 | } 25 | for (Runnable callback : callbacks) { 26 | try { 27 | callback.run(); 28 | } catch (Throwable t) { 29 | NPCLog.warn("Callback " + callback.getClass().getSimpleName() + " threw an exception", t); 30 | } 31 | } 32 | callbacks.clear(); 33 | } 34 | 35 | /** 36 | * Add a callback to be ticked as soon as possible 37 | *

38 | * Tasks are guaranteed to be ticked before callbacks 39 | * 40 | * @param callback the callback to run 41 | */ 42 | public void addCallback(Runnable callback) { 43 | Preconditions.checkNotNull(callback, "Null callback"); 44 | callbacks.add(callback); 45 | } 46 | 47 | /** 48 | * Remove this task from the ai environment 49 | * 50 | * @param task the task to remove 51 | */ 52 | public void addTask(AITask task) { 53 | Preconditions.checkNotNull(task, "Null task"); 54 | tasks.add(task); 55 | } 56 | 57 | /** 58 | * Remove this task from the ai environment 59 | *

60 | * Does nothing if the task isn't there 61 | * 62 | * @param task the task to remove 63 | */ 64 | public void removeTask(AITask task) { 65 | Preconditions.checkNotNull(task, "Null task to remove"); 66 | tasks.remove(task); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /api/src/main/java/net/techcable/npclib/ai/AITask.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.ai; 2 | 3 | /** 4 | * A task for this npc's AI to perform 5 | */ 6 | public interface AITask { 7 | 8 | /** 9 | * Run this task in the given ai environment 10 | * 11 | * @param environment the ai environment 12 | */ 13 | public void tick(AIEnvironment environment); 14 | } 15 | -------------------------------------------------------------------------------- /api/src/main/java/net/techcable/npclib/nms/IHumanNPCHook.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms; 2 | 3 | import java.util.UUID; 4 | 5 | public interface IHumanNPCHook extends ILivingNPCHook { 6 | 7 | public void setSkin(UUID id); //Remember to do this while despawned 8 | 9 | public void showInTablist(); 10 | 11 | public void hideFromTablist(); 12 | } 13 | -------------------------------------------------------------------------------- /api/src/main/java/net/techcable/npclib/nms/ILivingNPCHook.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms; 2 | 3 | import net.techcable.npclib.Animation; 4 | 5 | import net.techcable.npclib.PathNotFoundException; 6 | import org.bukkit.Location; 7 | import org.bukkit.entity.LivingEntity; 8 | 9 | public interface ILivingNPCHook extends INPCHook { 10 | 11 | public LivingEntity getEntity(); 12 | 13 | public void look(float pitch, float yaw); 14 | 15 | public void onTick(); 16 | 17 | public void setName(String s); 18 | 19 | public void navigateTo(Location l) throws PathNotFoundException; 20 | 21 | public void animate(Animation animation); // NOTE -- API performs validation 22 | } 23 | -------------------------------------------------------------------------------- /api/src/main/java/net/techcable/npclib/nms/INPCHook.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms; 2 | 3 | import org.bukkit.entity.Entity; 4 | 5 | /** 6 | * Does things with a npc you need NMS for 7 | */ 8 | public interface INPCHook { 9 | 10 | public void onDespawn(); 11 | 12 | public Entity getEntity(); 13 | } 14 | -------------------------------------------------------------------------------- /api/src/main/java/net/techcable/npclib/nms/NMS.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms; 2 | 3 | import java.util.Collection; 4 | 5 | import net.techcable.npclib.HumanNPC; 6 | import net.techcable.npclib.LivingNPC; 7 | import net.techcable.npclib.NPC; 8 | 9 | import org.bukkit.Location; 10 | import org.bukkit.entity.EntityType; 11 | import org.bukkit.entity.Player; 12 | 13 | public interface NMS { 14 | 15 | public IHumanNPCHook spawnHumanNPC(Location toSpawn, HumanNPC npc); 16 | 17 | //Events 18 | public void onJoin(Player joined, Collection npcs); 19 | } -------------------------------------------------------------------------------- /api/src/main/java/net/techcable/npclib/utils/HttpUtils.java: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License 3 | * Copyright (c) 2014-2015 Techcable 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | * THE SOFTWARE. 22 | */ 23 | package net.techcable.npclib.utils; 24 | 25 | import java.io.BufferedReader; 26 | import java.io.IOException; 27 | import java.io.InputStreamReader; 28 | import java.io.OutputStream; 29 | import java.net.HttpURLConnection; 30 | import java.net.URL; 31 | 32 | import org.json.simple.JSONArray; 33 | import org.json.simple.parser.JSONParser; 34 | 35 | public class HttpUtils { 36 | 37 | private static JSONParser PARSER = new JSONParser(); 38 | 39 | public static Object getJson(String rawUrl) { 40 | BufferedReader reader = null; 41 | try { 42 | URL url = new URL(rawUrl); 43 | HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 44 | connection.setRequestMethod("GET"); 45 | 46 | reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); 47 | StringBuffer result = new StringBuffer(); 48 | String line; 49 | while ((line = reader.readLine()) != null) result.append(line); 50 | return PARSER.parse(result.toString()); 51 | } catch (Exception ex) { 52 | return null; 53 | } finally { 54 | try { 55 | if (reader != null) reader.close(); 56 | } catch (IOException ex) { 57 | ex.printStackTrace(); 58 | return null; 59 | } 60 | } 61 | } 62 | 63 | public static Object postJson(String url, JSONArray body) { 64 | String rawResponse = post(url, body.toJSONString()); 65 | if (rawResponse == null) return null; 66 | try { 67 | return PARSER.parse(rawResponse); 68 | } catch (Exception e) { 69 | return null; 70 | } 71 | } 72 | 73 | public static String post(String rawUrl, String body) { 74 | BufferedReader reader = null; 75 | OutputStream out = null; 76 | 77 | try { 78 | URL url = new URL(rawUrl); 79 | HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 80 | connection.setRequestMethod("POST"); 81 | connection.setDoOutput(true); 82 | connection.setDoInput(true); 83 | connection.setRequestProperty("Content-Type", "application/json"); 84 | out = connection.getOutputStream(); 85 | out.write(body.getBytes()); 86 | reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); 87 | StringBuffer result = new StringBuffer(); 88 | String line; 89 | while ((line = reader.readLine()) != null) result.append(line); 90 | return result.toString(); 91 | } catch (IOException ex) { 92 | ex.printStackTrace(); 93 | return null; 94 | } finally { 95 | try { 96 | if (out != null) out.close(); 97 | if (reader != null) reader.close(); 98 | } catch (IOException ex) { 99 | ex.printStackTrace(); 100 | return null; 101 | } 102 | } 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /api/src/main/java/net/techcable/npclib/utils/NPCLog.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.utils; 2 | 3 | import lombok.*; 4 | 5 | import java.util.logging.Level; 6 | 7 | import org.bukkit.Bukkit; 8 | 9 | @NoArgsConstructor(access = AccessLevel.PRIVATE) 10 | public class NPCLog { 11 | 12 | public static final boolean DEBUG = Boolean.parseBoolean(System.getProperty("npclib.debug", "false")); 13 | 14 | public static final String PREFIX = "NPCLib"; 15 | 16 | public static void info(String msg) { 17 | log(Level.INFO, msg); 18 | } 19 | 20 | public static void info(String msg, Object... args) { 21 | log(Level.INFO, msg, args); 22 | } 23 | 24 | public static void warn(String msg) { 25 | log(Level.WARNING, msg); 26 | } 27 | 28 | public static void warn(String msg, Object... args) { 29 | log(Level.WARNING, msg, args); 30 | } 31 | 32 | public static void warn(String msg, Throwable t) { 33 | log(Level.WARNING, msg, t); 34 | } 35 | 36 | public static void severe(String msg, Throwable t) { 37 | log(Level.SEVERE, msg, t); 38 | } 39 | 40 | public static void debug(String msg) { 41 | if (DEBUG) { 42 | log(Level.INFO, msg); 43 | } 44 | } 45 | 46 | public static void debug(String msg, Throwable t) { 47 | if (DEBUG) { 48 | log(Level.INFO, msg, t); 49 | } 50 | } 51 | 52 | private static void log(Level level, String msg, Throwable t) { 53 | Bukkit.getLogger().log(level, PREFIX + " " + msg, t); 54 | } 55 | 56 | private static void log(Level level, String msg, Object... args) { 57 | Bukkit.getLogger().log(level, String.format(msg, args)); 58 | } 59 | 60 | private static void log(Level level, String msg) { 61 | Bukkit.getLogger().log(level, msg); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /base/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /base/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | npclib-base 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /base/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 3 | org.eclipse.jdt.core.compiler.compliance=1.7 4 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 5 | org.eclipse.jdt.core.compiler.source=1.7 6 | -------------------------------------------------------------------------------- /base/.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /base/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | net.techcable.npclib 5 | parent 6 | 2.0.0-beta2-SNAPSHOT 7 | ../pom.xml 8 | 9 | net.techcable 10 | npclib 11 | 12 | 13 | 14 | net.techcable.npclib 15 | api 16 | ${parent.version} 17 | compile 18 | 19 | 20 | net.techcable.npclib 21 | citizens 22 | ${parent.version} 23 | 24 | 25 | net.techcable.npclib 26 | nms 27 | ${parent.version} 28 | 29 | 30 | junit 31 | junit 32 | 4.12 33 | test 34 | 35 | 36 | 37 | NPCLib 38 | 39 | 40 | -------------------------------------------------------------------------------- /base/src/main/java/net/techcable/npclib/NPCLib.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib; 2 | 3 | import java.util.HashMap; 4 | import java.util.List; 5 | import java.util.Map; 6 | import java.util.concurrent.Executors; 7 | import java.util.concurrent.ScheduledExecutorService; 8 | 9 | import net.techcable.npclib.citizens.CitizensNPCRegistry; 10 | import net.techcable.npclib.nms.NMSRegistry; 11 | 12 | import org.bukkit.Bukkit; 13 | import org.bukkit.entity.Entity; 14 | import org.bukkit.metadata.MetadataValue; 15 | import org.bukkit.plugin.Plugin; 16 | 17 | public class NPCLib { 18 | 19 | public static final String VERSION = "2.0.0-beta1"; 20 | public static final ScheduledExecutorService executor = Executors.newScheduledThreadPool(2); 21 | 22 | private NPCLib() { 23 | } 24 | 25 | private static NMSRegistry defaultNMS; 26 | private static Map registryMap = new HashMap<>(); 27 | 28 | public static NPCRegistry getNPCRegistry(Plugin plugin) { 29 | if (hasNMS()) { 30 | NPCMetrics.addUsingPlugin(plugin); 31 | if (defaultNMS == null) { 32 | defaultNMS = new NMSRegistry(plugin); 33 | } 34 | return defaultNMS; 35 | } else if (hasCitizens()) { 36 | NPCMetrics.addUsingPlugin(plugin); 37 | return CitizensNPCRegistry.getRegistry(plugin); 38 | } else { 39 | throw new UnsupportedVersionException("This version of minecraft isn't supported, please install citizens"); 40 | } 41 | } 42 | 43 | public static NPCRegistry getNPCRegistry(String name, Plugin plugin) { 44 | if (hasNMS()) { 45 | NPCMetrics.addUsingPlugin(plugin); 46 | if (!registryMap.containsKey(name)) { 47 | registryMap.put(name, new NMSRegistry(plugin)); 48 | } 49 | return registryMap.get(name); 50 | } else if (hasCitizens()) { 51 | NPCMetrics.addUsingPlugin(plugin); 52 | return CitizensNPCRegistry.getRegistry(name, plugin); 53 | } else { 54 | throw new UnsupportedVersionException("This version of minecraft isn't supported, please install citizens"); 55 | } 56 | } 57 | 58 | public static boolean isSupported() { 59 | return hasCitizens() || hasNMS(); 60 | } 61 | 62 | private static boolean hasCitizens() { 63 | try { 64 | Class.forName("net.citizensnpcs.api.CitizensAPI"); 65 | } catch (ClassNotFoundException e) { 66 | return false; 67 | } 68 | return Bukkit.getPluginManager().isPluginEnabled("Citizens"); 69 | } 70 | 71 | private static boolean hasNMS() { 72 | try { 73 | return NMSRegistry.getNms() != null; 74 | } catch (UnsupportedOperationException ex) { 75 | return false; 76 | } 77 | } 78 | 79 | public static boolean isNPC(Entity e) { 80 | if (hasCitizens()) { 81 | for (CitizensNPCRegistry registry : CitizensNPCRegistry.getRegistries()) { 82 | if (registry.isNPC(e)) return true; 83 | } 84 | } else if (hasNMS()) { 85 | if (e.hasMetadata(NMSRegistry.METADATA_KEY)) { 86 | List metadataList = e.getMetadata(NMSRegistry.METADATA_KEY); 87 | for (MetadataValue metadataValue : metadataList) { 88 | if (metadataValue.value() instanceof NPC) return true; 89 | } 90 | } 91 | } 92 | return false; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /base/src/main/java/net/techcable/npclib/NPCMetrics.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib; 2 | 3 | import lombok.*; 4 | 5 | import java.io.File; 6 | import java.io.IOException; 7 | import java.util.HashSet; 8 | import java.util.Set; 9 | 10 | import net.techcable.npclib.Metrics.Graph; 11 | import net.techcable.npclib.Metrics.Plotter; 12 | import net.techcable.npclib.utils.NPCLog; 13 | 14 | import org.bukkit.plugin.Plugin; 15 | 16 | @NoArgsConstructor(access = AccessLevel.NONE) 17 | public class NPCMetrics { 18 | 19 | private static Metrics metrics; 20 | private static Graph graph; 21 | 22 | public static void start(Plugin aPlugin) { 23 | if (metrics != null) return; 24 | File dataFolder = aPlugin.getDataFolder().getParentFile(); 25 | try { 26 | metrics = new Metrics(NPCLib.executor, dataFolder, "NPCLib", NPCLib.VERSION); 27 | graph = metrics.createGraph("Using Plugins"); 28 | metrics.start(); 29 | } catch (IOException e) { 30 | NPCLog.warn("Unable to start metrics", e); 31 | } 32 | } 33 | 34 | private static final Set usingPlugins = new HashSet<>(); 35 | 36 | public static void addUsingPlugin(Plugin plugin) { 37 | if (metrics == null) start(plugin); 38 | if (usingPlugins.contains(plugin.getName())) return; 39 | graph.addPlotter(new Plotter(plugin.getName()) { 40 | 41 | @Override 42 | public int getValue() { 43 | return 1; 44 | } 45 | }); 46 | usingPlugins.add(plugin.getName()); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /base/src/main/java/net/techcable/npclib/Plugin.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib; 2 | 3 | import org.bukkit.plugin.java.JavaPlugin; 4 | 5 | public class Plugin extends JavaPlugin { 6 | 7 | @Override 8 | public void onEnable() { 9 | NPCMetrics.start(this); 10 | } 11 | } -------------------------------------------------------------------------------- /base/src/main/java/net/techcable/npclib/UnsupportedVersionException.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib; 2 | 3 | public class UnsupportedVersionException extends RuntimeException { 4 | 5 | public UnsupportedVersionException(String msg) { 6 | super(msg); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /base/src/main/resources/plugin.yml: -------------------------------------------------------------------------------- 1 | name: NPCLib 2 | version: 1.0.0-SNAPSHOT 3 | authors: 4 | - Techcable 5 | softdepend: [Citizens] 6 | main: net.techcable.npclib.Plugin -------------------------------------------------------------------------------- /base/src/test/java/net/techcable/npclib/NPCLibLoaderTest.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib; 2 | 3 | import java.io.IOException; 4 | 5 | import org.junit.Test; 6 | 7 | import static org.junit.Assert.assertFalse; 8 | 9 | public class NPCLibLoaderTest { 10 | 11 | @Test 12 | public void testLoader() throws IOException { 13 | NPCLibLoader.loadNPCLib("2.0.0-beta1-SNAPSHOT"); 14 | assertFalse("NPCLib is supported without bukkit installed", NPCLibLoader.isSupported()); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /citizens/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /citizens/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | npclib-citizens 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /citizens/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 3 | org.eclipse.jdt.core.compiler.compliance=1.7 4 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 5 | org.eclipse.jdt.core.compiler.source=1.7 6 | -------------------------------------------------------------------------------- /citizens/.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /citizens/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | 4 | net.techcable.npclib 5 | parent 6 | 2.0.0-beta2-SNAPSHOT 7 | ../pom.xml 8 | 9 | citizens 10 | 11 | 12 | 13 | net.techcable.npclib 14 | api 15 | ${parent.version} 16 | provided 17 | 18 | 19 | net.citizensnpcs 20 | citizens 21 | 2.0.16-SNAPSHOT 22 | provided 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /citizens/src/main/java/net/techcable/npclib/citizens/CitizensNPC.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.citizens; 2 | 3 | 4 | import lombok.*; 5 | 6 | import java.lang.ref.WeakReference; 7 | import java.util.UUID; 8 | 9 | import net.citizensnpcs.api.npc.NPC; 10 | import net.techcable.npclib.ai.AITask; 11 | import net.techcable.npclib.citizens.ai.CitizensAIEnvironment; 12 | 13 | import org.bukkit.Location; 14 | import org.bukkit.entity.Entity; 15 | 16 | import com.google.common.base.Preconditions; 17 | 18 | public class CitizensNPC implements net.techcable.npclib.NPC { 19 | 20 | public CitizensNPC(NPC handle) { 21 | this.handle = new WeakReference(handle); 22 | } 23 | 24 | public NPC getHandle() { 25 | return handle.get(); 26 | } 27 | 28 | private final WeakReference handle; 29 | 30 | private boolean destroyed; 31 | 32 | @Override 33 | public void despawn() { 34 | Preconditions.checkState(isSpawned(), "Already despawned"); 35 | getHandle().despawn(); 36 | getHandle().destroy(); 37 | destroyed = true; 38 | } 39 | 40 | @Override 41 | public Entity getEntity() { 42 | if (getHandle() == null) return null; 43 | return getHandle().getEntity(); 44 | } 45 | 46 | @Override 47 | public UUID getUUID() { 48 | return getHandle().getUniqueId(); 49 | } 50 | 51 | @Override 52 | public boolean isSpawned() { 53 | return getHandle() != null && getHandle().isSpawned(); 54 | } 55 | 56 | @Override 57 | public boolean isDestroyed() { 58 | return getHandle() == null || destroyed; 59 | } 60 | 61 | @Override 62 | public void spawn(Location toSpawn) { 63 | Preconditions.checkNotNull(toSpawn, "Null location"); 64 | Preconditions.checkState(getHandle() != null, "This npc has been destroyed"); 65 | Preconditions.checkState(!isSpawned(), "Already spawned"); 66 | getHandle().spawn(toSpawn); 67 | } 68 | 69 | @Override 70 | public void setProtected(boolean protect) { 71 | Preconditions.checkState(getHandle() != null, "This npc has been destroyed"); 72 | getHandle().setProtected(protect); 73 | } 74 | 75 | @Override 76 | public boolean isProtected() { 77 | if (getHandle() == null) return false; 78 | return getHandle().isProtected(); 79 | } 80 | 81 | @Override 82 | public void addTask(AITask task) { 83 | getAIEnvironment().addTask(task); 84 | } 85 | 86 | @Getter(lazy = true) 87 | private final CitizensAIEnvironment aIEnvironment = new CitizensAIEnvironment(this); 88 | } 89 | -------------------------------------------------------------------------------- /citizens/src/main/java/net/techcable/npclib/citizens/HumanCitizensNPC.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.citizens; 2 | 3 | import java.util.UUID; 4 | 5 | import com.google.common.base.Preconditions; 6 | 7 | import net.citizensnpcs.api.npc.NPC; 8 | import net.citizensnpcs.util.PlayerAnimation; 9 | import net.techcable.npclib.Animation; 10 | import net.techcable.npclib.HumanNPC; 11 | 12 | import org.bukkit.Bukkit; 13 | import org.bukkit.entity.Player; 14 | 15 | public class HumanCitizensNPC extends LivingCitizensNPC implements HumanNPC { 16 | 17 | public HumanCitizensNPC(NPC handle) { 18 | super(handle); 19 | } 20 | 21 | @Override 22 | public UUID getSkin() { 23 | if (getHandle() == null) return null; //I'm too nice 24 | if (!getHandle().data().has(NPC.PLAYER_SKIN_UUID_METADATA)) return null; 25 | return UUID.fromString((String) getHandle().data().get(NPC.PLAYER_SKIN_UUID_METADATA)); 26 | } 27 | 28 | @Override 29 | public void setSkin(UUID skin) { 30 | Preconditions.checkState(getHandle() != null, "NPC has been destroyed"); 31 | getHandle().data().set(NPC.PLAYER_SKIN_UUID_METADATA, skin.toString()); 32 | if (isSpawned()) { 33 | despawn(); 34 | spawn(getHandle().getStoredLocation()); 35 | } 36 | } 37 | 38 | @Override 39 | public void setSkin(String skin) { 40 | Preconditions.checkNotNull(skin, "Skin is null"); 41 | // Hacky uuid load 42 | UUID id = Bukkit.getOfflinePlayer(skin).getUniqueId(); 43 | // If the uuid's variant is '3' than it must be an offline uuid 44 | Preconditions.checkArgument(id.variant() != 3, "Invalid player name %s", skin); 45 | setSkin(id); 46 | } 47 | 48 | @Override 49 | public Player getEntity() { 50 | if (super.getEntity() == null) return null; 51 | return (Player) super.getEntity(); 52 | 53 | } 54 | 55 | public static final String REMOVE_PLAYER_LIST_META = "removefromplayerlist"; 56 | 57 | @Override 58 | public void setShowInTabList(boolean show) { 59 | Preconditions.checkState(isSpawned(), "Can not set shown in tablist if not spawned"); 60 | getHandle().data().set(REMOVE_PLAYER_LIST_META, !show); 61 | } 62 | 63 | @Override 64 | public boolean isShownInTabList() { 65 | return !((Boolean) getHandle().data().get(REMOVE_PLAYER_LIST_META)); 66 | } 67 | 68 | @Override 69 | public void animate(Animation animation) { 70 | Preconditions.checkArgument(animation.getAppliesTo().isInstance(this), "%s can't be applied to human npcs", animation.toString()); 71 | Preconditions.checkState(isSpawned(), "NPC isn't spawned"); 72 | PlayerAnimation citizensAnimation; 73 | switch (animation) { 74 | case HURT : 75 | citizensAnimation = PlayerAnimation.HURT; 76 | break; 77 | // case DEAD - Unsupported 78 | case ARM_SWING : 79 | citizensAnimation = PlayerAnimation.ARM_SWING; 80 | break; 81 | case EAT : 82 | citizensAnimation = PlayerAnimation.EAT_FOOD; 83 | break; 84 | case CRITICAL : 85 | citizensAnimation = PlayerAnimation.CRIT; 86 | break; 87 | case MAGIC_CRITICAL : 88 | citizensAnimation = PlayerAnimation.MAGIC_CRIT; 89 | break; 90 | default : 91 | super.animate(animation); 92 | return; 93 | } 94 | for (Player player : Bukkit.getOnlinePlayers()) { 95 | citizensAnimation.play(player); 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /citizens/src/main/java/net/techcable/npclib/citizens/LivingCitizensNPC.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.citizens; 2 | 3 | import net.citizensnpcs.api.npc.NPC; 4 | import net.techcable.npclib.Animation; 5 | import net.techcable.npclib.LivingNPC; 6 | 7 | import org.bukkit.Location; 8 | import org.bukkit.entity.LivingEntity; 9 | 10 | import com.google.common.base.Preconditions; 11 | 12 | public class LivingCitizensNPC extends CitizensNPC implements LivingNPC { 13 | 14 | public LivingCitizensNPC(NPC handle) { 15 | super(handle); 16 | } 17 | 18 | @Override 19 | public void setName(String name) { 20 | Preconditions.checkState(getHandle() != null, "NPC has been destroyed"); 21 | getHandle().setName(name); 22 | } 23 | 24 | @Override 25 | public String getName() { 26 | if (getHandle() == null) return ""; //I'm a nice guy 27 | return getHandle().getName(); 28 | } 29 | 30 | @Override 31 | public void faceLocation(Location toFace) { 32 | Preconditions.checkState(getHandle() != null, "NPC has been destroyed"); 33 | Preconditions.checkState(isSpawned(), "NPC has been despawned"); 34 | getHandle().faceLocation(toFace); 35 | } 36 | 37 | @Override 38 | public boolean isAbleToWalk() { 39 | return isSpawned(); 40 | } 41 | 42 | @Override 43 | public void walkTo(Location l) { 44 | Preconditions.checkNotNull(l, "Null destination"); 45 | Preconditions.checkState(isAbleToWalk(), "Unable to walk"); 46 | getHandle().getNavigator().setTarget(l); 47 | } 48 | 49 | /** 50 | * {@inhertDoc} 51 | *

52 | * Doesn't handle {@link net.techcable.npclib.Animation#HURT} and {@link net.techcable.npclib.Animation#DEAD} 53 | *

54 | * 55 | */ 56 | @Override 57 | public void animate(Animation animation) { 58 | Preconditions.checkArgument(animation.getAppliesTo().isInstance(this), "%s can't be applied to living npcs", animation.toString()); 59 | Preconditions.checkState(isSpawned(), "NPC isn't spawned"); 60 | throw new UnsupportedOperationException(animation.toString() + " is unimplemented for living npcs"); 61 | } 62 | 63 | @Override 64 | public LivingEntity getEntity() { 65 | return (LivingEntity) super.getEntity(); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /citizens/src/main/java/net/techcable/npclib/citizens/ai/CitizensAIEnvironment.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.citizens.ai; 2 | 3 | import net.citizensnpcs.api.CitizensAPI; 4 | import net.techcable.npclib.ai.AIEnvironment; 5 | import net.techcable.npclib.citizens.CitizensNPC; 6 | 7 | import org.bukkit.scheduler.BukkitRunnable; 8 | 9 | public class CitizensAIEnvironment extends AIEnvironment { 10 | 11 | private final CitizensNPC npc; 12 | 13 | public CitizensAIEnvironment(CitizensNPC npc) { 14 | this.npc = npc; 15 | new BukkitRunnable() { 16 | 17 | @Override 18 | public void run() { 19 | tick(); 20 | } 21 | }.runTaskTimer(CitizensAPI.getPlugin(), 0, 1); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /nms-v1_7_R3/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /nms-v1_7_R3/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | npclib-nms-v1_7_R3 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /nms-v1_7_R3/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 3 | org.eclipse.jdt.core.compiler.compliance=1.7 4 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 5 | org.eclipse.jdt.core.compiler.source=1.7 6 | -------------------------------------------------------------------------------- /nms-v1_7_R3/.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /nms-v1_7_R3/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 4.0.0 5 | 6 | 7 | net.techcable.npclib 8 | parent 9 | 2.0.0-beta2-SNAPSHOT 10 | ../pom.xml 11 | 12 | 13 | nms-v1_7_R3 14 | 15 | 16 | 17 | net.techcable.npclib 18 | api 19 | ${parent.version} 20 | provided 21 | 22 | 23 | org.bukkit 24 | craftbukkit 25 | 1.7.9-R0.2 26 | provided 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /nms-v1_7_R3/src/main/java/net/techcable/npclib/nms/versions/v1_7_R3/HumanNPCHook.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_7_R3; 2 | 3 | import lombok.*; 4 | 5 | import java.lang.reflect.Field; 6 | import java.util.UUID; 7 | 8 | import net.minecraft.server.v1_7_R3.EntityPlayer; 9 | import net.minecraft.server.v1_7_R3.Packet; 10 | import net.minecraft.server.v1_7_R3.PacketPlayOutAnimation; 11 | import net.minecraft.server.v1_7_R3.PacketPlayOutPlayerInfo; 12 | import net.minecraft.util.com.mojang.authlib.GameProfile; 13 | import net.techcable.npclib.Animation; 14 | import net.techcable.npclib.HumanNPC; 15 | import net.techcable.npclib.nms.IHumanNPCHook; 16 | import net.techcable.npclib.nms.versions.v1_7_R3.entity.EntityNPCPlayer; 17 | import net.techcable.npclib.utils.Reflection; 18 | 19 | import org.bukkit.Bukkit; 20 | import org.bukkit.Location; 21 | import org.bukkit.entity.EntityType; 22 | import org.bukkit.entity.Player; 23 | 24 | import com.google.common.base.Preconditions; 25 | 26 | public class HumanNPCHook extends LivingNPCHook implements IHumanNPCHook { 27 | 28 | public HumanNPCHook(HumanNPC npc, Location toSpawn) { 29 | super(npc, toSpawn, EntityType.PLAYER); 30 | getNmsEntity().setHook(this); 31 | getNmsEntity().getWorld().players.remove(getNmsEntity()); 32 | } 33 | 34 | @Override 35 | public void setSkin(UUID id) { 36 | NMS.setSkin(getNmsEntity().getProfile(), id); 37 | respawn(); 38 | } 39 | 40 | private boolean shownInTabList; 41 | 42 | @Override 43 | public void showInTablist() { 44 | if (shownInTabList) return; 45 | PacketPlayOutPlayerInfo packet = new PacketPlayOutPlayerInfo(getNmsEntity().getProfile().getName(), true, 0); 46 | NMS.sendToAll(packet); 47 | shownInTabList = true; 48 | } 49 | 50 | @Override 51 | public void hideFromTablist() { 52 | if (!shownInTabList) return; 53 | PacketPlayOutPlayerInfo packet = new PacketPlayOutPlayerInfo(getNmsEntity().getProfile().getName(), false, 0); 54 | NMS.sendToAll(packet); 55 | shownInTabList = false; 56 | } 57 | 58 | public EntityNPCPlayer getNmsEntity() { 59 | return (EntityNPCPlayer) super.getNmsEntity(); 60 | } 61 | 62 | @Override 63 | public HumanNPC getNpc() { 64 | return (HumanNPC) super.getNpc(); 65 | } 66 | 67 | private static final Field nameField = Reflection.makeField(GameProfile.class, "name"); 68 | private static final Field modifiersField = Reflection.makeField(Field.class, "modifiers"); 69 | 70 | @Override 71 | public void setName(String s) { 72 | respawn(); 73 | } 74 | 75 | public void respawn() { 76 | Location lastLocation = getEntity().getLocation(); 77 | boolean wasShown = shownInTabList; 78 | hideFromTablist(); 79 | getNmsEntity().setHook(null); 80 | getNmsEntity().dead = true; // Kill old entity 81 | this.nmsEntity = spawn(lastLocation, EntityType.PLAYER); 82 | getNmsEntity().setHook(this); 83 | showInTablist(); 84 | if (!wasShown) hideFromTablist(); 85 | } 86 | 87 | @Override 88 | public void onDespawn() { 89 | hideFromTablist(); 90 | super.onDespawn(); 91 | } 92 | 93 | @Override 94 | protected EntityNPCPlayer spawn(Location toSpawn, EntityType type) { 95 | Preconditions.checkArgument(type == EntityType.PLAYER, "HumanNPCHook can only handle players"); 96 | EntityNPCPlayer entity = new EntityNPCPlayer(getNpc(), toSpawn); 97 | this.nmsEntity = entity; 98 | showInTablist(); 99 | this.nmsEntity = null; 100 | return entity; 101 | } 102 | 103 | @Override 104 | public void animate(Animation animation) { 105 | Packet packet; 106 | switch (animation) { 107 | case ARM_SWING : 108 | packet = new PacketPlayOutAnimation(getNmsEntity(), 0); 109 | break; 110 | case HURT : 111 | packet = new PacketPlayOutAnimation(getNmsEntity(), 1); 112 | break; 113 | case EAT : 114 | packet = new PacketPlayOutAnimation(getNmsEntity(), 3); 115 | break; 116 | case CRITICAL : 117 | packet = new PacketPlayOutAnimation(getNmsEntity(), 4); 118 | break; 119 | case MAGIC_CRITICAL : 120 | packet = new PacketPlayOutAnimation(getNmsEntity(), 5); 121 | break; 122 | default : 123 | super.animate(animation); 124 | return; 125 | } 126 | for (Player player : Bukkit.getOnlinePlayers()) { 127 | EntityPlayer handle = NMS.getHandle(player); 128 | handle.playerConnection.sendPacket(packet); 129 | } 130 | } 131 | 132 | public void onJoin(Player joined) { 133 | PacketPlayOutPlayerInfo packet = new PacketPlayOutPlayerInfo(getNmsEntity().getProfile().getName(), true, 0); 134 | NMS.getHandle(joined).playerConnection.sendPacket(packet); 135 | if (!shownInTabList) { 136 | PacketPlayOutPlayerInfo removePacket = new PacketPlayOutPlayerInfo(getNmsEntity().getProfile().getName(), false, 0); 137 | NMS.getHandle(joined).playerConnection.sendPacket(packet); 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /nms-v1_7_R3/src/main/java/net/techcable/npclib/nms/versions/v1_7_R3/NMS.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_7_R3; 2 | 3 | import java.util.Collection; 4 | import java.util.UUID; 5 | import java.util.concurrent.TimeUnit; 6 | 7 | import com.google.common.cache.Cache; 8 | import com.google.common.cache.CacheBuilder; 9 | import com.google.common.cache.CacheLoader; 10 | 11 | import net.minecraft.server.v1_7_R3.EntityLiving; 12 | import net.minecraft.server.v1_7_R3.EntityPlayer; 13 | import net.minecraft.server.v1_7_R3.MinecraftServer; 14 | import net.minecraft.server.v1_7_R3.Packet; 15 | import net.minecraft.server.v1_7_R3.WorldServer; 16 | import net.minecraft.util.com.google.common.cache.LoadingCache; 17 | import net.minecraft.util.com.mojang.authlib.GameProfile; 18 | import net.techcable.npclib.HumanNPC; 19 | import net.techcable.npclib.LivingNPC; 20 | import net.techcable.npclib.NPC; 21 | import net.techcable.npclib.nms.IHumanNPCHook; 22 | import net.techcable.npclib.nms.ILivingNPCHook; 23 | import net.techcable.npclib.nms.versions.v1_7_R3.LivingNPCHook.LivingHookable; 24 | import net.techcable.npclib.nms.versions.v1_7_R3.entity.EntityNPCPlayer; 25 | import net.techcable.npclib.utils.NPCLog; 26 | 27 | import org.bukkit.Bukkit; 28 | import org.bukkit.Location; 29 | import org.bukkit.Server; 30 | import org.bukkit.World; 31 | import org.bukkit.craftbukkit.v1_7_R3.CraftServer; 32 | import org.bukkit.craftbukkit.v1_7_R3.CraftWorld; 33 | import org.bukkit.craftbukkit.v1_7_R3.entity.CraftLivingEntity; 34 | import org.bukkit.craftbukkit.v1_7_R3.entity.CraftPlayer; 35 | import org.bukkit.entity.EntityType; 36 | import org.bukkit.entity.LivingEntity; 37 | import org.bukkit.entity.Player; 38 | 39 | public class NMS implements net.techcable.npclib.nms.NMS { 40 | 41 | private static NMS instance; 42 | 43 | public NMS() { 44 | if (instance == null) instance = this; 45 | } 46 | 47 | public static NMS getInstance() { 48 | return instance; 49 | } 50 | 51 | 52 | @Override 53 | public IHumanNPCHook spawnHumanNPC(Location toSpawn, HumanNPC npc) { 54 | return new HumanNPCHook(npc, toSpawn); 55 | } 56 | 57 | @Override 58 | public void onJoin(Player joined, Collection npcs) { 59 | for (NPC npc : npcs) { 60 | if (!(npc instanceof HumanNPC)) continue; 61 | HumanNPCHook hook = getHandle((HumanNPC) npc); 62 | if (hook == null) continue; 63 | hook.onJoin(joined); 64 | } 65 | } 66 | 67 | // UTILS 68 | public static final String NO_CRAFTBUKKIT_MSG = "Non-CraftBukkit implementations are unsupported"; 69 | 70 | public static EntityPlayer getHandle(Player player) { 71 | if (!(player instanceof CraftPlayer)) throw new UnsupportedOperationException(NO_CRAFTBUKKIT_MSG); 72 | return ((CraftPlayer) player).getHandle(); 73 | } 74 | 75 | public static EntityLiving getHandle(LivingEntity entity) { 76 | if (!(entity instanceof CraftLivingEntity)) throw new UnsupportedOperationException(NO_CRAFTBUKKIT_MSG); 77 | return ((CraftLivingEntity) entity).getHandle(); 78 | } 79 | 80 | public static MinecraftServer getServer() { 81 | Server server = Bukkit.getServer(); 82 | if (!(server instanceof CraftServer)) throw new UnsupportedOperationException(NO_CRAFTBUKKIT_MSG); 83 | return ((CraftServer) server).getServer(); 84 | } 85 | 86 | public static WorldServer getHandle(World world) { 87 | if (!(world instanceof CraftWorld)) throw new UnsupportedOperationException(NO_CRAFTBUKKIT_MSG); 88 | return ((CraftWorld) world).getHandle(); 89 | } 90 | 91 | public static HumanNPCHook getHandle(HumanNPC npc) { 92 | EntityPlayer player = getHandle(npc.getEntity()); 93 | if (player instanceof EntityNPCPlayer) return null; 94 | return ((EntityNPCPlayer) player).getHook(); 95 | } 96 | 97 | public static LivingNPCHook getHook(LivingNPC npc) { 98 | if (getHandle((HumanNPC) npc) != null) return getHandle((HumanNPC) npc); 99 | EntityLiving entity = getHandle(npc.getEntity()); 100 | if (entity instanceof LivingHookable) { 101 | return ((LivingHookable) entity).getHook(); 102 | } 103 | return null; 104 | } 105 | 106 | public static void sendToAll(Packet packet) { 107 | for (Player p : Bukkit.getOnlinePlayers()) { 108 | getHandle(p).playerConnection.sendPacket(packet); 109 | } 110 | } 111 | 112 | private static final Cache properties = CacheBuilder.newBuilder() 113 | .expireAfterAccess(5, TimeUnit.MINUTES) 114 | .build(new CacheLoader() { 115 | 116 | @Override 117 | public GameProfile load(UUID uuid) throws Exception { 118 | return MinecraftServer.getServer().av().fillProfileProperties(new GameProfile(uuid, null), true); 119 | } 120 | }); 121 | 122 | public static void setSkin(GameProfile profile, UUID skinId) { 123 | GameProfile skinProfile; 124 | if (Bukkit.getPlayer(skinId) != null) { 125 | skinProfile = getHandle(Bukkit.getPlayer(skinId)).getProfile(); 126 | } else { 127 | skinProfile = properties.getUnchecked(skinId); 128 | } 129 | if (skinProfile.getProperties().containsKey("textures")) { 130 | profile.getProperties().removeAll("textures"); 131 | profile.getProperties().putAll("textures", skinProfile.getProperties().get("textures")); 132 | } else { 133 | NPCLog.debug("Skin with uuid not found: " + skinId); 134 | } 135 | } 136 | } -------------------------------------------------------------------------------- /nms-v1_7_R3/src/main/java/net/techcable/npclib/nms/versions/v1_7_R3/NPCHook.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_7_R3; 2 | 3 | import lombok.*; 4 | 5 | import net.minecraft.server.v1_7_R3.Entity; 6 | import net.techcable.npclib.NPC; 7 | import net.techcable.npclib.nms.INPCHook; 8 | 9 | @Getter 10 | @RequiredArgsConstructor 11 | public class NPCHook implements INPCHook { 12 | 13 | private final NPC npc; 14 | protected Entity nmsEntity; 15 | 16 | @Override 17 | public void onDespawn() { 18 | nmsEntity = null; 19 | } 20 | 21 | @Override 22 | public org.bukkit.entity.Entity getEntity() { 23 | return nmsEntity == null ? null : nmsEntity.getBukkitEntity(); 24 | } 25 | } -------------------------------------------------------------------------------- /nms-v1_7_R3/src/main/java/net/techcable/npclib/nms/versions/v1_7_R3/ai/NPCPath.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_7_R3.ai; 2 | 3 | import net.minecraft.server.v1_7_R3.EntityHuman; 4 | import net.minecraft.server.v1_7_R3.EntityLiving; 5 | import net.minecraft.server.v1_7_R3.MathHelper; 6 | import net.minecraft.server.v1_7_R3.PathEntity; 7 | import net.minecraft.server.v1_7_R3.Vec3D; 8 | import net.techcable.npclib.LivingNPC; 9 | import net.techcable.npclib.ai.AIEnvironment; 10 | import net.techcable.npclib.ai.AITask; 11 | import net.techcable.npclib.nms.versions.v1_7_R3.NMS; 12 | 13 | import org.bukkit.Location; 14 | 15 | /** 16 | * A npc pathing class 17 | *

18 | * Taken from "https://github.com/lenis0012/NPCFactory/blob/master/src/main/java/com/lenis0012/bukkit/npc/NPCPath.java" 19 | * It is MIT Licensed by lenis0012 20 | */ 21 | public class NPCPath implements AITask { 22 | 23 | private final LivingNPC npc; 24 | private final PathEntity nmsPath; 25 | private final double speed; 26 | private double progress; 27 | private Vec3D currentPoint; 28 | 29 | protected NPCPath(LivingNPC npc, PathEntity nmsPath, double speed) { 30 | this.npc = npc; 31 | this.nmsPath = nmsPath; 32 | this.speed = speed; 33 | this.progress = 0.0; 34 | this.currentPoint = nmsPath.a(getEntity()); // Just base it off signature 35 | } 36 | 37 | public void tick(AIEnvironment environment) { 38 | int current = MathHelper.floor(progress); 39 | double d = progress - current; 40 | double d1 = 1 - d; 41 | if (d + speed < 1) { 42 | double dx = (currentPoint.a - getEntity().locX) * speed; // a is x 43 | double dz = (currentPoint.c - getEntity().locZ) * speed; // c is z 44 | 45 | getEntity().move(dx, 0, dz); 46 | if (getEntity() instanceof EntityHuman) ((EntityHuman) getEntity()).checkMovement(dx, 0, dz); 47 | progress += speed; 48 | } else { 49 | //First complete old point. 50 | double bx = (currentPoint.a - getEntity().locX) * d1; 51 | double bz = (currentPoint.c - getEntity().locZ) * d1; 52 | 53 | //Check if new point exists 54 | nmsPath.a(); // Increments the second field (first int field) 55 | if (!nmsPath.b()) { // Checks if first field is greater than second field 56 | //Append new movement 57 | this.currentPoint = nmsPath.a(getEntity()); // Just base it off signature 58 | double d2 = speed - d1; 59 | 60 | double dx = bx + ((currentPoint.a - getEntity().locX) * d2); // a -> x 61 | double dy = currentPoint.b - getEntity().locY; //Jump if needed to reach next block. // b -> y 62 | double dz = bz + ((currentPoint.c - getEntity().locZ) * d2); // c -> z 63 | 64 | getEntity().move(dx, dy, dz); 65 | if (getEntity() instanceof EntityHuman) ((EntityHuman) getEntity()).checkMovement(dx, dy, dz); 66 | progress += speed; 67 | } else { 68 | //Complete final movement 69 | getEntity().move(bx, 0, bz); 70 | if (getEntity() instanceof EntityHuman) ((EntityHuman) getEntity()).checkMovement(bx, 0, bz); 71 | environment.removeTask(this); 72 | } 73 | } 74 | } 75 | 76 | public static NPCPath find(final LivingNPC npc, Location to, double range, double speed) { 77 | if (speed > 1) { 78 | throw new IllegalArgumentException("Speed cannot be higher than 1!"); 79 | } 80 | 81 | final EntityLiving entity = NMS.getHandle(npc.getEntity()); 82 | 83 | try { 84 | PathEntity path = entity.world.a(entity, to.getBlockX(), to.getBlockY(), to.getBlockZ(), (float) range, true, false, false, true); 85 | if (path != null) { 86 | return new NPCPath(npc, path, speed); 87 | } else { 88 | return null; 89 | } 90 | } catch (Exception e) { 91 | return null; 92 | } 93 | } 94 | 95 | public EntityLiving getEntity() { 96 | return NMS.getHandle(npc.getEntity()); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /nms-v1_7_R3/src/main/java/net/techcable/npclib/nms/versions/v1_7_R3/entity/EntityNPCPlayer.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_7_R3.entity; 2 | 3 | import lombok.*; 4 | 5 | import java.util.UUID; 6 | 7 | import net.minecraft.server.v1_7_R3.DamageSource; 8 | import net.minecraft.server.v1_7_R3.EntityPlayer; 9 | import net.minecraft.server.v1_7_R3.EnumGamemode; 10 | import net.minecraft.server.v1_7_R3.PlayerInteractManager; 11 | import net.minecraft.util.com.mojang.authlib.GameProfile; 12 | import net.techcable.npclib.HumanNPC; 13 | import net.techcable.npclib.nms.versions.v1_7_R3.HumanNPCHook; 14 | import net.techcable.npclib.nms.versions.v1_7_R3.NMS; 15 | import net.techcable.npclib.nms.versions.v1_7_R3.network.NPCConnection; 16 | 17 | import org.bukkit.Location; 18 | 19 | @Getter 20 | public class EntityNPCPlayer extends EntityPlayer { 21 | 22 | private final HumanNPC npc; 23 | @Setter 24 | private HumanNPCHook hook; 25 | 26 | public EntityNPCPlayer(HumanNPC npc, Location location) { 27 | super(NMS.getServer(), NMS.getHandle(location.getWorld()), makeProfile(npc), new PlayerInteractManager(NMS.getHandle(location.getWorld()))); 28 | playerInteractManager.b(EnumGamemode.SURVIVAL); //MCP = initializeGameType ---- SRG=func_73077_b 29 | this.npc = npc; 30 | playerConnection = new NPCConnection(this); 31 | 32 | setPosition(location.getX(), location.getY(), location.getZ()); 33 | } 34 | 35 | @Override 36 | public boolean damageEntity(DamageSource source, float damage) { 37 | if (npc.isProtected()) { 38 | return false; 39 | } 40 | return super.damageEntity(source, damage); 41 | } 42 | 43 | private static GameProfile makeProfile(HumanNPC npc) { 44 | GameProfile profile = new GameProfile(UUID.randomUUID(), npc.getName()); 45 | NMS.setSkin(profile, npc.getSkin()); 46 | return profile; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /nms-v1_7_R3/src/main/java/net/techcable/npclib/nms/versions/v1_7_R3/network/NPCConnection.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_7_R3.network; 2 | 3 | import lombok.*; 4 | 5 | import net.minecraft.server.v1_7_R3.EntityPlayer; 6 | import net.minecraft.server.v1_7_R3.Packet; 7 | import net.minecraft.server.v1_7_R3.PlayerConnection; 8 | import net.techcable.npclib.nms.versions.v1_7_R3.NMS; 9 | 10 | @Getter 11 | public class NPCConnection extends PlayerConnection { 12 | 13 | public NPCConnection(EntityPlayer npc) { 14 | super(NMS.getServer(), new NPCNetworkManager(), npc); 15 | } 16 | 17 | @Override 18 | public void sendPacket(Packet packet) { 19 | //Don't send packets to an npc 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /nms-v1_7_R3/src/main/java/net/techcable/npclib/nms/versions/v1_7_R3/network/NPCNetworkManager.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_7_R3.network; 2 | 3 | import lombok.*; 4 | 5 | import java.lang.reflect.Field; 6 | 7 | import net.minecraft.server.v1_7_R3.NetworkManager; 8 | import net.techcable.npclib.utils.Reflection; 9 | 10 | @Getter 11 | public class NPCNetworkManager extends NetworkManager { 12 | 13 | public NPCNetworkManager() { 14 | super(false); //MCP = isClientSide 15 | Field channel = Reflection.makeField(NetworkManager.class, "m"); //MCP = channel 16 | Field address = Reflection.makeField(NetworkManager.class, "n"); //MCP = socketAddress 17 | 18 | Reflection.setField(channel, this, new NullChannel()); 19 | Reflection.setField(address, this, new NullSocketAddress()); 20 | 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /nms-v1_7_R3/src/main/java/net/techcable/npclib/nms/versions/v1_7_R3/network/NullChannel.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_7_R3.network; 2 | 3 | import lombok.*; 4 | 5 | import java.net.SocketAddress; 6 | 7 | import net.minecraft.util.io.netty.channel.AbstractChannel; 8 | import net.minecraft.util.io.netty.channel.ChannelConfig; 9 | import net.minecraft.util.io.netty.channel.ChannelMetadata; 10 | import net.minecraft.util.io.netty.channel.ChannelOutboundBuffer; 11 | import net.minecraft.util.io.netty.channel.EventLoop; 12 | 13 | @Getter 14 | public class NullChannel extends AbstractChannel { 15 | 16 | public NullChannel() { 17 | super(null); 18 | } 19 | 20 | @Override 21 | public ChannelConfig config() { 22 | return null; 23 | } 24 | 25 | @Override 26 | public boolean isActive() { 27 | return false; 28 | } 29 | 30 | @Override 31 | public boolean isOpen() { 32 | return false; 33 | } 34 | 35 | @Override 36 | public ChannelMetadata metadata() { 37 | return null; 38 | } 39 | 40 | @Override 41 | protected void doBeginRead() throws Exception { 42 | } 43 | 44 | @Override 45 | protected void doBind(SocketAddress arg0) throws Exception { 46 | } 47 | 48 | @Override 49 | protected void doClose() throws Exception { 50 | } 51 | 52 | @Override 53 | protected void doDisconnect() throws Exception { 54 | } 55 | 56 | @Override 57 | protected void doWrite(ChannelOutboundBuffer arg0) throws Exception { 58 | } 59 | 60 | @Override 61 | protected boolean isCompatible(EventLoop arg0) { 62 | return false; 63 | } 64 | 65 | @Override 66 | protected SocketAddress localAddress0() { 67 | return null; 68 | } 69 | 70 | @Override 71 | protected AbstractUnsafe newUnsafe() { 72 | return null; 73 | } 74 | 75 | @Override 76 | protected SocketAddress remoteAddress0() { 77 | return null; 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /nms-v1_7_R3/src/main/java/net/techcable/npclib/nms/versions/v1_7_R3/network/NullSocketAddress.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_7_R3.network; 2 | 3 | import java.net.SocketAddress; 4 | 5 | public class NullSocketAddress extends SocketAddress { 6 | 7 | private static final long serialVersionUID = 1L; 8 | 9 | } 10 | -------------------------------------------------------------------------------- /nms-v1_7_R4/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /nms-v1_7_R4/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | npclib-nms-v1_8_R1 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /nms-v1_7_R4/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 3 | org.eclipse.jdt.core.compiler.compliance=1.7 4 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 5 | org.eclipse.jdt.core.compiler.source=1.7 6 | -------------------------------------------------------------------------------- /nms-v1_7_R4/.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /nms-v1_7_R4/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 4.0.0 5 | 6 | 7 | net.techcable.npclib 8 | parent 9 | 2.0.0-beta2-SNAPSHOT 10 | ../pom.xml 11 | 12 | 13 | nms-v1_7_R4 14 | 15 | 16 | 17 | net.techcable.npclib 18 | api 19 | ${parent.version} 20 | provided 21 | 22 | 23 | org.bukkit 24 | craftbukkit 25 | 1.7.10-R0.1-SNAPSHOT 26 | provided 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /nms-v1_7_R4/src/main/java/net/techcable/npclib/nms/versions/v1_7_R4/NMS.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_7_R4; 2 | 3 | import java.util.Collection; 4 | import java.util.List; 5 | import java.util.UUID; 6 | import java.util.concurrent.TimeUnit; 7 | 8 | import com.google.common.cache.Cache; 9 | import com.google.common.cache.CacheBuilder; 10 | import com.google.common.cache.CacheLoader; 11 | 12 | import net.minecraft.server.v1_7_R4.EntityLiving; 13 | import net.minecraft.server.v1_7_R4.EntityPlayer; 14 | import net.minecraft.server.v1_7_R4.MinecraftServer; 15 | import net.minecraft.server.v1_7_R4.Packet; 16 | import net.minecraft.server.v1_7_R4.WorldServer; 17 | import net.minecraft.util.com.mojang.authlib.GameProfile; 18 | import net.techcable.npclib.HumanNPC; 19 | import net.techcable.npclib.LivingNPC; 20 | import net.techcable.npclib.NPC; 21 | import net.techcable.npclib.nms.IHumanNPCHook; 22 | import net.techcable.npclib.nms.ILivingNPCHook; 23 | import net.techcable.npclib.nms.versions.v1_7_R4.entity.EntityNPCPlayer; 24 | import net.techcable.npclib.utils.NPCLog; 25 | 26 | import org.bukkit.Bukkit; 27 | import org.bukkit.Location; 28 | import org.bukkit.Server; 29 | import org.bukkit.World; 30 | import org.bukkit.craftbukkit.v1_7_R4.CraftServer; 31 | import org.bukkit.craftbukkit.v1_7_R4.CraftWorld; 32 | import org.bukkit.craftbukkit.v1_7_R4.entity.CraftLivingEntity; 33 | import org.bukkit.craftbukkit.v1_7_R4.entity.CraftPlayer; 34 | import org.bukkit.entity.EntityType; 35 | import org.bukkit.entity.LivingEntity; 36 | import org.bukkit.entity.Player; 37 | 38 | public class NMS implements net.techcable.npclib.nms.NMS { 39 | 40 | private static NMS instance; 41 | 42 | public NMS() { 43 | if (instance == null) instance = this; 44 | } 45 | 46 | public static NMS getInstance() { 47 | return instance; 48 | } 49 | 50 | @Override 51 | public IHumanNPCHook spawnHumanNPC(Location toSpawn, HumanNPC npc) { 52 | return new HumanNPCHook(npc, toSpawn); 53 | } 54 | 55 | @Override 56 | public void onJoin(Player joined, Collection npcs) { 57 | for (NPC npc : npcs) { 58 | if (!(npc instanceof HumanNPC)) continue; 59 | HumanNPCHook hook = getHandle((HumanNPC) npc); 60 | if (hook == null) continue; 61 | hook.onJoin(joined); 62 | } 63 | } 64 | 65 | // UTILS 66 | public static final String NO_CRAFTBUKKIT_MSG = "Non-CraftBukkit implementations are unsupported"; 67 | 68 | public static EntityPlayer getHandle(Player player) { 69 | if (!(player instanceof CraftPlayer)) throw new UnsupportedOperationException(NO_CRAFTBUKKIT_MSG); 70 | return ((CraftPlayer) player).getHandle(); 71 | } 72 | 73 | public static EntityLiving getHandle(LivingEntity player) { 74 | if (!(player instanceof CraftLivingEntity)) throw new UnsupportedOperationException(NO_CRAFTBUKKIT_MSG); 75 | return ((CraftLivingEntity) player).getHandle(); 76 | } 77 | 78 | public static MinecraftServer getServer() { 79 | Server server = Bukkit.getServer(); 80 | if (!(server instanceof CraftServer)) throw new UnsupportedOperationException(NO_CRAFTBUKKIT_MSG); 81 | return ((CraftServer) server).getServer(); 82 | } 83 | 84 | public static WorldServer getHandle(World world) { 85 | if (!(world instanceof CraftWorld)) throw new UnsupportedOperationException(NO_CRAFTBUKKIT_MSG); 86 | return ((CraftWorld) world).getHandle(); 87 | } 88 | 89 | public static HumanNPCHook getHandle(HumanNPC npc) { 90 | EntityPlayer player = getHandle(npc.getEntity()); 91 | if (player instanceof EntityNPCPlayer) return null; 92 | return ((EntityNPCPlayer) player).getHook(); 93 | } 94 | 95 | public static void sendToAll(Packet packet) { 96 | for (EntityPlayer p : (List) MinecraftServer.getServer().getPlayerList().players) { 97 | p.playerConnection.sendPacket(packet); 98 | } 99 | } 100 | private static final Cache properties = CacheBuilder.newBuilder() 101 | .expireAfterAccess(5, TimeUnit.MINUTES) 102 | .build(new CacheLoader() { 103 | 104 | @Override 105 | public GameProfile load(UUID uuid) throws Exception { 106 | return MinecraftServer.getServer().av().fillProfileProperties(new GameProfile(uuid, null), true); 107 | } 108 | }); 109 | 110 | public static void setSkin(GameProfile profile, UUID skinId) { 111 | GameProfile skinProfile; 112 | if (Bukkit.getPlayer(skinId) != null) { 113 | skinProfile = getHandle(Bukkit.getPlayer(skinId)).getProfile(); 114 | } else { 115 | skinProfile = properties.getUnchecked(skinId); 116 | } 117 | if (skinProfile.getProperties().containsKey("textures")) { 118 | profile.getProperties().removeAll("textures"); 119 | profile.getProperties().putAll("textures", skinProfile.getProperties().get("textures")); 120 | } else { 121 | NPCLog.debug("Skin with uuid not found: " + skinId); 122 | } 123 | } 124 | } -------------------------------------------------------------------------------- /nms-v1_7_R4/src/main/java/net/techcable/npclib/nms/versions/v1_7_R4/NPCHook.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_7_R4; 2 | 3 | import lombok.*; 4 | 5 | import net.minecraft.server.v1_7_R4.Entity; 6 | import net.techcable.npclib.NPC; 7 | import net.techcable.npclib.nms.INPCHook; 8 | 9 | @Getter 10 | @RequiredArgsConstructor 11 | public class NPCHook implements INPCHook { 12 | 13 | private final NPC npc; 14 | protected Entity nmsEntity; 15 | 16 | @Override 17 | public void onDespawn() { 18 | nmsEntity = null; 19 | } 20 | 21 | @Override 22 | public org.bukkit.entity.Entity getEntity() { 23 | return nmsEntity == null ? null : nmsEntity.getBukkitEntity(); 24 | } 25 | } -------------------------------------------------------------------------------- /nms-v1_7_R4/src/main/java/net/techcable/npclib/nms/versions/v1_7_R4/ProtocolHack.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_7_R4; 2 | 3 | import java.lang.reflect.Method; 4 | 5 | import net.minecraft.server.v1_7_R4.EntityPlayer; 6 | import net.minecraft.server.v1_7_R4.Packet; 7 | import net.techcable.npclib.utils.Reflection; 8 | 9 | public class ProtocolHack { 10 | 11 | private ProtocolHack() { 12 | } 13 | 14 | public static boolean isProtocolHack() { 15 | try { 16 | Class.forName("org.spigotmc.ProtocolData"); 17 | return true; 18 | } catch (ClassNotFoundException ex) { 19 | return false; 20 | } 21 | } 22 | 23 | private static final Method addPlayerMethod = Reflection.makeMethod(getPlayerInfoClass(), "addPlayer", EntityPlayer.class); 24 | 25 | public static Packet newPlayerInfoDataAdd(EntityPlayer player) { 26 | return Reflection.callMethod(addPlayerMethod, null, player); 27 | } 28 | 29 | private static final Method removePlayerMethod = Reflection.makeMethod(getPlayerInfoClass(), "removePlayer", EntityPlayer.class); 30 | 31 | public static Packet newPlayerInfoDataRemove(EntityPlayer player) { 32 | return Reflection.callMethod(removePlayerMethod, null, player); 33 | } 34 | 35 | public static Class getPlayerInfoClass() { 36 | try { 37 | return Class.forName("net.minecraft.server.v1_7_R4.PacketPlayOutPlayerInfo"); 38 | } catch (Exception ex) { 39 | throw new RuntimeException(ex); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /nms-v1_7_R4/src/main/java/net/techcable/npclib/nms/versions/v1_7_R4/ai/NPCPath.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_7_R4.ai; 2 | 3 | import net.minecraft.server.v1_7_R4.EntityHuman; 4 | import net.minecraft.server.v1_7_R4.EntityLiving; 5 | import net.minecraft.server.v1_7_R4.MathHelper; 6 | import net.minecraft.server.v1_7_R4.PathEntity; 7 | import net.minecraft.server.v1_7_R4.Vec3D; 8 | import net.techcable.npclib.LivingNPC; 9 | import net.techcable.npclib.ai.AIEnvironment; 10 | import net.techcable.npclib.ai.AITask; 11 | import net.techcable.npclib.nms.versions.v1_7_R4.NMS; 12 | 13 | import org.bukkit.Location; 14 | 15 | /** 16 | * A npc pathing class 17 | *

18 | * Taken from "https://github.com/lenis0012/NPCFactory/blob/master/src/main/java/com/lenis0012/bukkit/npc/NPCPath.java" 19 | * It is MIT Licensed by lenis0012 20 | */ 21 | public class NPCPath implements AITask { 22 | 23 | private final LivingNPC npc; 24 | private final PathEntity nmsPath; 25 | private final double speed; 26 | private double progress; 27 | private Vec3D currentPoint; 28 | 29 | protected NPCPath(LivingNPC npc, PathEntity nmsPath, double speed) { 30 | this.npc = npc; 31 | this.nmsPath = nmsPath; 32 | this.speed = speed; 33 | this.progress = 0.0; 34 | this.currentPoint = nmsPath.a(getEntity()); // Just base it off signature 35 | } 36 | 37 | public void tick(AIEnvironment environment) { 38 | int current = MathHelper.floor(progress); 39 | double d = progress - current; 40 | double d1 = 1 - d; 41 | if (d + speed < 1) { 42 | double dx = (currentPoint.a - getEntity().locX) * speed; // a is x 43 | double dz = (currentPoint.c - getEntity().locZ) * speed; // c is z 44 | 45 | getEntity().move(dx, 0, dz); 46 | if (getEntity() instanceof EntityHuman) ((EntityHuman) getEntity()).checkMovement(dx, 0, dz); 47 | progress += speed; 48 | } else { 49 | //First complete old point. 50 | double bx = (currentPoint.a - getEntity().locX) * d1; 51 | double bz = (currentPoint.c - getEntity().locZ) * d1; 52 | 53 | //Check if new point exists 54 | nmsPath.a(); // Increments the second field (first int field) 55 | if (!nmsPath.b()) { // Checks if first field is greater than second field 56 | //Append new movement 57 | this.currentPoint = nmsPath.a(getEntity()); // Just base it off signature 58 | double d2 = speed - d1; 59 | 60 | double dx = bx + ((currentPoint.a - getEntity().locX) * d2); // a -> x 61 | double dy = currentPoint.b - getEntity().locY; //Jump if needed to reach next block. // b -> y 62 | double dz = bz + ((currentPoint.c - getEntity().locZ) * d2); // c -> z 63 | 64 | getEntity().move(dx, dy, dz); 65 | if (getEntity() instanceof EntityHuman) ((EntityHuman) getEntity()).checkMovement(dx, dy, dz); 66 | progress += speed; 67 | } else { 68 | //Complete final movement 69 | getEntity().move(bx, 0, bz); 70 | if (getEntity() instanceof EntityHuman) ((EntityHuman) getEntity()).checkMovement(bx, 0, bz); 71 | environment.removeTask(this); 72 | } 73 | } 74 | } 75 | 76 | public static NPCPath find(final LivingNPC npc, Location to, double range, double speed) { 77 | if (speed > 1) { 78 | throw new IllegalArgumentException("Speed cannot be higher than 1!"); 79 | } 80 | 81 | final EntityLiving entity = NMS.getHandle(npc.getEntity()); 82 | 83 | try { 84 | PathEntity path = entity.world.a(entity, to.getBlockX(), to.getBlockY(), to.getBlockZ(), (float) range, true, false, false, true); 85 | if (path != null) { 86 | return new NPCPath(npc, path, speed); 87 | } else { 88 | return null; 89 | } 90 | } catch (Exception e) { 91 | return null; 92 | } 93 | } 94 | 95 | public EntityLiving getEntity() { 96 | return NMS.getHandle(npc.getEntity()); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /nms-v1_7_R4/src/main/java/net/techcable/npclib/nms/versions/v1_7_R4/entity/EntityNPCPlayer.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_7_R4.entity; 2 | 3 | import lombok.*; 4 | 5 | import java.util.UUID; 6 | 7 | import net.minecraft.server.v1_7_R4.DamageSource; 8 | import net.minecraft.server.v1_7_R4.EntityPlayer; 9 | import net.minecraft.server.v1_7_R4.EnumGamemode; 10 | import net.minecraft.server.v1_7_R4.PlayerInteractManager; 11 | import net.minecraft.util.com.mojang.authlib.GameProfile; 12 | import net.techcable.npclib.HumanNPC; 13 | import net.techcable.npclib.nms.versions.v1_7_R4.HumanNPCHook; 14 | import net.techcable.npclib.nms.versions.v1_7_R4.NMS; 15 | import net.techcable.npclib.nms.versions.v1_7_R4.network.NPCConnection; 16 | 17 | import org.bukkit.Location; 18 | 19 | @Getter 20 | public class EntityNPCPlayer extends EntityPlayer { 21 | 22 | private final HumanNPC npc; 23 | @Setter 24 | private HumanNPCHook hook; 25 | 26 | public EntityNPCPlayer(HumanNPC npc, Location location) { 27 | super(NMS.getServer(), NMS.getHandle(location.getWorld()), makeProfile(npc), new PlayerInteractManager(NMS.getHandle(location.getWorld()))); 28 | playerInteractManager.b(EnumGamemode.SURVIVAL); //MCP = initializeGameType ---- SRG=func_73077_b 29 | this.npc = npc; 30 | playerConnection = new NPCConnection(this); 31 | 32 | setPosition(location.getX(), location.getY(), location.getZ()); 33 | } 34 | 35 | @Override 36 | public boolean damageEntity(DamageSource source, float damage) { 37 | if (npc.isProtected()) { 38 | return false; 39 | } 40 | return super.damageEntity(source, damage); 41 | } 42 | 43 | private static GameProfile makeProfile(HumanNPC npc) { 44 | GameProfile profile = new GameProfile(UUID.randomUUID(), npc.getName()); 45 | NMS.setSkin(profile, npc.getSkin()); 46 | return profile; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /nms-v1_7_R4/src/main/java/net/techcable/npclib/nms/versions/v1_7_R4/network/NPCConnection.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_7_R4.network; 2 | 3 | import lombok.*; 4 | 5 | import net.minecraft.server.v1_7_R4.EntityPlayer; 6 | import net.minecraft.server.v1_7_R4.Packet; 7 | import net.minecraft.server.v1_7_R4.PlayerConnection; 8 | import net.techcable.npclib.nms.versions.v1_7_R4.NMS; 9 | 10 | @Getter 11 | public class NPCConnection extends PlayerConnection { 12 | 13 | public NPCConnection(EntityPlayer npc) { 14 | super(NMS.getServer(), new NPCNetworkManager(), npc); 15 | } 16 | 17 | @Override 18 | public void sendPacket(Packet packet) { 19 | //Don't send packets to an npc 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /nms-v1_7_R4/src/main/java/net/techcable/npclib/nms/versions/v1_7_R4/network/NPCNetworkManager.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_7_R4.network; 2 | 3 | import lombok.*; 4 | 5 | import java.lang.reflect.Field; 6 | 7 | import net.minecraft.server.v1_7_R4.NetworkManager; 8 | import net.techcable.npclib.utils.Reflection; 9 | 10 | @Getter 11 | public class NPCNetworkManager extends NetworkManager { 12 | 13 | public NPCNetworkManager() { 14 | super(false); //MCP = isClientSide 15 | 16 | Field channel = Reflection.makeField(NetworkManager.class, "m"); //MCP = channel 17 | Field address = Reflection.makeField(NetworkManager.class, "n"); //MCP = address 18 | 19 | Reflection.setField(channel, this, new NullChannel()); 20 | Reflection.setField(address, this, new NullSocketAddress()); 21 | 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /nms-v1_7_R4/src/main/java/net/techcable/npclib/nms/versions/v1_7_R4/network/NullChannel.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_7_R4.network; 2 | 3 | import lombok.*; 4 | 5 | import java.net.SocketAddress; 6 | 7 | import net.minecraft.util.io.netty.channel.AbstractChannel; 8 | import net.minecraft.util.io.netty.channel.ChannelConfig; 9 | import net.minecraft.util.io.netty.channel.ChannelMetadata; 10 | import net.minecraft.util.io.netty.channel.ChannelOutboundBuffer; 11 | import net.minecraft.util.io.netty.channel.EventLoop; 12 | 13 | @Getter 14 | public class NullChannel extends AbstractChannel { 15 | 16 | public NullChannel() { 17 | super(null); 18 | } 19 | 20 | @Override 21 | public ChannelConfig config() { 22 | return null; 23 | } 24 | 25 | @Override 26 | public boolean isActive() { 27 | return false; 28 | } 29 | 30 | @Override 31 | public boolean isOpen() { 32 | return false; 33 | } 34 | 35 | @Override 36 | public ChannelMetadata metadata() { 37 | return null; 38 | } 39 | 40 | @Override 41 | protected void doBeginRead() throws Exception { 42 | } 43 | 44 | @Override 45 | protected void doBind(SocketAddress arg0) throws Exception { 46 | } 47 | 48 | @Override 49 | protected void doClose() throws Exception { 50 | } 51 | 52 | @Override 53 | protected void doDisconnect() throws Exception { 54 | } 55 | 56 | @Override 57 | protected void doWrite(ChannelOutboundBuffer arg0) throws Exception { 58 | } 59 | 60 | @Override 61 | protected boolean isCompatible(EventLoop arg0) { 62 | return false; 63 | } 64 | 65 | @Override 66 | protected SocketAddress localAddress0() { 67 | return null; 68 | } 69 | 70 | @Override 71 | protected AbstractUnsafe newUnsafe() { 72 | return null; 73 | } 74 | 75 | @Override 76 | protected SocketAddress remoteAddress0() { 77 | return null; 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /nms-v1_7_R4/src/main/java/net/techcable/npclib/nms/versions/v1_7_R4/network/NullSocketAddress.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_7_R4.network; 2 | 3 | import java.net.SocketAddress; 4 | 5 | public class NullSocketAddress extends SocketAddress { 6 | 7 | private static final long serialVersionUID = 1L; 8 | 9 | } 10 | -------------------------------------------------------------------------------- /nms-v1_8_R1/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /nms-v1_8_R1/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | npclib-nms-v1_8_R1 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /nms-v1_8_R1/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 3 | org.eclipse.jdt.core.compiler.compliance=1.7 4 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 5 | org.eclipse.jdt.core.compiler.source=1.7 6 | -------------------------------------------------------------------------------- /nms-v1_8_R1/.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /nms-v1_8_R1/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 4.0.0 5 | 6 | 7 | net.techcable.npclib 8 | parent 9 | 2.0.0-beta2-SNAPSHOT 10 | ../pom.xml 11 | 12 | 13 | nms-v1_8_R1 14 | 15 | 16 | 17 | net.techcable.npclib 18 | api 19 | ${parent.version} 20 | provided 21 | 22 | 23 | org.bukkit 24 | craftbukkit 25 | 1.8-R0.1-SNAPSHOT 26 | provided 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /nms-v1_8_R1/src/main/java/net/techcable/npclib/nms/versions/v1_8_R1/HumanNPCHook.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_8_R1; 2 | 3 | import java.lang.reflect.Field; 4 | import java.lang.reflect.Modifier; 5 | import java.util.UUID; 6 | 7 | import net.minecraft.server.v1_8_R1.EntityPlayer; 8 | import net.minecraft.server.v1_8_R1.EnumPlayerInfoAction; 9 | import net.minecraft.server.v1_8_R1.Packet; 10 | import net.minecraft.server.v1_8_R1.PacketPlayOutAnimation; 11 | import net.minecraft.server.v1_8_R1.PacketPlayOutPlayerInfo; 12 | import net.techcable.npclib.Animation; 13 | import net.techcable.npclib.HumanNPC; 14 | import net.techcable.npclib.nms.IHumanNPCHook; 15 | import net.techcable.npclib.nms.versions.v1_8_R1.entity.EntityNPCPlayer; 16 | import net.techcable.npclib.utils.Reflection; 17 | 18 | import org.bukkit.Bukkit; 19 | import org.bukkit.Location; 20 | import org.bukkit.entity.EntityType; 21 | import org.bukkit.entity.Player; 22 | 23 | import com.google.common.base.Preconditions; 24 | import com.mojang.authlib.GameProfile; 25 | 26 | public class HumanNPCHook extends LivingNPCHook implements IHumanNPCHook { 27 | 28 | public HumanNPCHook(HumanNPC npc, Location toSpawn) { 29 | super(npc, toSpawn, EntityType.PLAYER); 30 | getNmsEntity().setHook(this); 31 | getNmsEntity().getWorld().players.remove(getNmsEntity()); 32 | } 33 | 34 | @Override 35 | public void setSkin(UUID id) { 36 | NMS.setSkin(getNmsEntity().getProfile(), id); 37 | refreshPlayerInfo(); 38 | } 39 | 40 | private boolean shownInTabList; 41 | 42 | @Override 43 | public void showInTablist() { 44 | if (shownInTabList) return; 45 | PacketPlayOutPlayerInfo packet = new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.ADD_PLAYER, getNmsEntity()); 46 | NMS.sendToAll(packet); 47 | shownInTabList = true; 48 | } 49 | 50 | @Override 51 | public void hideFromTablist() { 52 | if (!shownInTabList) return; 53 | PacketPlayOutPlayerInfo packet = new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.REMOVE_PLAYER, getNmsEntity()); 54 | NMS.sendToAll(packet); 55 | shownInTabList = false; 56 | } 57 | 58 | public void refreshPlayerInfo() { 59 | boolean wasShownInTabList = shownInTabList; 60 | hideFromTablist(); 61 | showInTablist(); 62 | if (!wasShownInTabList) hideFromTablist(); 63 | } 64 | 65 | @Override 66 | public void animate(Animation animation) { 67 | Packet packet; 68 | switch (animation) { 69 | case ARM_SWING : 70 | packet = new PacketPlayOutAnimation(getNmsEntity(), 0); 71 | break; 72 | case HURT : 73 | packet = new PacketPlayOutAnimation(getNmsEntity(), 1); 74 | break; 75 | case EAT : 76 | packet = new PacketPlayOutAnimation(getNmsEntity(), 3); 77 | break; 78 | case CRITICAL : 79 | packet = new PacketPlayOutAnimation(getNmsEntity(), 4); 80 | break; 81 | case MAGIC_CRITICAL : 82 | packet = new PacketPlayOutAnimation(getNmsEntity(), 5); 83 | break; 84 | default : 85 | super.animate(animation); 86 | return; 87 | } 88 | for (Player player : Bukkit.getOnlinePlayers()) { 89 | EntityPlayer handle = NMS.getHandle(player); 90 | handle.playerConnection.sendPacket(packet); 91 | } 92 | } 93 | 94 | public EntityNPCPlayer getNmsEntity() { 95 | return (EntityNPCPlayer) super.getNmsEntity(); 96 | } 97 | 98 | @Override 99 | public HumanNPC getNpc() { 100 | return (HumanNPC) super.getNpc(); 101 | } 102 | 103 | private static final Field nameField = Reflection.makeField(GameProfile.class, "name"); 104 | private static final Field modifiersField = Reflection.makeField(Field.class, "modifiers"); 105 | 106 | @Override 107 | public void setName(String s) { 108 | if (s.length() > 16) s = s.substring(0, 16); 109 | GameProfile profile = getNmsEntity().getProfile(); 110 | // Pro reflection hax 111 | nameField.setAccessible(true); // Allow access to private 112 | int modifiers = nameField.getModifiers(); 113 | modifiers = modifiers & ~Modifier.FINAL; 114 | modifiersField.setAccessible(true); 115 | Reflection.setField(modifiersField, nameField, modifiers); // Make Field.class think it isn't final 116 | Reflection.setField(nameField, profile, s); 117 | refreshPlayerInfo(); 118 | } 119 | 120 | @Override 121 | public void onDespawn() { 122 | hideFromTablist(); 123 | super.onDespawn(); 124 | } 125 | 126 | @Override 127 | protected EntityNPCPlayer spawn(Location toSpawn, EntityType type) { 128 | Preconditions.checkArgument(type == EntityType.PLAYER, "HumanNPCHook can only spawn players"); 129 | EntityNPCPlayer entity = new EntityNPCPlayer(getNpc(), toSpawn); 130 | this.nmsEntity = entity; 131 | showInTablist(); 132 | this.nmsEntity = null; 133 | return entity; 134 | } 135 | 136 | public void onJoin(Player joined) { 137 | PacketPlayOutPlayerInfo packet = new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.ADD_PLAYER, getNmsEntity()); 138 | NMS.getHandle(joined).playerConnection.sendPacket(packet); 139 | if (!shownInTabList) { 140 | PacketPlayOutPlayerInfo removePacket = new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.REMOVE_PLAYER, getNmsEntity()); 141 | NMS.getHandle(joined).playerConnection.sendPacket(packet); 142 | } 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /nms-v1_8_R1/src/main/java/net/techcable/npclib/nms/versions/v1_8_R1/NMS.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_8_R1; 2 | 3 | import java.util.Collection; 4 | import java.util.UUID; 5 | import java.util.concurrent.TimeUnit; 6 | 7 | import com.google.common.cache.CacheBuilder; 8 | import com.google.common.cache.CacheLoader; 9 | import com.google.common.cache.LoadingCache; 10 | import com.mojang.authlib.GameProfile; 11 | 12 | import net.minecraft.server.v1_8_R1.EntityLiving; 13 | import net.minecraft.server.v1_8_R1.EntityPlayer; 14 | import net.minecraft.server.v1_8_R1.MinecraftServer; 15 | import net.minecraft.server.v1_8_R1.Packet; 16 | import net.minecraft.server.v1_8_R1.WorldServer; 17 | import net.techcable.npclib.HumanNPC; 18 | import net.techcable.npclib.LivingNPC; 19 | import net.techcable.npclib.NPC; 20 | import net.techcable.npclib.nms.IHumanNPCHook; 21 | import net.techcable.npclib.nms.ILivingNPCHook; 22 | import net.techcable.npclib.nms.versions.v1_8_R1.LivingNPCHook.LivingHookable; 23 | import net.techcable.npclib.nms.versions.v1_8_R1.entity.EntityNPCPlayer; 24 | import net.techcable.npclib.utils.NPCLog; 25 | 26 | import org.bukkit.Bukkit; 27 | import org.bukkit.Location; 28 | import org.bukkit.Server; 29 | import org.bukkit.World; 30 | import org.bukkit.craftbukkit.v1_8_R1.CraftServer; 31 | import org.bukkit.craftbukkit.v1_8_R1.CraftWorld; 32 | import org.bukkit.craftbukkit.v1_8_R1.entity.CraftLivingEntity; 33 | import org.bukkit.craftbukkit.v1_8_R1.entity.CraftPlayer; 34 | import org.bukkit.entity.EntityType; 35 | import org.bukkit.entity.LivingEntity; 36 | import org.bukkit.entity.Player; 37 | 38 | public class NMS implements net.techcable.npclib.nms.NMS { 39 | 40 | private static NMS instance; 41 | 42 | public NMS() { 43 | if (instance == null) instance = this; 44 | } 45 | 46 | public static NMS getInstance() { 47 | return instance; 48 | } 49 | 50 | 51 | @Override 52 | public IHumanNPCHook spawnHumanNPC(Location toSpawn, HumanNPC npc) { 53 | return new HumanNPCHook(npc, toSpawn); 54 | } 55 | 56 | @Override 57 | public void onJoin(Player joined, Collection npcs) { 58 | for (NPC npc : npcs) { 59 | if (!(npc instanceof HumanNPC)) continue; 60 | HumanNPCHook hook = getHook((HumanNPC) npc); 61 | if (hook == null) continue; 62 | hook.onJoin(joined); 63 | } 64 | } 65 | 66 | // UTILS 67 | public static final String NO_CRAFTBUKKIT_MSG = "Non-CraftBukkit implementations are unsupported"; 68 | 69 | public static EntityPlayer getHandle(Player player) { 70 | if (!(player instanceof CraftPlayer)) throw new UnsupportedOperationException(NO_CRAFTBUKKIT_MSG); 71 | return ((CraftPlayer) player).getHandle(); 72 | } 73 | 74 | public static EntityLiving getHandle(LivingEntity player) { 75 | if (!(player instanceof CraftLivingEntity)) throw new UnsupportedOperationException(NO_CRAFTBUKKIT_MSG); 76 | return ((CraftLivingEntity) player).getHandle(); 77 | } 78 | 79 | public static MinecraftServer getServer() { 80 | Server server = Bukkit.getServer(); 81 | if (!(server instanceof CraftServer)) throw new UnsupportedOperationException(NO_CRAFTBUKKIT_MSG); 82 | return ((CraftServer) server).getServer(); 83 | } 84 | 85 | public static WorldServer getHandle(World world) { 86 | if (!(world instanceof CraftWorld)) throw new UnsupportedOperationException(NO_CRAFTBUKKIT_MSG); 87 | return ((CraftWorld) world).getHandle(); 88 | } 89 | 90 | public static HumanNPCHook getHook(HumanNPC npc) { 91 | EntityPlayer player = getHandle(npc.getEntity()); 92 | if (player instanceof EntityNPCPlayer) return null; 93 | return ((EntityNPCPlayer) player).getHook(); 94 | } 95 | 96 | public static LivingNPCHook getHook(LivingNPC npc) { 97 | if (npc instanceof HumanNPC) return getHook((HumanNPC) npc); 98 | EntityLiving entity = getHandle(npc.getEntity()); 99 | if (entity instanceof LivingHookable) return ((LivingHookable) entity).getHook(); 100 | return null; 101 | } 102 | 103 | public static void sendToAll(Packet packet) { 104 | for (Player p : Bukkit.getOnlinePlayers()) { 105 | getHandle(p).playerConnection.sendPacket(packet); 106 | } 107 | } 108 | private static final LoadingCache properties = CacheBuilder.newBuilder() 109 | .expireAfterAccess(5, TimeUnit.MINUTES) 110 | .build(new CacheLoader() { 111 | 112 | @Override 113 | public GameProfile load(UUID uuid) throws Exception { 114 | return MinecraftServer.getServer().aB().fillProfileProperties(new GameProfile(uuid, null), true); 115 | } 116 | }); 117 | 118 | public static void setSkin(GameProfile profile, UUID skinId) { 119 | GameProfile skinProfile; 120 | if (Bukkit.getPlayer(skinId) != null) { 121 | skinProfile = getHandle(Bukkit.getPlayer(skinId)).getProfile(); 122 | } else { 123 | skinProfile = properties.getUnchecked(skinId); 124 | } 125 | if (skinProfile.getProperties().containsKey("textures")) { 126 | profile.getProperties().removeAll("textures"); 127 | profile.getProperties().putAll("textures", skinProfile.getProperties().get("textures")); 128 | } else { 129 | NPCLog.debug("Skin with uuid not found: " + skinId); 130 | } 131 | } 132 | } -------------------------------------------------------------------------------- /nms-v1_8_R1/src/main/java/net/techcable/npclib/nms/versions/v1_8_R1/NPCHook.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_8_R1; 2 | 3 | import lombok.*; 4 | 5 | import net.minecraft.server.v1_8_R1.Entity; 6 | import net.techcable.npclib.NPC; 7 | import net.techcable.npclib.nms.INPCHook; 8 | 9 | @Getter 10 | @RequiredArgsConstructor 11 | public class NPCHook implements INPCHook { 12 | 13 | private final NPC npc; 14 | protected Entity nmsEntity; 15 | 16 | @Override 17 | public void onDespawn() { 18 | nmsEntity = null; 19 | } 20 | 21 | @Override 22 | public org.bukkit.entity.Entity getEntity() { 23 | return nmsEntity == null ? null : nmsEntity.getBukkitEntity(); 24 | } 25 | } -------------------------------------------------------------------------------- /nms-v1_8_R1/src/main/java/net/techcable/npclib/nms/versions/v1_8_R1/ai/NPCPath.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_8_R1.ai; 2 | 3 | import net.minecraft.server.v1_8_R1.BlockPosition; 4 | import net.minecraft.server.v1_8_R1.ChunkCache; 5 | import net.minecraft.server.v1_8_R1.EntityHuman; 6 | import net.minecraft.server.v1_8_R1.EntityLiving; 7 | import net.minecraft.server.v1_8_R1.MathHelper; 8 | import net.minecraft.server.v1_8_R1.PathEntity; 9 | import net.minecraft.server.v1_8_R1.Vec3D; 10 | import net.techcable.npclib.LivingNPC; 11 | import net.techcable.npclib.ai.AIEnvironment; 12 | import net.techcable.npclib.ai.AITask; 13 | import net.techcable.npclib.nms.versions.v1_8_R1.LivingNPCHook; 14 | import net.techcable.npclib.nms.versions.v1_8_R1.NMS; 15 | 16 | import org.bukkit.Location; 17 | 18 | /** 19 | * A npc pathing class 20 | *

21 | * Taken from "https://github.com/lenis0012/NPCFactory/blob/master/src/main/java/com/lenis0012/bukkit/npc/NPCPath.java" 22 | * It is MIT Licensed by lenis0012 23 | */ 24 | public class NPCPath implements AITask { 25 | 26 | private final LivingNPC npc; 27 | private final PathEntity nmsPath; 28 | private final double speed; 29 | private double progress; 30 | private Vec3D currentPoint; 31 | 32 | protected NPCPath(LivingNPC npc, PathEntity nmsPath, double speed) { 33 | this.npc = npc; 34 | this.nmsPath = nmsPath; 35 | this.speed = speed; 36 | this.progress = 0.0; 37 | this.currentPoint = nmsPath.a(getEntity()); // Just base it off signature 38 | } 39 | 40 | public void tick(AIEnvironment environment) { 41 | int current = MathHelper.floor(progress); 42 | double d = progress - current; 43 | double d1 = 1 - d; 44 | if (d + speed < 1) { 45 | double dx = (currentPoint.a - getEntity().locX) * speed; // a is x 46 | double dz = (currentPoint.c - getEntity().locZ) * speed; // c is z 47 | 48 | getEntity().move(dx, 0, dz); 49 | if (getEntity() instanceof EntityHuman) ((EntityHuman) getEntity()).checkMovement(dx, 0, dz); 50 | progress += speed; 51 | } else { 52 | //First complete old point. 53 | double bx = (currentPoint.a - getEntity().locX) * d1; 54 | double bz = (currentPoint.c - getEntity().locZ) * d1; 55 | 56 | //Check if new point exists 57 | nmsPath.a(); // Increments the second field (first int field) 58 | if (!nmsPath.b()) { // Checks if first field is greater than second field 59 | //Append new movement 60 | this.currentPoint = nmsPath.a(getEntity()); // Just base it off signature 61 | double d2 = speed - d1; 62 | 63 | double dx = bx + ((currentPoint.a - getEntity().locX) * d2); // a -> x 64 | double dy = currentPoint.b - getEntity().locY; //Jump if needed to reach next block. // b -> y 65 | double dz = bz + ((currentPoint.c - getEntity().locZ) * d2); // c -> z 66 | 67 | getEntity().move(dx, dy, dz); 68 | if (getEntity() instanceof EntityHuman) ((EntityHuman) getEntity()).checkMovement(dx, dy, dz); 69 | progress += speed; 70 | } else { 71 | //Complete final movement 72 | getEntity().move(bx, 0, bz); 73 | if (getEntity() instanceof EntityHuman) ((EntityHuman) getEntity()).checkMovement(bx, 0, bz); 74 | environment.removeTask(this); 75 | } 76 | } 77 | } 78 | 79 | public static NPCPath find(final LivingNPC npc, Location to, double range, double speed) { 80 | if (speed > 1) { 81 | throw new IllegalArgumentException("Speed cannot be higher than 1!"); 82 | } 83 | 84 | final EntityLiving entity = NMS.getHandle(npc.getEntity()); 85 | final LivingNPCHook hook = NMS.getHook(npc); 86 | 87 | try { 88 | BlockPosition posFrom = new BlockPosition(entity); 89 | BlockPosition posTo = new BlockPosition(to.getX(), to.getY(), to.getZ()); 90 | int k = (int) (range + 8.0); 91 | 92 | ChunkCache chunkCache = new ChunkCache(entity.world, posFrom.a(-k, -k, -k), posFrom.a(k, k, k), 0); 93 | PathEntity path = hook.getPathfinder().a(chunkCache, entity, posTo, (float) range); 94 | if (path != null) { 95 | return new NPCPath(npc, path, speed); 96 | } else { 97 | return null; 98 | } 99 | } catch (Exception e) { 100 | return null; 101 | } 102 | } 103 | 104 | public EntityLiving getEntity() { 105 | return NMS.getHandle(npc.getEntity()); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /nms-v1_8_R1/src/main/java/net/techcable/npclib/nms/versions/v1_8_R1/entity/EntityNPCPlayer.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_8_R1.entity; 2 | 3 | import lombok.*; 4 | 5 | import java.util.UUID; 6 | 7 | import net.minecraft.server.v1_8_R1.DamageSource; 8 | import net.minecraft.server.v1_8_R1.EntityPlayer; 9 | import net.minecraft.server.v1_8_R1.EnumGamemode; 10 | import net.minecraft.server.v1_8_R1.PlayerInteractManager; 11 | import net.techcable.npclib.HumanNPC; 12 | import net.techcable.npclib.nms.versions.v1_8_R1.HumanNPCHook; 13 | import net.techcable.npclib.nms.versions.v1_8_R1.NMS; 14 | import net.techcable.npclib.nms.versions.v1_8_R1.network.NPCConnection; 15 | 16 | import org.bukkit.Location; 17 | 18 | import com.mojang.authlib.GameProfile; 19 | 20 | @Getter 21 | public class EntityNPCPlayer extends EntityPlayer { 22 | 23 | private final HumanNPC npc; 24 | @Setter 25 | private HumanNPCHook hook; 26 | 27 | public EntityNPCPlayer(HumanNPC npc, Location location) { 28 | super(NMS.getServer(), NMS.getHandle(location.getWorld()), makeProfile(npc), new PlayerInteractManager(NMS.getHandle(location.getWorld()))); 29 | playerInteractManager.b(EnumGamemode.SURVIVAL); //MCP = initializeGameType ---- SRG=func_73077_b 30 | this.npc = npc; 31 | playerConnection = new NPCConnection(this); 32 | 33 | setPosition(location.getX(), location.getY(), location.getZ()); 34 | } 35 | 36 | @Override 37 | public boolean damageEntity(DamageSource source, float damage) { 38 | if (npc.isProtected()) { 39 | return false; 40 | } 41 | return super.damageEntity(source, damage); 42 | } 43 | 44 | private static GameProfile makeProfile(HumanNPC npc) { 45 | GameProfile profile = new GameProfile(UUID.randomUUID(), npc.getName()); 46 | NMS.setSkin(profile, npc.getSkin()); 47 | return profile; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /nms-v1_8_R1/src/main/java/net/techcable/npclib/nms/versions/v1_8_R1/network/NPCConnection.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_8_R1.network; 2 | 3 | import lombok.*; 4 | 5 | import net.minecraft.server.v1_8_R1.EntityPlayer; 6 | import net.minecraft.server.v1_8_R1.Packet; 7 | import net.minecraft.server.v1_8_R1.PlayerConnection; 8 | import net.techcable.npclib.nms.versions.v1_8_R1.NMS; 9 | 10 | @Getter 11 | public class NPCConnection extends PlayerConnection { 12 | 13 | public NPCConnection(EntityPlayer npc) { 14 | super(NMS.getServer(), new NPCNetworkManager(), npc); 15 | } 16 | 17 | @Override 18 | public void sendPacket(Packet packet) { 19 | //Don't send packets to an npc 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /nms-v1_8_R1/src/main/java/net/techcable/npclib/nms/versions/v1_8_R1/network/NPCNetworkManager.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_8_R1.network; 2 | 3 | import lombok.*; 4 | 5 | import java.lang.reflect.Field; 6 | 7 | import net.minecraft.server.v1_8_R1.EnumProtocolDirection; 8 | import net.minecraft.server.v1_8_R1.NetworkManager; 9 | import net.techcable.npclib.utils.Reflection; 10 | 11 | @Getter 12 | public class NPCNetworkManager extends NetworkManager { 13 | 14 | public NPCNetworkManager() { 15 | super(EnumProtocolDirection.CLIENTBOUND); //MCP = isClientSide ---- SRG=field_150747_h 16 | Field channel = Reflection.makeField(NetworkManager.class, "i"); //MCP = channel ---- SRG=field_150746_k 17 | Field address = Reflection.makeField(NetworkManager.class, "j"); //MCP = address ---- SRG=field_77527_e 18 | 19 | Reflection.setField(channel, this, new NullChannel()); 20 | Reflection.setField(address, this, new NullSocketAddress()); 21 | 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /nms-v1_8_R1/src/main/java/net/techcable/npclib/nms/versions/v1_8_R1/network/NullChannel.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_8_R1.network; 2 | 3 | import lombok.*; 4 | 5 | import java.net.SocketAddress; 6 | 7 | import io.netty.channel.AbstractChannel; 8 | import io.netty.channel.ChannelConfig; 9 | import io.netty.channel.ChannelMetadata; 10 | import io.netty.channel.ChannelOutboundBuffer; 11 | import io.netty.channel.EventLoop; 12 | 13 | @Getter 14 | public class NullChannel extends AbstractChannel { 15 | 16 | public NullChannel() { 17 | super(null); 18 | } 19 | 20 | @Override 21 | public ChannelConfig config() { 22 | return null; 23 | } 24 | 25 | @Override 26 | public boolean isActive() { 27 | return false; 28 | } 29 | 30 | @Override 31 | public boolean isOpen() { 32 | return false; 33 | } 34 | 35 | @Override 36 | public ChannelMetadata metadata() { 37 | return null; 38 | } 39 | 40 | @Override 41 | protected void doBeginRead() throws Exception { 42 | } 43 | 44 | @Override 45 | protected void doBind(SocketAddress arg0) throws Exception { 46 | } 47 | 48 | @Override 49 | protected void doClose() throws Exception { 50 | } 51 | 52 | @Override 53 | protected void doDisconnect() throws Exception { 54 | } 55 | 56 | @Override 57 | protected void doWrite(ChannelOutboundBuffer arg0) throws Exception { 58 | } 59 | 60 | @Override 61 | protected boolean isCompatible(EventLoop arg0) { 62 | return false; 63 | } 64 | 65 | @Override 66 | protected SocketAddress localAddress0() { 67 | return null; 68 | } 69 | 70 | @Override 71 | protected AbstractUnsafe newUnsafe() { 72 | return null; 73 | } 74 | 75 | @Override 76 | protected SocketAddress remoteAddress0() { 77 | return null; 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /nms-v1_8_R1/src/main/java/net/techcable/npclib/nms/versions/v1_8_R1/network/NullSocketAddress.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_8_R1.network; 2 | 3 | import java.net.SocketAddress; 4 | 5 | public class NullSocketAddress extends SocketAddress { 6 | 7 | private static final long serialVersionUID = 1L; 8 | 9 | } 10 | -------------------------------------------------------------------------------- /nms-v1_8_R2/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 4.0.0 5 | 6 | 7 | net.techcable.npclib 8 | parent 9 | 2.0.0-beta2-SNAPSHOT 10 | ../pom.xml 11 | 12 | 13 | nms-v1_8_R2 14 | 15 | 16 | 17 | net.techcable.npclib 18 | api 19 | ${parent.version} 20 | provided 21 | 22 | 23 | org.bukkit 24 | craftbukkit 25 | 1.8.3-R0.1-SNAPSHOT 26 | provided 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /nms-v1_8_R2/src/main/java/net/techcable/npclib/nms/versions/v1_8_R2/HumanNPCHook.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_8_R2; 2 | 3 | import java.lang.reflect.Field; 4 | import java.lang.reflect.Modifier; 5 | import java.util.UUID; 6 | 7 | import net.minecraft.server.v1_8_R2.EntityPlayer; 8 | import net.minecraft.server.v1_8_R2.Packet; 9 | import net.minecraft.server.v1_8_R2.PacketPlayOutAnimation; 10 | import net.minecraft.server.v1_8_R2.PacketPlayOutPlayerInfo; 11 | import net.minecraft.server.v1_8_R2.PacketPlayOutPlayerInfo.EnumPlayerInfoAction; 12 | import net.techcable.npclib.Animation; 13 | import net.techcable.npclib.HumanNPC; 14 | import net.techcable.npclib.nms.IHumanNPCHook; 15 | import net.techcable.npclib.nms.versions.v1_8_R2.entity.EntityNPCPlayer; 16 | import net.techcable.npclib.utils.Reflection; 17 | 18 | import org.bukkit.Bukkit; 19 | import org.bukkit.Location; 20 | import org.bukkit.entity.EntityType; 21 | import org.bukkit.entity.Player; 22 | 23 | import com.google.common.base.Preconditions; 24 | import com.mojang.authlib.GameProfile; 25 | 26 | public class HumanNPCHook extends LivingNPCHook implements IHumanNPCHook { 27 | 28 | public HumanNPCHook(HumanNPC npc, Location toSpawn) { 29 | super(npc, toSpawn, EntityType.PLAYER); 30 | getNmsEntity().setHook(this); 31 | getNmsEntity().getWorld().players.remove(getNmsEntity()); 32 | } 33 | 34 | @Override 35 | public void setSkin(UUID id) { 36 | NMS.setSkin(getNmsEntity().getProfile(), id); 37 | refreshPlayerInfo(); 38 | } 39 | 40 | private boolean shownInTabList; 41 | 42 | @Override 43 | public void showInTablist() { 44 | if (shownInTabList) return; 45 | PacketPlayOutPlayerInfo packet = new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.ADD_PLAYER, getNmsEntity()); 46 | NMS.sendToAll(packet); 47 | shownInTabList = true; 48 | } 49 | 50 | @Override 51 | public void hideFromTablist() { 52 | if (!shownInTabList) return; 53 | PacketPlayOutPlayerInfo packet = new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.REMOVE_PLAYER, getNmsEntity()); 54 | NMS.sendToAll(packet); 55 | shownInTabList = false; 56 | } 57 | 58 | public void refreshPlayerInfo() { 59 | boolean wasShownInTabList = shownInTabList; 60 | hideFromTablist(); 61 | showInTablist(); 62 | if (!wasShownInTabList) hideFromTablist(); 63 | } 64 | 65 | public EntityNPCPlayer getNmsEntity() { 66 | return (EntityNPCPlayer) super.getNmsEntity(); 67 | } 68 | 69 | @Override 70 | public HumanNPC getNpc() { 71 | return (HumanNPC) super.getNpc(); 72 | } 73 | 74 | private static final Field nameField = Reflection.makeField(GameProfile.class, "name"); 75 | private static final Field modifiersField = Reflection.makeField(Field.class, "modifiers"); 76 | 77 | @Override 78 | public void setName(String s) { 79 | if (s.length() > 16) s = s.substring(0, 16); 80 | GameProfile profile = getNmsEntity().getProfile(); 81 | // Pro reflection hax 82 | nameField.setAccessible(true); // Allow access to private 83 | int modifiers = nameField.getModifiers(); 84 | modifiers = modifiers & ~Modifier.FINAL; 85 | modifiersField.setAccessible(true); 86 | Reflection.setField(modifiersField, nameField, modifiers); // Make Field.class think it isn't final 87 | Reflection.setField(nameField, profile, s); 88 | refreshPlayerInfo(); 89 | } 90 | 91 | @Override 92 | public void onDespawn() { 93 | hideFromTablist(); 94 | super.onDespawn(); 95 | } 96 | 97 | @Override 98 | protected EntityNPCPlayer spawn(Location toSpawn, EntityType type) { 99 | Preconditions.checkArgument(type == EntityType.PLAYER, "HumanNPCHook can only handle players"); 100 | EntityNPCPlayer entity = new EntityNPCPlayer(getNpc(), toSpawn); 101 | this.nmsEntity = entity; 102 | showInTablist(); 103 | this.nmsEntity = null; 104 | return entity; 105 | } 106 | 107 | @Override 108 | public void animate(Animation animation) { 109 | Packet packet; 110 | switch (animation) { 111 | case ARM_SWING : 112 | packet = new PacketPlayOutAnimation(getNmsEntity(), 0); 113 | break; 114 | case HURT : 115 | packet = new PacketPlayOutAnimation(getNmsEntity(), 1); 116 | break; 117 | case EAT : 118 | packet = new PacketPlayOutAnimation(getNmsEntity(), 3); 119 | break; 120 | case CRITICAL : 121 | packet = new PacketPlayOutAnimation(getNmsEntity(), 4); 122 | break; 123 | case MAGIC_CRITICAL : 124 | packet = new PacketPlayOutAnimation(getNmsEntity(), 5); 125 | break; 126 | default : 127 | super.animate(animation); 128 | return; 129 | } 130 | for (Player player : Bukkit.getOnlinePlayers()) { 131 | EntityPlayer handle = NMS.getHandle(player); 132 | handle.playerConnection.sendPacket(packet); 133 | } 134 | } 135 | 136 | public void onJoin(Player joined) { 137 | PacketPlayOutPlayerInfo packet = new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.ADD_PLAYER, getNmsEntity()); 138 | NMS.getHandle(joined).playerConnection.sendPacket(packet); 139 | if (!shownInTabList) { 140 | PacketPlayOutPlayerInfo removePacket = new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.REMOVE_PLAYER, getNmsEntity()); 141 | NMS.getHandle(joined).playerConnection.sendPacket(removePacket); 142 | } 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /nms-v1_8_R2/src/main/java/net/techcable/npclib/nms/versions/v1_8_R2/NMS.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_8_R2; 2 | 3 | import java.util.Collection; 4 | import java.util.UUID; 5 | import java.util.concurrent.TimeUnit; 6 | 7 | import com.google.common.cache.CacheBuilder; 8 | import com.google.common.cache.CacheLoader; 9 | import com.google.common.cache.LoadingCache; 10 | import com.mojang.authlib.GameProfile; 11 | 12 | import net.minecraft.server.v1_8_R2.EntityLiving; 13 | import net.minecraft.server.v1_8_R2.EntityPlayer; 14 | import net.minecraft.server.v1_8_R2.MinecraftServer; 15 | import net.minecraft.server.v1_8_R2.Packet; 16 | import net.minecraft.server.v1_8_R2.WorldServer; 17 | import net.techcable.npclib.HumanNPC; 18 | import net.techcable.npclib.LivingNPC; 19 | import net.techcable.npclib.NPC; 20 | import net.techcable.npclib.nms.IHumanNPCHook; 21 | import net.techcable.npclib.nms.ILivingNPCHook; 22 | import net.techcable.npclib.nms.versions.v1_8_R2.LivingNPCHook.LivingHookable; 23 | import net.techcable.npclib.nms.versions.v1_8_R2.entity.EntityNPCPlayer; 24 | import net.techcable.npclib.utils.NPCLog; 25 | 26 | import org.bukkit.Bukkit; 27 | import org.bukkit.Location; 28 | import org.bukkit.Server; 29 | import org.bukkit.World; 30 | import org.bukkit.craftbukkit.v1_8_R2.CraftServer; 31 | import org.bukkit.craftbukkit.v1_8_R2.CraftWorld; 32 | import org.bukkit.craftbukkit.v1_8_R2.entity.CraftLivingEntity; 33 | import org.bukkit.craftbukkit.v1_8_R2.entity.CraftPlayer; 34 | import org.bukkit.entity.EntityType; 35 | import org.bukkit.entity.LivingEntity; 36 | import org.bukkit.entity.Player; 37 | 38 | public class NMS implements net.techcable.npclib.nms.NMS { 39 | 40 | private static NMS instance; 41 | 42 | public NMS() { 43 | if (instance == null) instance = this; 44 | } 45 | 46 | public static NMS getInstance() { 47 | return instance; 48 | } 49 | 50 | 51 | @Override 52 | public IHumanNPCHook spawnHumanNPC(Location toSpawn, HumanNPC npc) { 53 | return new HumanNPCHook(npc, toSpawn); 54 | } 55 | 56 | @Override 57 | public void onJoin(Player joined, Collection npcs) { 58 | for (NPC npc : npcs) { 59 | if (!(npc instanceof HumanNPC)) continue; 60 | HumanNPCHook hook = getHook((HumanNPC) npc); 61 | if (hook == null) continue; 62 | hook.onJoin(joined); 63 | } 64 | } 65 | 66 | // UTILS 67 | public static final String NO_CRAFTBUKKIT_MSG = "Non-CraftBukkit implementations are unsupported"; 68 | 69 | public static EntityPlayer getHandle(Player player) { 70 | if (!(player instanceof CraftPlayer)) throw new UnsupportedOperationException(NO_CRAFTBUKKIT_MSG); 71 | return ((CraftPlayer) player).getHandle(); 72 | } 73 | 74 | public static EntityLiving getHandle(LivingEntity entity) { 75 | if (!(entity instanceof CraftLivingEntity)) throw new UnsupportedOperationException(NO_CRAFTBUKKIT_MSG); 76 | return ((CraftLivingEntity) entity).getHandle(); 77 | } 78 | 79 | 80 | public static MinecraftServer getServer() { 81 | Server server = Bukkit.getServer(); 82 | if (!(server instanceof CraftServer)) throw new UnsupportedOperationException(NO_CRAFTBUKKIT_MSG); 83 | return ((CraftServer) server).getServer(); 84 | } 85 | 86 | public static WorldServer getHandle(World world) { 87 | if (!(world instanceof CraftWorld)) throw new UnsupportedOperationException(NO_CRAFTBUKKIT_MSG); 88 | return ((CraftWorld) world).getHandle(); 89 | } 90 | 91 | public static HumanNPCHook getHook(HumanNPC npc) { 92 | EntityPlayer player = getHandle(npc.getEntity()); 93 | if (player instanceof EntityNPCPlayer) return null; 94 | return ((EntityNPCPlayer) player).getHook(); 95 | } 96 | 97 | public static LivingNPCHook getHook(LivingNPC npc) { 98 | if (npc instanceof HumanNPC) return getHook((HumanNPC) npc); 99 | EntityLiving entity = getHandle(npc.getEntity()); 100 | if (entity instanceof LivingHookable) return ((LivingHookable) entity).getHook(); 101 | return null; 102 | } 103 | 104 | public static void sendToAll(Packet packet) { 105 | for (Player p : Bukkit.getOnlinePlayers()) { 106 | getHandle(p).playerConnection.sendPacket(packet); 107 | } 108 | } 109 | 110 | private static final LoadingCache properties = CacheBuilder.newBuilder() 111 | .expireAfterAccess(5, TimeUnit.MINUTES) 112 | .build(new CacheLoader() { 113 | 114 | @Override 115 | public GameProfile load(UUID uuid) throws Exception { 116 | return MinecraftServer.getServer().aC().fillProfileProperties(new GameProfile(uuid, null), true); 117 | } 118 | }); 119 | 120 | public static void setSkin(GameProfile profile, UUID skinId) { 121 | GameProfile skinProfile; 122 | if (Bukkit.getPlayer(skinId) != null) { 123 | skinProfile = getHandle(Bukkit.getPlayer(skinId)).getProfile(); 124 | } else { 125 | skinProfile = properties.getUnchecked(skinId); 126 | } 127 | if (skinProfile.getProperties().containsKey("textures")) { 128 | profile.getProperties().removeAll("textures"); 129 | profile.getProperties().putAll("textures", skinProfile.getProperties().get("textures")); 130 | } else { 131 | NPCLog.debug("Skin with uuid not found: " + skinId); 132 | } 133 | } 134 | } -------------------------------------------------------------------------------- /nms-v1_8_R2/src/main/java/net/techcable/npclib/nms/versions/v1_8_R2/NPCHook.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_8_R2; 2 | 3 | import lombok.*; 4 | 5 | import net.minecraft.server.v1_8_R2.Entity; 6 | import net.techcable.npclib.NPC; 7 | import net.techcable.npclib.nms.INPCHook; 8 | 9 | @Getter 10 | @RequiredArgsConstructor 11 | public class NPCHook implements INPCHook { 12 | 13 | private final NPC npc; 14 | protected Entity nmsEntity; 15 | 16 | @Override 17 | public void onDespawn() { 18 | nmsEntity = null; 19 | } 20 | 21 | @Override 22 | public org.bukkit.entity.Entity getEntity() { 23 | return nmsEntity == null ? null : nmsEntity.getBukkitEntity(); 24 | } 25 | } -------------------------------------------------------------------------------- /nms-v1_8_R2/src/main/java/net/techcable/npclib/nms/versions/v1_8_R2/ai/NPCPath.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_8_R2.ai; 2 | 3 | import net.minecraft.server.v1_8_R2.BlockPosition; 4 | import net.minecraft.server.v1_8_R2.ChunkCache; 5 | import net.minecraft.server.v1_8_R2.EntityHuman; 6 | import net.minecraft.server.v1_8_R2.EntityLiving; 7 | import net.minecraft.server.v1_8_R2.MathHelper; 8 | import net.minecraft.server.v1_8_R2.PathEntity; 9 | import net.minecraft.server.v1_8_R2.Vec3D; 10 | import net.techcable.npclib.LivingNPC; 11 | import net.techcable.npclib.ai.AIEnvironment; 12 | import net.techcable.npclib.ai.AITask; 13 | import net.techcable.npclib.nms.versions.v1_8_R2.LivingNPCHook; 14 | import net.techcable.npclib.nms.versions.v1_8_R2.NMS; 15 | 16 | import org.bukkit.Location; 17 | 18 | /** 19 | * A npc pathing class 20 | *

21 | * Taken from "https://github.com/lenis0012/NPCFactory/blob/master/src/main/java/com/lenis0012/bukkit/npc/NPCPath.java" 22 | * It is MIT Licensed by lenis0012 23 | */ 24 | public class NPCPath implements AITask { 25 | 26 | private final LivingNPC npc; 27 | private final PathEntity nmsPath; 28 | private final double speed; 29 | private double progress; 30 | private Vec3D currentPoint; 31 | 32 | protected NPCPath(LivingNPC npc, PathEntity nmsPath, double speed) { 33 | this.npc = npc; 34 | this.nmsPath = nmsPath; 35 | this.speed = speed; 36 | this.progress = 0.0; 37 | this.currentPoint = nmsPath.a(getEntity()); // Just base it off signature 38 | } 39 | 40 | public void tick(AIEnvironment environment) { 41 | int current = MathHelper.floor(progress); 42 | double d = progress - current; 43 | double d1 = 1 - d; 44 | if (d + speed < 1) { 45 | double dx = (currentPoint.a - getEntity().locX) * speed; // a is x 46 | double dz = (currentPoint.c - getEntity().locZ) * speed; // c is z 47 | 48 | getEntity().move(dx, 0, dz); 49 | if (getEntity() instanceof EntityHuman) ((EntityHuman) getEntity()).checkMovement(dx, 0, dz); 50 | progress += speed; 51 | } else { 52 | //First complete old point. 53 | double bx = (currentPoint.a - getEntity().locX) * d1; 54 | double bz = (currentPoint.c - getEntity().locZ) * d1; 55 | 56 | //Check if new point exists 57 | nmsPath.a(); // Increments the second field (first int field) 58 | if (!nmsPath.b()) { // Checks if first field is greater than second field 59 | //Append new movement 60 | this.currentPoint = nmsPath.a(getEntity()); // Just base it off signature 61 | double d2 = speed - d1; 62 | 63 | double dx = bx + ((currentPoint.a - getEntity().locX) * d2); // a -> x 64 | double dy = currentPoint.b - getEntity().locY; //Jump if needed to reach next block. // b -> y 65 | double dz = bz + ((currentPoint.c - getEntity().locZ) * d2); // c -> z 66 | 67 | getEntity().move(dx, dy, dz); 68 | if (getEntity() instanceof EntityHuman) ((EntityHuman) getEntity()).checkMovement(dx, dy, dz); 69 | progress += speed; 70 | } else { 71 | //Complete final movement 72 | getEntity().move(bx, 0, bz); 73 | if (getEntity() instanceof EntityHuman) ((EntityHuman) getEntity()).checkMovement(bx, 0, bz); 74 | environment.removeTask(this); 75 | } 76 | } 77 | } 78 | 79 | public static NPCPath find(final LivingNPC npc, Location to, double range, double speed) { 80 | if (speed > 1) { 81 | throw new IllegalArgumentException("Speed cannot be higher than 1!"); 82 | } 83 | 84 | final EntityLiving entity = NMS.getHandle(npc.getEntity()); 85 | final LivingNPCHook hook = NMS.getHook(npc); 86 | 87 | try { 88 | BlockPosition posFrom = new BlockPosition(entity); 89 | BlockPosition posTo = new BlockPosition(to.getX(), to.getY(), to.getZ()); 90 | int k = (int) (range + 8.0); 91 | 92 | ChunkCache chunkCache = new ChunkCache(entity.world, posFrom.a(-k, -k, -k), posFrom.a(k, k, k), 0); 93 | PathEntity path = hook.getPathfinder().a(chunkCache, entity, posTo, (float) range); 94 | if (path != null) { 95 | return new NPCPath(npc, path, speed); 96 | } else { 97 | return null; 98 | } 99 | } catch (Exception e) { 100 | return null; 101 | } 102 | } 103 | 104 | public EntityLiving getEntity() { 105 | return NMS.getHandle(npc.getEntity()); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /nms-v1_8_R2/src/main/java/net/techcable/npclib/nms/versions/v1_8_R2/entity/EntityNPCPlayer.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_8_R2.entity; 2 | 3 | import lombok.*; 4 | 5 | import java.util.UUID; 6 | 7 | import net.minecraft.server.v1_8_R2.DamageSource; 8 | import net.minecraft.server.v1_8_R2.EntityPlayer; 9 | import net.minecraft.server.v1_8_R2.PlayerInteractManager; 10 | import net.minecraft.server.v1_8_R2.WorldSettings.EnumGamemode; 11 | import net.techcable.npclib.HumanNPC; 12 | import net.techcable.npclib.nms.versions.v1_8_R2.HumanNPCHook; 13 | import net.techcable.npclib.nms.versions.v1_8_R2.NMS; 14 | import net.techcable.npclib.nms.versions.v1_8_R2.network.NPCConnection; 15 | 16 | import org.bukkit.Location; 17 | 18 | import com.mojang.authlib.GameProfile; 19 | 20 | @Getter 21 | public class EntityNPCPlayer extends EntityPlayer { 22 | 23 | private final HumanNPC npc; 24 | @Setter 25 | private HumanNPCHook hook; 26 | 27 | public EntityNPCPlayer(HumanNPC npc, Location location) { 28 | super(NMS.getServer(), NMS.getHandle(location.getWorld()), makeProfile(npc), new PlayerInteractManager(NMS.getHandle(location.getWorld()))); 29 | playerInteractManager.b(EnumGamemode.SURVIVAL); //MCP = initializeGameType ---- SRG=func_73077_b 30 | this.npc = npc; 31 | playerConnection = new NPCConnection(this); 32 | 33 | setPosition(location.getX(), location.getY(), location.getZ()); 34 | } 35 | 36 | @Override 37 | public boolean damageEntity(DamageSource source, float damage) { 38 | if (npc.isProtected()) { 39 | return false; 40 | } 41 | return super.damageEntity(source, damage); 42 | } 43 | 44 | private static GameProfile makeProfile(HumanNPC npc) { 45 | GameProfile profile = new GameProfile(UUID.randomUUID(), npc.getName()); 46 | NMS.setSkin(profile, npc.getSkin()); 47 | return profile; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /nms-v1_8_R2/src/main/java/net/techcable/npclib/nms/versions/v1_8_R2/network/NPCConnection.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_8_R2.network; 2 | 3 | import lombok.*; 4 | 5 | import net.minecraft.server.v1_8_R2.EntityPlayer; 6 | import net.minecraft.server.v1_8_R2.Packet; 7 | import net.minecraft.server.v1_8_R2.PlayerConnection; 8 | import net.techcable.npclib.nms.versions.v1_8_R2.NMS; 9 | 10 | @Getter 11 | public class NPCConnection extends PlayerConnection { 12 | 13 | public NPCConnection(EntityPlayer player) { 14 | super(NMS.getServer(), new NPCNetworkManager(), player); 15 | } 16 | 17 | @Override 18 | public void sendPacket(Packet packet) { 19 | //Don't send packets to an npc 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /nms-v1_8_R2/src/main/java/net/techcable/npclib/nms/versions/v1_8_R2/network/NPCNetworkManager.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_8_R2.network; 2 | 3 | import lombok.*; 4 | 5 | import java.lang.reflect.Field; 6 | 7 | import net.minecraft.server.v1_8_R2.EnumProtocolDirection; 8 | import net.minecraft.server.v1_8_R2.NetworkManager; 9 | import net.techcable.npclib.utils.Reflection; 10 | 11 | @Getter 12 | public class NPCNetworkManager extends NetworkManager { 13 | 14 | public NPCNetworkManager() { 15 | super(EnumProtocolDirection.CLIENTBOUND); //MCP = isClientSide ---- SRG=field_150747_h 16 | Field channel = Reflection.makeField(NetworkManager.class, "k"); //MCP = channel ---- SRG=field_150746_k 17 | Field address = Reflection.makeField(NetworkManager.class, "l"); //MCP = address ---- SRG=field_77527_e 18 | 19 | Reflection.setField(channel, this, new NullChannel()); 20 | Reflection.setField(address, this, new NullSocketAddress()); 21 | 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /nms-v1_8_R2/src/main/java/net/techcable/npclib/nms/versions/v1_8_R2/network/NullChannel.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_8_R2.network; 2 | 3 | import lombok.*; 4 | 5 | import java.net.SocketAddress; 6 | 7 | import io.netty.channel.AbstractChannel; 8 | import io.netty.channel.ChannelConfig; 9 | import io.netty.channel.ChannelMetadata; 10 | import io.netty.channel.ChannelOutboundBuffer; 11 | import io.netty.channel.EventLoop; 12 | 13 | @Getter 14 | public class NullChannel extends AbstractChannel { 15 | 16 | public NullChannel() { 17 | super(null); 18 | } 19 | 20 | @Override 21 | public ChannelConfig config() { 22 | return null; 23 | } 24 | 25 | @Override 26 | public boolean isActive() { 27 | return false; 28 | } 29 | 30 | @Override 31 | public boolean isOpen() { 32 | return false; 33 | } 34 | 35 | @Override 36 | public ChannelMetadata metadata() { 37 | return null; 38 | } 39 | 40 | @Override 41 | protected void doBeginRead() throws Exception { 42 | } 43 | 44 | @Override 45 | protected void doBind(SocketAddress arg0) throws Exception { 46 | } 47 | 48 | @Override 49 | protected void doClose() throws Exception { 50 | } 51 | 52 | @Override 53 | protected void doDisconnect() throws Exception { 54 | } 55 | 56 | @Override 57 | protected void doWrite(ChannelOutboundBuffer arg0) throws Exception { 58 | } 59 | 60 | @Override 61 | protected boolean isCompatible(EventLoop arg0) { 62 | return false; 63 | } 64 | 65 | @Override 66 | protected SocketAddress localAddress0() { 67 | return null; 68 | } 69 | 70 | @Override 71 | protected AbstractUnsafe newUnsafe() { 72 | return null; 73 | } 74 | 75 | @Override 76 | protected SocketAddress remoteAddress0() { 77 | return null; 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /nms-v1_8_R2/src/main/java/net/techcable/npclib/nms/versions/v1_8_R2/network/NullSocketAddress.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_8_R2.network; 2 | 3 | import java.net.SocketAddress; 4 | 5 | public class NullSocketAddress extends SocketAddress { 6 | 7 | private static final long serialVersionUID = 1L; 8 | 9 | } 10 | -------------------------------------------------------------------------------- /nms-v1_8_R3/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 4.0.0 6 | 7 | 8 | net.techcable.npclib 9 | parent 10 | 2.0.0-beta2-SNAPSHOT 11 | ../pom.xml 12 | 13 | 14 | nms-v1_8_R3 15 | 16 | 17 | 18 | net.techcable.npclib 19 | api 20 | ${parent.version} 21 | provided 22 | 23 | 24 | org.bukkit 25 | craftbukkit 26 | 1.8.4-R0.1-SNAPSHOT 27 | provided 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /nms-v1_8_R3/src/main/java/net/techcable/npclib/nms/versions/v1_8_R3/NMS.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_8_R3; 2 | 3 | import java.util.Collection; 4 | import java.util.UUID; 5 | import java.util.concurrent.TimeUnit; 6 | 7 | import com.google.common.cache.CacheBuilder; 8 | import com.google.common.cache.CacheLoader; 9 | import com.google.common.cache.LoadingCache; 10 | import com.mojang.authlib.GameProfile; 11 | 12 | import net.minecraft.server.v1_8_R3.EntityLiving; 13 | import net.minecraft.server.v1_8_R3.EntityPlayer; 14 | import net.minecraft.server.v1_8_R3.MinecraftServer; 15 | import net.minecraft.server.v1_8_R3.Packet; 16 | import net.minecraft.server.v1_8_R3.WorldServer; 17 | import net.techcable.npclib.HumanNPC; 18 | import net.techcable.npclib.LivingNPC; 19 | import net.techcable.npclib.NPC; 20 | import net.techcable.npclib.nms.IHumanNPCHook; 21 | import net.techcable.npclib.nms.ILivingNPCHook; 22 | import net.techcable.npclib.nms.versions.v1_8_R3.LivingNPCHook.LivingHookable; 23 | import net.techcable.npclib.nms.versions.v1_8_R3.entity.EntityNPCPlayer; 24 | import net.techcable.npclib.utils.NPCLog; 25 | 26 | import org.bukkit.Bukkit; 27 | import org.bukkit.Location; 28 | import org.bukkit.Server; 29 | import org.bukkit.World; 30 | import org.bukkit.craftbukkit.v1_8_R3.CraftServer; 31 | import org.bukkit.craftbukkit.v1_8_R3.CraftWorld; 32 | import org.bukkit.craftbukkit.v1_8_R3.entity.CraftLivingEntity; 33 | import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; 34 | import org.bukkit.entity.EntityType; 35 | import org.bukkit.entity.LivingEntity; 36 | import org.bukkit.entity.Player; 37 | 38 | public class NMS implements net.techcable.npclib.nms.NMS { 39 | 40 | private static NMS instance; 41 | 42 | public NMS() { 43 | if (instance == null) instance = this; 44 | } 45 | 46 | public static NMS getInstance() { 47 | return instance; 48 | } 49 | 50 | 51 | @Override 52 | public IHumanNPCHook spawnHumanNPC(Location toSpawn, HumanNPC npc) { 53 | return new HumanNPCHook(npc, toSpawn); 54 | } 55 | 56 | @Override 57 | public void onJoin(Player joined, Collection npcs) { 58 | for (NPC npc : npcs) { 59 | if (!(npc instanceof HumanNPC)) continue; 60 | HumanNPCHook hook = getHook((HumanNPC) npc); 61 | if (hook == null) continue; 62 | hook.onJoin(joined); 63 | } 64 | } 65 | 66 | // UTILS 67 | public static final String NO_CRAFTBUKKIT_MSG = "Non-CraftBukkit implementations are unsupported"; 68 | 69 | public static EntityPlayer getHandle(Player player) { 70 | if (!(player instanceof CraftPlayer)) throw new UnsupportedOperationException(NO_CRAFTBUKKIT_MSG); 71 | return ((CraftPlayer) player).getHandle(); 72 | } 73 | 74 | public static EntityLiving getHandle(LivingEntity player) { 75 | if (!(player instanceof CraftLivingEntity)) throw new UnsupportedOperationException(NO_CRAFTBUKKIT_MSG); 76 | return ((CraftLivingEntity) player).getHandle(); 77 | } 78 | 79 | public static MinecraftServer getServer() { 80 | Server server = Bukkit.getServer(); 81 | if (!(server instanceof CraftServer)) throw new UnsupportedOperationException(NO_CRAFTBUKKIT_MSG); 82 | return ((CraftServer) server).getServer(); 83 | } 84 | 85 | public static WorldServer getHandle(World world) { 86 | if (!(world instanceof CraftWorld)) throw new UnsupportedOperationException(NO_CRAFTBUKKIT_MSG); 87 | return ((CraftWorld) world).getHandle(); 88 | } 89 | 90 | public static HumanNPCHook getHook(HumanNPC npc) { 91 | EntityPlayer player = getHandle(npc.getEntity()); 92 | if (player instanceof EntityNPCPlayer) return null; 93 | return ((EntityNPCPlayer) player).getHook(); 94 | } 95 | 96 | public static LivingNPCHook getHook(LivingNPC npc) { 97 | if (npc instanceof HumanNPC) return getHook((HumanNPC) npc); 98 | EntityLiving entity = getHandle(npc.getEntity()); 99 | if (entity instanceof LivingHookable) return ((LivingHookable) entity).getHook(); 100 | return null; 101 | } 102 | 103 | public static void sendToAll(Packet packet) { 104 | for (Player p : Bukkit.getOnlinePlayers()) { 105 | getHandle(p).playerConnection.sendPacket(packet); 106 | } 107 | } 108 | 109 | private static final LoadingCache properties = CacheBuilder.newBuilder() 110 | .expireAfterAccess(5, TimeUnit.MINUTES) 111 | .build(new CacheLoader() { 112 | 113 | @Override 114 | public GameProfile load(UUID uuid) throws Exception { 115 | return MinecraftServer.getServer().aD().fillProfileProperties(new GameProfile(uuid, null), true); 116 | } 117 | }); 118 | 119 | public static void setSkin(GameProfile profile, UUID skinId) { 120 | GameProfile skinProfile; 121 | if (Bukkit.getPlayer(skinId) != null) { 122 | skinProfile = getHandle(Bukkit.getPlayer(skinId)).getProfile(); 123 | } else { 124 | skinProfile = properties.getUnchecked(skinId); 125 | } 126 | if (skinProfile.getProperties().containsKey("textures")) { 127 | profile.getProperties().removeAll("textures"); 128 | profile.getProperties().putAll("textures", skinProfile.getProperties().get("textures")); 129 | } else { 130 | NPCLog.debug("Skin with uuid not found: " + skinId); 131 | } 132 | } 133 | } -------------------------------------------------------------------------------- /nms-v1_8_R3/src/main/java/net/techcable/npclib/nms/versions/v1_8_R3/NPCHook.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_8_R3; 2 | 3 | import lombok.*; 4 | 5 | import net.minecraft.server.v1_8_R3.Entity; 6 | import net.techcable.npclib.NPC; 7 | import net.techcable.npclib.nms.INPCHook; 8 | 9 | @Getter 10 | @RequiredArgsConstructor 11 | public class NPCHook implements INPCHook { 12 | 13 | private final NPC npc; 14 | protected Entity nmsEntity; 15 | 16 | @Override 17 | public void onDespawn() { 18 | nmsEntity = null; 19 | } 20 | 21 | @Override 22 | public org.bukkit.entity.Entity getEntity() { 23 | return nmsEntity == null ? null : nmsEntity.getBukkitEntity(); 24 | } 25 | } -------------------------------------------------------------------------------- /nms-v1_8_R3/src/main/java/net/techcable/npclib/nms/versions/v1_8_R3/ai/NPCPath.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_8_R3.ai; 2 | 3 | import net.minecraft.server.v1_8_R3.BlockPosition; 4 | import net.minecraft.server.v1_8_R3.ChunkCache; 5 | import net.minecraft.server.v1_8_R3.EntityHuman; 6 | import net.minecraft.server.v1_8_R3.EntityLiving; 7 | import net.minecraft.server.v1_8_R3.MathHelper; 8 | import net.minecraft.server.v1_8_R3.PathEntity; 9 | import net.minecraft.server.v1_8_R3.Vec3D; 10 | import net.techcable.npclib.LivingNPC; 11 | import net.techcable.npclib.ai.AIEnvironment; 12 | import net.techcable.npclib.ai.AITask; 13 | import net.techcable.npclib.nms.versions.v1_8_R3.LivingNPCHook; 14 | import net.techcable.npclib.nms.versions.v1_8_R3.NMS; 15 | 16 | import org.bukkit.Location; 17 | 18 | /** 19 | * A npc pathing class 20 | *

21 | * Taken from "https://github.com/lenis0012/NPCFactory/blob/master/src/main/java/com/lenis0012/bukkit/npc/NPCPath.java" 22 | * It is MIT Licensed by lenis0012 23 | */ 24 | public class NPCPath implements AITask { 25 | 26 | private final LivingNPC npc; 27 | private final PathEntity nmsPath; 28 | private final double speed; 29 | private double progress; 30 | private Vec3D currentPoint; 31 | 32 | protected NPCPath(LivingNPC npc, PathEntity nmsPath, double speed) { 33 | this.npc = npc; 34 | this.nmsPath = nmsPath; 35 | this.speed = speed; 36 | this.progress = 0.0; 37 | this.currentPoint = nmsPath.a(getEntity()); // Just base it off signature 38 | } 39 | 40 | public void tick(AIEnvironment environment) { 41 | int current = MathHelper.floor(progress); 42 | double d = progress - current; 43 | double d1 = 1 - d; 44 | if (d + speed < 1) { 45 | double dx = (currentPoint.a - getEntity().locX) * speed; // a is x 46 | double dz = (currentPoint.c - getEntity().locZ) * speed; // c is z 47 | 48 | getEntity().move(dx, 0, dz); 49 | if (getEntity() instanceof EntityHuman) ((EntityHuman) getEntity()).checkMovement(dx, 0, dz); 50 | progress += speed; 51 | } else { 52 | //First complete old point. 53 | double bx = (currentPoint.a - getEntity().locX) * d1; 54 | double bz = (currentPoint.c - getEntity().locZ) * d1; 55 | 56 | //Check if new point exists 57 | nmsPath.a(); // Increments the second field (first int field) 58 | if (!nmsPath.b()) { // Checks if first field is greater than second field 59 | //Append new movement 60 | this.currentPoint = nmsPath.a(getEntity()); // Just base it off signature 61 | double d2 = speed - d1; 62 | 63 | double dx = bx + ((currentPoint.a - getEntity().locX) * d2); // a -> x 64 | double dy = currentPoint.b - getEntity().locY; //Jump if needed to reach next block. // b -> y 65 | double dz = bz + ((currentPoint.c - getEntity().locZ) * d2); // c -> z 66 | 67 | getEntity().move(dx, dy, dz); 68 | if (getEntity() instanceof EntityHuman) ((EntityHuman) getEntity()).checkMovement(dx, dy, dz); 69 | progress += speed; 70 | } else { 71 | //Complete final movement 72 | getEntity().move(bx, 0, bz); 73 | if (getEntity() instanceof EntityHuman) ((EntityHuman) getEntity()).checkMovement(bx, 0, bz); 74 | environment.removeTask(this); 75 | } 76 | } 77 | } 78 | 79 | public static NPCPath find(final LivingNPC npc, Location to, double range, double speed) { 80 | if (speed > 1) { 81 | throw new IllegalArgumentException("Speed cannot be higher than 1!"); 82 | } 83 | 84 | final EntityLiving entity = NMS.getHandle(npc.getEntity()); 85 | final LivingNPCHook hook = NMS.getHook(npc); 86 | 87 | try { 88 | BlockPosition posFrom = new BlockPosition(entity); 89 | BlockPosition posTo = new BlockPosition(to.getX(), to.getY(), to.getZ()); 90 | int k = (int) (range + 8.0); 91 | 92 | ChunkCache chunkCache = new ChunkCache(entity.world, posFrom.a(-k, -k, -k), posFrom.a(k, k, k), 0); 93 | PathEntity path = hook.getPathfinder().a(chunkCache, entity, posTo, (float) range); 94 | if (path != null) { 95 | return new NPCPath(npc, path, speed); 96 | } else { 97 | return null; 98 | } 99 | } catch (Exception e) { 100 | return null; 101 | } 102 | } 103 | 104 | public EntityLiving getEntity() { 105 | return NMS.getHandle(npc.getEntity()); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /nms-v1_8_R3/src/main/java/net/techcable/npclib/nms/versions/v1_8_R3/entity/EntityNPCPlayer.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_8_R3.entity; 2 | 3 | import lombok.*; 4 | 5 | import java.util.UUID; 6 | 7 | import net.minecraft.server.v1_8_R3.DamageSource; 8 | import net.minecraft.server.v1_8_R3.EntityPlayer; 9 | import net.minecraft.server.v1_8_R3.PlayerInteractManager; 10 | import net.minecraft.server.v1_8_R3.WorldSettings.EnumGamemode; 11 | import net.techcable.npclib.HumanNPC; 12 | import net.techcable.npclib.nms.versions.v1_8_R3.HumanNPCHook; 13 | import net.techcable.npclib.nms.versions.v1_8_R3.NMS; 14 | import net.techcable.npclib.nms.versions.v1_8_R3.network.NPCConnection; 15 | 16 | import org.bukkit.Location; 17 | 18 | import com.mojang.authlib.GameProfile; 19 | 20 | @Getter 21 | public class EntityNPCPlayer extends EntityPlayer { 22 | 23 | private final HumanNPC npc; 24 | @Setter 25 | private HumanNPCHook hook; 26 | 27 | public EntityNPCPlayer(HumanNPC npc, Location location) { 28 | super(NMS.getServer(), NMS.getHandle(location.getWorld()), makeProfile(npc), new PlayerInteractManager(NMS.getHandle(location.getWorld()))); 29 | playerInteractManager.b(EnumGamemode.SURVIVAL); //MCP = initializeGameType ---- SRG=func_73077_b 30 | this.npc = npc; 31 | playerConnection = new NPCConnection(this); 32 | 33 | setPosition(location.getX(), location.getY(), location.getZ()); 34 | } 35 | 36 | @Override 37 | public boolean damageEntity(DamageSource source, float damage) { 38 | if (npc.isProtected()) { 39 | return false; 40 | } 41 | return super.damageEntity(source, damage); 42 | } 43 | 44 | private static GameProfile makeProfile(HumanNPC npc) { 45 | GameProfile profile = new GameProfile(UUID.randomUUID(), npc.getName()); 46 | NMS.setSkin(profile, npc.getSkin()); 47 | return profile; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /nms-v1_8_R3/src/main/java/net/techcable/npclib/nms/versions/v1_8_R3/network/NPCConnection.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_8_R3.network; 2 | 3 | import lombok.*; 4 | 5 | import net.minecraft.server.v1_8_R3.EntityPlayer; 6 | import net.minecraft.server.v1_8_R3.Packet; 7 | import net.minecraft.server.v1_8_R3.PlayerConnection; 8 | import net.techcable.npclib.nms.versions.v1_8_R3.NMS; 9 | 10 | @Getter 11 | public class NPCConnection extends PlayerConnection { 12 | 13 | public NPCConnection(EntityPlayer player) { 14 | super(NMS.getServer(), new NPCNetworkManager(), player); 15 | } 16 | 17 | @Override 18 | public void sendPacket(Packet packet) { 19 | //Don't send packets to an npc 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /nms-v1_8_R3/src/main/java/net/techcable/npclib/nms/versions/v1_8_R3/network/NPCNetworkManager.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_8_R3.network; 2 | 3 | import lombok.*; 4 | 5 | import java.lang.reflect.Field; 6 | 7 | import net.minecraft.server.v1_8_R3.EnumProtocolDirection; 8 | import net.minecraft.server.v1_8_R3.NetworkManager; 9 | import net.techcable.npclib.utils.Reflection; 10 | 11 | @Getter 12 | public class NPCNetworkManager extends NetworkManager { 13 | 14 | public NPCNetworkManager() { 15 | super(EnumProtocolDirection.CLIENTBOUND); //MCP = isClientSide ---- SRG=field_150747_h 16 | Field channel = Reflection.makeField(NetworkManager.class, "channel"); //MCP = channel ---- SRG=field_150746_k 17 | Field address = Reflection.makeField(NetworkManager.class, "l"); //MCP = address ---- SRG=field_77527_e 18 | 19 | Reflection.setField(channel, this, new NullChannel()); 20 | Reflection.setField(address, this, new NullSocketAddress()); 21 | 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /nms-v1_8_R3/src/main/java/net/techcable/npclib/nms/versions/v1_8_R3/network/NullChannel.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_8_R3.network; 2 | 3 | import lombok.*; 4 | 5 | import java.net.SocketAddress; 6 | 7 | import io.netty.channel.AbstractChannel; 8 | import io.netty.channel.ChannelConfig; 9 | import io.netty.channel.ChannelMetadata; 10 | import io.netty.channel.ChannelOutboundBuffer; 11 | import io.netty.channel.EventLoop; 12 | 13 | @Getter 14 | public class NullChannel extends AbstractChannel { 15 | 16 | public NullChannel() { 17 | super(null); 18 | } 19 | 20 | @Override 21 | public ChannelConfig config() { 22 | return null; 23 | } 24 | 25 | @Override 26 | public boolean isActive() { 27 | return false; 28 | } 29 | 30 | @Override 31 | public boolean isOpen() { 32 | return false; 33 | } 34 | 35 | @Override 36 | public ChannelMetadata metadata() { 37 | return null; 38 | } 39 | 40 | @Override 41 | protected void doBeginRead() throws Exception { 42 | } 43 | 44 | @Override 45 | protected void doBind(SocketAddress arg0) throws Exception { 46 | } 47 | 48 | @Override 49 | protected void doClose() throws Exception { 50 | } 51 | 52 | @Override 53 | protected void doDisconnect() throws Exception { 54 | } 55 | 56 | @Override 57 | protected void doWrite(ChannelOutboundBuffer arg0) throws Exception { 58 | } 59 | 60 | @Override 61 | protected boolean isCompatible(EventLoop arg0) { 62 | return false; 63 | } 64 | 65 | @Override 66 | protected SocketAddress localAddress0() { 67 | return null; 68 | } 69 | 70 | @Override 71 | protected AbstractUnsafe newUnsafe() { 72 | return null; 73 | } 74 | 75 | @Override 76 | protected SocketAddress remoteAddress0() { 77 | return null; 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /nms-v1_8_R3/src/main/java/net/techcable/npclib/nms/versions/v1_8_R3/network/NullSocketAddress.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_8_R3.network; 2 | 3 | import java.net.SocketAddress; 4 | 5 | public class NullSocketAddress extends SocketAddress { 6 | 7 | private static final long serialVersionUID = 1L; 8 | 9 | } 10 | -------------------------------------------------------------------------------- /nms-v1_9_R1/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 4.0.0 6 | 7 | 8 | net.techcable.npclib 9 | parent 10 | 2.0.0-beta2-SNAPSHOT 11 | ../pom.xml 12 | 13 | 14 | nms-v1_9_R1 15 | 16 | 17 | 18 | net.techcable.npclib 19 | api 20 | ${parent.version} 21 | provided 22 | 23 | 24 | org.bukkit 25 | craftbukkit 26 | 1.9-R0.1-SNAPSHOT 27 | provided 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /nms-v1_9_R1/src/main/java/net/techcable/npclib/nms/versions/v1_9_R1/HumanNPCHook.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_9_R1; 2 | 3 | import java.lang.reflect.Field; 4 | import java.lang.reflect.Modifier; 5 | import java.util.UUID; 6 | 7 | import net.minecraft.server.v1_9_R1.EntityPlayer; 8 | import net.minecraft.server.v1_9_R1.Packet; 9 | import net.minecraft.server.v1_9_R1.PacketPlayOutAnimation; 10 | import net.minecraft.server.v1_9_R1.PacketPlayOutPlayerInfo; 11 | import net.minecraft.server.v1_9_R1.PacketPlayOutPlayerInfo.EnumPlayerInfoAction; 12 | import net.techcable.npclib.Animation; 13 | import net.techcable.npclib.HumanNPC; 14 | import net.techcable.npclib.nms.IHumanNPCHook; 15 | import net.techcable.npclib.nms.versions.v1_9_R1.entity.EntityNPCPlayer; 16 | import net.techcable.npclib.utils.Reflection; 17 | 18 | import org.bukkit.Bukkit; 19 | import org.bukkit.Location; 20 | import org.bukkit.entity.EntityType; 21 | import org.bukkit.entity.Player; 22 | 23 | import com.google.common.base.Preconditions; 24 | import com.mojang.authlib.GameProfile; 25 | 26 | public class HumanNPCHook extends LivingNPCHook implements IHumanNPCHook { 27 | 28 | public HumanNPCHook(HumanNPC npc, Location toSpawn) { 29 | super(npc, toSpawn, EntityType.PLAYER); 30 | getNmsEntity().setHook(this); 31 | } 32 | 33 | @Override 34 | public void setSkin(UUID id) { 35 | boolean wasHidden = shownInTabList; 36 | NMS.setSkin(getNmsEntity().getProfile(), id); 37 | refreshPlayerInfo(); 38 | } 39 | 40 | private boolean shownInTabList; 41 | 42 | @Override 43 | public void showInTablist() { 44 | if (shownInTabList) return; 45 | PacketPlayOutPlayerInfo packet = new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.ADD_PLAYER, getNmsEntity()); 46 | NMS.sendToAll(packet); 47 | shownInTabList = true; 48 | } 49 | 50 | @Override 51 | public void animate(Animation animation) { 52 | Packet packet; 53 | switch (animation) { 54 | case ARM_SWING : 55 | packet = new PacketPlayOutAnimation(getNmsEntity(), 0); 56 | break; 57 | case HURT : 58 | packet = new PacketPlayOutAnimation(getNmsEntity(), 1); 59 | break; 60 | case EAT : 61 | packet = new PacketPlayOutAnimation(getNmsEntity(), 3); 62 | break; 63 | case CRITICAL : 64 | packet = new PacketPlayOutAnimation(getNmsEntity(), 4); 65 | break; 66 | case MAGIC_CRITICAL : 67 | packet = new PacketPlayOutAnimation(getNmsEntity(), 5); 68 | break; 69 | default : 70 | super.animate(animation); 71 | return; 72 | } 73 | for (Player player : Bukkit.getOnlinePlayers()) { 74 | EntityPlayer handle = NMS.getHandle(player); 75 | handle.playerConnection.sendPacket(packet); 76 | } 77 | } 78 | 79 | @Override 80 | public void hideFromTablist() { 81 | if (!shownInTabList) return; 82 | PacketPlayOutPlayerInfo packet = new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.REMOVE_PLAYER, getNmsEntity()); 83 | NMS.sendToAll(packet); 84 | shownInTabList = false; 85 | } 86 | 87 | public void refreshPlayerInfo() { 88 | boolean wasShownInTabList = shownInTabList; 89 | hideFromTablist(); 90 | showInTablist(); 91 | if (!wasShownInTabList) hideFromTablist(); 92 | } 93 | 94 | public EntityNPCPlayer getNmsEntity() { 95 | return (EntityNPCPlayer) super.getNmsEntity(); 96 | } 97 | 98 | @Override 99 | public HumanNPC getNpc() { 100 | return (HumanNPC) super.getNpc(); 101 | } 102 | 103 | private static final Field nameField = Reflection.makeField(GameProfile.class, "name"); 104 | private static final Field modifiersField = Reflection.makeField(Field.class, "modifiers"); 105 | 106 | @Override 107 | public void setName(String s) { 108 | if (s.length() > 16) s = s.substring(0, 16); 109 | GameProfile profile = getNmsEntity().getProfile(); 110 | // Pro reflection hax 111 | nameField.setAccessible(true); // Allow access to private 112 | int modifiers = nameField.getModifiers(); 113 | modifiers = modifiers & ~Modifier.FINAL; 114 | modifiersField.setAccessible(true); 115 | Reflection.setField(modifiersField, nameField, modifiers); // Make Field.class think it isn't final 116 | Reflection.setField(nameField, profile, s); 117 | refreshPlayerInfo(); 118 | } 119 | 120 | @Override 121 | public void onDespawn() { 122 | hideFromTablist(); 123 | super.onDespawn(); 124 | } 125 | 126 | @Override 127 | protected EntityNPCPlayer spawn(Location toSpawn, EntityType type) { 128 | Preconditions.checkArgument(type == EntityType.PLAYER, "HumanNPCHook can only handle players"); 129 | EntityNPCPlayer entity = new EntityNPCPlayer(getNpc(), toSpawn); 130 | this.nmsEntity = entity; 131 | showInTablist(); 132 | this.nmsEntity = null; 133 | return entity; 134 | } 135 | 136 | public void onJoin(Player joined) { 137 | PacketPlayOutPlayerInfo packet = new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.ADD_PLAYER, getNmsEntity()); 138 | NMS.getHandle(joined).playerConnection.sendPacket(packet); 139 | if (!shownInTabList) { 140 | PacketPlayOutPlayerInfo removePacket = new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.REMOVE_PLAYER, getNmsEntity()); 141 | NMS.getHandle(joined).playerConnection.sendPacket(packet); 142 | } 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /nms-v1_9_R1/src/main/java/net/techcable/npclib/nms/versions/v1_9_R1/LivingNPCHook.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_9_R1; 2 | 3 | import java.util.Objects; 4 | 5 | import net.minecraft.server.v1_9_R1.EntityHuman; 6 | import net.minecraft.server.v1_9_R1.EntityLiving; 7 | import net.minecraft.server.v1_9_R1.EntityPlayer; 8 | import net.minecraft.server.v1_9_R1.EnumItemSlot; 9 | import net.minecraft.server.v1_9_R1.ItemStack; 10 | import net.minecraft.server.v1_9_R1.MinecraftServer; 11 | import net.minecraft.server.v1_9_R1.Packet; 12 | import net.minecraft.server.v1_9_R1.PacketPlayOutEntityEquipment; 13 | import net.minecraft.server.v1_9_R1.PacketPlayOutEntityStatus; 14 | import net.techcable.npclib.Animation; 15 | import net.techcable.npclib.LivingNPC; 16 | import net.techcable.npclib.PathNotFoundException; 17 | import net.techcable.npclib.nms.ILivingNPCHook; 18 | 19 | import org.bukkit.Bukkit; 20 | import org.bukkit.Location; 21 | import org.bukkit.entity.EntityType; 22 | import org.bukkit.entity.LivingEntity; 23 | import org.bukkit.entity.Player; 24 | 25 | public class LivingNPCHook extends NPCHook implements ILivingNPCHook { 26 | 27 | public LivingNPCHook(LivingNPC npc, Location toSpawn, EntityType type) { 28 | super(npc); 29 | nmsEntity = spawn(toSpawn, type); 30 | getNmsEntity().spawnIn(NMS.getHandle(toSpawn.getWorld())); 31 | getNmsEntity().setPositionRotation(toSpawn.getX(), toSpawn.getY(), toSpawn.getZ(), toSpawn.getYaw(), toSpawn.getPitch()); 32 | NMS.getHandle(toSpawn.getWorld()).addEntity(getNmsEntity()); 33 | if (nmsEntity instanceof LivingHookable) ((LivingHookable) nmsEntity).setHook(this); 34 | } 35 | 36 | @Override 37 | public void look(float pitch, float yaw) { 38 | yaw = clampYaw(yaw); 39 | getNmsEntity().yaw = yaw; 40 | getNmsEntity().pitch = pitch; 41 | getNmsEntity().aK = yaw; // MCP -- rotationYawHead Srg -- field_70759_as 42 | if (getNmsEntity() instanceof EntityHuman) 43 | getNmsEntity().aI = yaw; // MCP -- renderYawOffset Srg -- field_70761_aq 44 | getNmsEntity().aL = yaw; // MCP -- prevRotationYawHead Srg -- field_70758_at 45 | } 46 | 47 | private final ItemStack[] lastEquipment = new ItemStack[5]; 48 | 49 | public static float clampYaw(float yaw) { 50 | while (yaw < -180.0F) { 51 | yaw += 360.0F; 52 | } 53 | while (yaw >= 180.0F) { 54 | yaw -= 360.0F; 55 | } 56 | return yaw; 57 | } 58 | 59 | 60 | @Override 61 | public void navigateTo(Location l) throws PathNotFoundException { 62 | throw new UnsupportedOperationException("Pathfining is currently unsupported in 1.9"); 63 | } 64 | 65 | @Override 66 | public void animate(Animation animation) { 67 | Packet packet; 68 | switch (animation) { 69 | case HURT: 70 | packet = new PacketPlayOutEntityStatus(getNmsEntity(), (byte) 2); // 1.8 hurt status is 2 71 | break; 72 | case DEAD: 73 | packet = new PacketPlayOutEntityStatus(getNmsEntity(), (byte) 3); // 1.8 dead status is 2 74 | break; 75 | default: 76 | throw new UnsupportedOperationException("Unsupported animation " + animation); 77 | } 78 | for (Player player : Bukkit.getOnlinePlayers()) { 79 | EntityPlayer handle = NMS.getHandle(player); 80 | handle.playerConnection.sendPacket(packet); 81 | } 82 | } 83 | 84 | @Override 85 | public void onTick() { 86 | if (MinecraftServer.currentTick % 5 != 0) return; // Every 5 ticks 87 | for (EnumItemSlot slot : EnumItemSlot.values()) { 88 | ItemStack currentEquipment = getNmsEntity().getEquipment(slot); 89 | ItemStack lastEquipment = this.lastEquipment[slot.ordinal()]; 90 | if (!Objects.equals(currentEquipment, lastEquipment)) { 91 | Packet packet = new PacketPlayOutEntityEquipment(getNmsEntity().getId(), slot, currentEquipment); 92 | NMS.sendToAll(packet); 93 | } 94 | this.lastEquipment[slot.ordinal()] = currentEquipment; 95 | } 96 | } 97 | 98 | @Override 99 | public void setName(String s) { 100 | if (s == null || s.trim().isEmpty()) { 101 | getNmsEntity().setCustomName(""); 102 | getNmsEntity().setCustomNameVisible(false); 103 | return; 104 | } 105 | getNmsEntity().setCustomName(s); 106 | getNmsEntity().setCustomNameVisible(true); 107 | } 108 | 109 | public EntityLiving getNmsEntity() { 110 | return (EntityLiving) super.getNmsEntity(); 111 | } 112 | 113 | @Override 114 | public LivingNPC getNpc() { 115 | return (LivingNPC) super.getNpc(); 116 | } 117 | 118 | @Override 119 | public LivingEntity getEntity() { 120 | return (LivingEntity) getNmsEntity().getBukkitEntity(); 121 | } 122 | 123 | protected EntityLiving spawn(Location toSpawn, EntityType type) { // TODO Update this each version with new entities 124 | if (type.isAlive()) throw new UnsupportedOperationException("Unsupported living entity: " + type.getName()); 125 | else throw new IllegalArgumentException("Not a living entity"); 126 | } 127 | 128 | public static interface LivingHookable { 129 | 130 | public LivingNPCHook getHook(); 131 | 132 | public void setHook(LivingNPCHook hook); 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /nms-v1_9_R1/src/main/java/net/techcable/npclib/nms/versions/v1_9_R1/NMS.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_9_R1; 2 | 3 | import java.util.Collection; 4 | import java.util.UUID; 5 | import java.util.concurrent.TimeUnit; 6 | 7 | import com.google.common.cache.CacheBuilder; 8 | import com.google.common.cache.CacheLoader; 9 | import com.google.common.cache.LoadingCache; 10 | import com.mojang.authlib.GameProfile; 11 | 12 | import net.minecraft.server.v1_9_R1.EntityLiving; 13 | import net.minecraft.server.v1_9_R1.EntityPlayer; 14 | import net.minecraft.server.v1_9_R1.MinecraftServer; 15 | import net.minecraft.server.v1_9_R1.Packet; 16 | import net.minecraft.server.v1_9_R1.WorldServer; 17 | import net.techcable.npclib.HumanNPC; 18 | import net.techcable.npclib.LivingNPC; 19 | import net.techcable.npclib.NPC; 20 | import net.techcable.npclib.nms.IHumanNPCHook; 21 | import net.techcable.npclib.nms.ILivingNPCHook; 22 | import net.techcable.npclib.nms.versions.v1_9_R1.LivingNPCHook.LivingHookable; 23 | import net.techcable.npclib.nms.versions.v1_9_R1.entity.EntityNPCPlayer; 24 | import net.techcable.npclib.utils.NPCLog; 25 | 26 | import org.bukkit.Bukkit; 27 | import org.bukkit.Location; 28 | import org.bukkit.Server; 29 | import org.bukkit.World; 30 | import org.bukkit.craftbukkit.v1_9_R1.CraftServer; 31 | import org.bukkit.craftbukkit.v1_9_R1.CraftWorld; 32 | import org.bukkit.craftbukkit.v1_9_R1.entity.CraftLivingEntity; 33 | import org.bukkit.craftbukkit.v1_9_R1.entity.CraftPlayer; 34 | import org.bukkit.entity.EntityType; 35 | import org.bukkit.entity.LivingEntity; 36 | import org.bukkit.entity.Player; 37 | 38 | public class NMS implements net.techcable.npclib.nms.NMS { 39 | 40 | private static NMS instance; 41 | 42 | public NMS() { 43 | if (instance == null) instance = this; 44 | } 45 | 46 | public static NMS getInstance() { 47 | return instance; 48 | } 49 | 50 | 51 | @Override 52 | public IHumanNPCHook spawnHumanNPC(Location toSpawn, HumanNPC npc) { 53 | return new HumanNPCHook(npc, toSpawn); 54 | } 55 | 56 | @Override 57 | public void onJoin(Player joined, Collection npcs) { 58 | for (NPC npc : npcs) { 59 | if (!(npc instanceof HumanNPC)) continue; 60 | HumanNPCHook hook = getHook((HumanNPC) npc); 61 | if (hook == null) continue; 62 | hook.onJoin(joined); 63 | } 64 | } 65 | 66 | // UTILS 67 | public static final String NO_CRAFTBUKKIT_MSG = "Non-CraftBukkit implementations are unsupported"; 68 | 69 | public static EntityPlayer getHandle(Player player) { 70 | if (!(player instanceof CraftPlayer)) throw new UnsupportedOperationException(NO_CRAFTBUKKIT_MSG); 71 | return ((CraftPlayer) player).getHandle(); 72 | } 73 | 74 | public static EntityLiving getHandle(LivingEntity player) { 75 | if (!(player instanceof CraftLivingEntity)) throw new UnsupportedOperationException(NO_CRAFTBUKKIT_MSG); 76 | return ((CraftLivingEntity) player).getHandle(); 77 | } 78 | 79 | public static MinecraftServer getServer() { 80 | Server server = Bukkit.getServer(); 81 | if (!(server instanceof CraftServer)) throw new UnsupportedOperationException(NO_CRAFTBUKKIT_MSG); 82 | return ((CraftServer) server).getServer(); 83 | } 84 | 85 | public static WorldServer getHandle(World world) { 86 | if (!(world instanceof CraftWorld)) throw new UnsupportedOperationException(NO_CRAFTBUKKIT_MSG); 87 | return ((CraftWorld) world).getHandle(); 88 | } 89 | 90 | public static HumanNPCHook getHook(HumanNPC npc) { 91 | EntityPlayer player = getHandle(npc.getEntity()); 92 | if (player instanceof EntityNPCPlayer) return null; 93 | return ((EntityNPCPlayer) player).getHook(); 94 | } 95 | 96 | public static LivingNPCHook getHook(LivingNPC npc) { 97 | if (npc instanceof HumanNPC) return getHook((HumanNPC) npc); 98 | EntityLiving entity = getHandle(npc.getEntity()); 99 | if (entity instanceof LivingHookable) return ((LivingHookable) entity).getHook(); 100 | return null; 101 | } 102 | 103 | public static void sendToAll(Packet packet) { 104 | for (Player p : Bukkit.getOnlinePlayers()) { 105 | getHandle(p).playerConnection.sendPacket(packet); 106 | } 107 | } 108 | 109 | private static final LoadingCache properties = CacheBuilder.newBuilder() 110 | .expireAfterAccess(5, TimeUnit.MINUTES) 111 | .build(new CacheLoader() { 112 | 113 | @Override 114 | public GameProfile load(UUID uuid) throws Exception { 115 | return MinecraftServer.getServer().ay().fillProfileProperties(new GameProfile(uuid, null), true); 116 | } 117 | }); 118 | 119 | public static void setSkin(GameProfile profile, UUID skinId) { 120 | GameProfile skinProfile; 121 | if (Bukkit.getPlayer(skinId) != null) { 122 | skinProfile = getHandle(Bukkit.getPlayer(skinId)).getProfile(); 123 | } else { 124 | skinProfile = properties.getUnchecked(skinId); 125 | } 126 | if (skinProfile.getProperties().containsKey("textures")) { 127 | profile.getProperties().removeAll("textures"); 128 | profile.getProperties().putAll("textures", skinProfile.getProperties().get("textures")); 129 | } else { 130 | NPCLog.debug("Skin with uuid not found: " + skinId); 131 | } 132 | } 133 | } -------------------------------------------------------------------------------- /nms-v1_9_R1/src/main/java/net/techcable/npclib/nms/versions/v1_9_R1/NPCHook.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_9_R1; 2 | 3 | import lombok.*; 4 | 5 | import net.minecraft.server.v1_9_R1.Entity; 6 | import net.techcable.npclib.NPC; 7 | import net.techcable.npclib.nms.INPCHook; 8 | 9 | @Getter 10 | @RequiredArgsConstructor 11 | public class NPCHook implements INPCHook { 12 | 13 | private final NPC npc; 14 | protected Entity nmsEntity; 15 | 16 | @Override 17 | public void onDespawn() { 18 | nmsEntity = null; 19 | } 20 | 21 | @Override 22 | public org.bukkit.entity.Entity getEntity() { 23 | return nmsEntity == null ? null : nmsEntity.getBukkitEntity(); 24 | } 25 | } -------------------------------------------------------------------------------- /nms-v1_9_R1/src/main/java/net/techcable/npclib/nms/versions/v1_9_R1/entity/EntityNPCPlayer.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_9_R1.entity; 2 | 3 | import lombok.*; 4 | 5 | import java.util.UUID; 6 | 7 | import net.minecraft.server.v1_9_R1.DamageSource; 8 | import net.minecraft.server.v1_9_R1.EntityPlayer; 9 | import net.minecraft.server.v1_9_R1.PlayerInteractManager; 10 | import net.minecraft.server.v1_9_R1.WorldSettings.EnumGamemode; 11 | import net.techcable.npclib.HumanNPC; 12 | import net.techcable.npclib.nms.versions.v1_9_R1.HumanNPCHook; 13 | import net.techcable.npclib.nms.versions.v1_9_R1.NMS; 14 | import net.techcable.npclib.nms.versions.v1_9_R1.network.NPCConnection; 15 | 16 | import org.bukkit.Location; 17 | 18 | import com.mojang.authlib.GameProfile; 19 | 20 | @Getter 21 | public class EntityNPCPlayer extends EntityPlayer { 22 | 23 | private final HumanNPC npc; 24 | @Setter 25 | private HumanNPCHook hook; 26 | 27 | public EntityNPCPlayer(HumanNPC npc, Location location) { 28 | super(NMS.getServer(), NMS.getHandle(location.getWorld()), makeProfile(npc), new PlayerInteractManager(NMS.getHandle(location.getWorld()))); 29 | playerInteractManager.b(EnumGamemode.SURVIVAL); //MCP = initializeGameType ---- SRG=func_73077_b 30 | this.npc = npc; 31 | playerConnection = new NPCConnection(this); 32 | setPosition(location.getX(), location.getY(), location.getZ()); 33 | } 34 | 35 | @Override 36 | public boolean damageEntity(DamageSource source, float damage) { 37 | if (npc.isProtected()) { 38 | return false; 39 | } 40 | return super.damageEntity(source, damage); 41 | } 42 | 43 | private static GameProfile makeProfile(HumanNPC npc) { 44 | GameProfile profile = new GameProfile(UUID.randomUUID(), npc.getName()); 45 | NMS.setSkin(profile, npc.getSkin()); 46 | return profile; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /nms-v1_9_R1/src/main/java/net/techcable/npclib/nms/versions/v1_9_R1/network/NPCConnection.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_9_R1.network; 2 | 3 | import lombok.*; 4 | 5 | import net.minecraft.server.v1_9_R1.EntityPlayer; 6 | import net.minecraft.server.v1_9_R1.Packet; 7 | import net.minecraft.server.v1_9_R1.PlayerConnection; 8 | import net.techcable.npclib.nms.versions.v1_9_R1.NMS; 9 | 10 | @Getter 11 | public class NPCConnection extends PlayerConnection { 12 | 13 | public NPCConnection(EntityPlayer player) { 14 | super(NMS.getServer(), new NPCNetworkManager(), player); 15 | } 16 | 17 | @Override 18 | public void sendPacket(Packet packet) { 19 | //Don't send packets to an npc 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /nms-v1_9_R1/src/main/java/net/techcable/npclib/nms/versions/v1_9_R1/network/NPCNetworkManager.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_9_R1.network; 2 | 3 | import lombok.*; 4 | 5 | import java.lang.reflect.Field; 6 | 7 | import net.minecraft.server.v1_9_R1.EnumProtocolDirection; 8 | import net.minecraft.server.v1_9_R1.NetworkManager; 9 | import net.techcable.npclib.utils.Reflection; 10 | 11 | @Getter 12 | public class NPCNetworkManager extends NetworkManager { 13 | 14 | public NPCNetworkManager() { 15 | super(EnumProtocolDirection.CLIENTBOUND); //MCP = isClientSide ---- SRG=field_150747_h 16 | Field channel = Reflection.makeField(NetworkManager.class, "channel"); //MCP = channel ---- SRG=field_150746_k 17 | Field address = Reflection.makeField(NetworkManager.class, "l"); //MCP = address ---- SRG=field_77527_e 18 | 19 | Reflection.setField(channel, this, new NullChannel()); 20 | Reflection.setField(address, this, new NullSocketAddress()); 21 | 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /nms-v1_9_R1/src/main/java/net/techcable/npclib/nms/versions/v1_9_R1/network/NullChannel.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_9_R1.network; 2 | 3 | import lombok.*; 4 | 5 | import java.net.SocketAddress; 6 | 7 | import io.netty.channel.AbstractChannel; 8 | import io.netty.channel.ChannelConfig; 9 | import io.netty.channel.ChannelMetadata; 10 | import io.netty.channel.ChannelOutboundBuffer; 11 | import io.netty.channel.EventLoop; 12 | 13 | @Getter 14 | public class NullChannel extends AbstractChannel { 15 | 16 | public NullChannel() { 17 | super(null); 18 | } 19 | 20 | @Override 21 | public ChannelConfig config() { 22 | return null; 23 | } 24 | 25 | @Override 26 | public boolean isActive() { 27 | return false; 28 | } 29 | 30 | @Override 31 | public boolean isOpen() { 32 | return false; 33 | } 34 | 35 | @Override 36 | public ChannelMetadata metadata() { 37 | return null; 38 | } 39 | 40 | @Override 41 | protected void doBeginRead() throws Exception { 42 | } 43 | 44 | @Override 45 | protected void doBind(SocketAddress arg0) throws Exception { 46 | } 47 | 48 | @Override 49 | protected void doClose() throws Exception { 50 | } 51 | 52 | @Override 53 | protected void doDisconnect() throws Exception { 54 | } 55 | 56 | @Override 57 | protected void doWrite(ChannelOutboundBuffer arg0) throws Exception { 58 | } 59 | 60 | @Override 61 | protected boolean isCompatible(EventLoop arg0) { 62 | return false; 63 | } 64 | 65 | @Override 66 | protected SocketAddress localAddress0() { 67 | return null; 68 | } 69 | 70 | @Override 71 | protected AbstractUnsafe newUnsafe() { 72 | return null; 73 | } 74 | 75 | @Override 76 | protected SocketAddress remoteAddress0() { 77 | return null; 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /nms-v1_9_R1/src/main/java/net/techcable/npclib/nms/versions/v1_9_R1/network/NullSocketAddress.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.versions.v1_9_R1.network; 2 | 3 | import java.net.SocketAddress; 4 | 5 | public class NullSocketAddress extends SocketAddress { 6 | 7 | private static final long serialVersionUID = 1L; 8 | 9 | } 10 | -------------------------------------------------------------------------------- /nms/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /nms/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | npclib-nms 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /nms/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 3 | org.eclipse.jdt.core.compiler.compliance=1.7 4 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 5 | org.eclipse.jdt.core.compiler.source=1.7 6 | -------------------------------------------------------------------------------- /nms/.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /nms/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 4.0.0 5 | 6 | 7 | net.techcable.npclib 8 | parent 9 | 2.0.0-beta2-SNAPSHOT 10 | ../pom.xml 11 | 12 | 13 | nms 14 | 15 | 16 | net.techcable.npclib 17 | api 18 | ${parent.version} 19 | provided 20 | 21 | 22 | 23 | net.techcable.npclib 24 | nms-v1_7_R3 25 | ${parent.version} 26 | compile 27 | 28 | 29 | net.techcable.npclib 30 | nms-v1_7_R4 31 | ${parent.version} 32 | compile 33 | 34 | 35 | net.techcable.npclib 36 | nms-v1_8_R1 37 | ${parent.version} 38 | compile 39 | 40 | 41 | net.techcable.npclib 42 | nms-v1_8_R2 43 | ${parent.version} 44 | compile 45 | 46 | 47 | net.techcable.npclib 48 | nms-v1_8_R3 49 | ${parent.version} 50 | compile 51 | 52 | 53 | net.techcable.npclib 54 | nms-v1_9_R1 55 | ${parent.version} 56 | compile 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /nms/src/main/java/net/techcable/npclib/nms/NMSHumanNPC.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms; 2 | 3 | import java.util.UUID; 4 | 5 | import com.google.common.base.Preconditions; 6 | 7 | import net.techcable.npclib.HumanNPC; 8 | 9 | import org.bukkit.Bukkit; 10 | import org.bukkit.Location; 11 | import org.bukkit.entity.EntityType; 12 | import org.bukkit.entity.Player; 13 | 14 | public class NMSHumanNPC extends NMSLivingNPC implements HumanNPC { 15 | 16 | public NMSHumanNPC(NMSRegistry registry, UUID id, String name) { 17 | super(registry, id, name, EntityType.PLAYER); 18 | } 19 | 20 | @Override 21 | protected IHumanNPCHook doSpawn(Location toSpawn) { 22 | return NMSRegistry.getNms().spawnHumanNPC(toSpawn, this); 23 | } 24 | 25 | private UUID skin; 26 | 27 | @Override 28 | public UUID getSkin() { 29 | return skin; 30 | } 31 | 32 | @Override 33 | public void setSkin(UUID skin) { 34 | this.skin = skin; 35 | if (isSpawned()) getHook().setSkin(skin); 36 | } 37 | 38 | @Override 39 | public void setSkin(String skin) { 40 | Preconditions.checkNotNull(skin, "Skin is null"); 41 | // Hacky uuid load 42 | UUID id = Bukkit.getOfflinePlayer(skin).getUniqueId(); 43 | // If the uuid's variant is '3' than it must be an offline uuid 44 | Preconditions.checkArgument(id.variant() != 3, "Invalid player name %s", skin); 45 | setSkin(id); 46 | } 47 | 48 | private boolean showInTabList = true; 49 | 50 | @Override 51 | public void setShowInTabList(boolean show) { 52 | boolean wasShownInTabList = showInTabList; 53 | this.showInTabList = show; 54 | if (isSpawned() && showInTabList != wasShownInTabList) { 55 | if (showInTabList) { 56 | getHook().showInTablist(); 57 | } else { 58 | getHook().hideFromTablist(); 59 | } 60 | } 61 | } 62 | 63 | @Override 64 | public boolean isShownInTabList() { 65 | return showInTabList; 66 | } 67 | 68 | @Override 69 | public Player getEntity() { 70 | return (Player) getHook().getEntity(); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /nms/src/main/java/net/techcable/npclib/nms/NMSLivingNPC.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms; 2 | 3 | import lombok.*; 4 | 5 | import java.util.UUID; 6 | 7 | import net.techcable.npclib.Animation; 8 | import net.techcable.npclib.LivingNPC; 9 | import net.techcable.npclib.PathNotFoundException; 10 | import net.techcable.npclib.ai.AITask; 11 | import net.techcable.npclib.nms.ai.NMSAIEnvironment; 12 | 13 | import org.bukkit.Location; 14 | import org.bukkit.entity.EntityType; 15 | import org.bukkit.entity.LivingEntity; 16 | 17 | import com.google.common.base.Preconditions; 18 | 19 | public abstract class NMSLivingNPC extends NMSNPC implements LivingNPC { 20 | 21 | private final EntityType entityType; 22 | 23 | public NMSLivingNPC(NMSRegistry registry, UUID id, String name, EntityType entityType) { 24 | super(registry, id, name); 25 | this.entityType = entityType; 26 | } 27 | 28 | @Override 29 | public void setName(String s) { 30 | super.setName(s); 31 | if (isSpawned()) getHook().setName(s); 32 | } 33 | 34 | @Override 35 | public LivingEntity getEntity() { 36 | return (LivingEntity) super.getEntity(); 37 | } 38 | 39 | @Override 40 | public void walkTo(Location l) throws PathNotFoundException { 41 | Preconditions.checkState(isSpawned(), "Can't walk if not spawned"); 42 | Preconditions.checkNotNull(l, "Location can't be null"); 43 | Preconditions.checkArgument(l.getWorld().equals(getEntity().getWorld()), "Can't walk to a location in a different world"); 44 | getHook().navigateTo(l); 45 | } 46 | 47 | @Override 48 | public void animate(Animation animation) { 49 | Preconditions.checkArgument(animation.getAppliesTo().isInstance(this), "%s can't be applied to a " + getEntity().getCustomName()); 50 | Preconditions.checkState(isSpawned(), "NPC isn't spawned"); 51 | getHook().animate(animation); 52 | } 53 | 54 | @Override 55 | public boolean isAbleToWalk() { 56 | return isSpawned(); 57 | } 58 | 59 | @Override 60 | public void faceLocation(Location toLook) { 61 | if (!getEntity().getWorld().equals(toLook.getWorld())) return; 62 | Location fromLocation = getEntity().getLocation(); 63 | double xDiff, yDiff, zDiff; 64 | xDiff = toLook.getX() - fromLocation.getX(); 65 | yDiff = toLook.getY() - fromLocation.getY(); 66 | zDiff = toLook.getZ() - fromLocation.getZ(); 67 | 68 | double distanceXZ = Math.sqrt(xDiff * xDiff + zDiff * zDiff); 69 | double distanceY = Math.sqrt(distanceXZ * distanceXZ + yDiff * yDiff); 70 | 71 | double yaw = Math.toDegrees(Math.acos(xDiff / distanceXZ)); 72 | double pitch = Math.toDegrees(Math.acos(yDiff / distanceY)) - 90; 73 | if (zDiff < 0.0) yaw += Math.abs(180 - yaw) * 2; 74 | 75 | getHook().look((float) pitch, (float) yaw - 90); 76 | } 77 | 78 | @Override 79 | public void run() { 80 | super.run(); 81 | if (!isSpawned()) return; 82 | if (getHook().getEntity() == null) return; 83 | getHook().onTick(); 84 | } 85 | 86 | 87 | @Override 88 | public void addTask(AITask task) { 89 | getAIEnvironment().addTask(task); 90 | } 91 | 92 | @Getter(lazy = true) 93 | private final NMSAIEnvironment aIEnvironment = new NMSAIEnvironment(this); 94 | } 95 | -------------------------------------------------------------------------------- /nms/src/main/java/net/techcable/npclib/nms/NMSNPC.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms; 2 | 3 | import lombok.*; 4 | 5 | import java.util.UUID; 6 | 7 | import net.techcable.npclib.NPC; 8 | 9 | import org.bukkit.Location; 10 | import org.bukkit.entity.Entity; 11 | import org.bukkit.metadata.FixedMetadataValue; 12 | import org.bukkit.scheduler.BukkitRunnable; 13 | 14 | import com.google.common.base.Preconditions; 15 | 16 | @Getter 17 | public abstract class NMSNPC extends BukkitRunnable implements NPC { 18 | 19 | private final NMSRegistry registry; 20 | private T hook; 21 | private final UUID id; 22 | @Setter 23 | private String name; 24 | 25 | private NPCState state = NPCState.NOT_SPAWNED; 26 | 27 | public NMSNPC(NMSRegistry registry, UUID id, String name) { 28 | this.registry = registry; 29 | this.id = id; 30 | this.name = name; 31 | runTaskTimer(registry.getPlugin(), 0, 1); 32 | } 33 | 34 | @Override 35 | public void despawn() { 36 | Preconditions.checkState(!isDestroyed(), "NPC has already been destroyed"); 37 | Preconditions.checkState(isSpawned(), "NPC is not spawned"); 38 | hook.getEntity().remove(); 39 | hook.onDespawn(); 40 | hook = null; 41 | state = NPCState.DESTROYED; 42 | cancel(); 43 | getRegistry().deregister(this); 44 | } 45 | 46 | @Override 47 | public Entity getEntity() { 48 | return hook.getEntity(); 49 | } 50 | 51 | @Override 52 | public UUID getUUID() { 53 | return id; 54 | } 55 | 56 | @Override 57 | public boolean isSpawned() { 58 | return hook != null && state == NPCState.SPAWNED; 59 | } 60 | 61 | @Override 62 | public boolean isDestroyed() { 63 | return !isSpawned() && state == NPCState.DESTROYED; 64 | } 65 | 66 | @Override 67 | public void spawn(Location toSpawn) { 68 | Preconditions.checkNotNull(toSpawn, "Location may not be null"); 69 | Preconditions.checkState(!isDestroyed(), "NPC has been destroyed"); 70 | Preconditions.checkState(!isSpawned(), "NPC is already spawned"); 71 | hook = doSpawn(toSpawn); 72 | hook.getEntity().setMetadata(NMSRegistry.METADATA_KEY, new FixedMetadataValue(getRegistry().getPlugin(), this)); 73 | state = NPCState.SPAWNED; 74 | } 75 | 76 | protected abstract T doSpawn(Location toSpawn); 77 | 78 | @Getter(AccessLevel.NONE) 79 | private boolean protect; 80 | 81 | @Override 82 | public void setProtected(boolean protect) { 83 | this.protect = protect; 84 | } 85 | 86 | @Override 87 | public boolean isProtected() { 88 | return protect; 89 | } 90 | 91 | @Override 92 | public void run() { 93 | } 94 | 95 | private static enum NPCState { 96 | NOT_SPAWNED, 97 | SPAWNED, 98 | DESTROYED; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /nms/src/main/java/net/techcable/npclib/nms/NMSRegistry.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms; 2 | 3 | import lombok.*; 4 | 5 | import java.lang.reflect.Constructor; 6 | import java.lang.reflect.InvocationTargetException; 7 | import java.util.HashMap; 8 | import java.util.List; 9 | import java.util.Map; 10 | import java.util.UUID; 11 | 12 | import net.techcable.npclib.HumanNPC; 13 | import net.techcable.npclib.LivingNPC; 14 | import net.techcable.npclib.NPC; 15 | import net.techcable.npclib.NPCRegistry; 16 | 17 | import org.bukkit.Bukkit; 18 | import org.bukkit.entity.Entity; 19 | import org.bukkit.entity.EntityType; 20 | import org.bukkit.event.Listener; 21 | import org.bukkit.metadata.MetadataValue; 22 | import org.bukkit.plugin.Plugin; 23 | 24 | import com.google.common.base.Preconditions; 25 | import com.google.common.base.Throwables; 26 | import com.google.common.collect.ImmutableCollection; 27 | import com.google.common.collect.ImmutableSet; 28 | 29 | @Getter 30 | @RequiredArgsConstructor 31 | public class NMSRegistry implements NPCRegistry, Listener { 32 | 33 | private final Plugin plugin; 34 | 35 | public static final String METADATA_KEY = "NPCLib"; 36 | 37 | @Override 38 | public HumanNPC createHumanNPC(String name) { 39 | return createHumanNPC(UUID.randomUUID(), name); 40 | } 41 | 42 | @Override 43 | public HumanNPC createHumanNPC(UUID uuid, String name) { 44 | Preconditions.checkNotNull(uuid, "Cant have null id"); 45 | Preconditions.checkNotNull(name, "Cant have null name"); 46 | NMSHumanNPC npc = new NMSHumanNPC(this, uuid, name); 47 | npcs.put(uuid, npc); 48 | return npc; 49 | } 50 | 51 | @Override 52 | public LivingNPC createLivingNPC(String name, EntityType type) { 53 | return createLivingNPC(UUID.randomUUID(), name, type); 54 | } 55 | 56 | @Override 57 | public LivingNPC createLivingNPC(UUID uuid, String name, EntityType type) { 58 | throw new UnsupportedOperationException("Living npcs aren't supported"); 59 | } 60 | 61 | @Getter(AccessLevel.NONE) 62 | private final Map npcs = new HashMap<>(); 63 | 64 | @Override 65 | public void deregister(NPC npc) { 66 | Preconditions.checkState(!npc.isSpawned(), "NPC is Spawned"); 67 | npcs.remove(npc.getUUID()); 68 | } 69 | 70 | @Override 71 | public void deregisterAll() { 72 | for (NPC npc : npcs.values()) { 73 | deregister(npc); 74 | } 75 | } 76 | 77 | @Override 78 | public NPC getByUUID(UUID uuid) { 79 | return npcs.get(uuid); 80 | } 81 | 82 | @Override 83 | public NPC getByName(String name) { 84 | for (NPC npc : npcs.values()) { 85 | if (npc instanceof LivingNPC) { 86 | if (((LivingNPC) npc).getName().equals(name)) { 87 | return npc; 88 | } 89 | } 90 | } 91 | return null; 92 | } 93 | 94 | @Override 95 | public NPC getAsNPC(Entity entity) { 96 | List metadataList = entity.getMetadata(METADATA_KEY); 97 | for (MetadataValue metadata : metadataList) { 98 | if (metadata.value() instanceof NPC) { 99 | return (NPC) metadata.value(); 100 | } 101 | } 102 | return null; 103 | } 104 | 105 | @Override 106 | public boolean isNPC(Entity entity) { 107 | return entity.hasMetadata(METADATA_KEY) && getAsNPC(entity) != null; 108 | } 109 | 110 | @Override 111 | public ImmutableCollection listNpcs() { 112 | return ImmutableSet.copyOf(npcs.values()); 113 | } 114 | 115 | @Getter(lazy = true) 116 | private final static NMS nms = makeNms(); 117 | 118 | private static NMS makeNms() { 119 | try { 120 | if (Bukkit.getServer() == null) return null; 121 | String packageName = Bukkit.getServer().getClass().getPackage().getName(); 122 | String version = packageName.substring(packageName.lastIndexOf(".") + 1); 123 | if (!version.startsWith("v")) return null; 124 | Class rawClass = Class.forName("net.techcable.npclib.nms.versions." + version + ".NMS"); 125 | Class nmsClass = rawClass.asSubclass(NMS.class); 126 | Constructor constructor = nmsClass.getConstructor(); 127 | return constructor.newInstance(); 128 | } catch (ClassNotFoundException ex) { 129 | throw new UnsupportedOperationException("Unsupported nms version", ex); 130 | } catch (InvocationTargetException ex) { 131 | throw Throwables.propagate(ex.getTargetException()); 132 | } catch (Exception ex) { 133 | throw Throwables.propagate(ex); 134 | } 135 | } 136 | } -------------------------------------------------------------------------------- /nms/src/main/java/net/techcable/npclib/nms/ai/NMSAIEnvironment.java: -------------------------------------------------------------------------------- 1 | package net.techcable.npclib.nms.ai; 2 | 3 | import net.techcable.npclib.ai.AIEnvironment; 4 | import net.techcable.npclib.nms.NMSNPC; 5 | 6 | import org.bukkit.scheduler.BukkitRunnable; 7 | 8 | public class NMSAIEnvironment extends AIEnvironment { 9 | 10 | private final NMSNPC npc; 11 | 12 | public NMSAIEnvironment(final NMSNPC npc) { 13 | this.npc = npc; 14 | new BukkitRunnable() { 15 | 16 | @Override 17 | public void run() { 18 | if (npc.isDestroyed()) cancel(); 19 | if (!npc.isSpawned()) return; 20 | tick(); 21 | } 22 | }.runTaskTimer(npc.getRegistry().getPlugin(), 0, 1); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | net.techcable.npclib 4 | parent 5 | NPC Lib 6 | 2.0.0-beta2-SNAPSHOT 7 | pom 8 | 9 | 10 | 11 | techcable-repo 12 | http://repo.techcable.net/content/groups/public/ 13 | 14 | 15 | citizens-repo 16 | http://repo.citizensnpcs.co/ 17 | 18 | 19 | 20 | 21 | 22 | org.bukkit 23 | bukkit 24 | 1.7.9-R0.2 25 | provided 26 | 27 | 28 | org.projectlombok 29 | lombok 30 | 1.14.8 31 | provided 32 | 33 | 34 | 35 | 36 | api 37 | nms-v1_7_R3 38 | nms-v1_7_R4 39 | nms-v1_8_R1 40 | nms-v1_8_R2 41 | nms-v1_8_R3 42 | nms-v1_9_R1 43 | nms 44 | citizens 45 | base 46 | 47 | 48 | 49 | 50 | 51 | org.apache.maven.plugins 52 | maven-compiler-plugin 53 | 3.2 54 | 55 | 1.7 56 | 1.7 57 | 58 | 59 | 60 | org.apache.maven.plugins 61 | maven-shade-plugin 62 | 2.3 63 | 64 | 65 | package 66 | 67 | shade 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | techcable-repo 78 | Releases 79 | http://repo.techcable.net/content/repositories/releases/ 80 | 81 | 82 | techcable-repo 83 | Snapshots 84 | http://repo.techcable.net/content/repositories/snapshots/ 85 | 86 | 87 | 88 | --------------------------------------------------------------------------------