mirror of
https://github.com/CitizensDev/Citizens2.git
synced 2024-11-10 21:02:36 +01:00
Merge Speech branch into master for testing. Please backup your current saves and config before using this build.
This commit is contained in:
parent
3dd8d9242b
commit
17bb7a9cd6
@ -1,351 +1,363 @@
|
|||||||
package net.citizensnpcs;
|
package net.citizensnpcs;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
import net.citizensnpcs.Settings.Setting;
|
import net.citizensnpcs.Settings.Setting;
|
||||||
import net.citizensnpcs.api.CitizensAPI;
|
import net.citizensnpcs.api.CitizensAPI;
|
||||||
import net.citizensnpcs.api.CitizensPlugin;
|
import net.citizensnpcs.api.CitizensPlugin;
|
||||||
import net.citizensnpcs.api.event.CitizensDisableEvent;
|
import net.citizensnpcs.api.ai.speech.SpeechFactory;
|
||||||
import net.citizensnpcs.api.event.CitizensEnableEvent;
|
import net.citizensnpcs.api.event.CitizensDisableEvent;
|
||||||
import net.citizensnpcs.api.event.CitizensReloadEvent;
|
import net.citizensnpcs.api.event.CitizensEnableEvent;
|
||||||
import net.citizensnpcs.api.exception.NPCLoadException;
|
import net.citizensnpcs.api.event.CitizensReloadEvent;
|
||||||
import net.citizensnpcs.api.npc.NPC;
|
import net.citizensnpcs.api.exception.NPCLoadException;
|
||||||
import net.citizensnpcs.api.npc.NPCRegistry;
|
import net.citizensnpcs.api.npc.NPC;
|
||||||
import net.citizensnpcs.api.scripting.EventRegistrar;
|
import net.citizensnpcs.api.npc.NPCRegistry;
|
||||||
import net.citizensnpcs.api.scripting.ObjectProvider;
|
import net.citizensnpcs.api.scripting.EventRegistrar;
|
||||||
import net.citizensnpcs.api.scripting.ScriptCompiler;
|
import net.citizensnpcs.api.scripting.ObjectProvider;
|
||||||
import net.citizensnpcs.api.trait.Trait;
|
import net.citizensnpcs.api.scripting.ScriptCompiler;
|
||||||
import net.citizensnpcs.api.trait.TraitFactory;
|
import net.citizensnpcs.api.trait.Trait;
|
||||||
import net.citizensnpcs.command.CommandContext;
|
import net.citizensnpcs.api.trait.TraitFactory;
|
||||||
import net.citizensnpcs.command.CommandManager;
|
import net.citizensnpcs.command.CommandContext;
|
||||||
import net.citizensnpcs.command.CommandManager.CommandInfo;
|
import net.citizensnpcs.command.CommandManager;
|
||||||
import net.citizensnpcs.command.Injector;
|
import net.citizensnpcs.command.CommandManager.CommandInfo;
|
||||||
import net.citizensnpcs.command.RequirementsProcessor;
|
import net.citizensnpcs.command.Injector;
|
||||||
import net.citizensnpcs.command.command.AdminCommands;
|
import net.citizensnpcs.command.RequirementsProcessor;
|
||||||
import net.citizensnpcs.command.command.EditorCommands;
|
import net.citizensnpcs.command.command.AdminCommands;
|
||||||
import net.citizensnpcs.command.command.HelpCommands;
|
import net.citizensnpcs.command.command.EditorCommands;
|
||||||
import net.citizensnpcs.command.command.NPCCommands;
|
import net.citizensnpcs.command.command.HelpCommands;
|
||||||
import net.citizensnpcs.command.command.ScriptCommands;
|
import net.citizensnpcs.command.command.NPCCommands;
|
||||||
import net.citizensnpcs.command.command.TemplateCommands;
|
import net.citizensnpcs.command.command.ScriptCommands;
|
||||||
import net.citizensnpcs.command.command.TraitCommands;
|
import net.citizensnpcs.command.command.TemplateCommands;
|
||||||
import net.citizensnpcs.command.command.WaypointCommands;
|
import net.citizensnpcs.command.command.TraitCommands;
|
||||||
import net.citizensnpcs.editor.Editor;
|
import net.citizensnpcs.command.command.WaypointCommands;
|
||||||
import net.citizensnpcs.npc.CitizensNPCRegistry;
|
import net.citizensnpcs.editor.Editor;
|
||||||
import net.citizensnpcs.npc.CitizensTraitFactory;
|
import net.citizensnpcs.npc.CitizensNPCRegistry;
|
||||||
import net.citizensnpcs.npc.NPCSelector;
|
import net.citizensnpcs.npc.CitizensTraitFactory;
|
||||||
import net.citizensnpcs.util.Messages;
|
import net.citizensnpcs.npc.NPCSelector;
|
||||||
import net.citizensnpcs.util.Messaging;
|
import net.citizensnpcs.npc.ai.speech.Chat;
|
||||||
import net.citizensnpcs.util.NMS;
|
import net.citizensnpcs.npc.ai.speech.CitizensSpeechFactory;
|
||||||
import net.citizensnpcs.util.StringHelper;
|
import net.citizensnpcs.util.Messages;
|
||||||
import net.citizensnpcs.util.Util;
|
import net.citizensnpcs.util.Messaging;
|
||||||
import net.milkbowl.vault.economy.Economy;
|
import net.citizensnpcs.util.NMS;
|
||||||
|
import net.citizensnpcs.util.StringHelper;
|
||||||
import org.bukkit.Bukkit;
|
import net.citizensnpcs.util.Util;
|
||||||
import org.bukkit.ChatColor;
|
import net.milkbowl.vault.economy.Economy;
|
||||||
import org.bukkit.command.Command;
|
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.ChatColor;
|
||||||
import org.bukkit.plugin.RegisteredServiceProvider;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
import com.google.common.collect.Iterables;
|
import org.bukkit.plugin.RegisteredServiceProvider;
|
||||||
import com.google.common.io.Files;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
import com.google.common.io.InputSupplier;
|
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
public class Citizens extends JavaPlugin implements CitizensPlugin {
|
import com.google.common.io.Files;
|
||||||
private final CommandManager commands = new CommandManager();
|
import com.google.common.io.InputSupplier;
|
||||||
private boolean compatible;
|
|
||||||
private Settings config;
|
public class Citizens extends JavaPlugin implements CitizensPlugin {
|
||||||
private CitizensNPCRegistry npcRegistry;
|
private final CommandManager commands = new CommandManager();
|
||||||
private NPCDataStore saves;
|
private boolean compatible;
|
||||||
private NPCSelector selector;
|
private Settings config;
|
||||||
private CitizensTraitFactory traitFactory;
|
private CitizensNPCRegistry npcRegistry;
|
||||||
|
private NPCDataStore saves;
|
||||||
private void despawnNPCs() {
|
private NPCSelector selector;
|
||||||
Iterator<NPC> itr = npcRegistry.iterator();
|
private CitizensTraitFactory traitFactory;
|
||||||
while (itr.hasNext()) {
|
private CitizensSpeechFactory speechFactory;
|
||||||
NPC npc = itr.next();
|
|
||||||
try {
|
private void despawnNPCs() {
|
||||||
npc.despawn();
|
Iterator<NPC> itr = npcRegistry.iterator();
|
||||||
for (Trait trait : npc.getTraits())
|
while (itr.hasNext()) {
|
||||||
trait.onRemove();
|
NPC npc = itr.next();
|
||||||
} catch (Throwable e) {
|
try {
|
||||||
e.printStackTrace();
|
npc.despawn();
|
||||||
// ensure that all entities are despawned
|
for (Trait trait : npc.getTraits())
|
||||||
}
|
trait.onRemove();
|
||||||
itr.remove();
|
} catch (Throwable e) {
|
||||||
}
|
e.printStackTrace();
|
||||||
}
|
// ensure that all entities are despawned
|
||||||
|
}
|
||||||
public void test() {
|
itr.remove();
|
||||||
getDataFolder().mkdirs();
|
}
|
||||||
final InputStream dllResource = getResource("path/to/dll");
|
}
|
||||||
try {
|
|
||||||
Files.copy(new InputSupplier<InputStream>() {
|
public void test() {
|
||||||
@Override
|
getDataFolder().mkdirs();
|
||||||
public InputStream getInput() throws IOException {
|
final InputStream dllResource = getResource("path/to/dll");
|
||||||
return dllResource;
|
try {
|
||||||
}
|
Files.copy(new InputSupplier<InputStream>() {
|
||||||
}, new File(getDataFolder(), "name.dll"));
|
@Override
|
||||||
} catch (IOException e) {
|
public InputStream getInput() throws IOException {
|
||||||
e.printStackTrace();
|
return dllResource;
|
||||||
}
|
}
|
||||||
// code here
|
}, new File(getDataFolder(), "name.dll"));
|
||||||
new File(getDataFolder(), "name.dll").delete();
|
} catch (IOException e) {
|
||||||
}
|
e.printStackTrace();
|
||||||
|
}
|
||||||
private void enableSubPlugins() {
|
// code here
|
||||||
File root = new File(getDataFolder(), Setting.SUBPLUGIN_FOLDER.asString());
|
new File(getDataFolder(), "name.dll").delete();
|
||||||
if (!root.exists() || !root.isDirectory())
|
}
|
||||||
return;
|
|
||||||
File[] files = root.listFiles();
|
private void enableSubPlugins() {
|
||||||
for (File file : files) {
|
File root = new File(getDataFolder(), Setting.SUBPLUGIN_FOLDER.asString());
|
||||||
Plugin plugin;
|
if (!root.exists() || !root.isDirectory())
|
||||||
try {
|
return;
|
||||||
plugin = Bukkit.getPluginManager().loadPlugin(file);
|
File[] files = root.listFiles();
|
||||||
} catch (Exception e) {
|
for (File file : files) {
|
||||||
continue;
|
Plugin plugin;
|
||||||
}
|
try {
|
||||||
if (plugin == null)
|
plugin = Bukkit.getPluginManager().loadPlugin(file);
|
||||||
continue;
|
} catch (Exception e) {
|
||||||
// code beneath modified from CraftServer
|
continue;
|
||||||
try {
|
}
|
||||||
Messaging.logTr(Messages.LOADING_SUB_PLUGIN, plugin.getDescription().getFullName());
|
if (plugin == null)
|
||||||
plugin.onLoad();
|
continue;
|
||||||
} catch (Throwable ex) {
|
// code beneath modified from CraftServer
|
||||||
Messaging.severeTr(Messages.ERROR_INITALISING_SUB_PLUGIN, ex.getMessage(), plugin
|
try {
|
||||||
.getDescription().getFullName());
|
Messaging.logTr(Messages.LOADING_SUB_PLUGIN, plugin.getDescription().getFullName());
|
||||||
ex.printStackTrace();
|
plugin.onLoad();
|
||||||
}
|
} catch (Throwable ex) {
|
||||||
}
|
Messaging.severeTr(Messages.ERROR_INITALISING_SUB_PLUGIN, ex.getMessage(), plugin
|
||||||
NMS.loadPlugins();
|
.getDescription().getFullName());
|
||||||
}
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
public CommandInfo getCommandInfo(String rootCommand, String modifier) {
|
}
|
||||||
return commands.getCommand(rootCommand, modifier);
|
NMS.loadPlugins();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterable<CommandInfo> getCommands(String base) {
|
public CommandInfo getCommandInfo(String rootCommand, String modifier) {
|
||||||
return commands.getCommands(base);
|
return commands.getCommand(rootCommand, modifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public Iterable<CommandInfo> getCommands(String base) {
|
||||||
public NPCRegistry getNPCRegistry() {
|
return commands.getCommands(base);
|
||||||
return npcRegistry;
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
public NPCSelector getNPCSelector() {
|
public NPCRegistry getNPCRegistry() {
|
||||||
return selector;
|
return npcRegistry;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public NPCSelector getNPCSelector() {
|
||||||
public File getScriptFolder() {
|
return selector;
|
||||||
return new File(getDataFolder(), "scripts");
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
@Override
|
public File getScriptFolder() {
|
||||||
public TraitFactory getTraitFactory() {
|
return new File(getDataFolder(), "scripts");
|
||||||
return traitFactory;
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
@Override
|
public TraitFactory getTraitFactory() {
|
||||||
public boolean onCommand(CommandSender sender, Command command, String cmdName, String[] args) {
|
return traitFactory;
|
||||||
String modifier = args.length > 0 ? args[0] : "";
|
}
|
||||||
if (!commands.hasCommand(command, modifier) && !modifier.isEmpty()) {
|
|
||||||
return suggestClosestModifier(sender, command.getName(), modifier);
|
@Override
|
||||||
}
|
public SpeechFactory getSpeechFactory() {
|
||||||
|
return speechFactory;
|
||||||
NPC npc = selector == null ? null : selector.getSelected(sender);
|
}
|
||||||
// TODO: change the args supplied to a context style system for
|
|
||||||
// flexibility (ie. adding more context in the future without
|
@Override
|
||||||
// changing everything)
|
public boolean onCommand(CommandSender sender, Command command, String cmdName, String[] args) {
|
||||||
|
String modifier = args.length > 0 ? args[0] : "";
|
||||||
Object[] methodArgs = { sender, npc };
|
if (!commands.hasCommand(command, modifier) && !modifier.isEmpty()) {
|
||||||
return commands.executeSafe(command, args, sender, methodArgs);
|
return suggestClosestModifier(sender, command.getName(), modifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
NPC npc = selector == null ? null : selector.getSelected(sender);
|
||||||
public void onDisable() {
|
// TODO: change the args supplied to a context style system for
|
||||||
Bukkit.getPluginManager().callEvent(new CitizensDisableEvent());
|
// flexibility (ie. adding more context in the future without
|
||||||
Editor.leaveAll();
|
// changing everything)
|
||||||
CitizensAPI.shutdown();
|
|
||||||
|
Object[] methodArgs = { sender, npc };
|
||||||
// Don't bother with this part if MC versions are not compatible
|
return commands.executeSafe(command, args, sender, methodArgs);
|
||||||
if (compatible) {
|
}
|
||||||
saves.storeAll(npcRegistry);
|
|
||||||
saves.saveToDiskImmediate();
|
@Override
|
||||||
despawnNPCs();
|
public void onDisable() {
|
||||||
npcRegistry = null;
|
Bukkit.getPluginManager().callEvent(new CitizensDisableEvent());
|
||||||
}
|
Editor.leaveAll();
|
||||||
}
|
CitizensAPI.shutdown();
|
||||||
|
|
||||||
@Override
|
// Don't bother with this part if MC versions are not compatible
|
||||||
public void onEnable() {
|
if (compatible) {
|
||||||
CitizensAPI.setImplementation(this);
|
saves.storeAll(npcRegistry);
|
||||||
// Disable if the server is not using the compatible Minecraft version
|
saves.saveToDiskImmediate();
|
||||||
String mcVersion = Util.getMinecraftVersion();
|
despawnNPCs();
|
||||||
compatible = mcVersion.startsWith(COMPATIBLE_MC_VERSION);
|
npcRegistry = null;
|
||||||
if (!compatible) {
|
}
|
||||||
Messaging.severeTr(Messages.CITIZENS_INCOMPATIBLE, getDescription().getVersion(), mcVersion);
|
}
|
||||||
getServer().getPluginManager().disablePlugin(this);
|
|
||||||
return;
|
@Override
|
||||||
}
|
public void onEnable() {
|
||||||
config = new Settings(getDataFolder());
|
CitizensAPI.setImplementation(this);
|
||||||
registerScriptHelpers();
|
// Disable if the server is not using the compatible Minecraft version
|
||||||
|
String mcVersion = Util.getMinecraftVersion();
|
||||||
saves = NPCDataStore.create(getDataFolder());
|
compatible = mcVersion.startsWith(COMPATIBLE_MC_VERSION);
|
||||||
if (saves == null) {
|
if (!compatible) {
|
||||||
Messaging.severeTr(Messages.FAILED_LOAD_SAVES);
|
Messaging.severeTr(Messages.CITIZENS_INCOMPATIBLE, getDescription().getVersion(), mcVersion);
|
||||||
getServer().getPluginManager().disablePlugin(this);
|
getServer().getPluginManager().disablePlugin(this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
config = new Settings(getDataFolder());
|
||||||
npcRegistry = new CitizensNPCRegistry(saves);
|
registerScriptHelpers();
|
||||||
traitFactory = new CitizensTraitFactory();
|
|
||||||
selector = new NPCSelector(this);
|
saves = NPCDataStore.create(getDataFolder());
|
||||||
|
if (saves == null) {
|
||||||
getServer().getPluginManager().registerEvents(new EventListen(), this);
|
Messaging.severeTr(Messages.FAILED_LOAD_SAVES);
|
||||||
|
getServer().getPluginManager().disablePlugin(this);
|
||||||
if (Setting.NPC_COST.asDouble() > 0)
|
return;
|
||||||
setupEconomy();
|
}
|
||||||
|
|
||||||
registerCommands();
|
npcRegistry = new CitizensNPCRegistry(saves);
|
||||||
enableSubPlugins();
|
traitFactory = new CitizensTraitFactory();
|
||||||
|
selector = new NPCSelector(this);
|
||||||
// Setup NPCs after all plugins have been enabled (allows for multiworld
|
speechFactory = new CitizensSpeechFactory();
|
||||||
// support and for NPCs to properly register external settings)
|
speechFactory.register(Chat.class, "chat");
|
||||||
if (getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
|
|
||||||
@Override
|
getServer().getPluginManager().registerEvents(new EventListen(), this);
|
||||||
public void run() {
|
|
||||||
saves.loadInto(npcRegistry);
|
if (Setting.NPC_COST.asDouble() > 0)
|
||||||
startMetrics();
|
setupEconomy();
|
||||||
scheduleSaveTask(Setting.SAVE_TASK_DELAY.asInt());
|
|
||||||
Bukkit.getPluginManager().callEvent(new CitizensEnableEvent());
|
registerCommands();
|
||||||
}
|
enableSubPlugins();
|
||||||
}, 1) == -1) {
|
|
||||||
Messaging.severeTr(Messages.LOAD_TASK_NOT_SCHEDULED);
|
// Setup NPCs after all plugins have been enabled (allows for multiworld
|
||||||
getServer().getPluginManager().disablePlugin(this);
|
// support and for NPCs to properly register external settings)
|
||||||
}
|
if (getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
|
||||||
}
|
@Override
|
||||||
|
public void run() {
|
||||||
@Override
|
saves.loadInto(npcRegistry);
|
||||||
public void onImplementationChanged() {
|
startMetrics();
|
||||||
Messaging.severeTr(Messages.CITIZENS_IMPLEMENTATION_DISABLED);
|
scheduleSaveTask(Setting.SAVE_TASK_DELAY.asInt());
|
||||||
Bukkit.getPluginManager().disablePlugin(this);
|
Bukkit.getPluginManager().callEvent(new CitizensEnableEvent());
|
||||||
}
|
}
|
||||||
|
}, 1) == -1) {
|
||||||
public void registerCommandClass(Class<?> clazz) {
|
Messaging.severeTr(Messages.LOAD_TASK_NOT_SCHEDULED);
|
||||||
try {
|
getServer().getPluginManager().disablePlugin(this);
|
||||||
commands.register(clazz);
|
}
|
||||||
} catch (Throwable ex) {
|
}
|
||||||
Messaging.logTr(Messages.CITIZENS_INVALID_COMMAND_CLASS);
|
|
||||||
ex.printStackTrace();
|
@Override
|
||||||
}
|
public void onImplementationChanged() {
|
||||||
}
|
Messaging.severeTr(Messages.CITIZENS_IMPLEMENTATION_DISABLED);
|
||||||
|
Bukkit.getPluginManager().disablePlugin(this);
|
||||||
private void registerCommands() {
|
}
|
||||||
commands.setInjector(new Injector(this));
|
|
||||||
commands.registerAnnotationProcessor(new RequirementsProcessor());
|
public void registerCommandClass(Class<?> clazz) {
|
||||||
|
try {
|
||||||
// Register command classes
|
commands.register(clazz);
|
||||||
commands.register(AdminCommands.class);
|
} catch (Throwable ex) {
|
||||||
commands.register(EditorCommands.class);
|
Messaging.logTr(Messages.CITIZENS_INVALID_COMMAND_CLASS);
|
||||||
commands.register(HelpCommands.class);
|
ex.printStackTrace();
|
||||||
commands.register(NPCCommands.class);
|
}
|
||||||
commands.register(ScriptCommands.class);
|
}
|
||||||
commands.register(TemplateCommands.class);
|
|
||||||
commands.register(TraitCommands.class);
|
private void registerCommands() {
|
||||||
commands.register(WaypointCommands.class);
|
commands.setInjector(new Injector(this));
|
||||||
}
|
commands.registerAnnotationProcessor(new RequirementsProcessor());
|
||||||
|
|
||||||
private void registerScriptHelpers() {
|
// Register command classes
|
||||||
ScriptCompiler compiler = CitizensAPI.getScriptCompiler();
|
commands.register(AdminCommands.class);
|
||||||
compiler.registerGlobalContextProvider(new EventRegistrar(this));
|
commands.register(EditorCommands.class);
|
||||||
compiler.registerGlobalContextProvider(new ObjectProvider("plugin", this));
|
commands.register(HelpCommands.class);
|
||||||
}
|
commands.register(NPCCommands.class);
|
||||||
|
commands.register(ScriptCommands.class);
|
||||||
public void reload() throws NPCLoadException {
|
commands.register(TemplateCommands.class);
|
||||||
Editor.leaveAll();
|
commands.register(TraitCommands.class);
|
||||||
config.reload();
|
commands.register(WaypointCommands.class);
|
||||||
despawnNPCs();
|
}
|
||||||
saves.loadInto(npcRegistry);
|
|
||||||
|
private void registerScriptHelpers() {
|
||||||
getServer().getPluginManager().callEvent(new CitizensReloadEvent());
|
ScriptCompiler compiler = CitizensAPI.getScriptCompiler();
|
||||||
}
|
compiler.registerGlobalContextProvider(new EventRegistrar(this));
|
||||||
|
compiler.registerGlobalContextProvider(new ObjectProvider("plugin", this));
|
||||||
private void scheduleSaveTask(int delay) {
|
}
|
||||||
Bukkit.getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
|
|
||||||
@Override
|
public void reload() throws NPCLoadException {
|
||||||
public void run() {
|
Editor.leaveAll();
|
||||||
storeNPCs();
|
config.reload();
|
||||||
saves.saveToDisk();
|
despawnNPCs();
|
||||||
}
|
saves.loadInto(npcRegistry);
|
||||||
});
|
|
||||||
}
|
getServer().getPluginManager().callEvent(new CitizensReloadEvent());
|
||||||
|
}
|
||||||
private void setupEconomy() {
|
|
||||||
try {
|
private void scheduleSaveTask(int delay) {
|
||||||
RegisteredServiceProvider<Economy> provider = Bukkit.getServicesManager().getRegistration(
|
Bukkit.getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
|
||||||
Economy.class);
|
@Override
|
||||||
if (provider != null && provider.getProvider() != null) {
|
public void run() {
|
||||||
Economy economy = provider.getProvider();
|
storeNPCs();
|
||||||
Bukkit.getPluginManager().registerEvents(new PaymentListener(economy), this);
|
saves.saveToDisk();
|
||||||
}
|
}
|
||||||
} catch (NoClassDefFoundError e) {
|
});
|
||||||
Messaging.logTr(Messages.ERROR_LOADING_ECONOMY);
|
}
|
||||||
}
|
|
||||||
}
|
private void setupEconomy() {
|
||||||
|
try {
|
||||||
private void startMetrics() {
|
RegisteredServiceProvider<Economy> provider = Bukkit.getServicesManager().getRegistration(
|
||||||
try {
|
Economy.class);
|
||||||
Metrics metrics = new Metrics(Citizens.this);
|
if (provider != null && provider.getProvider() != null) {
|
||||||
if (metrics.isOptOut())
|
Economy economy = provider.getProvider();
|
||||||
return;
|
Bukkit.getPluginManager().registerEvents(new PaymentListener(economy), this);
|
||||||
metrics.addCustomData(new Metrics.Plotter("Total NPCs") {
|
}
|
||||||
@Override
|
} catch (NoClassDefFoundError e) {
|
||||||
public int getValue() {
|
Messaging.logTr(Messages.ERROR_LOADING_ECONOMY);
|
||||||
if (npcRegistry == null)
|
}
|
||||||
return 0;
|
}
|
||||||
return Iterables.size(npcRegistry);
|
|
||||||
}
|
private void startMetrics() {
|
||||||
});
|
try {
|
||||||
|
Metrics metrics = new Metrics(Citizens.this);
|
||||||
traitFactory.addPlotters(metrics.createGraph("traits"));
|
if (metrics.isOptOut())
|
||||||
saves.addPlotters(metrics.createGraph("Storage type"));
|
return;
|
||||||
metrics.start();
|
metrics.addCustomData(new Metrics.Plotter("Total NPCs") {
|
||||||
} catch (IOException e) {
|
@Override
|
||||||
Messaging.logTr(Messages.METRICS_ERROR_NOTIFICATION, e.getMessage());
|
public int getValue() {
|
||||||
}
|
if (npcRegistry == null)
|
||||||
}
|
return 0;
|
||||||
|
return Iterables.size(npcRegistry);
|
||||||
public void storeNPCs() {
|
}
|
||||||
if (saves == null)
|
});
|
||||||
return;
|
|
||||||
for (NPC npc : npcRegistry)
|
traitFactory.addPlotters(metrics.createGraph("traits"));
|
||||||
saves.store(npc);
|
saves.addPlotters(metrics.createGraph("Storage type"));
|
||||||
}
|
metrics.start();
|
||||||
|
} catch (IOException e) {
|
||||||
public void storeNPCs(CommandContext args) {
|
Messaging.logTr(Messages.METRICS_ERROR_NOTIFICATION, e.getMessage());
|
||||||
storeNPCs();
|
}
|
||||||
boolean async = args.hasFlag('a');
|
}
|
||||||
if (async)
|
|
||||||
saves.saveToDisk();
|
public void storeNPCs() {
|
||||||
else
|
if (saves == null)
|
||||||
saves.saveToDiskImmediate();
|
return;
|
||||||
}
|
for (NPC npc : npcRegistry)
|
||||||
|
saves.store(npc);
|
||||||
private boolean suggestClosestModifier(CommandSender sender, String command, String modifier) {
|
}
|
||||||
String closest = commands.getClosestCommandModifier(command, modifier);
|
|
||||||
if (!closest.isEmpty()) {
|
public void storeNPCs(CommandContext args) {
|
||||||
sender.sendMessage(ChatColor.GRAY + Messaging.tr(Messages.UNKNOWN_COMMAND));
|
storeNPCs();
|
||||||
sender.sendMessage(StringHelper.wrap(" /") + command + " " + StringHelper.wrap(closest));
|
boolean async = args.hasFlag('a');
|
||||||
return true;
|
if (async)
|
||||||
}
|
saves.saveToDisk();
|
||||||
return false;
|
else
|
||||||
}
|
saves.saveToDiskImmediate();
|
||||||
|
}
|
||||||
private static final String COMPATIBLE_MC_VERSION = "1.4.6";
|
|
||||||
|
private boolean suggestClosestModifier(CommandSender sender, String command, String modifier) {
|
||||||
|
String closest = commands.getClosestCommandModifier(command, modifier);
|
||||||
|
if (!closest.isEmpty()) {
|
||||||
|
sender.sendMessage(ChatColor.GRAY + Messaging.tr(Messages.UNKNOWN_COMMAND));
|
||||||
|
sender.sendMessage(StringHelper.wrap(" /") + command + " " + StringHelper.wrap(closest));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String COMPATIBLE_MC_VERSION = "1.4.6";
|
||||||
|
|
||||||
}
|
}
|
@ -1,142 +1,149 @@
|
|||||||
package net.citizensnpcs;
|
package net.citizensnpcs;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import net.citizensnpcs.api.util.DataKey;
|
import net.citizensnpcs.api.util.DataKey;
|
||||||
import net.citizensnpcs.api.util.Storage;
|
import net.citizensnpcs.api.util.Storage;
|
||||||
import net.citizensnpcs.api.util.YamlStorage;
|
import net.citizensnpcs.api.util.YamlStorage;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
public class Settings {
|
public class Settings {
|
||||||
private final Storage config;
|
private final Storage config;
|
||||||
private final DataKey root;
|
private final DataKey root;
|
||||||
|
|
||||||
public Settings(File folder) {
|
public Settings(File folder) {
|
||||||
config = new YamlStorage(new File(folder, "config.yml"), "Citizens Configuration");
|
config = new YamlStorage(new File(folder, "config.yml"), "Citizens Configuration");
|
||||||
root = config.getKey("");
|
root = config.getKey("");
|
||||||
|
|
||||||
config.load();
|
config.load();
|
||||||
for (Setting setting : Setting.values()) {
|
for (Setting setting : Setting.values()) {
|
||||||
if (!root.keyExists(setting.path)) {
|
if (!root.keyExists(setting.path)) {
|
||||||
setting.setAtKey(root);
|
setting.setAtKey(root);
|
||||||
} else
|
} else
|
||||||
setting.loadFromKey(root);
|
setting.loadFromKey(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
save();
|
save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reload() {
|
public void reload() {
|
||||||
config.load();
|
config.load();
|
||||||
for (Setting setting : Setting.values())
|
for (Setting setting : Setting.values())
|
||||||
if (root.keyExists(setting.path))
|
if (root.keyExists(setting.path))
|
||||||
setting.loadFromKey(root);
|
setting.loadFromKey(root);
|
||||||
|
|
||||||
save();
|
save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void save() {
|
public void save() {
|
||||||
config.save();
|
config.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Setting {
|
public enum Setting {
|
||||||
CHAT_PREFIX("npc.chat.prefix", "[<npc>]: "),
|
CHAT_FORMAT("npc.chat.format.no-targets", "[<npc>]: <text>"),
|
||||||
DATABASE_DRIVER("storage.database.driver", ""),
|
CHAT_FORMAT_TO_TARGET("npc.chat.format.to-target", "[<npc>] -> You: <text>"),
|
||||||
DATABASE_PASSWORD("storage.database.password", ""),
|
CHAT_FORMAT_TO_BYSTANDERS("npc.chat.format.with-target-to-bystanders", "[<npc>] -> [<target>]: <text>"),
|
||||||
DATABASE_URL("storage.database.url", ""),
|
CHAT_FORMAT_WITH_TARGETS_TO_BYSTANDERS("npc.chat.format.with-targets-to-bystanders", "[<npc>] -> [<targets>]: <text>"),
|
||||||
DATABASE_USERNAME("storage.database.username", ""),
|
CHAT_RANGE("npc.chat.options.range", 5),
|
||||||
DEBUG_MODE("general.debug-mode", false),
|
CHAT_BYSTANDERS_HEAR_TARGETED_CHAT("npc.chat.options.bystanders-hear-targeted-chat", true),
|
||||||
DEFAULT_LOOK_CLOSE("npc.default.look-close.enabled", false),
|
CHAT_MAX_NUMBER_OF_TARGETS("npc.chat.options.max-number-of-targets-to-show", 2),
|
||||||
DEFAULT_LOOK_CLOSE_RANGE("npc.default.look-close.range", 5),
|
CHAT_MULTIPLE_TARGETS_FORMAT("npc.chat.options.multiple-targets-format", "<target>|, <target>| & <target>| & others"),
|
||||||
DEFAULT_NPC_LIMIT("npc.limits.default-limit", 10),
|
DATABASE_DRIVER("storage.database.driver", ""),
|
||||||
DEFAULT_PATHFINDING_RANGE("npc.default.pathfinding.range", 25F),
|
DATABASE_PASSWORD("storage.database.password", ""),
|
||||||
DEFAULT_RANDOM_TALKER("npc.default.random-talker", true),
|
DATABASE_URL("storage.database.url", ""),
|
||||||
DEFAULT_REALISTIC_LOOKING("npc.default.realistic-looking", false),
|
DATABASE_USERNAME("storage.database.username", ""),
|
||||||
DEFAULT_STATIONARY_TICKS("npc.default.stationary-ticks", -1),
|
DEBUG_MODE("general.debug-mode", false),
|
||||||
DEFAULT_TALK_CLOSE("npc.default.talk-close.enabled", false),
|
DEFAULT_LOOK_CLOSE("npc.default.look-close.enabled", false),
|
||||||
DEFAULT_TALK_CLOSE_RANGE("npc.default.talk-close.range", 5),
|
DEFAULT_LOOK_CLOSE_RANGE("npc.default.look-close.range", 5),
|
||||||
DEFAULT_TEXT("npc.default.text.0", "Hi, I'm <npc>!") {
|
DEFAULT_NPC_LIMIT("npc.limits.default-limit", 10),
|
||||||
@Override
|
DEFAULT_PATHFINDING_RANGE("npc.default.pathfinding.range", 25F),
|
||||||
public void loadFromKey(DataKey root) {
|
DEFAULT_RANDOM_TALKER("npc.default.random-talker", true),
|
||||||
List<String> list = new ArrayList<String>();
|
DEFAULT_REALISTIC_LOOKING("npc.default.realistic-looking", false),
|
||||||
for (DataKey key : root.getRelative("npc.default.text").getSubKeys())
|
DEFAULT_STATIONARY_TICKS("npc.default.stationary-ticks", -1),
|
||||||
list.add(key.getString(""));
|
DEFAULT_TALK_CLOSE("npc.default.talk-close.enabled", false),
|
||||||
value = list;
|
DEFAULT_TALK_CLOSE_RANGE("npc.default.talk-close.range", 5),
|
||||||
}
|
DEFAULT_TEXT("npc.default.text.0", "Hi, I'm <npc>!") {
|
||||||
},
|
@Override
|
||||||
HIGHLIGHT_COLOUR("general.color-scheme.message-highlight", "<e>"),
|
public void loadFromKey(DataKey root) {
|
||||||
KEEP_CHUNKS_LOADED("npc.chunks.always-keep-loaded", false),
|
List<String> list = new ArrayList<String>();
|
||||||
LOCALE("general.translation.locale", ""),
|
for (DataKey key : root.getRelative("npc.default.text").getSubKeys())
|
||||||
MAX_NPC_LIMIT_CHECKS("npc.limits.max-permission-checks", 100),
|
list.add(key.getString(""));
|
||||||
MAX_SPEED("npc.limits.max-speed", 100),
|
value = list;
|
||||||
MESSAGE_COLOUR("general.color-scheme.message", "<a>"),
|
}
|
||||||
NPC_COST("economy.npc.cost", 100D),
|
},
|
||||||
QUICK_SELECT("npc.selection.quick-select", false),
|
HIGHLIGHT_COLOUR("general.color-scheme.message-highlight", "<e>"),
|
||||||
REMOVE_PLAYERS_FROM_PLAYER_LIST("npc.player.remove-from-list", true),
|
KEEP_CHUNKS_LOADED("npc.chunks.always-keep-loaded", false),
|
||||||
SAVE_TASK_DELAY("storage.save-task.delay", 20 * 60 * 60),
|
LOCALE("general.translation.locale", ""),
|
||||||
SELECTION_ITEM("npc.selection.item", "280"),
|
MAX_NPC_LIMIT_CHECKS("npc.limits.max-permission-checks", 100),
|
||||||
SELECTION_MESSAGE("npc.selection.message", "<b>You selected <a><npc><b>!"),
|
MAX_SPEED("npc.limits.max-speed", 100),
|
||||||
SERVER_OWNS_NPCS("npc.server-ownership", false),
|
MESSAGE_COLOUR("general.color-scheme.message", "<a>"),
|
||||||
STORAGE_FILE("storage.file", "saves.yml"),
|
NPC_COST("economy.npc.cost", 100D),
|
||||||
STORAGE_TYPE("storage.type", "yaml"),
|
QUICK_SELECT("npc.selection.quick-select", false),
|
||||||
SUBPLUGIN_FOLDER("subplugins.folder", "plugins"),
|
REMOVE_PLAYERS_FROM_PLAYER_LIST("npc.player.remove-from-list", true),
|
||||||
TALK_CLOSE_MAXIMUM_COOLDOWN("npc.text.max-talk-cooldown", 60),
|
SAVE_TASK_DELAY("storage.save-task.delay", 20 * 60 * 60),
|
||||||
TALK_CLOSE_MINIMUM_COOLDOWN("npc.text.min-talk-cooldown", 30),
|
SELECTION_ITEM("npc.selection.item", "280"),
|
||||||
TALK_ITEM("npc.text.talk-item", "340"),
|
SELECTION_MESSAGE("npc.selection.message", "<b>You selected <a><npc><b>!"),
|
||||||
USE_NEW_PATHFINDER("npc.pathfinding.use-new-finder", false);
|
SERVER_OWNS_NPCS("npc.server-ownership", false),
|
||||||
|
STORAGE_FILE("storage.file", "saves.yml"),
|
||||||
protected String path;
|
STORAGE_TYPE("storage.type", "yaml"),
|
||||||
protected Object value;
|
SUBPLUGIN_FOLDER("subplugins.folder", "plugins"),
|
||||||
|
TALK_CLOSE_MAXIMUM_COOLDOWN("npc.text.max-talk-cooldown", 60),
|
||||||
Setting(String path, Object value) {
|
TALK_CLOSE_MINIMUM_COOLDOWN("npc.text.min-talk-cooldown", 30),
|
||||||
this.path = path;
|
TALK_ITEM("npc.text.talk-item", "340"),
|
||||||
this.value = value;
|
USE_NEW_PATHFINDER("npc.pathfinding.use-new-finder", false);
|
||||||
}
|
|
||||||
|
protected String path;
|
||||||
public boolean asBoolean() {
|
protected Object value;
|
||||||
return (Boolean) value;
|
|
||||||
}
|
Setting(String path, Object value) {
|
||||||
|
this.path = path;
|
||||||
public double asDouble() {
|
this.value = value;
|
||||||
return ((Number) value).doubleValue();
|
}
|
||||||
}
|
|
||||||
|
public boolean asBoolean() {
|
||||||
public float asFloat() {
|
return (Boolean) value;
|
||||||
return ((Number) value).floatValue();
|
}
|
||||||
}
|
|
||||||
|
public double asDouble() {
|
||||||
public int asInt() {
|
return ((Number) value).doubleValue();
|
||||||
if (value instanceof String) {
|
}
|
||||||
return Integer.parseInt(value.toString());
|
|
||||||
}
|
public float asFloat() {
|
||||||
return ((Number) value).intValue();
|
return ((Number) value).floatValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
public int asInt() {
|
||||||
public List<String> asList() {
|
if (value instanceof String) {
|
||||||
if (!(value instanceof List)) {
|
return Integer.parseInt(value.toString());
|
||||||
value = Lists.newArrayList(value);
|
}
|
||||||
}
|
return ((Number) value).intValue();
|
||||||
return (List<String>) value;
|
}
|
||||||
}
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public long asLong() {
|
public List<String> asList() {
|
||||||
return ((Number) value).longValue();
|
if (!(value instanceof List)) {
|
||||||
}
|
value = Lists.newArrayList(value);
|
||||||
|
}
|
||||||
public String asString() {
|
return (List<String>) value;
|
||||||
return value.toString();
|
}
|
||||||
}
|
|
||||||
|
public long asLong() {
|
||||||
protected void loadFromKey(DataKey root) {
|
return ((Number) value).longValue();
|
||||||
value = root.getRaw(path);
|
}
|
||||||
}
|
|
||||||
|
public String asString() {
|
||||||
protected void setAtKey(DataKey root) {
|
return value.toString();
|
||||||
root.setRaw(path, value);
|
}
|
||||||
}
|
|
||||||
}
|
protected void loadFromKey(DataKey root) {
|
||||||
|
value = root.getRaw(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setAtKey(DataKey root) {
|
||||||
|
root.setRaw(path, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -8,6 +8,7 @@ import java.util.List;
|
|||||||
import net.citizensnpcs.Citizens;
|
import net.citizensnpcs.Citizens;
|
||||||
import net.citizensnpcs.Settings.Setting;
|
import net.citizensnpcs.Settings.Setting;
|
||||||
import net.citizensnpcs.api.CitizensAPI;
|
import net.citizensnpcs.api.CitizensAPI;
|
||||||
|
import net.citizensnpcs.api.ai.speech.SpeechContext;
|
||||||
import net.citizensnpcs.api.event.PlayerCreateNPCEvent;
|
import net.citizensnpcs.api.event.PlayerCreateNPCEvent;
|
||||||
import net.citizensnpcs.api.npc.NPC;
|
import net.citizensnpcs.api.npc.NPC;
|
||||||
import net.citizensnpcs.api.npc.NPCRegistry;
|
import net.citizensnpcs.api.npc.NPCRegistry;
|
||||||
@ -15,6 +16,7 @@ import net.citizensnpcs.api.trait.Trait;
|
|||||||
import net.citizensnpcs.api.trait.trait.MobType;
|
import net.citizensnpcs.api.trait.trait.MobType;
|
||||||
import net.citizensnpcs.api.trait.trait.Owner;
|
import net.citizensnpcs.api.trait.trait.Owner;
|
||||||
import net.citizensnpcs.api.trait.trait.Spawned;
|
import net.citizensnpcs.api.trait.trait.Spawned;
|
||||||
|
import net.citizensnpcs.api.trait.trait.Speech;
|
||||||
import net.citizensnpcs.api.util.DataKey;
|
import net.citizensnpcs.api.util.DataKey;
|
||||||
import net.citizensnpcs.api.util.MemoryDataKey;
|
import net.citizensnpcs.api.util.MemoryDataKey;
|
||||||
import net.citizensnpcs.command.Command;
|
import net.citizensnpcs.command.Command;
|
||||||
@ -959,6 +961,45 @@ public class NPCCommands {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Command(
|
||||||
|
aliases = { "npc" },
|
||||||
|
usage = "speak message to speak --target npcid|player_name --type vocal_type",
|
||||||
|
desc = "Uses the NPCs SpeechController to talk",
|
||||||
|
modifiers = { "speak" },
|
||||||
|
min = 2,
|
||||||
|
permission = "npc.speak")
|
||||||
|
public void speak(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
||||||
|
|
||||||
|
String type = npc.getTrait(Speech.class).getDefaultVocalChord();
|
||||||
|
String message = StringHelper.parseColors(args.getJoinedStrings(1));
|
||||||
|
|
||||||
|
if (message.length() <= 0) {
|
||||||
|
Messaging.send(sender, "Default Vocal Chord for " + npc.getName() + ": " + npc.getTrait(Speech.class).getDefaultVocalChord());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpeechContext context = new SpeechContext(message);
|
||||||
|
|
||||||
|
if (args.hasValueFlag("target")) {
|
||||||
|
if (args.getFlag("target").matches("\\d+")) {
|
||||||
|
NPC target = CitizensAPI.getNPCRegistry().getById(Integer.valueOf(args.getFlag("target")));
|
||||||
|
if ( target != null)
|
||||||
|
context.addRecipient(target.getBukkitEntity());
|
||||||
|
} else {
|
||||||
|
Player player = Bukkit.getPlayer(args.getFlag("target"));
|
||||||
|
if (player != null)
|
||||||
|
context.addRecipient(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.hasValueFlag("type")) {
|
||||||
|
if (CitizensAPI.getSpeechFactory().isRegistered(args.getFlag("type")))
|
||||||
|
type = args.getFlag("type");
|
||||||
|
}
|
||||||
|
|
||||||
|
npc.getDefaultSpeechController().speak(context, type);
|
||||||
|
}
|
||||||
|
|
||||||
@Command(
|
@Command(
|
||||||
aliases = { "npc" },
|
aliases = { "npc" },
|
||||||
usage = "speed [speed]",
|
usage = "speed [speed]",
|
||||||
|
@ -1,246 +1,247 @@
|
|||||||
package net.citizensnpcs.npc;
|
package net.citizensnpcs.npc;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import net.citizensnpcs.EventListen;
|
import net.citizensnpcs.EventListen;
|
||||||
import net.citizensnpcs.Settings.Setting;
|
import net.citizensnpcs.Settings.Setting;
|
||||||
import net.citizensnpcs.api.CitizensAPI;
|
import net.citizensnpcs.api.CitizensAPI;
|
||||||
import net.citizensnpcs.api.ai.Navigator;
|
import net.citizensnpcs.api.ai.Navigator;
|
||||||
import net.citizensnpcs.api.event.DespawnReason;
|
import net.citizensnpcs.api.event.DespawnReason;
|
||||||
import net.citizensnpcs.api.event.NPCDespawnEvent;
|
import net.citizensnpcs.api.event.NPCDespawnEvent;
|
||||||
import net.citizensnpcs.api.event.NPCSpawnEvent;
|
import net.citizensnpcs.api.event.NPCSpawnEvent;
|
||||||
import net.citizensnpcs.api.npc.AbstractNPC;
|
import net.citizensnpcs.api.npc.AbstractNPC;
|
||||||
import net.citizensnpcs.api.persistence.PersistenceLoader;
|
import net.citizensnpcs.api.persistence.PersistenceLoader;
|
||||||
import net.citizensnpcs.api.trait.Trait;
|
import net.citizensnpcs.api.trait.Trait;
|
||||||
import net.citizensnpcs.api.trait.trait.Spawned;
|
import net.citizensnpcs.api.trait.trait.Spawned;
|
||||||
import net.citizensnpcs.api.util.DataKey;
|
import net.citizensnpcs.api.util.DataKey;
|
||||||
import net.citizensnpcs.npc.ai.CitizensNavigator;
|
import net.citizensnpcs.npc.ai.CitizensNavigator;
|
||||||
import net.citizensnpcs.trait.CurrentLocation;
|
import net.citizensnpcs.trait.CurrentLocation;
|
||||||
import net.citizensnpcs.util.Messages;
|
import net.citizensnpcs.util.Messages;
|
||||||
import net.citizensnpcs.util.Messaging;
|
import net.citizensnpcs.util.Messaging;
|
||||||
import net.citizensnpcs.util.NMS;
|
import net.citizensnpcs.util.NMS;
|
||||||
import net.citizensnpcs.util.Util;
|
import net.citizensnpcs.util.Util;
|
||||||
import net.minecraft.server.v1_4_6.EntityLiving;
|
import net.minecraft.server.v1_4_6.EntityLiving;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.craftbukkit.v1_4_6.entity.CraftLivingEntity;
|
import org.bukkit.craftbukkit.v1_4_6.entity.CraftLivingEntity;
|
||||||
import org.bukkit.entity.LivingEntity;
|
import org.bukkit.entity.LivingEntity;
|
||||||
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
|
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
|
||||||
import org.bukkit.metadata.FixedMetadataValue;
|
import org.bukkit.metadata.FixedMetadataValue;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.common.base.Splitter;
|
import com.google.common.base.Splitter;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
public class CitizensNPC extends AbstractNPC {
|
public class CitizensNPC extends AbstractNPC {
|
||||||
private EntityController entityController;
|
private EntityController entityController;
|
||||||
private final CitizensNavigator navigator = new CitizensNavigator(this);
|
private final CitizensNavigator navigator = new CitizensNavigator(this);
|
||||||
private final List<String> removedTraits = Lists.newArrayList();
|
private final List<String> removedTraits = Lists.newArrayList();
|
||||||
|
|
||||||
public CitizensNPC(int id, String name, EntityController entityController) {
|
public CitizensNPC(int id, String name, EntityController entityController) {
|
||||||
super(id, name);
|
super(id, name);
|
||||||
Preconditions.checkNotNull(entityController);
|
Preconditions.checkNotNull(entityController);
|
||||||
this.entityController = entityController;
|
this.entityController = entityController;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean despawn(DespawnReason reason) {
|
public boolean despawn(DespawnReason reason) {
|
||||||
if (!isSpawned())
|
if (!isSpawned())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
NPCDespawnEvent event = new NPCDespawnEvent(this, reason);
|
NPCDespawnEvent event = new NPCDespawnEvent(this, reason);
|
||||||
if (reason == DespawnReason.CHUNK_UNLOAD)
|
if (reason == DespawnReason.CHUNK_UNLOAD)
|
||||||
event.setCancelled(Setting.KEEP_CHUNKS_LOADED.asBoolean());
|
event.setCancelled(Setting.KEEP_CHUNKS_LOADED.asBoolean());
|
||||||
Bukkit.getPluginManager().callEvent(event);
|
Bukkit.getPluginManager().callEvent(event);
|
||||||
if (event.isCancelled()) {
|
if (event.isCancelled()) {
|
||||||
getBukkitEntity().getLocation().getChunk();
|
getBukkitEntity().getLocation().getChunk();
|
||||||
// ensure that we are in a loaded chunk.
|
// ensure that we are in a loaded chunk.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
boolean keepSelected = getTrait(Spawned.class).shouldSpawn();
|
boolean keepSelected = getTrait(Spawned.class).shouldSpawn();
|
||||||
if (!keepSelected)
|
if (!keepSelected)
|
||||||
data().remove("selectors");
|
data().remove("selectors");
|
||||||
for (Trait trait : traits.values())
|
for (Trait trait : traits.values())
|
||||||
trait.onDespawn();
|
trait.onDespawn();
|
||||||
entityController.remove();
|
entityController.remove();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LivingEntity getBukkitEntity() {
|
public LivingEntity getBukkitEntity() {
|
||||||
return entityController.getBukkitEntity();
|
return entityController.getBukkitEntity();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public EntityLiving getHandle() {
|
public EntityLiving getHandle() {
|
||||||
return ((CraftLivingEntity) getBukkitEntity()).getHandle();
|
return ((CraftLivingEntity) getBukkitEntity()).getHandle();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Navigator getNavigator() {
|
public Navigator getNavigator() {
|
||||||
return navigator;
|
return navigator;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSpawned() {
|
public boolean isSpawned() {
|
||||||
return getBukkitEntity() != null;
|
return getBukkitEntity() != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void load(final DataKey root) {
|
public void load(final DataKey root) {
|
||||||
metadata.loadFrom(root.getRelative("metadata"));
|
metadata.loadFrom(root.getRelative("metadata"));
|
||||||
// Load traits
|
// Load traits
|
||||||
|
|
||||||
String traitNames = root.getString("traitnames");
|
String traitNames = root.getString("traitnames");
|
||||||
Iterable<DataKey> keys = traitNames.isEmpty() ? root.getRelative("traits").getSubKeys() : Iterables
|
Iterable<DataKey> keys = traitNames.isEmpty() ? root.getRelative("traits").getSubKeys() : Iterables
|
||||||
.transform(Splitter.on(',').split(traitNames), new Function<String, DataKey>() {
|
.transform(Splitter.on(',').split(traitNames), new Function<String, DataKey>() {
|
||||||
@Override
|
@Override
|
||||||
public DataKey apply(@Nullable String input) {
|
public DataKey apply(@Nullable String input) {
|
||||||
return root.getRelative("traits." + input);
|
return root.getRelative("traits." + input);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
for (DataKey traitKey : keys) {
|
for (DataKey traitKey : keys) {
|
||||||
if (traitKey.keyExists("enabled") && !traitKey.getBoolean("enabled"))
|
if (traitKey.keyExists("enabled") && !traitKey.getBoolean("enabled"))
|
||||||
continue;
|
continue;
|
||||||
Class<? extends Trait> clazz = CitizensAPI.getTraitFactory().getTraitClass(traitKey.name());
|
Class<? extends Trait> clazz = CitizensAPI.getTraitFactory().getTraitClass(traitKey.name());
|
||||||
Trait trait;
|
Trait trait;
|
||||||
if (hasTrait(clazz)) {
|
if (hasTrait(clazz)) {
|
||||||
trait = getTrait(clazz);
|
trait = getTrait(clazz);
|
||||||
} else {
|
} else {
|
||||||
trait = CitizensAPI.getTraitFactory().getTrait(clazz);
|
trait = CitizensAPI.getTraitFactory().getTrait(clazz);
|
||||||
if (trait == null) {
|
if (trait == null) {
|
||||||
Messaging.severeTr(Messages.SKIPPING_BROKEN_TRAIT, traitKey.name(), getId());
|
Messaging.severeTr(Messages.SKIPPING_BROKEN_TRAIT, traitKey.name(), getId());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
addTrait(trait);
|
addTrait(trait);
|
||||||
}
|
}
|
||||||
loadTrait(trait, traitKey);
|
loadTrait(trait, traitKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spawn the NPC
|
// Spawn the NPC
|
||||||
CurrentLocation spawnLocation = getTrait(CurrentLocation.class);
|
CurrentLocation spawnLocation = getTrait(CurrentLocation.class);
|
||||||
if (getTrait(Spawned.class).shouldSpawn() && spawnLocation.getLocation() != null)
|
if (getTrait(Spawned.class).shouldSpawn() && spawnLocation.getLocation() != null)
|
||||||
spawn(spawnLocation.getLocation());
|
spawn(spawnLocation.getLocation());
|
||||||
|
|
||||||
navigator.load(root.getRelative("navigator"));
|
navigator.load(root.getRelative("navigator"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadTrait(Trait trait, DataKey traitKey) {
|
private void loadTrait(Trait trait, DataKey traitKey) {
|
||||||
try {
|
try {
|
||||||
trait.load(traitKey);
|
trait.load(traitKey);
|
||||||
PersistenceLoader.load(trait, traitKey);
|
PersistenceLoader.load(trait, traitKey);
|
||||||
} catch (Throwable ex) {
|
} catch (Throwable ex) {
|
||||||
Messaging.logTr(Messages.TRAIT_LOAD_FAILED, traitKey.name(), getId());
|
Messaging.logTr(Messages.TRAIT_LOAD_FAILED, traitKey.name(), getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeTrait(Class<? extends Trait> clazz) {
|
public void removeTrait(Class<? extends Trait> clazz) {
|
||||||
Trait present = traits.get(clazz);
|
Trait present = traits.get(clazz);
|
||||||
if (present != null)
|
if (present != null)
|
||||||
removedTraits.add(present.getName());
|
removedTraits.add(present.getName());
|
||||||
super.removeTrait(clazz);
|
super.removeTrait(clazz);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeTraitData(DataKey root) {
|
private void removeTraitData(DataKey root) {
|
||||||
for (String name : removedTraits) {
|
for (String name : removedTraits) {
|
||||||
root.removeKey("traits." + name);
|
root.removeKey("traits." + name);
|
||||||
}
|
}
|
||||||
removedTraits.clear();
|
removedTraits.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void save(DataKey root) {
|
public void save(DataKey root) {
|
||||||
root.setString("name", getFullName());
|
root.setString("name", getFullName());
|
||||||
|
|
||||||
metadata.saveTo(root.getRelative("metadata"));
|
metadata.saveTo(root.getRelative("metadata"));
|
||||||
navigator.save(root.getRelative("navigator"));
|
navigator.save(root.getRelative("navigator"));
|
||||||
|
|
||||||
// Save all existing traits
|
// Save all existing traits
|
||||||
StringBuilder traitNames = new StringBuilder();
|
StringBuilder traitNames = new StringBuilder();
|
||||||
for (Trait trait : traits.values()) {
|
for (Trait trait : traits.values()) {
|
||||||
DataKey traitKey = root.getRelative("traits." + trait.getName());
|
DataKey traitKey = root.getRelative("traits." + trait.getName());
|
||||||
trait.save(traitKey);
|
trait.save(traitKey);
|
||||||
PersistenceLoader.save(trait, traitKey);
|
PersistenceLoader.save(trait, traitKey);
|
||||||
removedTraits.remove(trait.getName());
|
removedTraits.remove(trait.getName());
|
||||||
traitNames.append(trait.getName() + ",");
|
traitNames.append(trait.getName() + ",");
|
||||||
}
|
}
|
||||||
if (traitNames.length() > 0) {
|
if (traitNames.length() > 0) {
|
||||||
root.setString("traitnames", traitNames.substring(0, traitNames.length() - 1));
|
root.setString("traitnames", traitNames.substring(0, traitNames.length() - 1));
|
||||||
}
|
}
|
||||||
removeTraitData(root);
|
removeTraitData(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEntityController(EntityController newController) {
|
public void setEntityController(EntityController newController) {
|
||||||
Preconditions.checkNotNull(newController);
|
Preconditions.checkNotNull(newController);
|
||||||
boolean wasSpawned = isSpawned();
|
boolean wasSpawned = isSpawned();
|
||||||
Location prev = null;
|
Location prev = null;
|
||||||
if (wasSpawned) {
|
if (wasSpawned) {
|
||||||
prev = getBukkitEntity().getLocation();
|
prev = getBukkitEntity().getLocation();
|
||||||
despawn();
|
despawn();
|
||||||
}
|
}
|
||||||
entityController = newController;
|
entityController = newController;
|
||||||
if (wasSpawned)
|
if (wasSpawned)
|
||||||
spawn(prev);
|
spawn(prev);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean spawn(Location at) {
|
public boolean spawn(Location at) {
|
||||||
Preconditions.checkNotNull(at, "location cannot be null");
|
Preconditions.checkNotNull(at, "location cannot be null");
|
||||||
if (isSpawned())
|
if (isSpawned())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
entityController.spawn(at, this);
|
entityController.spawn(at, this);
|
||||||
EntityLiving mcEntity = getHandle();
|
EntityLiving mcEntity = getHandle();
|
||||||
boolean couldSpawn = !Util.isLoaded(at) ? false : mcEntity.world.addEntity(mcEntity,
|
boolean couldSpawn = !Util.isLoaded(at) ? false : mcEntity.world.addEntity(mcEntity,
|
||||||
SpawnReason.CUSTOM);
|
SpawnReason.CUSTOM);
|
||||||
if (!couldSpawn) {
|
if (!couldSpawn) {
|
||||||
// we need to wait for a chunk load before trying to spawn
|
// we need to wait for a chunk load before trying to spawn
|
||||||
mcEntity = null;
|
mcEntity = null;
|
||||||
EventListen.addForRespawn(at, getId());
|
EventListen.addForRespawn(at, getId());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
NPCSpawnEvent spawnEvent = new NPCSpawnEvent(this, at);
|
NPCSpawnEvent spawnEvent = new NPCSpawnEvent(this, at);
|
||||||
Bukkit.getPluginManager().callEvent(spawnEvent);
|
Bukkit.getPluginManager().callEvent(spawnEvent);
|
||||||
if (spawnEvent.isCancelled()) {
|
if (spawnEvent.isCancelled()) {
|
||||||
mcEntity = null;
|
mcEntity = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
NMS.setHeadYaw(mcEntity, at.getYaw());
|
NMS.setHeadYaw(mcEntity, at.getYaw());
|
||||||
getBukkitEntity().setMetadata(NPC_METADATA_MARKER,
|
getBukkitEntity().setMetadata(NPC_METADATA_MARKER,
|
||||||
new FixedMetadataValue(CitizensAPI.getPlugin(), true));
|
new FixedMetadataValue(CitizensAPI.getPlugin(), true));
|
||||||
|
|
||||||
// Set the spawned state
|
// Set the spawned state
|
||||||
getTrait(CurrentLocation.class).setLocation(at);
|
getTrait(CurrentLocation.class).setLocation(at);
|
||||||
getTrait(Spawned.class).setSpawned(true);
|
getTrait(Spawned.class).setSpawned(true);
|
||||||
|
|
||||||
navigator.onSpawn();
|
navigator.onSpawn();
|
||||||
// Modify NPC using traits after the entity has been created
|
// Modify NPC using traits after the entity has been created
|
||||||
for (Trait trait : traits.values())
|
for (Trait trait : traits.values())
|
||||||
trait.onSpawn();
|
trait.onSpawn();
|
||||||
getBukkitEntity().setRemoveWhenFarAway(false);
|
getBukkitEntity().setRemoveWhenFarAway(false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update() {
|
public void update() {
|
||||||
try {
|
try {
|
||||||
super.update();
|
super.update();
|
||||||
if (isSpawned()) {
|
if (isSpawned()) {
|
||||||
NMS.trySwim(getBukkitEntity());
|
NMS.trySwim(getBukkitEntity());
|
||||||
navigator.run();
|
navigator.run();
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Messaging.logTr(Messages.EXCEPTION_UPDATING_NPC, getId(), ex.getMessage());
|
Messaging.logTr(Messages.EXCEPTION_UPDATING_NPC, getId(), ex.getMessage());
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String NPC_METADATA_MARKER = "NPC";
|
private static final String NPC_METADATA_MARKER = "NPC";
|
||||||
|
|
||||||
}
|
}
|
@ -1,136 +1,138 @@
|
|||||||
package net.citizensnpcs.npc;
|
package net.citizensnpcs.npc;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import net.citizensnpcs.Metrics;
|
import net.citizensnpcs.Metrics;
|
||||||
import net.citizensnpcs.Metrics.Graph;
|
import net.citizensnpcs.Metrics.Graph;
|
||||||
import net.citizensnpcs.api.CitizensAPI;
|
import net.citizensnpcs.api.CitizensAPI;
|
||||||
import net.citizensnpcs.api.npc.NPC;
|
import net.citizensnpcs.api.npc.NPC;
|
||||||
import net.citizensnpcs.api.trait.Trait;
|
import net.citizensnpcs.api.trait.Trait;
|
||||||
import net.citizensnpcs.api.trait.TraitFactory;
|
import net.citizensnpcs.api.trait.TraitFactory;
|
||||||
import net.citizensnpcs.api.trait.TraitInfo;
|
import net.citizensnpcs.api.trait.TraitInfo;
|
||||||
import net.citizensnpcs.api.trait.trait.Equipment;
|
import net.citizensnpcs.api.trait.trait.Equipment;
|
||||||
import net.citizensnpcs.api.trait.trait.Inventory;
|
import net.citizensnpcs.api.trait.trait.Inventory;
|
||||||
import net.citizensnpcs.api.trait.trait.MobType;
|
import net.citizensnpcs.api.trait.trait.MobType;
|
||||||
import net.citizensnpcs.api.trait.trait.Owner;
|
import net.citizensnpcs.api.trait.trait.Owner;
|
||||||
import net.citizensnpcs.api.trait.trait.Spawned;
|
import net.citizensnpcs.api.trait.trait.Spawned;
|
||||||
import net.citizensnpcs.trait.Age;
|
import net.citizensnpcs.api.trait.trait.Speech;
|
||||||
import net.citizensnpcs.trait.Anchors;
|
import net.citizensnpcs.trait.Age;
|
||||||
import net.citizensnpcs.trait.Behaviour;
|
import net.citizensnpcs.trait.Anchors;
|
||||||
import net.citizensnpcs.trait.Controllable;
|
import net.citizensnpcs.trait.Behaviour;
|
||||||
import net.citizensnpcs.trait.CurrentLocation;
|
import net.citizensnpcs.trait.Controllable;
|
||||||
import net.citizensnpcs.trait.Gravity;
|
import net.citizensnpcs.trait.CurrentLocation;
|
||||||
import net.citizensnpcs.trait.LookClose;
|
import net.citizensnpcs.trait.Gravity;
|
||||||
import net.citizensnpcs.trait.NPCSkeletonType;
|
import net.citizensnpcs.trait.LookClose;
|
||||||
import net.citizensnpcs.trait.Poses;
|
import net.citizensnpcs.trait.NPCSkeletonType;
|
||||||
import net.citizensnpcs.trait.Powered;
|
import net.citizensnpcs.trait.Poses;
|
||||||
import net.citizensnpcs.trait.Saddle;
|
import net.citizensnpcs.trait.Powered;
|
||||||
import net.citizensnpcs.trait.Sheared;
|
import net.citizensnpcs.trait.Saddle;
|
||||||
import net.citizensnpcs.trait.SlimeSize;
|
import net.citizensnpcs.trait.Sheared;
|
||||||
import net.citizensnpcs.trait.VillagerProfession;
|
import net.citizensnpcs.trait.SlimeSize;
|
||||||
import net.citizensnpcs.trait.WoolColor;
|
import net.citizensnpcs.trait.VillagerProfession;
|
||||||
import net.citizensnpcs.trait.ZombieModifier;
|
import net.citizensnpcs.trait.WoolColor;
|
||||||
import net.citizensnpcs.trait.text.Text;
|
import net.citizensnpcs.trait.ZombieModifier;
|
||||||
import net.citizensnpcs.trait.waypoint.Waypoints;
|
import net.citizensnpcs.trait.text.Text;
|
||||||
|
import net.citizensnpcs.trait.waypoint.Waypoints;
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Maps;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
public class CitizensTraitFactory implements TraitFactory {
|
|
||||||
private final Map<String, Class<? extends Trait>> registered = Maps.newHashMap();
|
public class CitizensTraitFactory implements TraitFactory {
|
||||||
|
private final Map<String, Class<? extends Trait>> registered = Maps.newHashMap();
|
||||||
public CitizensTraitFactory() {
|
|
||||||
registerTrait(TraitInfo.create(Age.class).withName("age"));
|
public CitizensTraitFactory() {
|
||||||
registerTrait(TraitInfo.create(Anchors.class).withName("anchors"));
|
registerTrait(TraitInfo.create(Age.class).withName("age"));
|
||||||
registerTrait(TraitInfo.create(Behaviour.class).withName("behaviour"));
|
registerTrait(TraitInfo.create(Anchors.class).withName("anchors"));
|
||||||
registerTrait(TraitInfo.create(Controllable.class).withName("controllable"));
|
registerTrait(TraitInfo.create(Behaviour.class).withName("behaviour"));
|
||||||
registerTrait(TraitInfo.create(Equipment.class).withName("equipment"));
|
registerTrait(TraitInfo.create(Controllable.class).withName("controllable"));
|
||||||
registerTrait(TraitInfo.create(Gravity.class).withName("gravity"));
|
registerTrait(TraitInfo.create(Equipment.class).withName("equipment"));
|
||||||
registerTrait(TraitInfo.create(Inventory.class).withName("inventory"));
|
registerTrait(TraitInfo.create(Gravity.class).withName("gravity"));
|
||||||
registerTrait(TraitInfo.create(CurrentLocation.class).withName("location"));
|
registerTrait(TraitInfo.create(Inventory.class).withName("inventory"));
|
||||||
registerTrait(TraitInfo.create(LookClose.class).withName("lookclose"));
|
registerTrait(TraitInfo.create(CurrentLocation.class).withName("location"));
|
||||||
registerTrait(TraitInfo.create(Owner.class).withName("owner"));
|
registerTrait(TraitInfo.create(LookClose.class).withName("lookclose"));
|
||||||
registerTrait(TraitInfo.create(Poses.class).withName("poses"));
|
registerTrait(TraitInfo.create(Owner.class).withName("owner"));
|
||||||
registerTrait(TraitInfo.create(Powered.class).withName("powered"));
|
registerTrait(TraitInfo.create(Poses.class).withName("poses"));
|
||||||
registerTrait(TraitInfo.create(VillagerProfession.class).withName("profession"));
|
registerTrait(TraitInfo.create(Powered.class).withName("powered"));
|
||||||
registerTrait(TraitInfo.create(Saddle.class).withName("saddle"));
|
registerTrait(TraitInfo.create(VillagerProfession.class).withName("profession"));
|
||||||
registerTrait(TraitInfo.create(Sheared.class).withName("sheared"));
|
registerTrait(TraitInfo.create(Saddle.class).withName("saddle"));
|
||||||
registerTrait(TraitInfo.create(NPCSkeletonType.class).withName("skeletontype"));
|
registerTrait(TraitInfo.create(Sheared.class).withName("sheared"));
|
||||||
registerTrait(TraitInfo.create(SlimeSize.class).withName("slimesize"));
|
registerTrait(TraitInfo.create(NPCSkeletonType.class).withName("skeletontype"));
|
||||||
registerTrait(TraitInfo.create(Spawned.class).withName("spawned"));
|
registerTrait(TraitInfo.create(SlimeSize.class).withName("slimesize"));
|
||||||
registerTrait(TraitInfo.create(Text.class).withName("text"));
|
registerTrait(TraitInfo.create(Spawned.class).withName("spawned"));
|
||||||
registerTrait(TraitInfo.create(MobType.class).withName("type"));
|
registerTrait(TraitInfo.create(Speech.class).withName("speech"));
|
||||||
registerTrait(TraitInfo.create(Waypoints.class).withName("waypoints"));
|
registerTrait(TraitInfo.create(Text.class).withName("text"));
|
||||||
registerTrait(TraitInfo.create(WoolColor.class).withName("woolcolor"));
|
registerTrait(TraitInfo.create(MobType.class).withName("type"));
|
||||||
registerTrait(TraitInfo.create(ZombieModifier.class).withName("zombiemodifier"));
|
registerTrait(TraitInfo.create(Waypoints.class).withName("waypoints"));
|
||||||
|
registerTrait(TraitInfo.create(WoolColor.class).withName("woolcolor"));
|
||||||
for (String trait : registered.keySet())
|
registerTrait(TraitInfo.create(ZombieModifier.class).withName("zombiemodifier"));
|
||||||
INTERNAL_TRAITS.add(trait);
|
|
||||||
}
|
for (String trait : registered.keySet())
|
||||||
|
INTERNAL_TRAITS.add(trait);
|
||||||
public void addPlotters(Graph graph) {
|
}
|
||||||
for (Map.Entry<String, Class<? extends Trait>> entry : registered.entrySet()) {
|
|
||||||
if (INTERNAL_TRAITS.contains(entry.getKey()))
|
public void addPlotters(Graph graph) {
|
||||||
continue;
|
for (Map.Entry<String, Class<? extends Trait>> entry : registered.entrySet()) {
|
||||||
final Class<? extends Trait> traitClass = entry.getValue();
|
if (INTERNAL_TRAITS.contains(entry.getKey()))
|
||||||
graph.addPlotter(new Metrics.Plotter(entry.getKey()) {
|
continue;
|
||||||
@Override
|
final Class<? extends Trait> traitClass = entry.getValue();
|
||||||
public int getValue() {
|
graph.addPlotter(new Metrics.Plotter(entry.getKey()) {
|
||||||
int numberUsingTrait = 0;
|
@Override
|
||||||
for (NPC npc : CitizensAPI.getNPCRegistry()) {
|
public int getValue() {
|
||||||
if (npc.hasTrait(traitClass))
|
int numberUsingTrait = 0;
|
||||||
++numberUsingTrait;
|
for (NPC npc : CitizensAPI.getNPCRegistry()) {
|
||||||
}
|
if (npc.hasTrait(traitClass))
|
||||||
return numberUsingTrait;
|
++numberUsingTrait;
|
||||||
}
|
}
|
||||||
});
|
return numberUsingTrait;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
}
|
||||||
private <T extends Trait> T create(Class<T> trait) {
|
}
|
||||||
try {
|
|
||||||
return trait.newInstance();
|
private <T extends Trait> T create(Class<T> trait) {
|
||||||
} catch (Exception ex) {
|
try {
|
||||||
ex.printStackTrace();
|
return trait.newInstance();
|
||||||
return null;
|
} catch (Exception ex) {
|
||||||
}
|
ex.printStackTrace();
|
||||||
}
|
return null;
|
||||||
|
}
|
||||||
@Override
|
}
|
||||||
public <T extends Trait> T getTrait(Class<T> clazz) {
|
|
||||||
if (!registered.containsValue(clazz))
|
@Override
|
||||||
return null;
|
public <T extends Trait> T getTrait(Class<T> clazz) {
|
||||||
return create(clazz);
|
if (!registered.containsValue(clazz))
|
||||||
}
|
return null;
|
||||||
|
return create(clazz);
|
||||||
@Override
|
}
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <T extends Trait> T getTrait(String name) {
|
@Override
|
||||||
Class<? extends Trait> clazz = registered.get(name);
|
@SuppressWarnings("unchecked")
|
||||||
if (clazz == null)
|
public <T extends Trait> T getTrait(String name) {
|
||||||
return null;
|
Class<? extends Trait> clazz = registered.get(name);
|
||||||
return (T) create(clazz);
|
if (clazz == null)
|
||||||
}
|
return null;
|
||||||
|
return (T) create(clazz);
|
||||||
@Override
|
}
|
||||||
public Class<? extends Trait> getTraitClass(String name) {
|
|
||||||
return registered.get(name.toLowerCase());
|
@Override
|
||||||
}
|
public Class<? extends Trait> getTraitClass(String name) {
|
||||||
|
return registered.get(name.toLowerCase());
|
||||||
@Override
|
}
|
||||||
public boolean isInternalTrait(Trait trait) {
|
|
||||||
return INTERNAL_TRAITS.contains(trait.getName());
|
@Override
|
||||||
}
|
public boolean isInternalTrait(Trait trait) {
|
||||||
|
return INTERNAL_TRAITS.contains(trait.getName());
|
||||||
@Override
|
}
|
||||||
public void registerTrait(TraitInfo info) {
|
|
||||||
Preconditions.checkNotNull(info, "info cannot be null");
|
@Override
|
||||||
if (registered.containsKey(info))
|
public void registerTrait(TraitInfo info) {
|
||||||
throw new IllegalArgumentException("trait name already registered");
|
Preconditions.checkNotNull(info, "info cannot be null");
|
||||||
registered.put(info.getTraitName(), info.getTraitClass());
|
if (registered.containsKey(info))
|
||||||
}
|
throw new IllegalArgumentException("trait name already registered");
|
||||||
|
registered.put(info.getTraitName(), info.getTraitClass());
|
||||||
private static final Set<String> INTERNAL_TRAITS = Sets.newHashSet();
|
}
|
||||||
|
|
||||||
|
private static final Set<String> INTERNAL_TRAITS = Sets.newHashSet();
|
||||||
}
|
}
|
117
src/main/java/net/citizensnpcs/npc/ai/speech/Chat.java
Normal file
117
src/main/java/net/citizensnpcs/npc/ai/speech/Chat.java
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
package net.citizensnpcs.npc.ai.speech;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
|
||||||
|
import net.citizensnpcs.Settings.Setting;
|
||||||
|
import net.citizensnpcs.api.CitizensAPI;
|
||||||
|
import net.citizensnpcs.api.ai.speech.Talkable;
|
||||||
|
import net.citizensnpcs.api.ai.speech.SpeechContext;
|
||||||
|
import net.citizensnpcs.api.ai.speech.VocalChord;
|
||||||
|
import net.citizensnpcs.api.npc.NPC;
|
||||||
|
import net.citizensnpcs.util.Messaging;
|
||||||
|
|
||||||
|
public class Chat implements VocalChord {
|
||||||
|
|
||||||
|
public final String VOCAL_CHORD_NAME = "chat";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return VOCAL_CHORD_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void talk(SpeechContext context) {
|
||||||
|
|
||||||
|
// Check valid talker
|
||||||
|
if (context.getTalker() == null) return;
|
||||||
|
NPC npc = CitizensAPI.getNPCRegistry().getNPC(context.getTalker().getEntity());
|
||||||
|
if (npc == null) return;
|
||||||
|
|
||||||
|
// If no recipients, chat to the world with CHAT_FORMAT and CHAT_RANGE settings
|
||||||
|
if (!context.hasRecipients()) {
|
||||||
|
String text = Setting.CHAT_FORMAT.asString().replace("<npc>", npc.getName()).replace("<text>", context.getMessage());
|
||||||
|
talkToBystanders(npc, text, context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assumed recipients at this point
|
||||||
|
else if (context.size() <= 1) { // One recipient
|
||||||
|
String text = Setting.CHAT_FORMAT_TO_TARGET.asString().replace("<npc>", npc.getName()).replace("<text>", context.getMessage());
|
||||||
|
String targetName = "";
|
||||||
|
// For each recipient
|
||||||
|
for (Talkable entity : context) {
|
||||||
|
entity.talkTo(context, text, this);
|
||||||
|
targetName = entity.getName();
|
||||||
|
}
|
||||||
|
// Check if bystanders hear targeted chat
|
||||||
|
if (!Setting.CHAT_BYSTANDERS_HEAR_TARGETED_CHAT.asBoolean()) return;
|
||||||
|
// Format message with config setting and send to bystanders
|
||||||
|
String bystanderText = Setting.CHAT_FORMAT_TO_BYSTANDERS.asString().replace("<npc>", npc.getName()).replace("<target>", targetName).replace("<text>", context.getMessage());
|
||||||
|
talkToBystanders(npc, bystanderText, context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
else { // Multiple recipients
|
||||||
|
String text = Setting.CHAT_FORMAT_TO_TARGET.asString().replace("<npc>", npc.getName()).replace("<text>", context.getMessage());
|
||||||
|
List<String> targetNames = Collections.emptyList();
|
||||||
|
// Talk to each recipient
|
||||||
|
for (Talkable entity : context) {
|
||||||
|
entity.talkTo(context, text, this);
|
||||||
|
targetNames.add(entity.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Setting.CHAT_BYSTANDERS_HEAR_TARGETED_CHAT.asBoolean()) return;
|
||||||
|
String targets = "";
|
||||||
|
int max = Setting.CHAT_MAX_NUMBER_OF_TARGETS.asInt();
|
||||||
|
String[] format = Setting.CHAT_FORMAT_WITH_TARGETS_TO_BYSTANDERS.asString().split("\\|");
|
||||||
|
if (format.length != 4) Messaging.log(Level.WARNING, "npc.chat.format.with-target-to-bystanders invalid!");
|
||||||
|
if (max == 1) {
|
||||||
|
targets = format[0].replace("<npc>", targetNames.get(0)) + format[3];
|
||||||
|
}
|
||||||
|
else if (max == 2 || targetNames.size() == 2) {
|
||||||
|
if (targetNames.size() == 2)
|
||||||
|
targets = format[0].replace("<npc>", targetNames.get(0)) + format[2].replace("<npc>", targetNames.get(1));
|
||||||
|
else
|
||||||
|
targets = format[0].replace("<npc>", targetNames.get(0)) + format[1].replace("<npc>", targetNames.get(1)) + format[3];
|
||||||
|
}
|
||||||
|
else if (max >= 3) {
|
||||||
|
targets = format[0].replace("<npc>", targetNames.get(0));
|
||||||
|
|
||||||
|
int x = 1;
|
||||||
|
for (x = 1; x < max - 1; x++) {
|
||||||
|
if (targetNames.size() - 1 == x) break;
|
||||||
|
targets = targets + format[1].replace("<npc>", targetNames.get(x));
|
||||||
|
}
|
||||||
|
if (targetNames.size() == max)
|
||||||
|
targets = targets + format[2].replace("<npc>", targetNames.get(x));
|
||||||
|
else targets = targets + format[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
String bystanderText = Setting.CHAT_FORMAT_WITH_TARGETS_TO_BYSTANDERS.asString().replace("<npc>", npc.getName()).replace("<targets>", targets).replace("<text>", context.getMessage());
|
||||||
|
talkToBystanders(npc, bystanderText, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void talkToBystanders(NPC npc, String text, SpeechContext context) {
|
||||||
|
// Get list of nearby entities
|
||||||
|
List<Entity> bystanderEntities = npc.getBukkitEntity().getNearbyEntities(Setting.CHAT_RANGE.asDouble(), Setting.CHAT_RANGE.asDouble(), Setting.CHAT_RANGE.asDouble());
|
||||||
|
for (Entity bystander : bystanderEntities)
|
||||||
|
// Continue if a LivingEntity, which is compatible with TalkableEntity
|
||||||
|
if (bystander instanceof LivingEntity) {
|
||||||
|
// Exclude targeted recipients
|
||||||
|
if (context.hasRecipients()) {
|
||||||
|
for (Talkable target : context)
|
||||||
|
if (target.getEntity() == bystander) continue;
|
||||||
|
else new TalkableEntity((LivingEntity) bystander).talkNear(context, text, this);
|
||||||
|
} else
|
||||||
|
// Found a nearby LivingEntity, make it Talkable and talkNear it
|
||||||
|
new TalkableEntity((LivingEntity) bystander).talkNear(context, text, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,79 @@
|
|||||||
|
package net.citizensnpcs.npc.ai.speech;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
|
||||||
|
import net.citizensnpcs.api.ai.speech.SpeechFactory;
|
||||||
|
import net.citizensnpcs.api.ai.speech.Talkable;
|
||||||
|
import net.citizensnpcs.api.ai.speech.VocalChord;
|
||||||
|
|
||||||
|
public class CitizensSpeechFactory implements SpeechFactory {
|
||||||
|
|
||||||
|
Map<String, Class<? extends VocalChord>> registered = new HashMap<String, Class <? extends VocalChord>>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VocalChord getVocalChord(Class<? extends VocalChord> clazz) {
|
||||||
|
// Return a new instance of the VocalChord specified
|
||||||
|
try {
|
||||||
|
return clazz.newInstance();
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VocalChord getVocalChord(String name) {
|
||||||
|
// Check if VocalChord name is a registered type
|
||||||
|
if (isRegistered(name))
|
||||||
|
// Return a new instance of the VocalChord specified
|
||||||
|
try {
|
||||||
|
return registered.get(name.toLowerCase()).newInstance();
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getVocalChordName(Class<? extends VocalChord> clazz) {
|
||||||
|
// Get the name of a VocalChord class that has been registered
|
||||||
|
for (Entry<String, Class<? extends VocalChord>> vocalChord : registered.entrySet())
|
||||||
|
if (vocalChord.getValue() == clazz) return vocalChord.getKey();
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRegistered(String name) {
|
||||||
|
if (registered.containsKey(name.toLowerCase())) return true;
|
||||||
|
else return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void register(Class<? extends VocalChord> clazz, String name) {
|
||||||
|
Preconditions.checkNotNull(name, "info cannot be null");
|
||||||
|
Preconditions.checkNotNull(clazz, "vocalchord cannot be null");
|
||||||
|
if (registered.containsKey(name.toLowerCase()))
|
||||||
|
throw new IllegalArgumentException("vocalchord name already registered");
|
||||||
|
registered.put(name.toLowerCase(), clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Talkable newTalkableEntity(LivingEntity entity) {
|
||||||
|
if (entity == null) return null;
|
||||||
|
return new TalkableEntity(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,91 @@
|
|||||||
|
package net.citizensnpcs.npc.ai.speech;
|
||||||
|
|
||||||
|
import net.citizensnpcs.api.CitizensAPI;
|
||||||
|
import net.citizensnpcs.api.ai.speech.SpeechContext;
|
||||||
|
import net.citizensnpcs.api.ai.speech.Talkable;
|
||||||
|
import net.citizensnpcs.api.ai.speech.VocalChord;
|
||||||
|
import net.citizensnpcs.api.ai.speech.event.SpeechBystanderEvent;
|
||||||
|
import net.citizensnpcs.api.ai.speech.event.SpeechTargetedEvent;
|
||||||
|
import net.citizensnpcs.api.npc.NPC;
|
||||||
|
import net.citizensnpcs.util.Messaging;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public class TalkableEntity implements Talkable {
|
||||||
|
|
||||||
|
LivingEntity entity;
|
||||||
|
|
||||||
|
public TalkableEntity(LivingEntity entity) {
|
||||||
|
this.entity = entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TalkableEntity(NPC npc) {
|
||||||
|
entity = npc.getBukkitEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TalkableEntity(Player player) {
|
||||||
|
entity = (LivingEntity) player;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to compare a LivingEntity to this TalkableEntity
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* 0 if the Entities are the same, 1 if they are not, -1 if
|
||||||
|
* the object compared is not a valid LivingEntity
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int compareTo(Object o) {
|
||||||
|
// If not living entity, return -1
|
||||||
|
if (!(o instanceof LivingEntity)) return -1;
|
||||||
|
// If NPC and matches, return 0
|
||||||
|
else if (CitizensAPI.getNPCRegistry().isNPC((LivingEntity) o)
|
||||||
|
&& CitizensAPI.getNPCRegistry().isNPC((LivingEntity) entity)
|
||||||
|
&& CitizensAPI.getNPCRegistry().getNPC((LivingEntity) o).getId() ==
|
||||||
|
CitizensAPI.getNPCRegistry().getNPC((LivingEntity) entity).getId())
|
||||||
|
return 0;
|
||||||
|
else if ((LivingEntity) o == entity) return 0;
|
||||||
|
// Not a match, return 1
|
||||||
|
else return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LivingEntity getEntity() {
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
if (CitizensAPI.getNPCRegistry().isNPC(entity))
|
||||||
|
return CitizensAPI.getNPCRegistry().getNPC(entity).getName();
|
||||||
|
else if (entity instanceof Player)
|
||||||
|
return ((Player) entity).getName();
|
||||||
|
else
|
||||||
|
return entity.getType().name().replace("_", " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void talk(String message) {
|
||||||
|
if (entity instanceof Player
|
||||||
|
&& !CitizensAPI.getNPCRegistry().isNPC(entity))
|
||||||
|
Messaging.send((Player) entity, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void talkNear(SpeechContext context, String text, VocalChord vocalChord) {
|
||||||
|
SpeechBystanderEvent event = new SpeechBystanderEvent(this, context, text, vocalChord);
|
||||||
|
Bukkit.getServer().getPluginManager().callEvent(event);
|
||||||
|
if (event.isCancelled()) return;
|
||||||
|
else talk(event.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void talkTo(SpeechContext context, String text, VocalChord vocalChord) {
|
||||||
|
SpeechTargetedEvent event = new SpeechTargetedEvent(this, context, text, vocalChord);
|
||||||
|
Bukkit.getServer().getPluginManager().callEvent(event);
|
||||||
|
if (event.isCancelled()) return;
|
||||||
|
else talk(event.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,232 +1,237 @@
|
|||||||
package net.citizensnpcs.trait.text;
|
package net.citizensnpcs.trait.text;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import net.citizensnpcs.Settings.Setting;
|
import net.citizensnpcs.Settings.Setting;
|
||||||
import net.citizensnpcs.api.CitizensAPI;
|
import net.citizensnpcs.api.CitizensAPI;
|
||||||
import net.citizensnpcs.api.event.NPCRightClickEvent;
|
import net.citizensnpcs.api.ai.speech.SpeechContext;
|
||||||
import net.citizensnpcs.api.exception.NPCLoadException;
|
import net.citizensnpcs.api.ai.speech.Talkable;
|
||||||
import net.citizensnpcs.api.trait.Trait;
|
import net.citizensnpcs.api.event.NPCRightClickEvent;
|
||||||
import net.citizensnpcs.api.util.DataKey;
|
import net.citizensnpcs.api.exception.NPCLoadException;
|
||||||
import net.citizensnpcs.editor.Editor;
|
import net.citizensnpcs.api.trait.Trait;
|
||||||
import net.citizensnpcs.trait.Toggleable;
|
import net.citizensnpcs.api.util.DataKey;
|
||||||
import net.citizensnpcs.util.Messages;
|
import net.citizensnpcs.editor.Editor;
|
||||||
import net.citizensnpcs.util.Messaging;
|
import net.citizensnpcs.npc.ai.speech.TalkableEntity;
|
||||||
import net.citizensnpcs.util.Paginator;
|
import net.citizensnpcs.trait.Toggleable;
|
||||||
import net.citizensnpcs.util.Util;
|
import net.citizensnpcs.util.Messages;
|
||||||
|
import net.citizensnpcs.util.Messaging;
|
||||||
import org.bukkit.Bukkit;
|
import net.citizensnpcs.util.Paginator;
|
||||||
import org.bukkit.conversations.Conversation;
|
import net.citizensnpcs.util.Util;
|
||||||
import org.bukkit.conversations.ConversationAbandonedEvent;
|
|
||||||
import org.bukkit.conversations.ConversationAbandonedListener;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.conversations.ConversationFactory;
|
import org.bukkit.conversations.Conversation;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.conversations.ConversationAbandonedEvent;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.conversations.ConversationAbandonedListener;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.conversations.ConversationFactory;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
public class Text extends Trait implements Runnable, Toggleable, Listener, ConversationAbandonedListener {
|
import org.bukkit.event.Listener;
|
||||||
private final Map<String, Date> cooldowns = new HashMap<String, Date>();
|
import org.bukkit.plugin.Plugin;
|
||||||
private int currentIndex;
|
|
||||||
private String itemInHandPattern = "default";
|
public class Text extends Trait implements Runnable, Toggleable, Listener, ConversationAbandonedListener {
|
||||||
private final Plugin plugin;
|
private final Map<String, Date> cooldowns = new HashMap<String, Date>();
|
||||||
private boolean randomTalker = Setting.DEFAULT_RANDOM_TALKER.asBoolean();
|
private int currentIndex;
|
||||||
private double range = Setting.DEFAULT_TALK_CLOSE_RANGE.asDouble();
|
private String itemInHandPattern = "default";
|
||||||
private boolean realisticLooker = Setting.DEFAULT_REALISTIC_LOOKING.asBoolean();
|
private final Plugin plugin;
|
||||||
private boolean talkClose = Setting.DEFAULT_TALK_CLOSE.asBoolean();
|
private boolean randomTalker = Setting.DEFAULT_RANDOM_TALKER.asBoolean();
|
||||||
private final List<String> text = new ArrayList<String>();
|
private double range = Setting.DEFAULT_TALK_CLOSE_RANGE.asDouble();
|
||||||
|
private boolean realisticLooker = Setting.DEFAULT_REALISTIC_LOOKING.asBoolean();
|
||||||
public Text() {
|
private boolean talkClose = Setting.DEFAULT_TALK_CLOSE.asBoolean();
|
||||||
super("text");
|
private final List<String> text = new ArrayList<String>();
|
||||||
this.plugin = CitizensAPI.getPlugin();
|
|
||||||
}
|
public Text() {
|
||||||
|
super("text");
|
||||||
void add(String string) {
|
this.plugin = CitizensAPI.getPlugin();
|
||||||
text.add(string);
|
}
|
||||||
}
|
|
||||||
|
void add(String string) {
|
||||||
@Override
|
text.add(string);
|
||||||
public void conversationAbandoned(ConversationAbandonedEvent event) {
|
}
|
||||||
Bukkit.dispatchCommand((Player) event.getContext().getForWhom(), "npc text");
|
|
||||||
}
|
@Override
|
||||||
|
public void conversationAbandoned(ConversationAbandonedEvent event) {
|
||||||
void edit(int index, String newText) {
|
Bukkit.dispatchCommand((Player) event.getContext().getForWhom(), "npc text");
|
||||||
text.set(index, newText);
|
}
|
||||||
}
|
|
||||||
|
void edit(int index, String newText) {
|
||||||
public Editor getEditor(final Player player) {
|
text.set(index, newText);
|
||||||
final Conversation conversation = new ConversationFactory(plugin)
|
}
|
||||||
.addConversationAbandonedListener(this).withLocalEcho(false).withEscapeSequence("/npc text")
|
|
||||||
.withEscapeSequence("exit").withModality(false).withFirstPrompt(new TextStartPrompt(this))
|
public Editor getEditor(final Player player) {
|
||||||
.buildConversation(player);
|
final Conversation conversation = new ConversationFactory(plugin)
|
||||||
return new Editor() {
|
.addConversationAbandonedListener(this).withLocalEcho(false).withEscapeSequence("/npc text")
|
||||||
|
.withEscapeSequence("exit").withModality(false).withFirstPrompt(new TextStartPrompt(this))
|
||||||
@Override
|
.buildConversation(player);
|
||||||
public void begin() {
|
return new Editor() {
|
||||||
Messaging.sendTr(player, Messages.TEXT_EDITOR_BEGIN);
|
|
||||||
conversation.begin();
|
@Override
|
||||||
}
|
public void begin() {
|
||||||
|
Messaging.sendTr(player, Messages.TEXT_EDITOR_BEGIN);
|
||||||
@Override
|
conversation.begin();
|
||||||
public void end() {
|
}
|
||||||
Messaging.sendTr(player, Messages.TEXT_EDITOR_END);
|
|
||||||
conversation.abandon();
|
@Override
|
||||||
}
|
public void end() {
|
||||||
};
|
Messaging.sendTr(player, Messages.TEXT_EDITOR_END);
|
||||||
}
|
conversation.abandon();
|
||||||
|
}
|
||||||
boolean hasIndex(int index) {
|
};
|
||||||
return index >= 0 && text.size() > index;
|
}
|
||||||
}
|
|
||||||
|
boolean hasIndex(int index) {
|
||||||
@Override
|
return index >= 0 && text.size() > index;
|
||||||
public void load(DataKey key) throws NPCLoadException {
|
}
|
||||||
text.clear();
|
|
||||||
// TODO: legacy, remove later
|
@Override
|
||||||
for (DataKey sub : key.getIntegerSubKeys())
|
public void load(DataKey key) throws NPCLoadException {
|
||||||
text.add(sub.getString(""));
|
text.clear();
|
||||||
for (DataKey sub : key.getRelative("text").getIntegerSubKeys())
|
// TODO: legacy, remove later
|
||||||
text.add(sub.getString(""));
|
for (DataKey sub : key.getIntegerSubKeys())
|
||||||
if (text.isEmpty())
|
text.add(sub.getString(""));
|
||||||
populateDefaultText();
|
for (DataKey sub : key.getRelative("text").getIntegerSubKeys())
|
||||||
|
text.add(sub.getString(""));
|
||||||
talkClose = key.getBoolean("talk-close", talkClose);
|
if (text.isEmpty())
|
||||||
realisticLooker = key.getBoolean("realistic-looking", realisticLooker);
|
populateDefaultText();
|
||||||
randomTalker = key.getBoolean("random-talker", randomTalker);
|
|
||||||
range = key.getDouble("range", range);
|
talkClose = key.getBoolean("talk-close", talkClose);
|
||||||
itemInHandPattern = key.getString("talkitem", itemInHandPattern);
|
realisticLooker = key.getBoolean("realistic-looking", realisticLooker);
|
||||||
}
|
randomTalker = key.getBoolean("random-talker", randomTalker);
|
||||||
|
range = key.getDouble("range", range);
|
||||||
@EventHandler
|
itemInHandPattern = key.getString("talkitem", itemInHandPattern);
|
||||||
public void onRightClick(NPCRightClickEvent event) {
|
}
|
||||||
if (!event.getNPC().equals(npc))
|
|
||||||
return;
|
@EventHandler
|
||||||
String localPattern = itemInHandPattern.equals("default") ? Setting.TALK_ITEM.asString()
|
public void onRightClick(NPCRightClickEvent event) {
|
||||||
: itemInHandPattern;
|
if (!event.getNPC().equals(npc))
|
||||||
if (Util.matchesItemInHand(event.getClicker(), localPattern) && !shouldTalkClose())
|
return;
|
||||||
sendText(event.getClicker());
|
String localPattern = itemInHandPattern.equals("default") ? Setting.TALK_ITEM.asString()
|
||||||
}
|
: itemInHandPattern;
|
||||||
|
if (Util.matchesItemInHand(event.getClicker(), localPattern) && !shouldTalkClose())
|
||||||
private void populateDefaultText() {
|
sendText(event.getClicker());
|
||||||
text.addAll(Setting.DEFAULT_TEXT.asList());
|
}
|
||||||
}
|
|
||||||
|
private void populateDefaultText() {
|
||||||
void remove(int index) {
|
text.addAll(Setting.DEFAULT_TEXT.asList());
|
||||||
text.remove(index);
|
}
|
||||||
}
|
|
||||||
|
void remove(int index) {
|
||||||
@Override
|
text.remove(index);
|
||||||
public void run() {
|
}
|
||||||
if (!talkClose || !npc.isSpawned())
|
|
||||||
return;
|
@Override
|
||||||
List<Entity> nearby = npc.getBukkitEntity().getNearbyEntities(range, range, range);
|
public void run() {
|
||||||
for (Entity search : nearby) {
|
if (!talkClose || !npc.isSpawned())
|
||||||
if (!(search instanceof Player))
|
return;
|
||||||
continue;
|
List<Entity> nearby = npc.getBukkitEntity().getNearbyEntities(range, range, range);
|
||||||
Player player = (Player) search;
|
for (Entity search : nearby) {
|
||||||
// If the cooldown is not expired, do not send text
|
if (!(search instanceof Player))
|
||||||
Date cooldown = cooldowns.get(player.getName());
|
continue;
|
||||||
if (cooldown != null) {
|
Player player = (Player) search;
|
||||||
if (!new Date().after(cooldown))
|
// If the cooldown is not expired, do not send text
|
||||||
return;
|
Date cooldown = cooldowns.get(player.getName());
|
||||||
cooldowns.remove(player.getName());
|
if (cooldown != null) {
|
||||||
}
|
if (!new Date().after(cooldown))
|
||||||
if (!sendText(player))
|
return;
|
||||||
return;
|
cooldowns.remove(player.getName());
|
||||||
// Add a cooldown if the text was successfully sent
|
}
|
||||||
Date wait = new Date();
|
if (!sendText(player))
|
||||||
int secondsDelta = RANDOM.nextInt(Setting.TALK_CLOSE_MAXIMUM_COOLDOWN.asInt())
|
return;
|
||||||
+ Setting.TALK_CLOSE_MINIMUM_COOLDOWN.asInt();
|
// Add a cooldown if the text was successfully sent
|
||||||
if (secondsDelta <= 0)
|
Date wait = new Date();
|
||||||
return;
|
int secondsDelta = RANDOM.nextInt(Setting.TALK_CLOSE_MAXIMUM_COOLDOWN.asInt())
|
||||||
long millisecondsDelta = TimeUnit.MILLISECONDS.convert(secondsDelta, TimeUnit.SECONDS);
|
+ Setting.TALK_CLOSE_MINIMUM_COOLDOWN.asInt();
|
||||||
wait.setTime(wait.getTime() + millisecondsDelta);
|
if (secondsDelta <= 0)
|
||||||
cooldowns.put(player.getName(), wait);
|
return;
|
||||||
}
|
long millisecondsDelta = TimeUnit.MILLISECONDS.convert(secondsDelta, TimeUnit.SECONDS);
|
||||||
}
|
wait.setTime(wait.getTime() + millisecondsDelta);
|
||||||
|
cooldowns.put(player.getName(), wait);
|
||||||
@Override
|
}
|
||||||
public void save(DataKey key) {
|
}
|
||||||
key.setBoolean("talk-close", talkClose);
|
|
||||||
key.setBoolean("random-talker", randomTalker);
|
@Override
|
||||||
key.setBoolean("realistic-looking", realisticLooker);
|
public void save(DataKey key) {
|
||||||
key.setDouble("range", range);
|
key.setBoolean("talk-close", talkClose);
|
||||||
key.setString("talkitem", itemInHandPattern);
|
key.setBoolean("random-talker", randomTalker);
|
||||||
// TODO: legacy, remove later
|
key.setBoolean("realistic-looking", realisticLooker);
|
||||||
for (int i = 0; i < 100; i++)
|
key.setDouble("range", range);
|
||||||
key.removeKey(String.valueOf(i));
|
key.setString("talkitem", itemInHandPattern);
|
||||||
key.removeKey("text");
|
// TODO: legacy, remove later
|
||||||
for (int i = 0; i < text.size(); i++)
|
for (int i = 0; i < 100; i++)
|
||||||
key.setString("text." + String.valueOf(i), text.get(i));
|
key.removeKey(String.valueOf(i));
|
||||||
}
|
key.removeKey("text");
|
||||||
|
for (int i = 0; i < text.size(); i++)
|
||||||
boolean sendPage(Player player, int page) {
|
key.setString("text." + String.valueOf(i), text.get(i));
|
||||||
Paginator paginator = new Paginator().header(npc.getName() + "'s Text Entries");
|
}
|
||||||
for (int i = 0; i < text.size(); i++)
|
|
||||||
paginator.addLine("<a>" + i + " <7>- <e>" + text.get(i));
|
boolean sendPage(Player player, int page) {
|
||||||
|
Paginator paginator = new Paginator().header(npc.getName() + "'s Text Entries");
|
||||||
return paginator.sendPage(player, page);
|
for (int i = 0; i < text.size(); i++)
|
||||||
}
|
paginator.addLine("<a>" + i + " <7>- <e>" + text.get(i));
|
||||||
|
|
||||||
private boolean sendText(Player player) {
|
return paginator.sendPage(player, page);
|
||||||
if (!player.hasPermission("citizens.admin") && !player.hasPermission("citizens.npc.talk"))
|
}
|
||||||
return false;
|
|
||||||
if (text.size() == 0)
|
private boolean sendText(Player player) {
|
||||||
return false;
|
if (!player.hasPermission("citizens.admin") && !player.hasPermission("citizens.npc.talk"))
|
||||||
|
return false;
|
||||||
int index = 0;
|
if (text.size() == 0)
|
||||||
if (randomTalker)
|
return false;
|
||||||
index = new Random().nextInt(text.size());
|
|
||||||
else {
|
int index = 0;
|
||||||
if (currentIndex > text.size() - 1)
|
if (randomTalker)
|
||||||
currentIndex = 0;
|
index = new Random().nextInt(text.size());
|
||||||
index = currentIndex++;
|
else {
|
||||||
}
|
if (currentIndex > text.size() - 1)
|
||||||
Messaging.sendWithNPC(player, Setting.CHAT_PREFIX.asString() + text.get(index), npc);
|
currentIndex = 0;
|
||||||
return true;
|
index = currentIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setItemInHandPattern(String pattern) {
|
npc.getDefaultSpeechController().speak(new SpeechContext(text.get(index), player));
|
||||||
itemInHandPattern = pattern;
|
// Messaging.sendWithNPC(player, Setting.CHAT_PREFIX.asString() + text.get(index), npc);
|
||||||
}
|
return true;
|
||||||
|
}
|
||||||
void setRange(double range) {
|
|
||||||
this.range = range;
|
void setItemInHandPattern(String pattern) {
|
||||||
}
|
itemInHandPattern = pattern;
|
||||||
|
}
|
||||||
boolean shouldTalkClose() {
|
|
||||||
return talkClose;
|
void setRange(double range) {
|
||||||
}
|
this.range = range;
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public boolean toggle() {
|
boolean shouldTalkClose() {
|
||||||
return (talkClose = !talkClose);
|
return talkClose;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean toggleRandomTalker() {
|
@Override
|
||||||
return (randomTalker = !randomTalker);
|
public boolean toggle() {
|
||||||
}
|
return (talkClose = !talkClose);
|
||||||
|
}
|
||||||
boolean toggleRealisticLooking() {
|
|
||||||
return (realisticLooker = !realisticLooker);
|
boolean toggleRandomTalker() {
|
||||||
}
|
return (randomTalker = !randomTalker);
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public String toString() {
|
boolean toggleRealisticLooking() {
|
||||||
StringBuilder builder = new StringBuilder();
|
return (realisticLooker = !realisticLooker);
|
||||||
builder.append("Text{talk-close=" + talkClose + ",text=");
|
}
|
||||||
for (String line : text)
|
|
||||||
builder.append(line + ",");
|
@Override
|
||||||
builder.append("}");
|
public String toString() {
|
||||||
return builder.toString();
|
StringBuilder builder = new StringBuilder();
|
||||||
}
|
builder.append("Text{talk-close=" + talkClose + ",text=");
|
||||||
|
for (String line : text)
|
||||||
private static Random RANDOM = Util.getFastRandom();
|
builder.append(line + ",");
|
||||||
|
builder.append("}");
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Random RANDOM = Util.getFastRandom();
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user