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);