Compare commits
No commits in common. "4a965def75e3f53421b64af8215f08c612a89d1d" and "ae1dd25a9a6497f606ed03ad5f0df0b9f452a8c2" have entirely different histories.
4a965def75
...
ae1dd25a9a
54 changed files with 141 additions and 452 deletions
|
@ -12,14 +12,14 @@ Looking for up-to-date builds of the plugin? Check out our [Jenkins](https://ci.
|
||||||
## Why is it so good?
|
## Why is it so good?
|
||||||
- 100% Packet Based - Nothing is ran on the main thread
|
- 100% Packet Based - Nothing is ran on the main thread
|
||||||
- Performance & stability oriented code
|
- Performance & stability oriented code
|
||||||
- Support for all versions from 1.8 to 1.20.4
|
- Support for all versions from 1.8 to 1.20.2
|
||||||
- Support for multiple different storage options
|
- Support for multiple different storage options
|
||||||
- Intuitive command system
|
- Intuitive command system
|
||||||
|
|
||||||
### Requirements, Extensions & Supported Software
|
### Requirements, Extensions & Supported Software
|
||||||
Requirements:
|
Requirements:
|
||||||
- Java 8+
|
- Java 8+
|
||||||
- Minecraft 1.8 - 1.20.4
|
- Minecraft 1.8 - 1.20.2
|
||||||
|
|
||||||
Supported Softwares:
|
Supported Softwares:
|
||||||
- Spigot ([Website](https://www.spigotmc.org/))
|
- Spigot ([Website](https://www.spigotmc.org/))
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package lol.pyr.znpcsplus.api.entity;
|
package lol.pyr.znpcsplus.api.entity;
|
||||||
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -34,19 +32,10 @@ public interface PropertyHolder {
|
||||||
*/
|
*/
|
||||||
<T> void setProperty(EntityProperty<T> key, T value);
|
<T> void setProperty(EntityProperty<T> key, T value);
|
||||||
|
|
||||||
/**
|
|
||||||
* Weird fix which is sadly required in order to not decrease performance
|
|
||||||
* when using item properties, read https://github.com/Pyrbu/ZNPCsPlus/pull/129#issuecomment-1948777764
|
|
||||||
*
|
|
||||||
* @param key Unique key representing a property
|
|
||||||
* @param value The value to assign to the property key on this holder
|
|
||||||
*/
|
|
||||||
void setItemProperty(EntityProperty<?> key, ItemStack value);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method used to get a set of all of the property keys that this holder has a value for
|
* Method used to get a set of all of the property keys that this holder has a value for
|
||||||
*
|
*
|
||||||
* @return Set of property keys
|
* @return List of property keys
|
||||||
*/
|
*/
|
||||||
Set<EntityProperty<?>> getAppliedProperties();
|
Set<EntityProperty<?>> getAppliedProperties();
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,10 +124,4 @@ public interface Npc extends PropertyHolder {
|
||||||
* @return The set of players that can currently see this npc
|
* @return The set of players that can currently see this npc
|
||||||
*/
|
*/
|
||||||
Set<Player> getViewers();
|
Set<Player> getViewers();
|
||||||
|
|
||||||
/**
|
|
||||||
* Swings the entity's hand
|
|
||||||
* @param offHand Should the hand be the offhand
|
|
||||||
*/
|
|
||||||
void swingHand(boolean offHand);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
package lol.pyr.znpcsplus.api.skin;
|
|
||||||
|
|
||||||
public interface Skin {
|
|
||||||
String getTexture();
|
|
||||||
String getSignature();
|
|
||||||
}
|
|
|
@ -1,11 +1,4 @@
|
||||||
package lol.pyr.znpcsplus.api.skin;
|
package lol.pyr.znpcsplus.api.skin;
|
||||||
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
|
|
||||||
public interface SkinDescriptor {
|
public interface SkinDescriptor {
|
||||||
CompletableFuture<? extends Skin> fetch(Player player);
|
|
||||||
Skin fetchInstant(Player player);
|
|
||||||
boolean supportsInstant(Player player);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,9 @@ subprojects {
|
||||||
maven {
|
maven {
|
||||||
url "https://repo.pyr.lol/releases"
|
url "https://repo.pyr.lol/releases"
|
||||||
}
|
}
|
||||||
|
maven {
|
||||||
|
url "https://jitpack.io/"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
publishing {
|
publishing {
|
||||||
|
|
|
@ -8,7 +8,7 @@ runServer {
|
||||||
javaLauncher = javaToolchains.launcherFor {
|
javaLauncher = javaToolchains.launcherFor {
|
||||||
languageVersion = JavaLanguageVersion.of(17)
|
languageVersion = JavaLanguageVersion.of(17)
|
||||||
}
|
}
|
||||||
minecraftVersion "1.20.4"
|
minecraftVersion "1.20.2"
|
||||||
}
|
}
|
||||||
|
|
||||||
processResources {
|
processResources {
|
||||||
|
@ -31,17 +31,17 @@ publishing {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compileOnly "me.clip:placeholderapi:2.11.5" // Placeholder support
|
compileOnly "me.clip:placeholderapi:2.11.3" // Placeholder support
|
||||||
compileOnly "com.google.code.gson:gson:2.10.1" // JSON parsing
|
compileOnly "com.google.code.gson:gson:2.10.1" // JSON parsing
|
||||||
compileOnly "org.bstats:bstats-bukkit:3.0.2" // Plugin stats
|
compileOnly "org.bstats:bstats-bukkit:3.0.2" // Plugin stats
|
||||||
compileOnly "me.robertlit:SpigotResourcesAPI:2.0" // Spigot API wrapper for update checker
|
compileOnly "com.github.robertlit:SpigotResourcesAPI:2.0" // Spigot API wrapper for update checker
|
||||||
compileOnly "com.github.retrooper.packetevents:spigot:2.2.1" // Packets
|
compileOnly "com.github.retrooper.packetevents:spigot:2.2.0" // Packets
|
||||||
compileOnly "space.arim.dazzleconf:dazzleconf-ext-snakeyaml:1.2.1" // Configs
|
compileOnly "space.arim.dazzleconf:dazzleconf-ext-snakeyaml:1.2.1" // Configs
|
||||||
compileOnly "lol.pyr:director-adventure:2.1.1" // Commands
|
compileOnly "lol.pyr:director-adventure:2.1.1" // Commands
|
||||||
|
|
||||||
// Fancy text library
|
// Fancy text library
|
||||||
compileOnly "net.kyori:adventure-platform-bukkit:4.3.2"
|
compileOnly "net.kyori:adventure-platform-bukkit:4.3.1"
|
||||||
compileOnly "net.kyori:adventure-text-minimessage:4.15.0"
|
compileOnly "net.kyori:adventure-text-minimessage:4.14.0"
|
||||||
|
|
||||||
implementation "me.lucko:jar-relocator:1.7"
|
implementation "me.lucko:jar-relocator:1.7"
|
||||||
implementation project(":api")
|
implementation project(":api")
|
||||||
|
@ -69,4 +69,4 @@ shadowJar {
|
||||||
minimize()
|
minimize()
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.assemble.dependsOn shadowJar
|
tasks.assemble.dependsOn shadowJar
|
|
@ -99,6 +99,16 @@ public class ZNpcsPlus {
|
||||||
PluginManager pluginManager = Bukkit.getPluginManager();
|
PluginManager pluginManager = Bukkit.getPluginManager();
|
||||||
long before = System.currentTimeMillis();
|
long before = System.currentTimeMillis();
|
||||||
|
|
||||||
|
boolean legacy = new File(getDataFolder(), "data.json").isFile() && !new File(getDataFolder(), "data").isDirectory();
|
||||||
|
if (legacy) try {
|
||||||
|
Files.move(getDataFolder().toPath(), new File(getDataFolder().getParentFile(), "ZNPCsPlusLegacy").toPath());
|
||||||
|
} catch (IOException e) {
|
||||||
|
log(ChatColor.RED + " * Moving legacy files to subfolder failed, plugin will shut down.");
|
||||||
|
e.printStackTrace();
|
||||||
|
pluginManager.disablePlugin(bootstrap);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
log(ChatColor.WHITE + " * Initializing libraries...");
|
log(ChatColor.WHITE + " * Initializing libraries...");
|
||||||
|
|
||||||
packetEvents.init();
|
packetEvents.init();
|
||||||
|
@ -149,6 +159,7 @@ public class ZNpcsPlus {
|
||||||
if (configManager.getConfig().checkForUpdates()) {
|
if (configManager.getConfig().checkForUpdates()) {
|
||||||
UpdateChecker updateChecker = new UpdateChecker(getDescription());
|
UpdateChecker updateChecker = new UpdateChecker(getDescription());
|
||||||
scheduler.runDelayedTimerAsync(updateChecker, 5L, 6000L);
|
scheduler.runDelayedTimerAsync(updateChecker, 5L, 6000L);
|
||||||
|
shutdownTasks.add(updateChecker::cancel);
|
||||||
pluginManager.registerEvents(new UpdateNotificationListener(this, adventure, updateChecker, scheduler), bootstrap);
|
pluginManager.registerEvents(new UpdateNotificationListener(this, adventure, updateChecker, scheduler), bootstrap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,7 +172,7 @@ public class ZNpcsPlus {
|
||||||
npcRegistry.reload();
|
npcRegistry.reload();
|
||||||
if (configManager.getConfig().autoSaveEnabled()) shutdownTasks.add(npcRegistry::save);
|
if (configManager.getConfig().autoSaveEnabled()) shutdownTasks.add(npcRegistry::save);
|
||||||
|
|
||||||
if (bootstrap.movedLegacy()) {
|
if (legacy) {
|
||||||
log(ChatColor.WHITE + " * Converting legacy data...");
|
log(ChatColor.WHITE + " * Converting legacy data...");
|
||||||
try {
|
try {
|
||||||
Collection<NpcEntryImpl> entries = importerRegistry.getImporter("znpcsplus_legacy").importData();
|
Collection<NpcEntryImpl> entries = importerRegistry.getImporter("znpcsplus_legacy").importData();
|
||||||
|
@ -199,12 +210,7 @@ public class ZNpcsPlus {
|
||||||
|
|
||||||
public void onDisable() {
|
public void onDisable() {
|
||||||
NpcApiProvider.unregister();
|
NpcApiProvider.unregister();
|
||||||
for (Runnable runnable : shutdownTasks) try {
|
for (Runnable runnable : shutdownTasks) runnable.run();
|
||||||
runnable.run();
|
|
||||||
} catch (Throwable throwable) {
|
|
||||||
bootstrap.getLogger().severe("One of the registered shutdown tasks threw an exception:");
|
|
||||||
throwable.printStackTrace();
|
|
||||||
}
|
|
||||||
shutdownTasks.clear();
|
shutdownTasks.clear();
|
||||||
PacketEvents.getAPI().terminate();
|
PacketEvents.getAPI().terminate();
|
||||||
}
|
}
|
||||||
|
@ -213,7 +219,7 @@ public class ZNpcsPlus {
|
||||||
HashMap<ServerVersion, LazyLoader<? extends PacketFactory>> versions = new HashMap<>();
|
HashMap<ServerVersion, LazyLoader<? extends PacketFactory>> versions = new HashMap<>();
|
||||||
versions.put(ServerVersion.V_1_8, LazyLoader.of(() -> new V1_8PacketFactory(scheduler, packetEvents, propertyRegistry, textSerializer, configManager)));
|
versions.put(ServerVersion.V_1_8, LazyLoader.of(() -> new V1_8PacketFactory(scheduler, packetEvents, propertyRegistry, textSerializer, configManager)));
|
||||||
versions.put(ServerVersion.V_1_17, LazyLoader.of(() -> new V1_17PacketFactory(scheduler, packetEvents, propertyRegistry, textSerializer, configManager)));
|
versions.put(ServerVersion.V_1_17, LazyLoader.of(() -> new V1_17PacketFactory(scheduler, packetEvents, propertyRegistry, textSerializer, configManager)));
|
||||||
versions.put(ServerVersion.V_1_19_3, LazyLoader.of(() -> new V1_19_3PacketFactory(scheduler, packetEvents, propertyRegistry, textSerializer, configManager)));
|
versions.put(ServerVersion.V_1_19_2, LazyLoader.of(() -> new V1_19_2PacketFactory(scheduler, packetEvents, propertyRegistry, textSerializer, configManager)));
|
||||||
versions.put(ServerVersion.V_1_20_2, LazyLoader.of(() -> new V1_20_2PacketFactory(scheduler, packetEvents, propertyRegistry, textSerializer, configManager)));
|
versions.put(ServerVersion.V_1_20_2, LazyLoader.of(() -> new V1_20_2PacketFactory(scheduler, packetEvents, propertyRegistry, textSerializer, configManager)));
|
||||||
|
|
||||||
ServerVersion version = packetEvents.getServerManager().getVersion();
|
ServerVersion version = packetEvents.getServerManager().getVersion();
|
||||||
|
|
|
@ -6,32 +6,18 @@ import lol.pyr.znpcsplus.libraries.LibraryLoader;
|
||||||
import lol.pyr.znpcsplus.util.FileUtil;
|
import lol.pyr.znpcsplus.util.FileUtil;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.ChatColor;
|
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
public class ZNpcsPlusBootstrap extends JavaPlugin {
|
public class ZNpcsPlusBootstrap extends JavaPlugin {
|
||||||
private ZNpcsPlus zNpcsPlus;
|
private ZNpcsPlus zNpcsPlus;
|
||||||
private boolean legacy;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoad() {
|
public void onLoad() {
|
||||||
legacy = new File(getDataFolder(), "data.json").isFile() && !new File(getDataFolder(), "data").isDirectory();
|
|
||||||
if (legacy) try {
|
|
||||||
Files.move(getDataFolder().toPath(), new File(getDataFolder().getParentFile(), "ZNPCsPlusLegacy").toPath());
|
|
||||||
} catch (IOException e) {
|
|
||||||
getLogger().severe(ChatColor.RED + "Failed to move legacy data folder! Plugin will disable.");
|
|
||||||
e.printStackTrace();
|
|
||||||
Bukkit.getPluginManager().disablePlugin(this);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
getLogger().info("Downloading and loading libraries, this might take a while if this is the first time you're launching the plugin");
|
getLogger().info("Downloading and loading libraries, this might take a while if this is the first time you're launching the plugin");
|
||||||
LibraryLoader loader = new LibraryLoader(this, new File(getDataFolder(), "libraries"));
|
LibraryLoader loader = new LibraryLoader(this, new File(getDataFolder(), "libraries"));
|
||||||
|
|
||||||
|
@ -52,10 +38,10 @@ public class ZNpcsPlusBootstrap extends JavaPlugin {
|
||||||
loader.loadLibrary(decrypt("org..bstats"), "bstats-base", "3.0.2");
|
loader.loadLibrary(decrypt("org..bstats"), "bstats-base", "3.0.2");
|
||||||
loader.loadLibrary(decrypt("org..bstats"), "bstats-bukkit", "3.0.2");
|
loader.loadLibrary(decrypt("org..bstats"), "bstats-bukkit", "3.0.2");
|
||||||
|
|
||||||
loader.loadLibrary("me.robertlit", "SpigotResourcesAPI", "2.0", "https://repo.pyr.lol/releases");
|
loader.loadLibrary("com.github.robertlit", "SpigotResourcesAPI", "2.0", "https://jitpack.io");
|
||||||
|
|
||||||
loader.loadLibrary(decrypt("com..github..retrooper..packetevents"), "api", "2.2.1", "https://repo.codemc.io/repository/maven-releases/");
|
loader.loadLibrary(decrypt("com..github..retrooper..packetevents"), "api", "2.2.0", "https://repo.codemc.io/repository/maven-releases/");
|
||||||
loader.loadLibrary(decrypt("com..github..retrooper..packetevents"), "spigot", "2.2.1", "https://repo.codemc.io/repository/maven-releases/");
|
loader.loadLibrary(decrypt("com..github..retrooper..packetevents"), "spigot", "2.2.0", "https://repo.codemc.io/repository/maven-releases/");
|
||||||
|
|
||||||
loader.loadLibrary(decrypt("space..arim..dazzleconf"), "dazzleconf-core", "1.2.1");
|
loader.loadLibrary(decrypt("space..arim..dazzleconf"), "dazzleconf-core", "1.2.1");
|
||||||
loader.loadLibrary(decrypt("space..arim..dazzleconf"), "dazzleconf-ext-snakeyaml", "1.2.1");
|
loader.loadLibrary(decrypt("space..arim..dazzleconf"), "dazzleconf-ext-snakeyaml", "1.2.1");
|
||||||
|
@ -63,19 +49,19 @@ public class ZNpcsPlusBootstrap extends JavaPlugin {
|
||||||
|
|
||||||
loader.loadLibrary("lol.pyr", "director-adventure", "2.1.1", "https://repo.pyr.lol/releases");
|
loader.loadLibrary("lol.pyr", "director-adventure", "2.1.1", "https://repo.pyr.lol/releases");
|
||||||
|
|
||||||
loader.loadLibrary(decrypt("net..kyori"), "adventure-api", "4.15.0");
|
loader.loadLibrary(decrypt("net..kyori"), "adventure-api", "4.14.0");
|
||||||
loader.loadLibrary(decrypt("net..kyori"), "adventure-key", "4.15.0");
|
loader.loadLibrary(decrypt("net..kyori"), "adventure-key", "4.14.0");
|
||||||
loader.loadLibrary(decrypt("net..kyori"), "adventure-nbt", "4.15.0");
|
loader.loadLibrary(decrypt("net..kyori"), "adventure-nbt", "4.14.0");
|
||||||
loader.loadLibrary(decrypt("net..kyori"), "adventure-platform-facet", "4.3.2");
|
loader.loadLibrary(decrypt("net..kyori"), "adventure-platform-facet", "4.3.1");
|
||||||
loader.loadLibrary(decrypt("net..kyori"), "adventure-platform-api", "4.3.2");
|
loader.loadLibrary(decrypt("net..kyori"), "adventure-platform-api", "4.3.1");
|
||||||
loader.loadLibrary(decrypt("net..kyori"), "adventure-platform-bukkit", "4.3.2");
|
loader.loadLibrary(decrypt("net..kyori"), "adventure-platform-bukkit", "4.3.1");
|
||||||
loader.loadLibrary(decrypt("net..kyori"), "adventure-text-minimessage", "4.15.0");
|
loader.loadLibrary(decrypt("net..kyori"), "adventure-text-minimessage", "4.14.0");
|
||||||
loader.loadLibrary(decrypt("net..kyori"), "adventure-text-serializer-bungeecord", "4.3.2");
|
loader.loadLibrary(decrypt("net..kyori"), "adventure-text-serializer-bungeecord", "4.3.1");
|
||||||
loader.loadLibrary(decrypt("net..kyori"), "adventure-text-serializer-gson", "4.15.0");
|
loader.loadLibrary(decrypt("net..kyori"), "adventure-text-serializer-gson", "4.14.0");
|
||||||
loader.loadLibrary(decrypt("net..kyori"), "adventure-text-serializer-gson-legacy-impl", "4.15.0");
|
loader.loadLibrary(decrypt("net..kyori"), "adventure-text-serializer-gson-legacy-impl", "4.14.0");
|
||||||
loader.loadLibrary(decrypt("net..kyori"), "adventure-text-serializer-json", "4.15.0");
|
loader.loadLibrary(decrypt("net..kyori"), "adventure-text-serializer-json", "4.14.0");
|
||||||
loader.loadLibrary(decrypt("net..kyori"), "adventure-text-serializer-json-legacy-impl", "4.15.0");
|
loader.loadLibrary(decrypt("net..kyori"), "adventure-text-serializer-json-legacy-impl", "4.14.0");
|
||||||
loader.loadLibrary(decrypt("net..kyori"), "adventure-text-serializer-legacy", "4.15.0");
|
loader.loadLibrary(decrypt("net..kyori"), "adventure-text-serializer-legacy", "4.14.0");
|
||||||
loader.loadLibrary(decrypt("net..kyori"), "examination-api", "1.3.0");
|
loader.loadLibrary(decrypt("net..kyori"), "examination-api", "1.3.0");
|
||||||
loader.loadLibrary(decrypt("net..kyori"), "examination-string", "1.3.0");
|
loader.loadLibrary(decrypt("net..kyori"), "examination-string", "1.3.0");
|
||||||
loader.deleteUnloadedLibraries();
|
loader.deleteUnloadedLibraries();
|
||||||
|
@ -117,10 +103,6 @@ public class ZNpcsPlusBootstrap extends JavaPlugin {
|
||||||
return context -> context.send(component);
|
return context -> context.send(component);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean movedLegacy() {
|
|
||||||
return legacy;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ugly hack because of https://github.com/johnrengelman/shadow/issues/232
|
// Ugly hack because of https://github.com/johnrengelman/shadow/issues/232
|
||||||
private static String decrypt(String packageName) {
|
private static String decrypt(String packageName) {
|
||||||
return packageName.replace("..", ".");
|
return packageName.replace("..", ".");
|
||||||
|
|
|
@ -10,7 +10,6 @@ import lol.pyr.znpcsplus.util.NpcLocation;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -25,9 +24,9 @@ public class SetLocationCommand implements CommandHandler {
|
||||||
public void run(CommandContext context) throws CommandExecutionException {
|
public void run(CommandContext context) throws CommandExecutionException {
|
||||||
context.setUsage(context.getLabel() + " setlocation <id> <x> <y> <z>");
|
context.setUsage(context.getLabel() + " setlocation <id> <x> <y> <z>");
|
||||||
NpcImpl npc = context.parse(NpcEntryImpl.class).getNpc();
|
NpcImpl npc = context.parse(NpcEntryImpl.class).getNpc();
|
||||||
double x = parseLocation(context.popString(), npc.getLocation().getX());
|
double x = context.parse(Double.class);
|
||||||
double y = parseLocation(context.popString(), npc.getLocation().getY());
|
double y = context.parse(Double.class);
|
||||||
double z = parseLocation(context.popString(), npc.getLocation().getZ());
|
double z = context.parse(Double.class);
|
||||||
npc.setLocation(new NpcLocation(x, y, z, npc.getLocation().getYaw(), npc.getLocation().getPitch()));
|
npc.setLocation(new NpcLocation(x, y, z, npc.getLocation().getYaw(), npc.getLocation().getPitch()));
|
||||||
context.send(Component.text("NPC has been moved to " + x + ", " + y + ", " + z + ".", NamedTextColor.GREEN));
|
context.send(Component.text("NPC has been moved to " + x + ", " + y + ", " + z + ".", NamedTextColor.GREEN));
|
||||||
}
|
}
|
||||||
|
@ -35,22 +34,6 @@ public class SetLocationCommand implements CommandHandler {
|
||||||
@Override
|
@Override
|
||||||
public List<String> suggest(CommandContext context) throws CommandExecutionException {
|
public List<String> suggest(CommandContext context) throws CommandExecutionException {
|
||||||
if (context.argSize() == 1) return context.suggestCollection(npcRegistry.getModifiableIds());
|
if (context.argSize() == 1) return context.suggestCollection(npcRegistry.getModifiableIds());
|
||||||
NpcImpl npc = context.suggestionParse(0, NpcEntryImpl.class).getNpc();
|
|
||||||
if (context.argSize() == 2) return Arrays.asList(String.valueOf(npc.getLocation().getX()), "~");
|
|
||||||
else if (context.argSize() == 3) return Arrays.asList(String.valueOf(npc.getLocation().getY()), "~");
|
|
||||||
else if (context.argSize() == 4) return Arrays.asList(String.valueOf(npc.getLocation().getZ()), "~");
|
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static double parseLocation(String input, double current) throws CommandExecutionException {
|
|
||||||
if (input.equals("~")) return current;
|
|
||||||
if (input.startsWith("~")) {
|
|
||||||
try {
|
|
||||||
return current + Double.parseDouble(input.substring(1));
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
throw new CommandExecutionException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Double.parseDouble(input);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@ import lol.pyr.znpcsplus.util.NpcLocation;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -25,12 +24,8 @@ public class SetRotationCommand implements CommandHandler {
|
||||||
public void run(CommandContext context) throws CommandExecutionException {
|
public void run(CommandContext context) throws CommandExecutionException {
|
||||||
context.setUsage(context.getLabel() + " setrotation <id> <yaw> <pitch>");
|
context.setUsage(context.getLabel() + " setrotation <id> <yaw> <pitch>");
|
||||||
NpcImpl npc = context.parse(NpcEntryImpl.class).getNpc();
|
NpcImpl npc = context.parse(NpcEntryImpl.class).getNpc();
|
||||||
float yaw = parseRotation(context.popString(), npc.getLocation().getYaw());
|
float yaw = context.parse(Float.class);
|
||||||
float pitch = parseRotation(context.popString(), npc.getLocation().getPitch());
|
float pitch = context.parse(Float.class);
|
||||||
if (pitch < -90 || pitch > 90) {
|
|
||||||
pitch = Math.min(Math.max(pitch, -90), 90);
|
|
||||||
context.send(Component.text("Warning: pitch is outside of the -90 to 90 range. It has been normalized to " + pitch + ".", NamedTextColor.YELLOW));
|
|
||||||
}
|
|
||||||
npc.setLocation(new NpcLocation(npc.getLocation().getX(), npc.getLocation().getY(), npc.getLocation().getZ(), yaw, pitch));
|
npc.setLocation(new NpcLocation(npc.getLocation().getX(), npc.getLocation().getY(), npc.getLocation().getZ(), yaw, pitch));
|
||||||
context.send(Component.text("NPC has been rotated to " + yaw + ", " + pitch + ".", NamedTextColor.GREEN));
|
context.send(Component.text("NPC has been rotated to " + yaw + ", " + pitch + ".", NamedTextColor.GREEN));
|
||||||
}
|
}
|
||||||
|
@ -38,21 +33,6 @@ public class SetRotationCommand implements CommandHandler {
|
||||||
@Override
|
@Override
|
||||||
public List<String> suggest(CommandContext context) throws CommandExecutionException {
|
public List<String> suggest(CommandContext context) throws CommandExecutionException {
|
||||||
if (context.argSize() == 1) return context.suggestCollection(npcRegistry.getModifiableIds());
|
if (context.argSize() == 1) return context.suggestCollection(npcRegistry.getModifiableIds());
|
||||||
NpcImpl npc = context.suggestionParse(0, NpcEntryImpl.class).getNpc();
|
|
||||||
if (context.argSize() == 2) return Arrays.asList(String.valueOf(npc.getLocation().getYaw()), "~");
|
|
||||||
else if (context.argSize() == 3) return Arrays.asList(String.valueOf(npc.getLocation().getPitch()), "~");
|
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static float parseRotation(String input, float current) throws CommandExecutionException {
|
|
||||||
if (input.equals("~")) return current;
|
|
||||||
if (input.startsWith("~")) {
|
|
||||||
try {
|
|
||||||
return current + Float.parseFloat(input.substring(1));
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
throw new CommandExecutionException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Float.parseFloat(input);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,9 +68,4 @@ public interface MainConfig {
|
||||||
})
|
})
|
||||||
@DefaultInteger(60)
|
@DefaultInteger(60)
|
||||||
int tabHideDelay();
|
int tabHideDelay();
|
||||||
|
|
||||||
@ConfKey("tab-display-name")
|
|
||||||
@ConfComments("The display name to use for npcs in the player list (aka tab)")
|
|
||||||
@DefaultString("ZNPC[{id}]")
|
|
||||||
String tabDisplayName();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import lol.pyr.znpcsplus.api.entity.EntityPropertyRegistry;
|
||||||
import lol.pyr.znpcsplus.api.skin.SkinDescriptor;
|
import lol.pyr.znpcsplus.api.skin.SkinDescriptor;
|
||||||
import lol.pyr.znpcsplus.conversion.citizens.model.SectionCitizensTrait;
|
import lol.pyr.znpcsplus.conversion.citizens.model.SectionCitizensTrait;
|
||||||
import lol.pyr.znpcsplus.npc.NpcImpl;
|
import lol.pyr.znpcsplus.npc.NpcImpl;
|
||||||
import lol.pyr.znpcsplus.skin.SkinImpl;
|
import lol.pyr.znpcsplus.skin.Skin;
|
||||||
import lol.pyr.znpcsplus.skin.descriptor.PrefetchedDescriptor;
|
import lol.pyr.znpcsplus.skin.descriptor.PrefetchedDescriptor;
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
@ -21,7 +21,7 @@ public class SkinTrait extends SectionCitizensTrait {
|
||||||
public @NotNull NpcImpl apply(NpcImpl npc, ConfigurationSection section) {
|
public @NotNull NpcImpl apply(NpcImpl npc, ConfigurationSection section) {
|
||||||
String texture = section.getString("textureRaw");
|
String texture = section.getString("textureRaw");
|
||||||
String signature = section.getString("signature");
|
String signature = section.getString("signature");
|
||||||
if (texture != null && signature != null) npc.setProperty(registry.getByName("skin", SkinDescriptor.class), new PrefetchedDescriptor(new SkinImpl(texture, signature)));
|
if (texture != null && signature != null) npc.setProperty(registry.getByName("skin", SkinDescriptor.class), new PrefetchedDescriptor(new Skin(texture, signature)));
|
||||||
return npc;
|
return npc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,9 @@ import lol.pyr.znpcsplus.api.interaction.InteractionType;
|
||||||
import lol.pyr.znpcsplus.api.skin.SkinDescriptor;
|
import lol.pyr.znpcsplus.api.skin.SkinDescriptor;
|
||||||
import lol.pyr.znpcsplus.config.ConfigManager;
|
import lol.pyr.znpcsplus.config.ConfigManager;
|
||||||
import lol.pyr.znpcsplus.conversion.DataImporter;
|
import lol.pyr.znpcsplus.conversion.DataImporter;
|
||||||
import lol.pyr.znpcsplus.conversion.znpcs.model.*;
|
import lol.pyr.znpcsplus.conversion.znpcs.model.ZNpcsAction;
|
||||||
|
import lol.pyr.znpcsplus.conversion.znpcs.model.ZNpcsLocation;
|
||||||
|
import lol.pyr.znpcsplus.conversion.znpcs.model.ZNpcsModel;
|
||||||
import lol.pyr.znpcsplus.entity.EntityPropertyImpl;
|
import lol.pyr.znpcsplus.entity.EntityPropertyImpl;
|
||||||
import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
|
import lol.pyr.znpcsplus.entity.EntityPropertyRegistryImpl;
|
||||||
import lol.pyr.znpcsplus.hologram.HologramImpl;
|
import lol.pyr.znpcsplus.hologram.HologramImpl;
|
||||||
|
@ -23,7 +25,7 @@ import lol.pyr.znpcsplus.npc.NpcImpl;
|
||||||
import lol.pyr.znpcsplus.npc.NpcTypeRegistryImpl;
|
import lol.pyr.znpcsplus.npc.NpcTypeRegistryImpl;
|
||||||
import lol.pyr.znpcsplus.packets.PacketFactory;
|
import lol.pyr.znpcsplus.packets.PacketFactory;
|
||||||
import lol.pyr.znpcsplus.scheduling.TaskScheduler;
|
import lol.pyr.znpcsplus.scheduling.TaskScheduler;
|
||||||
import lol.pyr.znpcsplus.skin.SkinImpl;
|
import lol.pyr.znpcsplus.skin.Skin;
|
||||||
import lol.pyr.znpcsplus.skin.cache.MojangSkinCache;
|
import lol.pyr.znpcsplus.skin.cache.MojangSkinCache;
|
||||||
import lol.pyr.znpcsplus.skin.descriptor.FetchingDescriptor;
|
import lol.pyr.znpcsplus.skin.descriptor.FetchingDescriptor;
|
||||||
import lol.pyr.znpcsplus.skin.descriptor.MirrorDescriptor;
|
import lol.pyr.znpcsplus.skin.descriptor.MirrorDescriptor;
|
||||||
|
@ -34,6 +36,7 @@ import lol.pyr.znpcsplus.util.LookType;
|
||||||
import lol.pyr.znpcsplus.util.NpcLocation;
|
import lol.pyr.znpcsplus.util.NpcLocation;
|
||||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||||
import org.bukkit.DyeColor;
|
import org.bukkit.DyeColor;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
@ -54,7 +57,6 @@ public class ZNpcImporter implements DataImporter {
|
||||||
private final EntityPropertyRegistryImpl propertyRegistry;
|
private final EntityPropertyRegistryImpl propertyRegistry;
|
||||||
private final MojangSkinCache skinCache;
|
private final MojangSkinCache skinCache;
|
||||||
private final File dataFile;
|
private final File dataFile;
|
||||||
private final File conversationFile;
|
|
||||||
private final Gson gson;
|
private final Gson gson;
|
||||||
private final BungeeConnector bungeeConnector;
|
private final BungeeConnector bungeeConnector;
|
||||||
|
|
||||||
|
@ -71,7 +73,6 @@ public class ZNpcImporter implements DataImporter {
|
||||||
this.propertyRegistry = propertyRegistry;
|
this.propertyRegistry = propertyRegistry;
|
||||||
this.skinCache = skinCache;
|
this.skinCache = skinCache;
|
||||||
this.dataFile = dataFile;
|
this.dataFile = dataFile;
|
||||||
this.conversationFile = new File(dataFile.getParentFile(), "conversations.json");
|
|
||||||
this.bungeeConnector = bungeeConnector;
|
this.bungeeConnector = bungeeConnector;
|
||||||
gson = new GsonBuilder()
|
gson = new GsonBuilder()
|
||||||
.create();
|
.create();
|
||||||
|
@ -88,19 +89,6 @@ public class ZNpcImporter implements DataImporter {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
if (models == null) return Collections.emptyList();
|
if (models == null) return Collections.emptyList();
|
||||||
|
|
||||||
|
|
||||||
ZnpcsConversations[] conversations;
|
|
||||||
try (BufferedReader fileReader = Files.newBufferedReader(conversationFile.toPath())) {
|
|
||||||
JsonElement element = JsonParser.parseReader(fileReader);
|
|
||||||
conversations = gson.fromJson(element, ZnpcsConversations[].class);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
if (conversations == null) return Collections.emptyList();
|
|
||||||
|
|
||||||
|
|
||||||
ArrayList<NpcEntryImpl> entries = new ArrayList<>(models.length);
|
ArrayList<NpcEntryImpl> entries = new ArrayList<>(models.length);
|
||||||
for (ZNpcsModel model : models) {
|
for (ZNpcsModel model : models) {
|
||||||
String type = model.getNpcType();
|
String type = model.getNpcType();
|
||||||
|
@ -120,41 +108,6 @@ public class ZNpcImporter implements DataImporter {
|
||||||
NpcImpl npc = new NpcImpl(uuid, propertyRegistry, configManager, packetFactory, textSerializer, oldLoc.getWorld(), typeRegistry.getByName(type), location);
|
NpcImpl npc = new NpcImpl(uuid, propertyRegistry, configManager, packetFactory, textSerializer, oldLoc.getWorld(), typeRegistry.getByName(type), location);
|
||||||
npc.getType().applyDefaultProperties(npc);
|
npc.getType().applyDefaultProperties(npc);
|
||||||
|
|
||||||
|
|
||||||
// Convert the conversations from each NPC
|
|
||||||
ZNpcsConversation conversation = model.getConversation();
|
|
||||||
if (conversation != null) {
|
|
||||||
|
|
||||||
// Loop through all conversations in the conversations.json file
|
|
||||||
for (ZnpcsConversations conv : conversations) {
|
|
||||||
|
|
||||||
// If the conversation name matches the conversation name in the data.json file, proceed
|
|
||||||
if (conv.getName().equalsIgnoreCase(conversation.getConversationName())) {
|
|
||||||
|
|
||||||
int totalDelay = 0;
|
|
||||||
|
|
||||||
// Loop through all texts in the conversation
|
|
||||||
for(ZNpcsConversationText text : conv.getTexts()) {
|
|
||||||
|
|
||||||
// Add the delay in ticks to the total delay
|
|
||||||
totalDelay += text.getDelay() * 20;
|
|
||||||
|
|
||||||
// Get the lines of text from the conversation
|
|
||||||
String[] lines = text.getLines();
|
|
||||||
|
|
||||||
// Loop through all lines of text
|
|
||||||
for (String line : lines) {
|
|
||||||
|
|
||||||
// Create a new message action for each line of text
|
|
||||||
InteractionActionImpl action = new MessageAction(adventure, line, InteractionType.ANY_CLICK, textSerializer, 0, totalDelay);
|
|
||||||
npc.addAction(action);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
HologramImpl hologram = npc.getHologram();
|
HologramImpl hologram = npc.getHologram();
|
||||||
hologram.setOffset(model.getHologramHeight());
|
hologram.setOffset(model.getHologramHeight());
|
||||||
for (String raw : model.getHologramLines()) {
|
for (String raw : model.getHologramLines()) {
|
||||||
|
@ -177,10 +130,10 @@ public class ZNpcImporter implements DataImporter {
|
||||||
npc.setProperty(propertyRegistry.getByName("skin", SkinDescriptor.class), new FetchingDescriptor(skinCache, model.getSkinName()));
|
npc.setProperty(propertyRegistry.getByName("skin", SkinDescriptor.class), new FetchingDescriptor(skinCache, model.getSkinName()));
|
||||||
}
|
}
|
||||||
else if (model.getSkin() != null && model.getSignature() != null) {
|
else if (model.getSkin() != null && model.getSignature() != null) {
|
||||||
npc.setProperty(propertyRegistry.getByName("skin", SkinDescriptor.class), new PrefetchedDescriptor(new SkinImpl(model.getSkin(), model.getSignature())));
|
npc.setProperty(propertyRegistry.getByName("skin", SkinDescriptor.class), new PrefetchedDescriptor(new Skin(model.getSkin(), model.getSignature())));
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, Object> toggleValues = model.getNpcToggleValues() == null ? model.getNpcFunctions() : model.getNpcToggleValues();
|
Map<String, Object> toggleValues = model.getNpcToggleValues();
|
||||||
if (toggleValues != null) {
|
if (toggleValues != null) {
|
||||||
if (toggleValues.containsKey("look")) {
|
if (toggleValues.containsKey("look")) {
|
||||||
npc.setProperty(propertyRegistry.getByName("look", LookType.class), LookType.CLOSEST_PLAYER);
|
npc.setProperty(propertyRegistry.getByName("look", LookType.class), LookType.CLOSEST_PLAYER);
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
package lol.pyr.znpcsplus.conversion.znpcs.model;
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public class ZNpcsConversation {
|
|
||||||
|
|
||||||
private String conversationName;
|
|
||||||
private String conversationType;
|
|
||||||
|
|
||||||
public String getConversationName() {
|
|
||||||
return conversationName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getConversationType() {
|
|
||||||
return conversationType;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
package lol.pyr.znpcsplus.conversion.znpcs.model;
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public class ZNpcsConversationText {
|
|
||||||
|
|
||||||
private String[] lines;
|
|
||||||
private ZNpcsAction[] actions;
|
|
||||||
private int delay;
|
|
||||||
|
|
||||||
public String[] getLines() {
|
|
||||||
return lines;
|
|
||||||
}
|
|
||||||
public ZNpcsAction[] getActions() {
|
|
||||||
return actions;
|
|
||||||
}
|
|
||||||
public int getDelay() {
|
|
||||||
return delay;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -14,15 +14,12 @@ public class ZNpcsModel {
|
||||||
private String signature;
|
private String signature;
|
||||||
|
|
||||||
private String glowName;
|
private String glowName;
|
||||||
|
|
||||||
private ZNpcsConversation conversation;
|
|
||||||
private ZNpcsLocation location;
|
private ZNpcsLocation location;
|
||||||
private String npcType;
|
private String npcType;
|
||||||
private List<String> hologramLines;
|
private List<String> hologramLines;
|
||||||
private List<ZNpcsAction> clickActions;
|
private List<ZNpcsAction> clickActions;
|
||||||
private Map<String, String> npcEquip;
|
private Map<String, String> npcEquip;
|
||||||
private Map<String, Object> npcToggleValues;
|
private Map<String, Object> npcToggleValues;
|
||||||
private Map<String, Object> npcFunctions;
|
|
||||||
private Map<String, String[]> customizationMap;
|
private Map<String, String[]> customizationMap;
|
||||||
|
|
||||||
public int getId() {
|
public int getId() {
|
||||||
|
@ -41,10 +38,6 @@ public class ZNpcsModel {
|
||||||
return skinName;
|
return skinName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ZNpcsConversation getConversation() {
|
|
||||||
return conversation;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ZNpcsLocation getLocation() {
|
public ZNpcsLocation getLocation() {
|
||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
|
@ -69,10 +62,6 @@ public class ZNpcsModel {
|
||||||
return npcToggleValues;
|
return npcToggleValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Object> getNpcFunctions() {
|
|
||||||
return npcFunctions;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, String[]> getCustomizationMap() {
|
public Map<String, String[]> getCustomizationMap() {
|
||||||
return customizationMap;
|
return customizationMap;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
package lol.pyr.znpcsplus.conversion.znpcs.model;
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public class ZnpcsConversations {
|
|
||||||
|
|
||||||
private String name;
|
|
||||||
private ZNpcsConversationText[] texts;
|
|
||||||
private int radius;
|
|
||||||
private int delay;
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
public ZNpcsConversationText[] getTexts() {
|
|
||||||
return texts;
|
|
||||||
}
|
|
||||||
public int getRadius() {
|
|
||||||
return radius;
|
|
||||||
}
|
|
||||||
public int getDelay() {
|
|
||||||
return delay;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -92,10 +92,18 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
|
||||||
/*
|
/*
|
||||||
registerType("using_item", false); // TODO: fix it for 1.8 and add new property to use offhand item and riptide animation
|
registerType("using_item", false); // TODO: fix it for 1.8 and add new property to use offhand item and riptide animation
|
||||||
|
|
||||||
|
// End Crystal
|
||||||
|
registerType("beam_target", null); // TODO: Make a block pos class for this
|
||||||
|
registerType("show_base", true); // TODO
|
||||||
|
|
||||||
// Enderman
|
// Enderman
|
||||||
registerType("enderman_held_block", new BlockState(0)); // TODO: figure out the type on this
|
registerType("enderman_held_block", new BlockState(0)); // TODO: figure out the type on this
|
||||||
registerType("enderman_screaming", false); // TODO
|
registerType("enderman_screaming", false); // TODO
|
||||||
registerType("enderman_staring", false); // TODO
|
registerType("enderman_staring", false); // TODO
|
||||||
|
|
||||||
|
// Guardian
|
||||||
|
registerType("is_elder", false); // TODO: ensure it only works till 1.10. Note: index is wrong on wiki.vg
|
||||||
|
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,6 @@ import lol.pyr.znpcsplus.packets.PacketFactory;
|
||||||
import lol.pyr.znpcsplus.reflection.Reflections;
|
import lol.pyr.znpcsplus.reflection.Reflections;
|
||||||
import lol.pyr.znpcsplus.util.NpcLocation;
|
import lol.pyr.znpcsplus.util.NpcLocation;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -73,10 +72,6 @@ public class PacketEntity implements PropertyHolder {
|
||||||
packetFactory.sendAllMetadata(player, this, properties);
|
packetFactory.sendAllMetadata(player, this, properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void swingHand(Player player, boolean offhand) {
|
|
||||||
packetFactory.sendHandSwing(player, this, offhand);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int reserveEntityID() {
|
private static int reserveEntityID() {
|
||||||
if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_14)) {
|
if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_14)) {
|
||||||
return Reflections.ATOMIC_ENTITY_ID_FIELD.get().incrementAndGet();
|
return Reflections.ATOMIC_ENTITY_ID_FIELD.get().incrementAndGet();
|
||||||
|
@ -102,11 +97,6 @@ public class PacketEntity implements PropertyHolder {
|
||||||
properties.setProperty(key, value);
|
properties.setProperty(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setItemProperty(EntityProperty<?> key, ItemStack value) {
|
|
||||||
properties.setItemProperty(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<EntityProperty<?>> getAppliedProperties() {
|
public Set<EntityProperty<?>> getAppliedProperties() {
|
||||||
return properties.getAppliedProperties();
|
return properties.getAppliedProperties();
|
||||||
|
|
|
@ -106,7 +106,7 @@ public class HologramImpl extends Viewable implements Hologram {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void insertTextLine(int index, String line) {
|
public void insertTextLine(int index, String line) {
|
||||||
insertTextLineComponent(index, textSerializer.deserialize(textSerializer.serialize(MiniMessage.miniMessage().deserialize(line))));
|
insertTextLineComponent(index, textSerializer.deserialize(line));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void insertItemLineStack(int index, org.bukkit.inventory.ItemStack item) {
|
public void insertItemLineStack(int index, org.bukkit.inventory.ItemStack item) {
|
||||||
|
|
|
@ -7,7 +7,6 @@ import lol.pyr.znpcsplus.entity.PacketEntity;
|
||||||
import lol.pyr.znpcsplus.packets.PacketFactory;
|
import lol.pyr.znpcsplus.packets.PacketFactory;
|
||||||
import lol.pyr.znpcsplus.util.NpcLocation;
|
import lol.pyr.znpcsplus.util.NpcLocation;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
@ -71,11 +70,6 @@ public class HologramLine<M> implements PropertyHolder {
|
||||||
throw new UnsupportedOperationException("Can't set properties on a hologram line");
|
throw new UnsupportedOperationException("Can't set properties on a hologram line");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setItemProperty(EntityProperty<?> key, ItemStack value) {
|
|
||||||
throw new UnsupportedOperationException("Can't set properties on a hologram line");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<EntityProperty<?>> getAppliedProperties() {
|
public Set<EntityProperty<?>> getAppliedProperties() {
|
||||||
return properties;
|
return properties;
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package lol.pyr.znpcsplus.npc;
|
package lol.pyr.znpcsplus.npc;
|
||||||
|
|
||||||
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
|
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
|
||||||
import io.github.retrooper.packetevents.util.SpigotConversionUtil;
|
|
||||||
import lol.pyr.znpcsplus.api.entity.EntityProperty;
|
import lol.pyr.znpcsplus.api.entity.EntityProperty;
|
||||||
import lol.pyr.znpcsplus.api.npc.Npc;
|
import lol.pyr.znpcsplus.api.npc.Npc;
|
||||||
import lol.pyr.znpcsplus.api.npc.NpcType;
|
import lol.pyr.znpcsplus.api.npc.NpcType;
|
||||||
|
@ -19,7 +18,6 @@ import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
@ -148,20 +146,9 @@ public class NpcImpl extends Viewable implements Npc {
|
||||||
return propertyMap.containsKey((EntityPropertyImpl<?>) key);
|
return propertyMap.containsKey((EntityPropertyImpl<?>) key);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
@Override
|
||||||
public <T> void setProperty(EntityProperty<T> key, T value) {
|
public <T> void setProperty(EntityProperty<T> key, T value) {
|
||||||
// See https://github.com/Pyrbu/ZNPCsPlus/pull/129#issuecomment-1948777764
|
setProperty((EntityPropertyImpl<T>) key, value );
|
||||||
Object val = value;
|
|
||||||
if (val instanceof ItemStack) val = SpigotConversionUtil.fromBukkitItemStack((ItemStack) val);
|
|
||||||
|
|
||||||
setProperty((EntityPropertyImpl<T>) key, (T) val);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public void setItemProperty(EntityProperty<?> key, ItemStack value) {
|
|
||||||
setProperty((EntityPropertyImpl<com.github.retrooper.packetevents.protocol.item.ItemStack>) key, SpigotConversionUtil.fromBukkitItemStack(value));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> void setProperty(EntityPropertyImpl<T> key, T value) {
|
public <T> void setProperty(EntityPropertyImpl<T> key, T value) {
|
||||||
|
@ -214,8 +201,4 @@ public class NpcImpl extends Viewable implements Npc {
|
||||||
delete();
|
delete();
|
||||||
this.worldName = world.getName();
|
this.worldName = world.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void swingHand(boolean offHand) {
|
|
||||||
for (Player viewer : getViewers()) entity.swingHand(viewer, offHand);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -156,7 +156,7 @@ public class NpcTypeImpl implements NpcType {
|
||||||
}
|
}
|
||||||
if (EntityTypes.isTypeInstanceOf(type, EntityTypes.PANDA)) {
|
if (EntityTypes.isTypeInstanceOf(type, EntityTypes.PANDA)) {
|
||||||
if (version.isNewerThanOrEquals(ServerVersion.V_1_15)) {
|
if (version.isNewerThanOrEquals(ServerVersion.V_1_15)) {
|
||||||
addProperties("panda_rolling", "panda_sitting", "panda_on_back", "hand");
|
addProperties("panda_rolling", "panda_sitting", "panda_on_back");
|
||||||
} else {
|
} else {
|
||||||
addProperties("panda_eating");
|
addProperties("panda_eating");
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,5 +23,4 @@ public interface PacketFactory {
|
||||||
void sendEquipment(Player player, PacketEntity entity, Equipment equipment);
|
void sendEquipment(Player player, PacketEntity entity, Equipment equipment);
|
||||||
void sendMetadata(Player player, PacketEntity entity, List<EntityData> data);
|
void sendMetadata(Player player, PacketEntity entity, List<EntityData> data);
|
||||||
void sendHeadRotation(Player player, PacketEntity entity, float yaw, float pitch);
|
void sendHeadRotation(Player player, PacketEntity entity, float yaw, float pitch);
|
||||||
void sendHandSwing(Player player, PacketEntity entity, boolean offHand);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,8 @@ import org.bukkit.plugin.Plugin;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
public class V1_19_3PacketFactory extends V1_17PacketFactory {
|
public class V1_19_2PacketFactory extends V1_17PacketFactory {
|
||||||
public V1_19_3PacketFactory(TaskScheduler scheduler, PacketEventsAPI<Plugin> packetEvents, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer, ConfigManager configManager) {
|
public V1_19_2PacketFactory(TaskScheduler scheduler, PacketEventsAPI<Plugin> packetEvents, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer, ConfigManager configManager) {
|
||||||
super(scheduler, packetEvents, propertyRegistry, textSerializer, configManager);
|
super(scheduler, packetEvents, propertyRegistry, textSerializer, configManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,8 +30,7 @@ public class V1_19_3PacketFactory extends V1_17PacketFactory {
|
||||||
CompletableFuture<Void> future = new CompletableFuture<>();
|
CompletableFuture<Void> future = new CompletableFuture<>();
|
||||||
skinned(player, properties, new UserProfile(entity.getUuid(), Integer.toString(entity.getEntityId()))).thenAccept(profile -> {
|
skinned(player, properties, new UserProfile(entity.getUuid(), Integer.toString(entity.getEntityId()))).thenAccept(profile -> {
|
||||||
WrapperPlayServerPlayerInfoUpdate.PlayerInfo info = new WrapperPlayServerPlayerInfoUpdate.PlayerInfo(
|
WrapperPlayServerPlayerInfoUpdate.PlayerInfo info = new WrapperPlayServerPlayerInfoUpdate.PlayerInfo(
|
||||||
profile, false, 1, GameMode.CREATIVE,
|
profile, false, 1, GameMode.CREATIVE, Component.empty(), null);
|
||||||
Component.text(configManager.getConfig().tabDisplayName().replace("{id}", Integer.toString(entity.getEntityId()))), null);
|
|
||||||
sendPacket(player, new WrapperPlayServerPlayerInfoUpdate(EnumSet.of(WrapperPlayServerPlayerInfoUpdate.Action.ADD_PLAYER,
|
sendPacket(player, new WrapperPlayServerPlayerInfoUpdate(EnumSet.of(WrapperPlayServerPlayerInfoUpdate.Action.ADD_PLAYER,
|
||||||
WrapperPlayServerPlayerInfoUpdate.Action.UPDATE_LISTED), info, info));
|
WrapperPlayServerPlayerInfoUpdate.Action.UPDATE_LISTED), info, info));
|
||||||
future.complete(null);
|
future.complete(null);
|
|
@ -17,13 +17,12 @@ import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
public class V1_20_2PacketFactory extends V1_19_3PacketFactory {
|
public class V1_20_2PacketFactory extends V1_19_2PacketFactory {
|
||||||
|
|
||||||
protected ConfigManager configManager;
|
protected ConfigManager configManager;
|
||||||
|
|
||||||
public V1_20_2PacketFactory(TaskScheduler scheduler, PacketEventsAPI<Plugin> packetEvents, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer, ConfigManager configManager) {
|
public V1_20_2PacketFactory(TaskScheduler scheduler, PacketEventsAPI<Plugin> packetEvents, EntityPropertyRegistryImpl propertyRegistry, LegacyComponentSerializer textSerializer, ConfigManager configManager) {
|
||||||
super(scheduler, packetEvents, propertyRegistry, textSerializer, configManager);
|
super(scheduler, packetEvents, propertyRegistry, textSerializer, configManager);
|
||||||
this.configManager = configManager;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -96,8 +96,7 @@ public class V1_8PacketFactory implements PacketFactory {
|
||||||
CompletableFuture<Void> future = new CompletableFuture<>();
|
CompletableFuture<Void> future = new CompletableFuture<>();
|
||||||
skinned(player, properties, new UserProfile(entity.getUuid(), Integer.toString(entity.getEntityId()))).thenAccept(profile -> {
|
skinned(player, properties, new UserProfile(entity.getUuid(), Integer.toString(entity.getEntityId()))).thenAccept(profile -> {
|
||||||
sendPacket(player, new WrapperPlayServerPlayerInfo(
|
sendPacket(player, new WrapperPlayServerPlayerInfo(
|
||||||
WrapperPlayServerPlayerInfo.Action.ADD_PLAYER, new WrapperPlayServerPlayerInfo.PlayerData(
|
WrapperPlayServerPlayerInfo.Action.ADD_PLAYER, new WrapperPlayServerPlayerInfo.PlayerData(Component.text(" "),
|
||||||
Component.text(configManager.getConfig().tabDisplayName().replace("{id}", Integer.toString(entity.getEntityId()))),
|
|
||||||
profile, GameMode.CREATIVE, 1)));
|
profile, GameMode.CREATIVE, 1)));
|
||||||
future.complete(null);
|
future.complete(null);
|
||||||
});
|
});
|
||||||
|
@ -115,7 +114,7 @@ public class V1_8PacketFactory implements PacketFactory {
|
||||||
@Override
|
@Override
|
||||||
public void createTeam(Player player, PacketEntity entity, NamedColor namedColor) {
|
public void createTeam(Player player, PacketEntity entity, NamedColor namedColor) {
|
||||||
sendPacket(player, new WrapperPlayServerTeams("npc_team_" + entity.getEntityId(), WrapperPlayServerTeams.TeamMode.CREATE, new WrapperPlayServerTeams.ScoreBoardTeamInfo(
|
sendPacket(player, new WrapperPlayServerTeams("npc_team_" + entity.getEntityId(), WrapperPlayServerTeams.TeamMode.CREATE, new WrapperPlayServerTeams.ScoreBoardTeamInfo(
|
||||||
Component.text(" "), null, null,
|
Component.empty(), Component.empty(), Component.empty(),
|
||||||
WrapperPlayServerTeams.NameTagVisibility.NEVER,
|
WrapperPlayServerTeams.NameTagVisibility.NEVER,
|
||||||
WrapperPlayServerTeams.CollisionRule.NEVER,
|
WrapperPlayServerTeams.CollisionRule.NEVER,
|
||||||
namedColor == null ? NamedTextColor.WHITE : NamedTextColor.NAMES.value(namedColor.name().toLowerCase()),
|
namedColor == null ? NamedTextColor.WHITE : NamedTextColor.NAMES.value(namedColor.name().toLowerCase()),
|
||||||
|
@ -175,11 +174,4 @@ public class V1_8PacketFactory implements PacketFactory {
|
||||||
protected void add(Map<Integer, EntityData> map, EntityData data) {
|
protected void add(Map<Integer, EntityData> map, EntityData data) {
|
||||||
map.put(data.getIndex(), data);
|
map.put(data.getIndex(), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendHandSwing(Player player, PacketEntity entity, boolean offHand) {
|
|
||||||
sendPacket(player, new WrapperPlayServerEntityAnimation(entity.getEntityId(), offHand ?
|
|
||||||
WrapperPlayServerEntityAnimation.EntityAnimationType.SWING_OFF_HAND :
|
|
||||||
WrapperPlayServerEntityAnimation.EntityAnimationType.SWING_MAIN_ARM));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,8 +13,8 @@ import java.util.List;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
public interface BaseSkinDescriptor extends SkinDescriptor {
|
public interface BaseSkinDescriptor extends SkinDescriptor {
|
||||||
CompletableFuture<SkinImpl> fetch(Player player);
|
CompletableFuture<Skin> fetch(Player player);
|
||||||
SkinImpl fetchInstant(Player player);
|
Skin fetchInstant(Player player);
|
||||||
boolean supportsInstant(Player player);
|
boolean supportsInstant(Player player);
|
||||||
String serialize();
|
String serialize();
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ public interface BaseSkinDescriptor extends SkinDescriptor {
|
||||||
for (int i = 0; i < (arr.length - 1) / 3; i++) {
|
for (int i = 0; i < (arr.length - 1) / 3; i++) {
|
||||||
properties.add(new TextureProperty(arr[i + 1], arr[i + 2], arr[i + 3]));
|
properties.add(new TextureProperty(arr[i + 1], arr[i + 2], arr[i + 3]));
|
||||||
}
|
}
|
||||||
return new PrefetchedDescriptor(new SkinImpl(properties));
|
return new PrefetchedDescriptor(new Skin(properties));
|
||||||
}
|
}
|
||||||
throw new IllegalArgumentException("Unknown SkinDescriptor type!");
|
throw new IllegalArgumentException("Unknown SkinDescriptor type!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ import com.github.retrooper.packetevents.protocol.player.TextureProperty;
|
||||||
import com.github.retrooper.packetevents.protocol.player.UserProfile;
|
import com.github.retrooper.packetevents.protocol.player.UserProfile;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import lol.pyr.znpcsplus.api.skin.Skin;
|
|
||||||
import lol.pyr.znpcsplus.reflection.Reflections;
|
import lol.pyr.znpcsplus.reflection.Reflections;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
@ -14,21 +13,21 @@ import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class SkinImpl implements Skin {
|
public class Skin {
|
||||||
private final long timestamp = System.currentTimeMillis();
|
private final long timestamp = System.currentTimeMillis();
|
||||||
private final List<TextureProperty> properties;
|
private final List<TextureProperty> properties;
|
||||||
private static final boolean V1_20_2 = PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_20_2);
|
private static final boolean V1_20_2 = PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_20_2);
|
||||||
|
|
||||||
public SkinImpl(String texture, String signature) {
|
public Skin(String texture, String signature) {
|
||||||
properties = new ArrayList<>(1);
|
properties = new ArrayList<>(1);
|
||||||
properties.add(new TextureProperty("textures", texture, signature));
|
properties.add(new TextureProperty("textures", texture, signature));
|
||||||
}
|
}
|
||||||
|
|
||||||
public SkinImpl(Collection<TextureProperty> properties) {
|
public Skin(Collection<TextureProperty> properties) {
|
||||||
this.properties = new ArrayList<>(properties);
|
this.properties = new ArrayList<>(properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SkinImpl(Object propertyMap) {
|
public Skin(Object propertyMap) {
|
||||||
this.properties = new ArrayList<>();
|
this.properties = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
Collection<?> properties = (Collection<?>) Reflections.PROPERTY_MAP_VALUES_METHOD.get().invoke(propertyMap);
|
Collection<?> properties = (Collection<?>) Reflections.PROPERTY_MAP_VALUES_METHOD.get().invoke(propertyMap);
|
||||||
|
@ -52,7 +51,7 @@ public class SkinImpl implements Skin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public SkinImpl(JsonObject obj) {
|
public Skin(JsonObject obj) {
|
||||||
properties = new ArrayList<>();
|
properties = new ArrayList<>();
|
||||||
for (JsonElement e : obj.get("properties").getAsJsonArray()) {
|
for (JsonElement e : obj.get("properties").getAsJsonArray()) {
|
||||||
JsonObject o = e.getAsJsonObject();
|
JsonObject o = e.getAsJsonObject();
|
||||||
|
@ -72,20 +71,4 @@ public class SkinImpl implements Skin {
|
||||||
public boolean isExpired() {
|
public boolean isExpired() {
|
||||||
return System.currentTimeMillis() - timestamp > 60000L;
|
return System.currentTimeMillis() - timestamp > 60000L;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getTexture() {
|
|
||||||
for (TextureProperty property : properties)
|
|
||||||
if (property.getName().equalsIgnoreCase("textures"))
|
|
||||||
return property.getValue();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getSignature() {
|
|
||||||
for (TextureProperty property : properties)
|
|
||||||
if (property.getName().equalsIgnoreCase("textures"))
|
|
||||||
return property.getSignature();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -36,7 +36,7 @@ public class SkinDescriptorFactoryImpl implements SkinDescriptorFactory {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SkinDescriptor createStaticDescriptor(String texture, String signature) {
|
public SkinDescriptor createStaticDescriptor(String texture, String signature) {
|
||||||
return new PrefetchedDescriptor(new SkinImpl(texture, signature));
|
return new PrefetchedDescriptor(new Skin(texture, signature));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -4,7 +4,7 @@ import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
import lol.pyr.znpcsplus.config.ConfigManager;
|
import lol.pyr.znpcsplus.config.ConfigManager;
|
||||||
import lol.pyr.znpcsplus.reflection.Reflections;
|
import lol.pyr.znpcsplus.reflection.Reflections;
|
||||||
import lol.pyr.znpcsplus.skin.SkinImpl;
|
import lol.pyr.znpcsplus.skin.Skin;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ public class MojangSkinCache {
|
||||||
|
|
||||||
private final ConfigManager configManager;
|
private final ConfigManager configManager;
|
||||||
|
|
||||||
private final Map<String, SkinImpl> cache = new ConcurrentHashMap<>();
|
private final Map<String, Skin> cache = new ConcurrentHashMap<>();
|
||||||
private final Map<String, CachedId> idCache = new ConcurrentHashMap<>();
|
private final Map<String, CachedId> idCache = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public MojangSkinCache(ConfigManager configManager) {
|
public MojangSkinCache(ConfigManager configManager) {
|
||||||
|
@ -32,11 +32,11 @@ public class MojangSkinCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cleanCache() {
|
public void cleanCache() {
|
||||||
for (Map.Entry<String, SkinImpl> entry : cache.entrySet()) if (entry.getValue().isExpired()) cache.remove(entry.getKey());
|
for (Map.Entry<String, Skin> entry : cache.entrySet()) if (entry.getValue().isExpired()) cache.remove(entry.getKey());
|
||||||
for (Map.Entry<String, CachedId> entry : idCache.entrySet()) if (entry.getValue().isExpired()) cache.remove(entry.getKey());
|
for (Map.Entry<String, CachedId> entry : idCache.entrySet()) if (entry.getValue().isExpired()) cache.remove(entry.getKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompletableFuture<SkinImpl> fetchByName(String name) {
|
public CompletableFuture<Skin> fetchByName(String name) {
|
||||||
Player player = Bukkit.getPlayerExact(name);
|
Player player = Bukkit.getPlayerExact(name);
|
||||||
if (player != null && player.isOnline()) return CompletableFuture.completedFuture(getFromPlayer(player));
|
if (player != null && player.isOnline()) return CompletableFuture.completedFuture(getFromPlayer(player));
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ public class MojangSkinCache {
|
||||||
if (obj.has("errorMessage")) return fetchByNameFallback(name).join();
|
if (obj.has("errorMessage")) return fetchByNameFallback(name).join();
|
||||||
String id = obj.get("id").getAsString();
|
String id = obj.get("id").getAsString();
|
||||||
idCache.put(name.toLowerCase(), new CachedId(id));
|
idCache.put(name.toLowerCase(), new CachedId(id));
|
||||||
SkinImpl skin = fetchByUUID(id).join();
|
Skin skin = fetchByUUID(id).join();
|
||||||
if (skin == null) return fetchByNameFallback(name).join();
|
if (skin == null) return fetchByNameFallback(name).join();
|
||||||
return skin;
|
return skin;
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ public class MojangSkinCache {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompletableFuture<SkinImpl> fetchByNameFallback(String name) {
|
public CompletableFuture<Skin> fetchByNameFallback(String name) {
|
||||||
Player player = Bukkit.getPlayerExact(name);
|
Player player = Bukkit.getPlayerExact(name);
|
||||||
if (player != null && player.isOnline()) return CompletableFuture.completedFuture(getFromPlayer(player));
|
if (player != null && player.isOnline()) return CompletableFuture.completedFuture(getFromPlayer(player));
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ public class MojangSkinCache {
|
||||||
JsonObject textures = obj.get("textures").getAsJsonObject();
|
JsonObject textures = obj.get("textures").getAsJsonObject();
|
||||||
String value = textures.get("raw").getAsJsonObject().get("value").getAsString();
|
String value = textures.get("raw").getAsJsonObject().get("value").getAsString();
|
||||||
String signature = textures.get("raw").getAsJsonObject().get("signature").getAsString();
|
String signature = textures.get("raw").getAsJsonObject().get("signature").getAsString();
|
||||||
SkinImpl skin = new SkinImpl(value, signature);
|
Skin skin = new Skin(value, signature);
|
||||||
cache.put(uuid, skin);
|
cache.put(uuid, skin);
|
||||||
return skin;
|
return skin;
|
||||||
}
|
}
|
||||||
|
@ -105,7 +105,7 @@ public class MojangSkinCache {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompletableFuture<SkinImpl> fetchByUrl(URL url, String variant) {
|
public CompletableFuture<Skin> fetchByUrl(URL url, String variant) {
|
||||||
return CompletableFuture.supplyAsync(() -> {
|
return CompletableFuture.supplyAsync(() -> {
|
||||||
URL apiUrl = parseUrl("https://api.mineskin.org/generate/url");
|
URL apiUrl = parseUrl("https://api.mineskin.org/generate/url");
|
||||||
HttpURLConnection connection = null;
|
HttpURLConnection connection = null;
|
||||||
|
@ -127,7 +127,7 @@ public class MojangSkinCache {
|
||||||
if (obj.has("error")) return null;
|
if (obj.has("error")) return null;
|
||||||
if (!obj.has("data")) return null;
|
if (!obj.has("data")) return null;
|
||||||
JsonObject texture = obj.get("data").getAsJsonObject().get("texture").getAsJsonObject();
|
JsonObject texture = obj.get("data").getAsJsonObject().get("texture").getAsJsonObject();
|
||||||
return new SkinImpl(texture.get("value").getAsString(), texture.get("signature").getAsString());
|
return new Skin(texture.get("value").getAsString(), texture.get("signature").getAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (IOException exception) {
|
} catch (IOException exception) {
|
||||||
|
@ -147,26 +147,26 @@ public class MojangSkinCache {
|
||||||
if (!idCache.containsKey(name)) return false;
|
if (!idCache.containsKey(name)) return false;
|
||||||
CachedId id = idCache.get(name);
|
CachedId id = idCache.get(name);
|
||||||
if (id.isExpired() || !cache.containsKey(id.getId())) return false;
|
if (id.isExpired() || !cache.containsKey(id.getId())) return false;
|
||||||
SkinImpl skin = cache.get(id.getId());
|
Skin skin = cache.get(id.getId());
|
||||||
return !skin.isExpired();
|
return !skin.isExpired();
|
||||||
}
|
}
|
||||||
|
|
||||||
public SkinImpl getFullyCachedByName(String s) {
|
public Skin getFullyCachedByName(String s) {
|
||||||
String name = s.toLowerCase();
|
String name = s.toLowerCase();
|
||||||
if (!idCache.containsKey(name)) return null;
|
if (!idCache.containsKey(name)) return null;
|
||||||
CachedId id = idCache.get(name);
|
CachedId id = idCache.get(name);
|
||||||
if (id.isExpired() || !cache.containsKey(id.getId())) return null;
|
if (id.isExpired() || !cache.containsKey(id.getId())) return null;
|
||||||
SkinImpl skin = cache.get(id.getId());
|
Skin skin = cache.get(id.getId());
|
||||||
if (skin.isExpired()) return null;
|
if (skin.isExpired()) return null;
|
||||||
return skin;
|
return skin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompletableFuture<SkinImpl> fetchByUUID(String uuid) {
|
public CompletableFuture<Skin> fetchByUUID(String uuid) {
|
||||||
Player player = Bukkit.getPlayer(uuid);
|
Player player = Bukkit.getPlayer(uuid);
|
||||||
if (player != null && player.isOnline()) return CompletableFuture.completedFuture(getFromPlayer(player));
|
if (player != null && player.isOnline()) return CompletableFuture.completedFuture(getFromPlayer(player));
|
||||||
|
|
||||||
if (cache.containsKey(uuid)) {
|
if (cache.containsKey(uuid)) {
|
||||||
SkinImpl skin = cache.get(uuid);
|
Skin skin = cache.get(uuid);
|
||||||
if (!skin.isExpired()) return CompletableFuture.completedFuture(skin);
|
if (!skin.isExpired()) return CompletableFuture.completedFuture(skin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,7 +179,7 @@ public class MojangSkinCache {
|
||||||
try (Reader reader = new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8)) {
|
try (Reader reader = new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8)) {
|
||||||
JsonObject obj = JsonParser.parseReader(reader).getAsJsonObject();
|
JsonObject obj = JsonParser.parseReader(reader).getAsJsonObject();
|
||||||
if (obj.has("errorMessage")) return null;
|
if (obj.has("errorMessage")) return null;
|
||||||
SkinImpl skin = new SkinImpl(obj);
|
Skin skin = new Skin(obj);
|
||||||
cache.put(uuid, skin);
|
cache.put(uuid, skin);
|
||||||
return skin;
|
return skin;
|
||||||
}
|
}
|
||||||
|
@ -195,12 +195,12 @@ public class MojangSkinCache {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public SkinImpl getFromPlayer(Player player) {
|
public Skin getFromPlayer(Player player) {
|
||||||
try {
|
try {
|
||||||
Object playerHandle = Reflections.GET_PLAYER_HANDLE_METHOD.get().invoke(player);
|
Object playerHandle = Reflections.GET_PLAYER_HANDLE_METHOD.get().invoke(player);
|
||||||
Object gameProfile = Reflections.GET_PROFILE_METHOD.get().invoke(playerHandle);
|
Object gameProfile = Reflections.GET_PROFILE_METHOD.get().invoke(playerHandle);
|
||||||
Object propertyMap = Reflections.GET_PROPERTY_MAP_METHOD.get().invoke(gameProfile);
|
Object propertyMap = Reflections.GET_PROPERTY_MAP_METHOD.get().invoke(gameProfile);
|
||||||
return new SkinImpl(propertyMap);
|
return new Skin(propertyMap);
|
||||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ package lol.pyr.znpcsplus.skin.descriptor;
|
||||||
|
|
||||||
import lol.pyr.znpcsplus.api.skin.SkinDescriptor;
|
import lol.pyr.znpcsplus.api.skin.SkinDescriptor;
|
||||||
import lol.pyr.znpcsplus.skin.BaseSkinDescriptor;
|
import lol.pyr.znpcsplus.skin.BaseSkinDescriptor;
|
||||||
import lol.pyr.znpcsplus.skin.SkinImpl;
|
import lol.pyr.znpcsplus.skin.Skin;
|
||||||
import lol.pyr.znpcsplus.skin.cache.MojangSkinCache;
|
import lol.pyr.znpcsplus.skin.cache.MojangSkinCache;
|
||||||
import lol.pyr.znpcsplus.util.PapiUtil;
|
import lol.pyr.znpcsplus.util.PapiUtil;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
@ -19,12 +19,12 @@ public class FetchingDescriptor implements BaseSkinDescriptor, SkinDescriptor {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<SkinImpl> fetch(Player player) {
|
public CompletableFuture<Skin> fetch(Player player) {
|
||||||
return skinCache.fetchByName(PapiUtil.set(player, name));
|
return skinCache.fetchByName(PapiUtil.set(player, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SkinImpl fetchInstant(Player player) {
|
public Skin fetchInstant(Player player) {
|
||||||
return skinCache.getFullyCachedByName(PapiUtil.set(player, name));
|
return skinCache.getFullyCachedByName(PapiUtil.set(player, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ package lol.pyr.znpcsplus.skin.descriptor;
|
||||||
|
|
||||||
import lol.pyr.znpcsplus.api.skin.SkinDescriptor;
|
import lol.pyr.znpcsplus.api.skin.SkinDescriptor;
|
||||||
import lol.pyr.znpcsplus.skin.BaseSkinDescriptor;
|
import lol.pyr.znpcsplus.skin.BaseSkinDescriptor;
|
||||||
import lol.pyr.znpcsplus.skin.SkinImpl;
|
import lol.pyr.znpcsplus.skin.Skin;
|
||||||
import lol.pyr.znpcsplus.skin.cache.MojangSkinCache;
|
import lol.pyr.znpcsplus.skin.cache.MojangSkinCache;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
@ -16,12 +16,12 @@ public class MirrorDescriptor implements BaseSkinDescriptor, SkinDescriptor {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<SkinImpl> fetch(Player player) {
|
public CompletableFuture<Skin> fetch(Player player) {
|
||||||
return CompletableFuture.completedFuture(skinCache.getFromPlayer(player));
|
return CompletableFuture.completedFuture(skinCache.getFromPlayer(player));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SkinImpl fetchInstant(Player player) {
|
public Skin fetchInstant(Player player) {
|
||||||
return skinCache.getFromPlayer(player);
|
return skinCache.getFromPlayer(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ package lol.pyr.znpcsplus.skin.descriptor;
|
||||||
import com.github.retrooper.packetevents.protocol.player.TextureProperty;
|
import com.github.retrooper.packetevents.protocol.player.TextureProperty;
|
||||||
import lol.pyr.znpcsplus.api.skin.SkinDescriptor;
|
import lol.pyr.znpcsplus.api.skin.SkinDescriptor;
|
||||||
import lol.pyr.znpcsplus.skin.BaseSkinDescriptor;
|
import lol.pyr.znpcsplus.skin.BaseSkinDescriptor;
|
||||||
import lol.pyr.znpcsplus.skin.SkinImpl;
|
import lol.pyr.znpcsplus.skin.Skin;
|
||||||
import lol.pyr.znpcsplus.skin.cache.MojangSkinCache;
|
import lol.pyr.znpcsplus.skin.cache.MojangSkinCache;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
@ -11,9 +11,9 @@ import java.net.URL;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
public class PrefetchedDescriptor implements BaseSkinDescriptor, SkinDescriptor {
|
public class PrefetchedDescriptor implements BaseSkinDescriptor, SkinDescriptor {
|
||||||
private final SkinImpl skin;
|
private final Skin skin;
|
||||||
|
|
||||||
public PrefetchedDescriptor(SkinImpl skin) {
|
public PrefetchedDescriptor(Skin skin) {
|
||||||
this.skin = skin;
|
this.skin = skin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,12 +26,12 @@ public class PrefetchedDescriptor implements BaseSkinDescriptor, SkinDescriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<SkinImpl> fetch(Player player) {
|
public CompletableFuture<Skin> fetch(Player player) {
|
||||||
return CompletableFuture.completedFuture(skin);
|
return CompletableFuture.completedFuture(skin);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SkinImpl fetchInstant(Player player) {
|
public Skin fetchInstant(Player player) {
|
||||||
return skin;
|
return skin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ public class PrefetchedDescriptor implements BaseSkinDescriptor, SkinDescriptor
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SkinImpl getSkin() {
|
public Skin getSkin() {
|
||||||
return skin;
|
return skin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,10 @@ public class UpdateChecker extends BukkitRunnable {
|
||||||
if (resource == null) return;
|
if (resource == null) return;
|
||||||
newestVersion = resource.getVersion();
|
newestVersion = resource.getVersion();
|
||||||
|
|
||||||
status = compareVersions(info.getVersion(), newestVersion);
|
int current = versionToNumber(info.getVersion());
|
||||||
|
int newest = versionToNumber(newestVersion);
|
||||||
|
|
||||||
|
status = current >= newest ? Status.LATEST_VERSION : Status.UPDATE_NEEDED;
|
||||||
if (status == Status.UPDATE_NEEDED) notifyConsole();
|
if (status == Status.UPDATE_NEEDED) notifyConsole();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,43 +40,10 @@ public class UpdateChecker extends BukkitRunnable {
|
||||||
logger.warning("Download it at " + UpdateChecker.DOWNLOAD_LINK);
|
logger.warning("Download it at " + UpdateChecker.DOWNLOAD_LINK);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Status compareVersions(String currentVersion, String newVersion) {
|
private int versionToNumber(String version) {
|
||||||
if (currentVersion.equalsIgnoreCase(newVersion)) return Status.LATEST_VERSION;
|
int num = Integer.parseInt(version.replaceAll("[^0-9]", ""));
|
||||||
ReleaseType currentType = parseReleaseType(currentVersion);
|
if (version.toLowerCase().contains("snapshot")) num -= 1;
|
||||||
ReleaseType newType = parseReleaseType(newVersion);
|
return num;
|
||||||
if (currentType == ReleaseType.UNKNOWN || newType == ReleaseType.UNKNOWN) return Status.UNKNOWN;
|
|
||||||
String currentVersionWithoutType = getVersionWithoutReleaseType(currentVersion);
|
|
||||||
String newVersionWithoutType = getVersionWithoutReleaseType(newVersion);
|
|
||||||
String[] currentParts = currentVersionWithoutType.split("\\.");
|
|
||||||
String[] newParts = newVersionWithoutType.split("\\.");
|
|
||||||
for (int i = 0; i < Math.min(currentParts.length, newParts.length); i++) {
|
|
||||||
int currentPart = Integer.parseInt(currentParts[i]);
|
|
||||||
int newPart = Integer.parseInt(newParts[i]);
|
|
||||||
if (newPart > currentPart) return Status.UPDATE_NEEDED;
|
|
||||||
}
|
|
||||||
if (newType.ordinal() > currentType.ordinal()) return Status.UPDATE_NEEDED;
|
|
||||||
if (newType == currentType) {
|
|
||||||
int currentReleaseTypeNumber = getReleaseTypeNumber(currentVersion);
|
|
||||||
int newReleaseTypeNumber = getReleaseTypeNumber(newVersion);
|
|
||||||
if (newReleaseTypeNumber > currentReleaseTypeNumber) return Status.UPDATE_NEEDED;
|
|
||||||
}
|
|
||||||
return Status.LATEST_VERSION;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ReleaseType parseReleaseType(String version) {
|
|
||||||
if (version.toLowerCase().contains("snapshot")) return ReleaseType.SNAPSHOT;
|
|
||||||
if (version.toLowerCase().contains("alpha")) return ReleaseType.ALPHA;
|
|
||||||
if (version.toLowerCase().contains("beta")) return ReleaseType.BETA;
|
|
||||||
return version.matches("\\d+\\.\\d+\\.\\d+") ? ReleaseType.RELEASE : ReleaseType.UNKNOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getVersionWithoutReleaseType(String version) {
|
|
||||||
return version.contains("-") ? version.split("-")[0] : version;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getReleaseTypeNumber(String version) {
|
|
||||||
if (!version.contains("-")) return 0;
|
|
||||||
return Integer.parseInt(version.split("-")[1].split("\\.")[1]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Status getStatus() {
|
public Status getStatus() {
|
||||||
|
@ -87,8 +57,4 @@ public class UpdateChecker extends BukkitRunnable {
|
||||||
public enum Status {
|
public enum Status {
|
||||||
UNKNOWN, LATEST_VERSION, UPDATE_NEEDED
|
UNKNOWN, LATEST_VERSION, UPDATE_NEEDED
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum ReleaseType {
|
|
||||||
UNKNOWN, SNAPSHOT, ALPHA, BETA, RELEASE
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
<gray>Usage <gold>» <yellow>/npc property remove <gold><id> <property>
|
|
||||||
|
|
||||||
<gray>Command used to unset properties on npcs
|
|
|
@ -1,3 +0,0 @@
|
||||||
<gray>Usage <gold>» <yellow>/npc property set <gold><id> <property> <value>
|
|
||||||
|
|
||||||
<gray>Command used to customize npcs with custom properties
|
|
|
@ -1,3 +0,0 @@
|
||||||
<gray>Usage <gold>» <yellow>/npc center <gold><id>
|
|
||||||
|
|
||||||
<gray>Command used to move an npc to the center of the block it's currently occupying
|
|
|
@ -1,3 +0,0 @@
|
||||||
<gray>Usage <gold>» <yellow>/npc changeid <gold><id> <new id>
|
|
||||||
|
|
||||||
<gray>Command used to change the id of an npc
|
|
|
@ -1,3 +0,0 @@
|
||||||
<gray>Usage <gold>» <yellow>/npc create <gold><id> <type>
|
|
||||||
|
|
||||||
<gray>Command used to create an npc of a given type
|
|
|
@ -1,3 +0,0 @@
|
||||||
<gray>Usage <gold>» <yellow>/npc delete <gold><id>
|
|
||||||
|
|
||||||
<gray>Command used to delete an npc
|
|
|
@ -1,3 +0,0 @@
|
||||||
<gray>Usage <gold>» <yellow>/npc list
|
|
||||||
|
|
||||||
<gray>Command used to list all npcs
|
|
|
@ -1,3 +0,0 @@
|
||||||
<gray>Usage <gold>» <yellow>/npc lookatme <gold><id>
|
|
||||||
|
|
||||||
<gray>Command used to set the rotation of an npc to be looking at your current location
|
|
|
@ -1,3 +0,0 @@
|
||||||
<gray>Usage <gold>» <yellow>/npc move <gold><id>
|
|
||||||
|
|
||||||
<gray>Command used to set the location of an npc to your current location
|
|
|
@ -1,3 +0,0 @@
|
||||||
<gray>Usage <gold>» <yellow>/npc near <gold><distance>
|
|
||||||
|
|
||||||
<gray>Command used to check which npcs are within a given radius around you
|
|
|
@ -1,3 +0,0 @@
|
||||||
<gray>Usage <gold>» <yellow>/npc setlocation <gold><id> <x> <y> <z>
|
|
||||||
|
|
||||||
<gray>Command used to manually adjust an npc's location
|
|
|
@ -1,3 +0,0 @@
|
||||||
<gray>Usage <gold>» <yellow>/npc setrotation <gold><id> <yaw> <pitch>
|
|
||||||
|
|
||||||
<gray>Command used to manually adjust an npc's rotation
|
|
|
@ -1,3 +1,6 @@
|
||||||
<gray>Usage <gold>» <yellow>/npc teleport <gold><id>
|
<gray>Examples:
|
||||||
|
<gold>* <yellow>/npc teleport <gold>cool_npc1
|
||||||
|
<gold>* <yellow>/npc teleport <gold>my_npc
|
||||||
|
<gold>* <yellow>/npc teleport <gold>12
|
||||||
|
|
||||||
<gray>Command used to teleport yourself to an npc
|
<gray>Command used to teleport yourself to an npc
|
|
@ -1,3 +1,6 @@
|
||||||
<gray>Usage <gold>» <yellow>/npc toggle <gold><id>
|
<gray>Examples:
|
||||||
|
<gold>* <yellow>/npc toggle <gold>cool_npc1
|
||||||
|
<gold>* <yellow>/npc toggle <gold>my_npc
|
||||||
|
<gold>* <yellow>/npc toggle <gold>12
|
||||||
|
|
||||||
<gray>Command used to enable or disable an npc
|
<gray>Command used to enable or disable an npc
|
|
@ -1,3 +1,6 @@
|
||||||
<gray>Usage <gold>» <yellow>/npc type <gold><id> <type>
|
<gray>Examples:
|
||||||
|
<gold>* <yellow>/npc type <gold>cool_npc1 zombie
|
||||||
|
<gold>* <yellow>/npc type <gold>my_npc skeleton
|
||||||
|
<gold>* <yellow>/npc type <gold>12 creeper
|
||||||
|
|
||||||
<gray>Command used to change the type of an npc
|
<gray>Command used to change the type of an npc
|
|
@ -1,8 +1,6 @@
|
||||||
<gray>Usage <gold>» <yellow>/npc storage import <gold><importer>
|
<gray>Examples:
|
||||||
|
<gold>* <yellow>/npc storage import <gold>znpcs
|
||||||
|
<gold>* <yellow>/npc storage import <gold>znpcsplus_legacy
|
||||||
|
<gold>* <yellow>/npc storage import <gold>citizens
|
||||||
|
|
||||||
<gray>Importers:
|
<gray>Command used to import npcs from a different npc plugin
|
||||||
<gold>* <yellow>znpcs <gray>- Imports npcs from the ZNPCs plugin
|
|
||||||
<gold>* <yellow>znpcsplus_legacy <gray>- Imports npcs from legacy versions of ZNPCsPlus
|
|
||||||
<gold>* <yellow>citizens <gray>- Imports npcs from the Citizens plugin
|
|
||||||
|
|
||||||
<gray>Command used to import npcs from a different source
|
|
|
@ -1,4 +1,5 @@
|
||||||
<gray>Usage <gold>» <yellow>/npc storage reload
|
<gray>Examples:
|
||||||
|
<gold>* <yellow>/npc storage reload
|
||||||
|
|
||||||
<gray>Command used to re-load all npcs from storage
|
<gray>Command used to re-load all npcs from storage
|
||||||
<red>Warning: This command will delete all unsaved changes to npcs
|
<red>Warning: This command will delete all unsaved changes to npcs
|
|
@ -1,3 +1,4 @@
|
||||||
<gray>Usage <gold>» <yellow>/npc storage save
|
<gray>Examples:
|
||||||
|
<gold>* <yellow>/npc storage save
|
||||||
|
|
||||||
<gray>Command used to save the currently loaded npcs to storage
|
<gray>Command used to save the currently loaded npcs to storage
|
Loading…
Reference in a new issue