mirror of
https://github.com/CitizensDev/Citizens2.git
synced 2024-10-04 02:17:26 +02:00
Add Anchors, saveable 'locations' for your NPCs. Usage: /npc anchor (--save [name]|--assume [name]|--remove [name]) (-a)
Also renamed /npc pose --load to /npc pose --assume
This commit is contained in:
parent
983ef2f1fd
commit
59218ae28c
@ -25,6 +25,7 @@ import net.citizensnpcs.npc.CitizensNPC;
|
||||
import net.citizensnpcs.npc.NPCSelector;
|
||||
import net.citizensnpcs.npc.Template;
|
||||
import net.citizensnpcs.trait.Age;
|
||||
import net.citizensnpcs.trait.Anchors;
|
||||
import net.citizensnpcs.trait.Behaviour;
|
||||
import net.citizensnpcs.trait.Controllable;
|
||||
import net.citizensnpcs.trait.CurrentLocation;
|
||||
@ -32,6 +33,7 @@ import net.citizensnpcs.trait.LookClose;
|
||||
import net.citizensnpcs.trait.Poses;
|
||||
import net.citizensnpcs.trait.Powered;
|
||||
import net.citizensnpcs.trait.VillagerProfession;
|
||||
import net.citizensnpcs.util.Anchor;
|
||||
import net.citizensnpcs.util.Messages;
|
||||
import net.citizensnpcs.util.Messaging;
|
||||
import net.citizensnpcs.util.Paginator;
|
||||
@ -108,6 +110,71 @@ public class NPCCommands {
|
||||
trait.setAge(age);
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "npc" },
|
||||
usage = "anchor (--save [name]|--assume [name]|--remove [name]) (-a)",
|
||||
desc = "Changes/Saves/Lists NPC's location anchor(s)",
|
||||
flags = "a",
|
||||
modifiers = { "anchor" },
|
||||
min = 1,
|
||||
max = 2,
|
||||
permission = "npc.anchor")
|
||||
@Requirements(selected = true, ownership = true, types = EntityType.PLAYER)
|
||||
public void anchor(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
||||
Anchors trait = npc.getTrait(Anchors.class);
|
||||
if (args.hasValueFlag("save")) {
|
||||
if (args.getFlag("save").isEmpty())
|
||||
throw new CommandException(Messages.INVALID_ANCHOR_NAME);
|
||||
|
||||
if (!(sender instanceof Player))
|
||||
throw new ServerCommandException();
|
||||
|
||||
if (trait.addAnchor(args.getFlag("save"), ((Player) sender).getLocation())) {
|
||||
Messaging.sendTr(sender, Messages.ANCHOR_ADDED);
|
||||
} else
|
||||
throw new CommandException(Messages.ANCHOR_ALREADY_EXISTS, args.getFlag("save"));
|
||||
} else if (args.hasValueFlag("assume")) {
|
||||
if (args.getFlag("assume").isEmpty())
|
||||
throw new CommandException(Messages.INVALID_ANCHOR_NAME);
|
||||
|
||||
Anchor anchor = trait.getAnchor(args.getFlag("assume"));
|
||||
if (anchor == null)
|
||||
throw new CommandException(Messages.ANCHOR_MISSING, args.getFlag("assume"));
|
||||
npc.getBukkitEntity().teleport(anchor.getLocation());
|
||||
} else if (args.hasValueFlag("remove")) {
|
||||
if (args.getFlag("remove").isEmpty())
|
||||
throw new CommandException(Messages.INVALID_ANCHOR_NAME);
|
||||
if (trait.removeAnchor(trait.getAnchor(args.getFlag("remove"))))
|
||||
Messaging.sendTr(sender, Messages.ANCHOR_REMOVED);
|
||||
else
|
||||
throw new CommandException(Messages.ANCHOR_MISSING, args.getFlag("remove"));
|
||||
} else if (!args.hasFlag('a')) {
|
||||
Paginator paginator = new Paginator().header("Anchors");
|
||||
paginator.addLine("<e>Key: <a>ID <b>Name <c>World <d>Location (X,Y,Z)");
|
||||
for (int i = 0; i < trait.getAnchors().size(); i++) {
|
||||
String line = "<a>" + i + "<b> " + trait.getAnchors().get(i).getName() + "<c> "
|
||||
+ trait.getAnchors().get(i).getLocation().getWorld().getName() + "<d> "
|
||||
+ trait.getAnchors().get(i).getLocation().getBlockX()+ ", "
|
||||
+ trait.getAnchors().get(i).getLocation().getBlockY()+ ", "
|
||||
+ trait.getAnchors().get(i).getLocation().getBlockZ();
|
||||
paginator.addLine(line);
|
||||
}
|
||||
|
||||
int page = args.getInteger(1, 1);
|
||||
if (!paginator.sendPage(sender, page))
|
||||
throw new CommandException(Messages.COMMAND_PAGE_MISSING);
|
||||
}
|
||||
|
||||
// Assume Player's position
|
||||
if (!args.hasFlag('a'))
|
||||
return;
|
||||
if (sender instanceof Player) {
|
||||
Location location = ((Player) sender).getLocation();
|
||||
npc.getBukkitEntity().teleport(location);
|
||||
} else
|
||||
throw new ServerCommandException();
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "npc" },
|
||||
usage = "behaviour [scripts] (-r)",
|
||||
@ -474,7 +541,7 @@ public class NPCCommands {
|
||||
|
||||
@Command(
|
||||
aliases = { "npc" },
|
||||
usage = "pose (--save [name]|--load [name]|--remove [name]|--list) (-a)",
|
||||
usage = "pose (--save [name]|--assume [name]|--remove [name]) (-a)",
|
||||
desc = "Changes/Saves/Lists NPC's head pose(s)",
|
||||
flags = "a",
|
||||
modifiers = { "pose" },
|
||||
@ -494,14 +561,14 @@ public class NPCCommands {
|
||||
if (trait.addPose(args.getFlag("save"), ((Player) sender).getLocation())) {
|
||||
Messaging.sendTr(sender, Messages.POSE_ADDED);
|
||||
} else
|
||||
throw new CommandException(Messages.POSE_ALREADY_EXISTS, args.getFlag("load"));
|
||||
} else if (args.hasValueFlag("load")) {
|
||||
if (args.getFlag("load").isEmpty())
|
||||
throw new CommandException(Messages.POSE_ALREADY_EXISTS, args.getFlag("assume"));
|
||||
} else if (args.hasValueFlag("assume")) {
|
||||
if (args.getFlag("assume").isEmpty())
|
||||
throw new CommandException(Messages.INVALID_POSE_NAME);
|
||||
|
||||
Pose pose = trait.getPose(args.getFlag("load"));
|
||||
Pose pose = trait.getPose(args.getFlag("assume"));
|
||||
if (pose == null)
|
||||
throw new CommandException(Messages.POSE_MISSING, args.getFlag("load"));
|
||||
throw new CommandException(Messages.POSE_MISSING, args.getFlag("assume"));
|
||||
trait.assumePose(pose);
|
||||
} else if (args.hasValueFlag("remove")) {
|
||||
if (args.getFlag("remove").isEmpty())
|
||||
|
@ -16,6 +16,7 @@ import net.citizensnpcs.api.trait.trait.MobType;
|
||||
import net.citizensnpcs.api.trait.trait.Owner;
|
||||
import net.citizensnpcs.api.trait.trait.Spawned;
|
||||
import net.citizensnpcs.trait.Age;
|
||||
import net.citizensnpcs.trait.Anchors;
|
||||
import net.citizensnpcs.trait.Behaviour;
|
||||
import net.citizensnpcs.trait.Controllable;
|
||||
import net.citizensnpcs.trait.CurrentLocation;
|
||||
@ -55,6 +56,7 @@ public class CitizensTraitFactory implements TraitFactory {
|
||||
registerTrait(TraitInfo.create(Controllable.class).withName("controllable"));
|
||||
registerTrait(TraitInfo.create(Behaviour.class).withName("behaviour"));
|
||||
registerTrait(TraitInfo.create(Poses.class).withName("poses"));
|
||||
registerTrait(TraitInfo.create(Anchors.class).withName("anchors"));
|
||||
|
||||
for (String trait : registered.keySet())
|
||||
INTERNAL_TRAITS.add(trait);
|
||||
|
67
src/main/java/net/citizensnpcs/trait/Anchors.java
Normal file
67
src/main/java/net/citizensnpcs/trait/Anchors.java
Normal file
@ -0,0 +1,67 @@
|
||||
package net.citizensnpcs.trait;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.citizensnpcs.api.exception.NPCLoadException;
|
||||
import net.citizensnpcs.api.trait.Trait;
|
||||
import net.citizensnpcs.api.util.DataKey;
|
||||
import net.citizensnpcs.util.Messages;
|
||||
import net.citizensnpcs.util.Messaging;
|
||||
import net.citizensnpcs.util.Anchor;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
|
||||
public class Anchors extends Trait {
|
||||
private final List<Anchor> anchors = new ArrayList<Anchor>();
|
||||
|
||||
public Anchors() {
|
||||
super("anchors");
|
||||
}
|
||||
|
||||
public boolean addAnchor(String name, Location location) {
|
||||
Anchor newAnchor = new Anchor(name, location);
|
||||
if (anchors.contains(newAnchor))
|
||||
return false;
|
||||
anchors.add(newAnchor);
|
||||
return true;
|
||||
}
|
||||
|
||||
public Anchor getAnchor(String name) {
|
||||
for (Anchor anchor : anchors)
|
||||
if (anchor.getName().equalsIgnoreCase(name))
|
||||
return anchor;
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<Anchor> getAnchors() {
|
||||
return anchors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(DataKey key) throws NPCLoadException {
|
||||
for (DataKey sub : key.getRelative("list").getIntegerSubKeys())
|
||||
try {
|
||||
String[] parts = sub.getString("").split(";");
|
||||
anchors.add(new Anchor(parts[0], new Location(Bukkit.getServer().getWorld(parts[1]), Double.valueOf(parts[2]), Double.valueOf(parts[3]), Double.valueOf(parts[4]))));
|
||||
} catch (NumberFormatException e) {
|
||||
Messaging.logTr(Messages.SKIPPING_INVALID_ANCHOR, sub.name(), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean removeAnchor(Anchor anchor) {
|
||||
if (anchors.contains(anchor)) {
|
||||
anchors.remove(anchor);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(DataKey key) {
|
||||
key.removeKey("list");
|
||||
for (int i = 0; i < anchors.size(); i++)
|
||||
key.setString("list." + String.valueOf(i), anchors.get(i).stringValue());
|
||||
}
|
||||
}
|
57
src/main/java/net/citizensnpcs/util/Anchor.java
Normal file
57
src/main/java/net/citizensnpcs/util/Anchor.java
Normal file
@ -0,0 +1,57 @@
|
||||
package net.citizensnpcs.util;
|
||||
|
||||
import org.apache.commons.lang.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
import org.bukkit.Location;
|
||||
|
||||
/*
|
||||
* Anchor object which holds a Location with a name to identify.
|
||||
*/
|
||||
|
||||
public class Anchor {
|
||||
private final String name;
|
||||
private final Location location;
|
||||
|
||||
public Anchor(String name, Location location) {
|
||||
this.location = location;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if (object == null) return false;
|
||||
if (object == this) return true;
|
||||
if (object.getClass() != getClass())
|
||||
return false;
|
||||
|
||||
Anchor op = (Anchor) object;
|
||||
return new EqualsBuilder().
|
||||
append(name, op.getName()).
|
||||
isEquals();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Location getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder(13, 21).
|
||||
append(name).
|
||||
toHashCode();
|
||||
}
|
||||
|
||||
public String stringValue() {
|
||||
return name + ";" + location.getWorld().getName() + ";" + location.getX() + ";" + location.getY() + ";" + location.getZ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Name: " + name + " World: " + location.getWorld().getName() + " Location: " + location.getBlockX() + "," + location.getBlockY() + "," + location.getBlockZ();
|
||||
}
|
||||
|
||||
}
|
@ -9,6 +9,10 @@ public class Messages {
|
||||
public static final String AGE_UNLOCKED = "citizens.commands.npc.age.unlocked";
|
||||
public static final String ALREADY_IN_EDITOR = "citizens.editors.already-in-editor";
|
||||
public static final String ALREADY_OWNER = "citizens.commands.npc.owner.already-owner";
|
||||
public static final String ANCHOR_ADDED = "citizens.commands.npc.anchor.added";
|
||||
public static final String ANCHOR_ALREADY_EXISTS = "citizens.commands.npc.anchor.already-exists";
|
||||
public static final String ANCHOR_MISSING = "citizens.commands.npc.anchor.missing";
|
||||
public static final String ANCHOR_REMOVED = "citizens.commands.npc.anchor.removed";
|
||||
public static final String AVAILABLE_WAYPOINT_PROVIDERS = "citizens.waypoints.available-providers-header";
|
||||
public static final String BEHAVIOUR_HELP = "citizens.commands.npc.behaviour.help";
|
||||
public static final String BEHAVIOURS_ADDED = "citizens.commands.npc.behaviour.added";
|
||||
@ -60,6 +64,7 @@ public class Messages {
|
||||
public static final String FAILED_TO_MOUNT_NPC = "citizens.commands.npc.mount.failed";
|
||||
public static final String FAILED_TO_REMOVE = "citizens.commands.trait.failed-to-remove";
|
||||
public static final String INVALID_AGE = "citizens.commands.npc.age.invalid-age";
|
||||
public static final String INVALID_ANCHOR_NAME = "citizens.commands.npc.anchor.invalid-name";
|
||||
public static final String INVALID_POSE_NAME = "citizens.commands.npc.pose.invalid-name";
|
||||
public static final String INVALID_PROFESSION = "citizens.commands.npc.profession.invalid-profession";
|
||||
public static final String LINEAR_WAYPOINT_EDITOR_ADDED_WAYPOINT = "citizens.editors.waypoints.linear.added-waypoint";
|
||||
@ -125,6 +130,7 @@ public class Messages {
|
||||
public static final String SHEARED_STOPPED = "citizens.editors.equipment.sheared-stopped";
|
||||
public static final String SKIPPING_BROKEN_TRAIT = "citizens.notifications.skipping-broken-trait";
|
||||
public static final String SKIPPING_INVALID_POSE = "citizens.notifications.skipping-invalid-pose";
|
||||
public static final String SKIPPING_INVALID_ANCHOR = "citizens.notifications.skipping-invalid-anchor";
|
||||
public static final String SPEED_MODIFIER_ABOVE_LIMIT = "citizens.commands.npc.speed.modifier-above-limit";
|
||||
public static final String SPEED_MODIFIER_SET = "citizens.commands.npc.speed.set";
|
||||
public static final String TELEPORTED_TO_NPC = "citizens.commands.npc.tp.teleported";
|
||||
|
@ -15,6 +15,11 @@ citizens.commands.npc.age.set-baby=[[{0}]] is now a baby.
|
||||
citizens.commands.npc.age.set-normal=[[{0}]] is now age [[{1}]].
|
||||
citizens.commands.npc.age.set=[[{0}]] is now [[{1}]].
|
||||
citizens.commands.npc.age.unlocked=Age unlocked.
|
||||
citizens.commands.npc.anchor.added=Anchor added.
|
||||
citizens.commands.npc.anchor.already-exists=The anchor '{0}' already exists.
|
||||
citizens.commands.npc.anchor.invalid-name=Invalid anchor name.
|
||||
citizens.commands.npc.anchor.missing=The anchor '{1}' does not exist.
|
||||
citizens.commands.npc.anchor.removed=Anchor removed.
|
||||
citizens.commands.npc.behaviour.added=Behaviours added.
|
||||
citizens.commands.npc.behaviour.help=The scripts argument is a comma-separated list of file names. Scripts will be loaded automatically and run every tick. Use the [[-r]] flag to remove behaviours.
|
||||
citizens.commands.npc.behaviour.removed=Behaviours removed.
|
||||
|
Loading…
Reference in New Issue
Block a user