Improve text

This commit is contained in:
fullwall 2012-11-04 13:31:22 +08:00
parent 8fea42eba4
commit 01ae2eca46
10 changed files with 122 additions and 82 deletions

View File

@ -72,9 +72,14 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
Iterator<NPC> itr = npcRegistry.iterator();
while (itr.hasNext()) {
NPC npc = itr.next();
npc.despawn();
for (Trait t : npc.getTraits())
t.onRemove();
try {
npc.despawn();
for (Trait t : npc.getTraits())
t.onRemove();
} catch (Exception e) {
e.printStackTrace();
// ensure that all entities are despawned
}
itr.remove();
}
}

View File

@ -70,7 +70,7 @@ public class NPCSelector implements Listener {
NPC npc = event.getNPC();
List<MetadataValue> selected = player.getMetadata("selected");
if (selected == null || selected.size() == 0 || selected.get(0).asInt() != npc.getId()) {
if (Util.isSettingFulfilled(player, Setting.SELECTION_ITEM)
if (Util.matchesItemInHand(player, Setting.SELECTION_ITEM.asString())
&& npc.getTrait(Owner.class).isOwnedBy(player)) {
player.removeMetadata("selected", plugin);
select(player, npc);

View File

@ -15,20 +15,18 @@ import net.citizensnpcs.api.exception.NPCLoadException;
import net.citizensnpcs.api.trait.Trait;
import net.citizensnpcs.api.util.DataKey;
import net.citizensnpcs.editor.Editor;
import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.trait.Toggleable;
import net.citizensnpcs.util.Messages;
import net.citizensnpcs.util.Messaging;
import net.citizensnpcs.util.Paginator;
import net.citizensnpcs.util.Util;
import net.minecraft.server.EntityHuman;
import net.minecraft.server.EntityLiving;
import org.bukkit.Bukkit;
import org.bukkit.conversations.Conversation;
import org.bukkit.conversations.ConversationAbandonedEvent;
import org.bukkit.conversations.ConversationAbandonedListener;
import org.bukkit.conversations.ConversationFactory;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
@ -37,6 +35,7 @@ import org.bukkit.plugin.Plugin;
public class Text extends Trait implements Runnable, Toggleable, Listener, ConversationAbandonedListener {
private final Map<String, Date> cooldowns = new HashMap<String, Date>();
private int currentIndex;
private String itemInHandPattern = Setting.TALK_ITEM.asString();
private final Plugin plugin;
private boolean randomTalker = Setting.DEFAULT_RANDOM_TALKER.asBoolean();
private double range = Setting.DEFAULT_TALK_CLOSE_RANGE.asDouble();
@ -49,7 +48,7 @@ public class Text extends Trait implements Runnable, Toggleable, Listener, Conve
this.plugin = CitizensAPI.getPlugin();
}
public void add(String string) {
void add(String string) {
text.add(string);
}
@ -58,7 +57,7 @@ public class Text extends Trait implements Runnable, Toggleable, Listener, Conve
Bukkit.dispatchCommand((Player) event.getContext().getForWhom(), "npc text");
}
public void edit(int index, String newText) {
void edit(int index, String newText) {
text.set(index, newText);
}
@ -78,18 +77,19 @@ public class Text extends Trait implements Runnable, Toggleable, Listener, Conve
@Override
public void end() {
Messaging.sendTr(player, Messages.TEXT_EDITOR_END);
conversation.abandon();
}
};
}
public boolean hasIndex(int index) {
boolean hasIndex(int index) {
return index >= 0 && text.size() > index;
}
@Override
public void load(DataKey key) throws NPCLoadException {
text.clear();
// TODO: backwards compat, remove later
// TODO: legacy, remove later
for (DataKey sub : key.getIntegerSubKeys())
text.add(sub.getString(""));
for (DataKey sub : key.getRelative("text").getIntegerSubKeys())
@ -101,13 +101,14 @@ public class Text extends Trait implements Runnable, Toggleable, Listener, Conve
realisticLooker = key.getBoolean("realistic-looking", realisticLooker);
randomTalker = key.getBoolean("random-talker", randomTalker);
range = key.getDouble("range", range);
itemInHandPattern = key.getString("talkitem", itemInHandPattern);
}
@EventHandler
public void onRightClick(NPCRightClickEvent event) {
if (!event.getNPC().equals(npc))
return;
if (Util.isSettingFulfilled(event.getClicker(), Setting.TALK_ITEM) && !shouldTalkClose())
if (Util.matchesItemInHand(event.getClicker(), itemInHandPattern) && !shouldTalkClose())
sendText(event.getClicker());
}
@ -115,33 +116,37 @@ public class Text extends Trait implements Runnable, Toggleable, Listener, Conve
text.addAll(Setting.DEFAULT_TEXT.asList());
}
public void remove(int index) {
void remove(int index) {
text.remove(index);
}
@Override
public void run() {
if (!npc.isSpawned())
if (!npc.isSpawned() || !talkClose)
return;
EntityHuman search = null;
EntityLiving handle = ((CitizensNPC) npc).getHandle();
if ((search = handle.world.findNearbyPlayer(handle, range)) != null && talkClose) {
Player player = (Player) search.getBukkitEntity();
List<Entity> nearby = npc.getBukkitEntity().getNearbyEntities(range, range, range);
for (Entity search : nearby) {
if (!(search instanceof Player))
continue;
Player player = (Player) search;
// If the cooldown is not expired, do not send text
if (cooldowns.get(player.getName()) != null) {
if (!new Date().after(cooldowns.get(player.getName())))
Date cooldown = cooldowns.get(player.getName());
if (cooldown != null) {
if (!new Date().after(cooldown))
return;
cooldowns.remove(player.getName());
}
if (sendText(player)) {
// Add a cooldown if the text was successfully sent
Date wait = new Date();
int secondsDelta = new Random().nextInt(Setting.TALK_CLOSE_MAXIMUM_COOLDOWN.asInt())
+ Setting.TALK_CLOSE_MINIMUM_COOLDOWN.asInt();
long millisecondsDelta = TimeUnit.MILLISECONDS.convert(secondsDelta, TimeUnit.SECONDS);
wait.setTime(wait.getTime() + millisecondsDelta);
cooldowns.put(player.getName(), wait);
}
if (!sendText(player))
return;
// Add a cooldown if the text was successfully sent
Date wait = new Date();
int secondsDelta = new Random().nextInt(Setting.TALK_CLOSE_MAXIMUM_COOLDOWN.asInt())
+ Setting.TALK_CLOSE_MINIMUM_COOLDOWN.asInt();
if (secondsDelta <= 0)
return;
long millisecondsDelta = TimeUnit.MILLISECONDS.convert(secondsDelta, TimeUnit.SECONDS);
wait.setTime(wait.getTime() + millisecondsDelta);
cooldowns.put(player.getName(), wait);
}
}
@ -151,7 +156,8 @@ public class Text extends Trait implements Runnable, Toggleable, Listener, Conve
key.setBoolean("random-talker", randomTalker);
key.setBoolean("realistic-looking", realisticLooker);
key.setDouble("range", range);
// TODO: for backwards compat purposes, remove later
key.setString("talkitem", itemInHandPattern);
// TODO: legacy, remove later
for (int i = 0; i < 100; i++)
key.removeKey(String.valueOf(i));
key.removeKey("text");
@ -159,7 +165,7 @@ public class Text extends Trait implements Runnable, Toggleable, Listener, Conve
key.setString("text." + String.valueOf(i), text.get(i));
}
public boolean sendPage(Player player, int page) {
boolean sendPage(Player player, int page) {
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));
@ -167,7 +173,7 @@ public class Text extends Trait implements Runnable, Toggleable, Listener, Conve
return paginator.sendPage(player, page);
}
public boolean sendText(Player player) {
private boolean sendText(Player player) {
if (!player.hasPermission("citizens.admin") && !player.hasPermission("citizens.npc.talk"))
return false;
if (text.size() == 0)
@ -185,7 +191,15 @@ public class Text extends Trait implements Runnable, Toggleable, Listener, Conve
return true;
}
public boolean shouldTalkClose() {
void setItemInHandPattern(String pattern) {
itemInHandPattern = pattern;
}
void setRange(double range) {
this.range = range;
}
boolean shouldTalkClose() {
return talkClose;
}
@ -194,11 +208,11 @@ public class Text extends Trait implements Runnable, Toggleable, Listener, Conve
return (talkClose = !talkClose);
}
public boolean toggleRandomTalker() {
boolean toggleRandomTalker() {
return (randomTalker = !randomTalker);
}
public boolean toggleRealisticLooking() {
boolean toggleRealisticLooking() {
return (realisticLooker = !realisticLooker);
}

View File

@ -17,8 +17,9 @@ public class TextStartPrompt extends StringPrompt {
}
@Override
public Prompt acceptInput(ConversationContext context, String input) {
input = ChatColor.stripColor(input.trim().split(" ")[0]);
public Prompt acceptInput(ConversationContext context, String original) {
String[] parts = ChatColor.stripColor(original.trim()).split(" ");
String input = parts[0];
CommandSender sender = (CommandSender) context.getForWhom();
if (input.equalsIgnoreCase("add"))
return new TextAddPrompt(text);
@ -31,9 +32,24 @@ public class TextStartPrompt extends StringPrompt {
else if (input.equalsIgnoreCase("realistic looking"))
Messaging.sendTr(sender, Messages.TEXT_EDITOR_REALISTIC_LOOKING_SET,
text.toggleRealisticLooking());
else if (input.equalsIgnoreCase("close"))
else if (input.equalsIgnoreCase("close") || input.equalsIgnoreCase("talk-close"))
Messaging.sendTr(sender, Messages.TEXT_EDITOR_CLOSE_TALKER_SET, text.toggle());
else if (input.equalsIgnoreCase("help")) {
else if (input.equalsIgnoreCase("range")) {
try {
double range = Math.max(0, Double.parseDouble(parts[1]));
text.setRange(range);
Messaging.sendTr(sender, Messages.TEXT_EDITOR_RANGE_SET, range);
} catch (NumberFormatException e) {
Messaging.sendErrorTr(sender, Messages.TEXT_EDITOR_INVALID_RANGE);
} catch (ArrayIndexOutOfBoundsException e) {
Messaging.sendErrorTr(sender, Messages.TEXT_EDITOR_INVALID_RANGE);
}
} else if (input.equalsIgnoreCase("item")) {
if (parts.length > 1) {
text.setItemInHandPattern(parts[1]);
Messaging.sendTr(sender, Messages.TEXT_EDITOR_SET_ITEM, parts[1]);
}
} else if (input.equalsIgnoreCase("help")) {
context.setSessionData("said-text", false);
Messaging.send(sender, getPromptText(context));
} else

View File

@ -104,6 +104,13 @@ public class LinearWaypointProvider implements WaypointProvider {
Messaging.sendTr(player, Messages.LINEAR_WAYPOINT_EDITOR_BEGIN);
}
private void clearWaypoints() {
editingSlot = 0;
waypoints.clear();
destroyWaypointMarkers();
Messaging.sendTr(player, Messages.LINEAR_WAYPOINT_EDITOR_WAYPOINTS_CLEARED);
}
private void createWaypointMarker(int index, Waypoint waypoint) {
Entity entity = spawnMarker(player.getWorld(), waypoint.getLocation().add(0, 1, 0));
if (entity == null)
@ -208,13 +215,6 @@ public class LinearWaypointProvider implements WaypointProvider {
});
}
private void clearWaypoints() {
editingSlot = 0;
waypoints.clear();
destroyWaypointMarkers();
Messaging.sendTr(player, Messages.LINEAR_WAYPOINT_EDITOR_WAYPOINTS_CLEARED);
}
@EventHandler(ignoreCancelled = true)
public void onPlayerInteract(PlayerInteractEvent event) {
if (!event.getPlayer().equals(player) || event.getAction() == Action.PHYSICAL)
@ -328,6 +328,10 @@ public class LinearWaypointProvider implements WaypointProvider {
itr = getNewIterator();
}
private Navigator getNavigator() {
return npc.getNavigator();
}
private Iterator<Waypoint> getNewIterator() {
LinearWaypointsCompleteEvent event = new LinearWaypointsCompleteEvent(
LinearWaypointProvider.this, waypoints.iterator());
@ -336,10 +340,6 @@ public class LinearWaypointProvider implements WaypointProvider {
return next;
}
private Navigator getNavigator() {
return npc.getNavigator();
}
public boolean isPaused() {
return paused;
}

View File

@ -15,26 +15,26 @@ public class LinearWaypointsCompleteEvent extends CitizensEvent {
this.provider = provider;
}
public WaypointProvider getWaypointProvider() {
return provider;
@Override
public HandlerList getHandlers() {
return handlers;
}
public Iterator<Waypoint> getNextWaypoints() {
return next;
}
public WaypointProvider getWaypointProvider() {
return provider;
}
public void setNextWaypoints(Iterator<Waypoint> waypoints) {
this.next = waypoints;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
private static final HandlerList handlers = new HandlerList();
public static HandlerList getHandlerList() {
return handlers;
}
private static final HandlerList handlers = new HandlerList();
}

View File

@ -174,11 +174,14 @@ public class Messages {
public static final String TEXT_EDITOR_INVALID_INDEX = "citizens.editors.text.invalid-index";
public static final String TEXT_EDITOR_INVALID_INPUT = "citizens.editors.text.invalid-input";
public static final String TEXT_EDITOR_INVALID_PAGE = "citizens.editors.text.invalid-page";
public static final String TEXT_EDITOR_INVALID_RANGE = "citizens.editors.text.invalid-range";
public static final String TEXT_EDITOR_PAGE_PROMPT = "citizens.editors.text.change-page-prompt";
public static final String TEXT_EDITOR_RANDOM_TALKER_SET = "citizens.editors.text.random-talker-set";
public static final String TEXT_EDITOR_RANGE_SET = "citizens.editors.text.range-set";
public static final String TEXT_EDITOR_REALISTIC_LOOKING_SET = "citizens.editors.text.realistic-looking-set";
public static final String TEXT_EDITOR_REMOVE_PROMPT = "citizens.editors.text.remove-prompt";
public static final String TEXT_EDITOR_REMOVED_ENTRY = "citizens.editors.text.removed-entry";
public static final String TEXT_EDITOR_SET_ITEM = "citizens.editors.text.talk-item-set";
public static final String TEXT_EDITOR_START_PROMPT = "citizens.editors.text.start-prompt";
public static final String TRAIT_LOAD_FAILED = "citizens.notifications.trait-load-failed";
public static final String TRAIT_NOT_CONFIGURABLE = "citizens.commands.traitc.not-configurable";

View File

@ -280,6 +280,10 @@ public class NMS {
}
}
public static void updateSenses(EntityLiving entity) {
entity.az().a();
}
static {
// true field above false and three synchronised lists
THREAD_STOPPER = getField(NetworkManager.class, "m");
@ -322,8 +326,4 @@ public class NMS {
STAIR_MATERIALS.add(material.getId());
}
}
public static void updateSenses(EntityLiving entity) {
entity.az().a();
}
}

View File

@ -1,6 +1,5 @@
package net.citizensnpcs.util;
import net.citizensnpcs.Settings.Setting;
import net.citizensnpcs.api.event.NPCCollisionEvent;
import net.citizensnpcs.api.event.NPCPushEvent;
import net.citizensnpcs.api.npc.NPC;
@ -104,16 +103,12 @@ public class Util {
return ((0 <= degrees) && (degrees < 45 + leeway)) || ((315 - leeway <= degrees) && (degrees <= 360));
}
public static boolean isSettingFulfilled(Player player, Setting setting) {
String parts = setting.asString();
if (parts.contains("*"))
return true;
for (String part : Splitter.on(',').split(parts)) {
if (Material.matchMaterial(part) == player.getItemInHand().getType()) {
return true;
}
}
return false;
public static boolean isLoaded(Location location) {
if (location.getWorld() == null)
return false;
int chunkX = location.getBlockX() >> 4;
int chunkZ = location.getBlockZ() >> 4;
return location.getWorld().isChunkLoaded(chunkX, chunkZ);
}
public static EntityType matchEntityType(String toMatch) {
@ -138,6 +133,18 @@ public class Util {
return type;
}
public static boolean matchesItemInHand(Player player, String setting) {
String parts = setting;
if (parts.contains("*"))
return true;
for (String part : Splitter.on(',').split(parts)) {
if (Material.matchMaterial(part) == player.getItemInHand().getType()) {
return true;
}
}
return false;
}
public static void sendPacketNearby(Location location, Packet packet) {
sendPacketNearby(location, packet, 64);
}
@ -166,12 +173,4 @@ public class Util {
}
}
}
public static boolean isLoaded(Location location) {
if (location.getWorld() == null)
return false;
int chunkX = location.getBlockX() >> 4;
int chunkZ = location.getBlockZ() >> 4;
return location.getWorld().isChunkLoaded(chunkX, chunkZ);
}
}

View File

@ -131,11 +131,14 @@ citizens.editors.text.invalid-edit-type=Invalid edit type.
citizens.editors.text.invalid-index={0} is not a valid index!
citizens.editors.text.invalid-input=Invalid input.
citizens.editors.text.invalid-page=Invalid page number.
citizens.editors.text.invalid-range=Invalid range.
citizens.editors.text.random-talker-set=[[Random talking]] set to [[{0}]].
citizens.editors.text.range-set=[[Range]] set to [[{0}]].
citizens.editors.text.realistic-looking-set=[[Realistic looking]] set to [[{0}]].
citizens.editors.text.remove-prompt=Enter the index of the entry you wish to remove or [[page]] to view more pages.
citizens.editors.text.removed-entry=[[Removed]] entry at index [[{0}]].
citizens.editors.text.start-prompt=Type [[add]] to add an entry, [[edit]] to edit entries, [[remove]] to remove entries, [[close]] to toggle the NPC as a close talker, and [[random]] to toggle the NPC as a random talker. Type [[help]] to show this again.
citizens.editors.text.start-prompt=Type [[add]] to add an entry, [[edit]] to edit entries, [[remove]] to remove entries, [[close]] to toggle the NPC as a close talker, [[item]] to set the item in hand pattern, [[range]] to set the talking range, and [[random]] to toggle the NPC as a random talker. Type [[help]] to show this again.
citizens.editors.text.talk-item-set=[[Talk item pattern]] set to [[{0}]].
citizens.editors.waypoints.linear.added-waypoint=[[Added]] a waypoint at ({0}) ([[{1}]], [[{2}]])
citizens.editors.waypoints.linear.begin=<b>Entered the linear waypoint editor!<br> [[Left click]] to add a waypoint, [[right click]] to remove.<br> Type [[toggle path]] to toggle showing entities at waypoints, [[triggers]] to enter the trigger editor and [[clear]] to clear all waypoints.
citizens.editors.waypoints.linear.edit-slot-set=Editing slot set to [[{0}]] ({1}).