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 extends NPC> 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 extends NPC> 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 extends NPC> 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 extends NPC> 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 extends NPC> 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 extends NPC> 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 extends NPC> 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 extends NPC> 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 extends NMS> nmsClass = rawClass.asSubclass(NMS.class);
126 | Constructor extends NMS> 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 |
--------------------------------------------------------------------------------