diff --git a/README.md b/README.md
index 470bcc4..983d057 100644
--- a/README.md
+++ b/README.md
@@ -20,7 +20,7 @@ Maven
com.github.juliarn
npc-lib
- 2.1-RELEASE
+ 2.2-RELEASE
```
@@ -31,7 +31,7 @@ maven {
url 'https://jitpack.io'
}
-compile group: 'com.github.juliarn', name: 'npc-lib', version: '2.1-RELEASE'
+compile group: 'com.github.juliarn', name: 'npc-lib', version: '2.2-RELEASE'
```
Add ProtocolLib as dependency to your plugin.yml. It could look like this:
diff --git a/pom.xml b/pom.xml
index 92a46ff..e09439c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
com.github.juliarn
npc-lib
- 2.1-RELEASE
+ 2.2-RELEASE
jar
diff --git a/src/main/java/com/github/juliarn/npc/NPC.java b/src/main/java/com/github/juliarn/npc/NPC.java
index 112a2a1..d522a70 100644
--- a/src/main/java/com/github/juliarn/npc/NPC.java
+++ b/src/main/java/com/github/juliarn/npc/NPC.java
@@ -2,10 +2,8 @@
import com.comphenix.protocol.wrappers.EnumWrappers;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
-import com.comphenix.protocol.wrappers.WrappedSignedProperty;
import com.github.juliarn.npc.modifier.*;
import com.github.juliarn.npc.profile.Profile;
-import com.github.juliarn.npc.profile.ProfileBuilder;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Player;
@@ -15,7 +13,6 @@
import java.util.Collection;
import java.util.HashSet;
import java.util.Random;
-import java.util.UUID;
import java.util.concurrent.CopyOnWriteArraySet;
public class NPC {
@@ -36,11 +33,9 @@ public class NPC {
private final SpawnCustomizer spawnCustomizer;
- private NPC(Collection profileProperties, WrappedGameProfile gameProfile, Location location, boolean lookAtPlayer, boolean imitatePlayer, SpawnCustomizer spawnCustomizer) {
+ private NPC(WrappedGameProfile gameProfile, Location location, boolean lookAtPlayer, boolean imitatePlayer, SpawnCustomizer spawnCustomizer) {
this.gameProfile = gameProfile;
- profileProperties.forEach(property -> this.gameProfile.getProperties().put(property.getName(), property));
-
this.location = location;
this.lookAtPlayer = lookAtPlayer;
this.imitatePlayer = imitatePlayer;
@@ -58,7 +53,7 @@ protected void show(@NotNull Player player, @NotNull JavaPlugin javaPlugin) {
this.spawnCustomizer.handleSpawn(this, player);
// keeping the NPC longer in the player list, otherwise the skin might not be shown sometimes.
- Bukkit.getScheduler().runTaskLater(javaPlugin, () -> visibilityModifier.queuePlayerListChange(EnumWrappers.PlayerInfoAction.REMOVE_PLAYER).send(player), 10L);
+ Bukkit.getScheduler().runTaskLater(javaPlugin, () -> visibilityModifier.queuePlayerListChange(EnumWrappers.PlayerInfoAction.REMOVE_PLAYER).send(player), 15L);
}, 20L);
}
@@ -122,7 +117,7 @@ public MetadataModifier metadata() {
return new MetadataModifier(this);
}
-
+ @NotNull
public WrappedGameProfile getGameProfile() {
return gameProfile;
}
@@ -131,6 +126,7 @@ public int getEntityId() {
return entityId;
}
+ @NotNull
public Location getLocation() {
return location;
}
@@ -154,13 +150,7 @@ public void setImitatePlayer(boolean imitatePlayer) {
public static class Builder {
- private Collection profileProperties;
-
- private final String name;
-
- private UUID textureUUID;
-
- private UUID uuid = new UUID(RANDOM.nextLong(), 0);
+ private final Profile profile;
private Location location = new Location(Bukkit.getWorlds().get(0), 0D, 0D, 0D);
@@ -174,34 +164,10 @@ public static class Builder {
/**
* Creates a new instance of the NPC builder
*
- * @param textureUUID textures of this profile will be fetched and shown on the NPC
- * @param name the name the NPC should have
- */
- public Builder(@NotNull UUID textureUUID, @NotNull String name) {
- this.textureUUID = textureUUID;
- this.name = name;
- }
-
- /**
- * Creates a new instance of the NPC builder
- *
- * @param profileProperties a collection of profile properties, including textures
- * @param name the name the NPC should have
- */
- public Builder(@NotNull Collection profileProperties, @NotNull String name) {
- this.profileProperties = profileProperties;
- this.name = name;
- }
-
- /**
- * Sets a custom uuid for the NPC instead of generating a random one
- *
- * @param uuid the uuid the NPC should have
- * @return this builder instance
+ * @param profile a player profile defining UUID, name and textures of the NPC
*/
- public Builder uuid(UUID uuid) {
- this.uuid = uuid;
- return this;
+ public Builder(@NotNull Profile profile) {
+ this.profile = profile;
}
/**
@@ -257,15 +223,8 @@ public Builder spawnCustomizer(@NotNull SpawnCustomizer spawnCustomizer) {
*/
@NotNull
public NPC build(@NotNull NPCPool pool) {
- if (this.profileProperties == null) {
- Profile profile = new ProfileBuilder(this.textureUUID).complete(true).build();
-
- this.profileProperties = profile.getWrappedProperties();
- }
-
NPC npc = new NPC(
- this.profileProperties,
- new WrappedGameProfile(this.uuid, this.name),
+ this.profile.asWrapped(),
this.location,
this.lookAtPlayer,
this.imitatePlayer,
diff --git a/src/main/java/com/github/juliarn/npc/NPCPool.java b/src/main/java/com/github/juliarn/npc/NPCPool.java
index 2354bbe..dd2b0b2 100644
--- a/src/main/java/com/github/juliarn/npc/NPCPool.java
+++ b/src/main/java/com/github/juliarn/npc/NPCPool.java
@@ -95,7 +95,7 @@ private void npcTick() {
Bukkit.getScheduler().runTaskTimerAsynchronously(this.javaPlugin, () -> {
for (Player player : ImmutableList.copyOf(Bukkit.getOnlinePlayers())) {
for (NPC npc : this.npcMap.values()) {
- if (!npc.getLocation().getWorld().getName().equals(player.getLocation().getWorld().getName())) {
+ if (!npc.getLocation().getWorld().equals(player.getLocation().getWorld())) {
continue;
}
diff --git a/src/main/java/com/github/juliarn/npc/profile/Profile.java b/src/main/java/com/github/juliarn/npc/profile/Profile.java
index 7e4a718..2b3dbc3 100644
--- a/src/main/java/com/github/juliarn/npc/profile/Profile.java
+++ b/src/main/java/com/github/juliarn/npc/profile/Profile.java
@@ -10,9 +10,11 @@
import com.google.gson.*;
import com.google.gson.reflect.TypeToken;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Type;
import java.util.Collection;
+import java.util.HashSet;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
@@ -45,16 +47,37 @@ public class Profile {
this.properties = properties;
}
+ /**
+ * @return if this profile is complete (has UUID and name)
+ */
public boolean isComplete() {
- return this.name != null && this.uniqueId != null && !this.properties.isEmpty();
+ return this.uniqueId != null && this.name != null;
}
+ /**
+ * @return if this profile has properties
+ */
+ public boolean hasProperties() {
+ return this.properties != null;
+ }
+
+ /**
+ * Fills this profiles with all missing attributes
+ *
+ * @return if the profile was successfully completed
+ */
public boolean complete() {
- return this.complete(Boolean.TRUE);
+ return this.complete(true);
}
- public boolean complete(boolean texturesAndName) {
- if (this.isComplete()) {
+ /**
+ * Fills this profiles with all missing attributes
+ *
+ * @param propertiesAndName if properties and name should be filled for this profile
+ * @return if the profile was successfully completed
+ */
+ public boolean complete(boolean propertiesAndName) {
+ if (this.isComplete() && this.hasProperties()) {
return true;
}
@@ -89,7 +112,7 @@ public boolean complete(boolean texturesAndName) {
}
}
- if ((this.name == null || this.properties.isEmpty()) && texturesAndName) {
+ if ((this.name == null || this.properties == null) && propertiesAndName) {
RequestBuilder builder = RequestBuilder
.newBuilder(String.format(TEXTURES_REQUEST_URL, this.uniqueId.toString().replace("-", ""), false))
.setConnectTimeout(10, TimeUnit.SECONDS)
@@ -108,8 +131,10 @@ public boolean complete(boolean texturesAndName) {
JsonObject jsonObject = jsonElement.getAsJsonObject();
if (jsonObject.has("name") && jsonObject.has("properties")) {
- this.name = jsonObject.get("name").getAsString();
- this.properties = GSON.get().fromJson(jsonObject.get("properties"), PROPERTY_LIST_TYPE);
+ this.name = this.name == null ? jsonObject.get("name").getAsString() : this.name;
+ this.properties = this.properties == null ? GSON.get().fromJson(jsonObject.get("properties"), PROPERTY_LIST_TYPE) : this.properties;
+ } else {
+ return false;
}
}
} catch (Exception exception) {
@@ -131,12 +156,12 @@ public String getName() {
@NotNull
public Collection getProperties() {
- return properties;
+ return this.properties == null ? new HashSet<>() : this.properties;
}
@NotNull
public Collection getWrappedProperties() {
- return this.properties.stream().map(Property::asWrapped).collect(Collectors.toList());
+ return this.getProperties().stream().map(Property::asWrapped).collect(Collectors.toList());
}
@NotNull
@@ -157,7 +182,7 @@ public WrappedGameProfile asWrapped(boolean withProperties) {
public static class Property {
- public Property(String name, String value, String signature) {
+ public Property(@NotNull String name, @NotNull String value, @Nullable String signature) {
this.name = name;
this.value = value;
this.signature = signature;
@@ -169,14 +194,17 @@ public Property(String name, String value, String signature) {
private final String signature;
+ @NotNull
public String getName() {
return name;
}
+ @NotNull
public String getValue() {
return value;
}
+ @Nullable
public String getSignature() {
return signature;
}
diff --git a/src/main/java/com/github/juliarn/npc/profile/ProfileBuilder.java b/src/main/java/com/github/juliarn/npc/profile/ProfileBuilder.java
index bbd3735..62f6d24 100644
--- a/src/main/java/com/github/juliarn/npc/profile/ProfileBuilder.java
+++ b/src/main/java/com/github/juliarn/npc/profile/ProfileBuilder.java
@@ -4,7 +4,6 @@
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
-import java.util.HashSet;
import java.util.UUID;
public class ProfileBuilder {
@@ -13,7 +12,7 @@ public class ProfileBuilder {
private String name;
- private Collection profileProperties = new HashSet<>();
+ private Collection profileProperties;
private boolean complete = false;
@@ -43,7 +42,7 @@ public ProfileBuilder complete(boolean complete) {
@NotNull
public Profile build() {
if (this.name == null && this.uniqueId == null) {
- throw new IllegalStateException("Either name or unique id has to be given");
+ throw new IllegalStateException("Either name or uniqueId has to be given!");
}
Profile profile = new Profile(this.uniqueId, this.name, this.profileProperties);