Skip to content

Commit

Permalink
Add Chatbot trait to make NPCs able to reply to everything said to th…
Browse files Browse the repository at this point in the history
…em, using Artificial Intelligence Markup Language files.

Such files are not included by default.
  • Loading branch information
davidcernat committed Oct 18, 2013
1 parent fc1b8e8 commit 2c80620
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 14 deletions.
6 changes: 6 additions & 0 deletions pom.xml
Expand Up @@ -110,6 +110,12 @@
<version>5.7.3-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.alicebot</groupId>
<artifactId>ab</artifactId>
<version>0.0.4.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>org.json</artifactId>
Expand Down
35 changes: 32 additions & 3 deletions src/main/java/net/aufdemrand/denizen/CommandHandler.java
Expand Up @@ -15,6 +15,7 @@
import net.aufdemrand.denizen.utilities.ScriptRepo;
import net.aufdemrand.denizen.utilities.Utilities;
import net.aufdemrand.denizen.utilities.debugging.dB;
import net.aufdemrand.denizen.utilities.depends.Depends;
import net.citizensnpcs.Citizens;
import net.citizensnpcs.api.command.Command;
import net.citizensnpcs.api.command.CommandContext;
Expand All @@ -25,6 +26,7 @@
import net.citizensnpcs.api.util.Paginator;
import net.citizensnpcs.util.Messages;

import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.EntityType;
Expand Down Expand Up @@ -410,9 +412,6 @@ public void standing(CommandContext args, CommandSender sender, NPC npc) throws
trait.stand();
npc.removeTrait(SneakingTrait.class);
}



}

/*
Expand Down Expand Up @@ -667,6 +666,36 @@ public void health(CommandContext args, CommandSender sender, NPC npc) throws Co
Messaging.send(sender, ChatColor.YELLOW + npc.getName() + "'s health is '" + trait.getHealth() + "/" + trait.getMaxhealth() + "'.");
}

/*
* Chatbot
*/
@Command(
aliases = { "npc" }, usage = "chatbot",
desc = "Turns the NPC into a chatbot.", flags = "", modifiers = { "chatbot", "bot" },
min = 1, max = 2, permission = "denizen.npc.chatbot")
@Requirements(selected = true, ownership = true)
public void chatbot(CommandContext args, CommandSender sender, NPC npc) throws CommandException {

if (!Depends.hasProgramAB) {
Messaging.send(sender, ChatColor.RED + "The Chatbot Trait " +
" cannot be used if Program AB is missing from Denizen/lib");
return;
}

if (!npc.hasTrait(ChatbotTrait.class)) {
npc.addTrait(ChatbotTrait.class);
Messaging.send(sender, ChatColor.BLUE + npc.getName() +
" has become a chatbot!");
}
ChatbotTrait trait = npc.getTrait(ChatbotTrait.class);

if (args.argsLength() > 1) {
trait.setBot(args.getString(1));
Messaging.send(sender, ChatColor.BLUE + npc.getName() +
" is now the chatbot " + args.getString(1));
}
}


/*
* DENIZEN DEBUG
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/net/aufdemrand/denizen/Denizen.java
Expand Up @@ -210,6 +210,12 @@ public void onEnable() {
CitizensAPI.getTraitFactory().registerTrait(TraitInfo.create(InvisibleTrait.class).withName("invisible"));
CitizensAPI.getTraitFactory().registerTrait(TraitInfo.create(MobproxTrait.class).withName("mobprox"));

// If Program AB, used for reading Artificial Intelligence Markup Language
// 2.0, is included as a dependency at Denizen/lib/Ab.jar, register the
// ChatbotTrait
if (Depends.hasProgramAB)
CitizensAPI.getTraitFactory().registerTrait(TraitInfo.create(ChatbotTrait.class).withName("chatbot"));

// Create instance of PacketHelper if ProtocolLib has been hooked
if(Depends.protocolManager != null) {
new PacketHelper(this);
Expand Down
53 changes: 53 additions & 0 deletions src/main/java/net/aufdemrand/denizen/npc/traits/ChatbotTrait.java
@@ -0,0 +1,53 @@
package net.aufdemrand.denizen.npc.traits;

import java.io.File;

import net.aufdemrand.denizen.Settings;
import net.aufdemrand.denizen.utilities.Utilities;
import net.citizensnpcs.api.ai.speech.SpeechContext;
import net.citizensnpcs.api.exception.NPCLoadException;
import net.citizensnpcs.api.persistence.Persist;
import net.citizensnpcs.api.trait.Trait;
import net.citizensnpcs.api.util.DataKey;

import org.alicebot.ab.*;
import org.bukkit.Bukkit;
import org.bukkit.entity.LivingEntity;

public class ChatbotTrait extends Trait {

public ChatbotTrait() {
super("chatbot");
}

static String path = Bukkit.getPluginManager().getPlugin("Denizen")
.getDataFolder() + File.separator;

@Persist("botname")
private String botname;
private Bot bot;
private Chat chatSession;

@Override
public void load(DataKey key) throws NPCLoadException {
setBot(key.getString("botname"));
}

public void chatTo(LivingEntity entity, String input) {
SpeechContext context = new SpeechContext(reponse(input));
context.addRecipient(entity);
context.setTalker(getNPC().getBukkitEntity());
npc.getDefaultSpeechController().speak(context, "chat");
}

public String reponse(String request) {
return chatSession.multisentenceRespond(request);
}

public void setBot(String newname) {
botname = newname;
bot = new Bot(botname, path);
chatSession = new Chat(bot);
}

}
Expand Up @@ -4,18 +4,12 @@
import net.aufdemrand.denizen.objects.*;
import net.aufdemrand.denizen.tags.TagManager;
import net.aufdemrand.denizen.utilities.DenizenAPI;
import net.aufdemrand.denizen.utilities.ParticleEffect;
import net.aufdemrand.denizen.utilities.Utilities;
import net.aufdemrand.denizen.utilities.blocks.FakeBlock;
import net.citizensnpcs.api.event.DespawnReason;
import net.citizensnpcs.api.persistence.Persist;
import net.citizensnpcs.api.trait.Trait;

import org.bukkit.Bukkit;
import org.bukkit.EntityEffect;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
Expand All @@ -27,7 +21,6 @@
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.inventory.ItemStack;

import java.util.HashMap;
import java.util.Map;
Expand Down
Expand Up @@ -2,6 +2,7 @@

import net.aufdemrand.denizen.Settings;
import net.aufdemrand.denizen.objects.*;
import net.aufdemrand.denizen.npc.traits.ChatbotTrait;
import net.aufdemrand.denizen.npc.traits.TriggerTrait;
import net.aufdemrand.denizen.scripts.containers.core.InteractScriptContainer;
import net.aufdemrand.denizen.scripts.containers.core.InteractScriptHelper;
Expand All @@ -11,6 +12,7 @@
import net.aufdemrand.denizen.utilities.Utilities;
import net.aufdemrand.denizen.utilities.entity.Rotation;
import net.aufdemrand.denizen.utilities.debugging.dB;
import net.citizensnpcs.api.ai.speech.SpeechContext;

import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
Expand Down Expand Up @@ -103,8 +105,15 @@ public Boolean process(Player player, String message) {
InteractScriptHelper.getCurrentStep(denizenPlayer,
script.getName()), ChatTrigger.class)) {

// If this is a Chatbot, make it chat anything it wants if
// it has no chat triggers for this step
if (npc.getCitizen().hasTrait(ChatbotTrait.class)) {
Utilities.talkToNPC(message, denizenPlayer, npc, Settings.ChatToNpcOverhearingRange());
npc.getCitizen().getTrait(ChatbotTrait.class).chatTo(player, message);
return true;
}
// No chat trigger for this step.. do we chat globally, or to the NPC?
if (!Settings.ChatGloballyIfNoChatTriggers()) {
else if (!Settings.ChatGloballyIfNoChatTriggers()) {
dB.echoDebug(player.getName() + " says to "
+ npc.getNicknameTrait().getNickname() + ", " + message);
return true;
Expand Down Expand Up @@ -183,8 +192,16 @@ else if (message.toUpperCase().contains(keyword.toUpperCase()))
context.put("message", new Element(message));
parse(npc, denizenPlayer, script, id, context);
return true;
} else {
if (!Settings.ChatGloballyIfFailedChatTriggers ()) {
}
else {
// If this is a Chatbot, make it chat anything it wants if
// none of its chat triggers worked
if (npc.getCitizen().hasTrait(ChatbotTrait.class)) {
Utilities.talkToNPC(message, denizenPlayer, npc, Settings.ChatToNpcOverhearingRange());
npc.getCitizen().getTrait(ChatbotTrait.class).chatTo(player, message);
return true;
}
else if (!Settings.ChatGloballyIfFailedChatTriggers ()) {
Utilities.talkToNPC(message, denizenPlayer, npc, Settings.ChatToNpcOverhearingRange());
return true;
}
Expand Down
Expand Up @@ -22,16 +22,18 @@ public class Depends {
public static WorldGuardPlugin worldGuard = null;
public static WorldEditPlugin worldEdit = null;


public static Citizens citizens = null;

public static Economy economy = null;
public static Permission permissions = null;
public static Chat chat = null;

public static boolean hasProgramAB = false;

public static ProtocolManager protocolManager = null;

public void initialize() {
hasProgramAB = checkProgramAB();
setupEconomy();
setupPermissions();
setupChat();
Expand All @@ -41,6 +43,16 @@ public void initialize() {
setupProtocolManager();
}

// Check if Program AB, used for reading Artificial Intelligence Markup
// Language 2.0, is included as a dependency at Denizen/lib/Ab.jar
private boolean checkProgramAB() {

try { Class.forName("org.alicebot.ab.Bot"); }
catch( ClassNotFoundException e ) { return false; }

return true;
}

private boolean setupProtocolManager() {
if (Bukkit.getServer().getPluginManager().getPlugin("ProtocolLib") != null) {
protocolManager = ProtocolLibrary.getProtocolManager();
Expand Down

0 comments on commit 2c80620

Please sign in to comment.