mirror of
https://github.com/CitizensDev/Citizens2.git
synced 2025-02-03 14:02:01 +01:00
Add /npc command cycle
This commit is contained in:
parent
deded77f34
commit
66708ac314
@ -455,7 +455,7 @@ public class NPCCommands {
|
||||
|
||||
@Command(
|
||||
aliases = { "npc" },
|
||||
usage = "command|cmd (add [command] | remove [id|all] | permissions [permissions] | sequential | random | clearerror [type] (name|uuid) | errormsg [type] [msg] | persistsequence [true|false] | cost [cost] (id) | expcost [cost] (id) | itemcost (id)) (-s(hift)) (-l[eft]/-r[ight]) (-p[layer] -o[p]), --cooldown --gcooldown [seconds] --delay [ticks] --permissions [perms] --n [max # of uses]",
|
||||
usage = "command|cmd (add [command] | remove [id|all] | permissions [permissions] | sequential | cycle | random | clearerror [type] (name|uuid) | errormsg [type] [msg] | persistsequence [true|false] | cost [cost] (id) | expcost [cost] (id) | itemcost (id)) (-s(hift)) (-l[eft]/-r[ight]) (-p[layer] -o[p]), --cooldown --gcooldown [seconds] --delay [ticks] --permissions [perms] --n [max # of uses]",
|
||||
desc = "Controls commands which will be run when clicking on an NPC",
|
||||
help = Messages.NPC_COMMAND_HELP,
|
||||
modifiers = { "command", "cmd" },
|
||||
@ -469,7 +469,7 @@ public class NPCCommands {
|
||||
@Flag(value = "delay", defValue = "0") Duration delay,
|
||||
@Arg(
|
||||
value = 1,
|
||||
completions = { "add", "remove", "permissions", "persistsequence", "sequential", "random",
|
||||
completions = { "add", "remove", "permissions", "persistsequence", "sequential", "cycle", "random",
|
||||
"hideerrors", "errormsg", "clearerror", "expcost", "itemcost", "cost" }) String action)
|
||||
throws CommandException {
|
||||
CommandTrait commands = npc.getOrAddTrait(CommandTrait.class);
|
||||
@ -521,6 +521,11 @@ public class NPCCommands {
|
||||
Messaging.sendTr(sender,
|
||||
commands.getExecutionMode() == ExecutionMode.SEQUENTIAL ? Messages.COMMANDS_SEQUENTIAL_SET
|
||||
: Messages.COMMANDS_SEQUENTIAL_UNSET);
|
||||
} else if (action.equalsIgnoreCase("cycle")) {
|
||||
commands.setExecutionMode(
|
||||
commands.getExecutionMode() == ExecutionMode.CYCLE ? ExecutionMode.LINEAR : ExecutionMode.CYCLE);
|
||||
Messaging.sendTr(sender, commands.getExecutionMode() == ExecutionMode.CYCLE ? Messages.COMMANDS_CYCLE_SET
|
||||
: Messages.COMMANDS_CYCLE_UNSET);
|
||||
} else if (action.equalsIgnoreCase("persistsequence")) {
|
||||
if (args.argsLength() == 2) {
|
||||
commands.setPersistSequence(!commands.persistSequence());
|
||||
@ -2078,11 +2083,12 @@ public class NPCCommands {
|
||||
|
||||
@Command(
|
||||
aliases = { "npc" },
|
||||
usage = "pathto me | here | cursor | [x] [y] [z] (--margin [distance margin])",
|
||||
usage = "pathto me | here | cursor | [x] [y] [z] (--margin [distance margin]) (-s[traight line])",
|
||||
desc = "Starts pathfinding to a certain location",
|
||||
modifiers = { "pathto" },
|
||||
min = 2,
|
||||
max = 4,
|
||||
flags = "s",
|
||||
permission = "citizens.npc.pathto")
|
||||
public void pathto(CommandContext args, CommandSender sender, NPC npc,
|
||||
@Arg(value = 1, completions = { "me", "here", "cursor" }) String option, @Flag("margin") Double margin)
|
||||
@ -2100,7 +2106,11 @@ public class NPCCommands {
|
||||
loc.setY(args.getDouble(2));
|
||||
loc.setZ(args.getDouble(3));
|
||||
}
|
||||
npc.getNavigator().setTarget(loc);
|
||||
if (args.hasFlag('s')) {
|
||||
npc.getNavigator().setStraightLineTarget(loc);
|
||||
} else {
|
||||
npc.getNavigator().setTarget(loc);
|
||||
}
|
||||
if (margin != null) {
|
||||
npc.getNavigator().getLocalParameters().distanceMargin(margin);
|
||||
}
|
||||
|
@ -191,9 +191,7 @@ public class CitizensNPCRegistry implements NPCRegistry {
|
||||
public NPC getNPC(Entity entity) {
|
||||
if (entity == null)
|
||||
return null;
|
||||
if (entity instanceof NPCHolder)
|
||||
return ((NPCHolder) entity).getNPC();
|
||||
return NMS.getNPC(entity);
|
||||
return entity instanceof NPCHolder ? ((NPCHolder) entity).getNPC() : NMS.getNPC(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -98,7 +98,7 @@ public class AStarNavigationStrategy extends AbstractPathStrategy {
|
||||
}
|
||||
Location loc = npc.getEntity().getLocation();
|
||||
/* Proper door movement - gets stuck on corners at times
|
||||
|
||||
|
||||
Block block = currLoc.getWorld().getBlockAt(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ());
|
||||
if (MinecraftBlockExaminer.isDoor(block.getType())) {
|
||||
Door door = (Door) block.getState().getData();
|
||||
@ -112,8 +112,8 @@ public class AStarNavigationStrategy extends AbstractPathStrategy {
|
||||
double dX = dest.getX() - loc.getX();
|
||||
double dZ = dest.getZ() - loc.getZ();
|
||||
double dY = dest.getY() - loc.getY();
|
||||
double xzDistance = dX * dX + dZ * dZ;
|
||||
if (Math.abs(dY) < 1 && Math.sqrt(xzDistance) <= params.distanceMargin()) {
|
||||
double xzDistance = Math.sqrt(dX * dX + dZ * dZ);
|
||||
if (Math.abs(dY) < 1 && xzDistance <= params.distanceMargin()) {
|
||||
plan.update(npc);
|
||||
if (plan.isComplete())
|
||||
return true;
|
||||
@ -128,7 +128,7 @@ public class AStarNavigationStrategy extends AbstractPathStrategy {
|
||||
} else {
|
||||
Vector dir = dest.toVector().subtract(npc.getEntity().getLocation().toVector()).normalize().multiply(0.2);
|
||||
boolean liquidOrInLiquid = MinecraftBlockExaminer.isLiquidOrInLiquid(loc.getBlock());
|
||||
if (dY >= 1 && Math.sqrt(xzDistance) <= 0.4 || dY >= 0.2 && liquidOrInLiquid) {
|
||||
if (dY >= 1 && xzDistance <= 0.4 || dY >= 0.2 && liquidOrInLiquid) {
|
||||
dir.add(new Vector(0, 0.75, 0));
|
||||
}
|
||||
npc.getEntity().setVelocity(dir);
|
||||
|
@ -334,12 +334,13 @@ public class CitizensNavigator implements Navigator, Runnable {
|
||||
return;
|
||||
}
|
||||
setTarget(params -> {
|
||||
if (npc.isFlyable())
|
||||
if (npc.isFlyable()) {
|
||||
return new FlyingAStarNavigationStrategy(npc, path, params);
|
||||
else if (params.useNewPathfinder() || !(npc.getEntity() instanceof LivingEntity))
|
||||
} else if (params.useNewPathfinder() || !(npc.getEntity() instanceof LivingEntity)) {
|
||||
return new AStarNavigationStrategy(npc, path, params);
|
||||
else
|
||||
} else {
|
||||
return new MCNavigationStrategy(npc, path, params);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -353,12 +354,13 @@ public class CitizensNavigator implements Navigator, Runnable {
|
||||
}
|
||||
Location target = targetIn.clone();
|
||||
setTarget(params -> {
|
||||
if (npc.isFlyable())
|
||||
if (npc.isFlyable()) {
|
||||
return new FlyingAStarNavigationStrategy(npc, target, params);
|
||||
else if (params.useNewPathfinder() || !(npc.getEntity() instanceof LivingEntity))
|
||||
} else if (params.useNewPathfinder() || !(npc.getEntity() instanceof LivingEntity)) {
|
||||
return new AStarNavigationStrategy(npc, target, params);
|
||||
else
|
||||
} else {
|
||||
return new MCNavigationStrategy(npc, target, params);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -62,9 +62,12 @@ public class StraightLineNavigationStrategy extends AbstractPathStrategy {
|
||||
return true;
|
||||
|
||||
Location currLoc = npc.getEntity().getLocation();
|
||||
if (currLoc.distance(destination) <= params.distanceMargin())
|
||||
if (currLoc.distance(destination) <= params.distanceMargin()) {
|
||||
if (npc.isFlyable()) {
|
||||
npc.getEntity().setVelocity(new Vector(0, 0, 0));
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
if (target != null) {
|
||||
destination = params.entityTargetLocationMapper().apply(target);
|
||||
}
|
||||
|
@ -77,6 +77,7 @@ public class CommandTrait extends Trait {
|
||||
private boolean hideErrorMessages;
|
||||
@Persist
|
||||
private final List<ItemStack> itemRequirements = Lists.newArrayList();
|
||||
private int lastUsedId = -1;
|
||||
@Persist
|
||||
private boolean persistSequence = false;
|
||||
@Persist(keyType = UUID.class, reify = true, value = "cooldowns")
|
||||
@ -278,7 +279,7 @@ public class CommandTrait extends Trait {
|
||||
return;
|
||||
}
|
||||
int max = -1;
|
||||
if (executionMode == ExecutionMode.SEQUENTIAL) {
|
||||
if (executionMode == ExecutionMode.SEQUENTIAL || executionMode == ExecutionMode.CYCLE) {
|
||||
Collections.sort(commandList, Comparator.comparing(o1 -> o1.id));
|
||||
max = commandList.size() > 0 ? commandList.get(commandList.size() - 1).id : -1;
|
||||
}
|
||||
@ -287,6 +288,13 @@ public class CommandTrait extends Trait {
|
||||
}
|
||||
for (NPCCommand command : commandList) {
|
||||
PlayerNPCCommand info = null;
|
||||
if (executionMode == ExecutionMode.CYCLE) {
|
||||
if (command.id <= lastUsedId) {
|
||||
if (lastUsedId != max)
|
||||
continue;
|
||||
lastUsedId = -1;
|
||||
}
|
||||
}
|
||||
if (executionMode == ExecutionMode.SEQUENTIAL
|
||||
&& (info = playerTracking.get(player.getUniqueId())) != null) {
|
||||
if (info.lastUsedHand != hand) {
|
||||
@ -300,7 +308,8 @@ public class CommandTrait extends Trait {
|
||||
}
|
||||
}
|
||||
runCommand(player, hand, command);
|
||||
if (executionMode == ExecutionMode.SEQUENTIAL || (charged != null && !charged))
|
||||
if (executionMode == ExecutionMode.SEQUENTIAL || executionMode == ExecutionMode.CYCLE
|
||||
|| (charged != null && !charged))
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -508,6 +517,7 @@ public class CommandTrait extends Trait {
|
||||
}
|
||||
|
||||
public enum ExecutionMode {
|
||||
CYCLE,
|
||||
LINEAR,
|
||||
RANDOM,
|
||||
SEQUENTIAL;
|
||||
|
@ -31,7 +31,6 @@ import net.citizensnpcs.api.CitizensAPI;
|
||||
import net.citizensnpcs.api.gui.CitizensInventoryClickEvent;
|
||||
import net.citizensnpcs.api.gui.ClickHandler;
|
||||
import net.citizensnpcs.api.gui.InputMenus;
|
||||
import net.citizensnpcs.api.gui.InputMenus.Choice;
|
||||
import net.citizensnpcs.api.gui.InventoryMenu;
|
||||
import net.citizensnpcs.api.gui.InventoryMenuPage;
|
||||
import net.citizensnpcs.api.gui.InventoryMenuPattern;
|
||||
@ -114,8 +113,6 @@ public class ShopTrait extends Trait {
|
||||
@Persist
|
||||
private String title;
|
||||
@Persist
|
||||
private ShopType type = ShopType.COMMAND;
|
||||
@Persist
|
||||
private String viewPermission;
|
||||
|
||||
private NPCShop() {
|
||||
@ -712,42 +709,31 @@ public class ShopTrait extends Trait {
|
||||
@Override
|
||||
public void initialise(MenuContext ctx) {
|
||||
this.ctx = ctx;
|
||||
ctx.getSlot(2)
|
||||
ctx.getSlot(0)
|
||||
.setDescription("<f>Edit permission required to view shop<br>" + shop.getRequiredPermission());
|
||||
ctx.getSlot(6).setDescription("<f>Edit shop title<br>" + shop.title);
|
||||
ctx.getSlot(4).setDescription("<f>Edit shop title<br>" + shop.title);
|
||||
if (trait != null) {
|
||||
ctx.getSlot(8).setDescription(
|
||||
ctx.getSlot(6).setDescription(
|
||||
"<f>Show shop on right click<br>" + shop.getName().equals(trait.rightClickShop));
|
||||
}
|
||||
}
|
||||
|
||||
@MenuSlot(slot = { 0, 4 }, material = Material.FEATHER, amount = 1, title = "<f>Edit shop items")
|
||||
@MenuSlot(slot = { 0, 2 }, material = Material.FEATHER, amount = 1, title = "<f>Edit shop items")
|
||||
public void onEditItems(InventoryMenuSlot slot, CitizensInventoryClickEvent event) {
|
||||
ctx.getMenu().transition(new NPCShopContentsEditor(shop));
|
||||
}
|
||||
|
||||
@MenuSlot(slot = { 0, 2 }, compatMaterial = { "OAK_SIGN", "SIGN" }, amount = 1)
|
||||
@MenuSlot(slot = { 0, 0 }, compatMaterial = { "OAK_SIGN", "SIGN" }, amount = 1)
|
||||
public void onPermissionChange(InventoryMenuSlot slot, CitizensInventoryClickEvent event) {
|
||||
ctx.getMenu().transition(InputMenus.stringSetter(shop::getRequiredPermission, shop::setPermission));
|
||||
}
|
||||
|
||||
@MenuSlot(slot = { 0, 6 }, material = Material.NAME_TAG, amount = 1)
|
||||
@MenuSlot(slot = { 0, 4 }, material = Material.NAME_TAG, amount = 1)
|
||||
public void onSetTitle(InventoryMenuSlot slot, CitizensInventoryClickEvent event) {
|
||||
ctx.getMenu().transition(InputMenus.stringSetter(() -> shop.title, newTitle -> shop.title = newTitle));
|
||||
}
|
||||
|
||||
@MenuSlot(slot = { 0, 0 }, material = Material.BOOK, amount = 1, title = "<f>Edit shop type")
|
||||
public void onShopTypeChange(InventoryMenuSlot slot, CitizensInventoryClickEvent event) {
|
||||
ctx.getMenu().transition(InputMenus.<ShopType> picker("Edit shop type",
|
||||
chosen -> shop.type = chosen.getValue(),
|
||||
Choice.<ShopType> of(ShopType.BUY, Material.DIAMOND, "Players buy items",
|
||||
shop.type == ShopType.BUY),
|
||||
Choice.of(ShopType.SELL, Material.EMERALD, "Players sell items", shop.type == ShopType.SELL),
|
||||
Choice.of(ShopType.COMMAND, Util.getFallbackMaterial("ENDER_EYE", "ENDER_PEARL"),
|
||||
"Clicks trigger commands only", shop.type == ShopType.COMMAND)));
|
||||
}
|
||||
|
||||
@MenuSlot(slot = { 0, 8 }, compatMaterial = { "COMMAND_BLOCK", "COMMAND" }, amount = 1)
|
||||
@MenuSlot(slot = { 0, 6 }, compatMaterial = { "COMMAND_BLOCK", "COMMAND" }, amount = 1)
|
||||
public void onToggleRightClick(InventoryMenuSlot slot, CitizensInventoryClickEvent event) {
|
||||
event.setCancelled(true);
|
||||
if (trait == null)
|
||||
@ -758,7 +744,7 @@ public class ShopTrait extends Trait {
|
||||
} else {
|
||||
trait.rightClickShop = shop.name;
|
||||
}
|
||||
ctx.getSlot(8)
|
||||
ctx.getSlot(6)
|
||||
.setDescription("<f>Show shop on right click<br>" + shop.getName().equals(trait.rightClickShop));
|
||||
}
|
||||
}
|
||||
@ -830,12 +816,6 @@ public class ShopTrait extends Trait {
|
||||
}
|
||||
}
|
||||
|
||||
public enum ShopType {
|
||||
BUY,
|
||||
COMMAND,
|
||||
SELL;
|
||||
}
|
||||
|
||||
static {
|
||||
NPCShopAction.register(ItemAction.class, "items", new ItemActionGUI());
|
||||
NPCShopAction.register(PermissionAction.class, "permissions", new PermissionActionGUI());
|
||||
|
@ -271,14 +271,15 @@ public class GuidedWaypointProvider implements EnumerableWaypointProvider {
|
||||
tree.clear();
|
||||
treePlusDestinations.clear();
|
||||
for (Waypoint waypoint : guides) {
|
||||
tree.put(new long[] { waypoint.getLocation().getBlockX(), waypoint.getLocation().getBlockY(),
|
||||
waypoint.getLocation().getBlockZ() }, waypoint);
|
||||
treePlusDestinations.put(new long[] { waypoint.getLocation().getBlockX(),
|
||||
waypoint.getLocation().getBlockY(), waypoint.getLocation().getBlockZ() }, waypoint);
|
||||
Location location = waypoint.getLocation();
|
||||
tree.put(new long[] { location.getBlockX(), location.getBlockY(), location.getBlockZ() }, waypoint);
|
||||
treePlusDestinations.put(new long[] { location.getBlockX(), location.getBlockY(), location.getBlockZ() },
|
||||
waypoint);
|
||||
}
|
||||
for (Waypoint waypoint : destinations) {
|
||||
treePlusDestinations.put(new long[] { waypoint.getLocation().getBlockX(),
|
||||
waypoint.getLocation().getBlockY(), waypoint.getLocation().getBlockZ() }, waypoint);
|
||||
Location location = waypoint.getLocation();
|
||||
treePlusDestinations.put(new long[] { location.getBlockX(), location.getBlockY(), location.getBlockZ() },
|
||||
waypoint);
|
||||
}
|
||||
if (currentGoal != null) {
|
||||
currentGoal.onProviderChanged();
|
||||
|
@ -79,6 +79,8 @@ public class Messages {
|
||||
public static final String COMMAND_TRIGGER_PROMPT = "citizens.editors.waypoints.triggers.command.prompt";
|
||||
public static final String COMMAND_UNKNOWN_COMMAND_ID = "citizens.commands.npc.command.unknown-id";
|
||||
public static final String COMMANDS_CLEARED = "citizens.commands.npc.command.cleared";
|
||||
public static final String COMMANDS_CYCLE_SET = "citizens.commands.npc.command.cycle-set";
|
||||
public static final String COMMANDS_CYCLE_UNSET = "citizens.commands.npc.command.cycle-unset";
|
||||
public static final String COMMANDS_PERSIST_SEQUENCE_SET = "citizens.commands.npc.command.persist-sequence-set";
|
||||
public static final String COMMANDS_PERSIST_SEQUENCE_UNSET = "citizens.commands.npc.command.persist-sequence-unset";
|
||||
public static final String COMMANDS_RANDOM_SET = "citizens.commands.npc.commands.random-set";
|
||||
|
@ -52,6 +52,8 @@
|
||||
"citizens.commands.npc.chunkload.unset" : "[[{0}]] will no longer force chunks to be loaded.",
|
||||
"citizens.commands.npc.collidable.set" : "[[{0}]] will now collide with entities.",
|
||||
"citizens.commands.npc.collidable.unset" : "[[{0}]] will no longer collide with entities.",
|
||||
"citizens.commands.npc.command.cycle-set": "[[{0}]] will now cycle through commands on player click",
|
||||
"citizens.commands.npc.command.cycle-unset": "[[{0}]] will no longer cycle through commands on player click",
|
||||
"citizens.commands.npc.command.command-added" : "Command [[{0}]] added with id [[{1}]].",
|
||||
"citizens.commands.npc.command.command-removed" : "Command [[{0}]] removed.",
|
||||
"citizens.commands.npc.command.cleared" : "[[{0}]]''s commands cleared.",
|
||||
@ -60,7 +62,7 @@
|
||||
"citizens.commands.npc.command.describe-format" : "<br> - {0} [{1}s] [cost:{2}] [exp:{3}] [<click:run_command:/npc cmd remove {4}><hover:show_text:Remove this command><red><u>-</hover></click>]",
|
||||
"citizens.commands.npc.command.errors-cleared" : "Errors cleared for [[{0}]].",
|
||||
"citizens.commands.npc.command.experience-cost-set" : "Set xp level cost per click to [[{0}]].",
|
||||
"citizens.commands.npc.command.help" : "<br>Use the [[-l]] flag to make the command run on left click, [[-r]] on right click (default).<br>Set the per-player cooldown before the command can be used again using [[--cooldown]] (in [[seconds]]).<br>Set the server-wide cooldown in seconds using [[--gcooldown]].<br>[[--delay]] will wait the specified amount in [[ticks]] before executing the command.<br>[[--permissions]] will set the command to require specific permissions (separate multiple with commas).<br>[[--n]] will only let the player run the command that number of times.<br>Use [[-o]] to temporarily execute the command as an op and [[-p]] to run the command as the clicking player instead of the server.<br>To give the player temporary permissions instead of op, use [[/npc command permissions]].<br>Set the cost of each click with [[/npc command cost/expcost/itemcost]].<br>Commands can be executed one by one instead of all at once by using [[/npc command sequential]].",
|
||||
"citizens.commands.npc.command.help" : "<br>Use the [[-l]] flag to make the command run on left click, [[-r]] on right click (default).<br>Set the per-player cooldown before the command can be used again using [[--cooldown]] (in [[seconds]]).<br>Set the server-wide cooldown in seconds using [[--gcooldown]].<br>[[--delay]] will wait the specified amount in [[ticks]] before executing the command.<br>[[--permissions]] will set the command to require specific permissions (separate multiple with commas).<br>[[--n]] will only let the player run the command that number of times.<br>Use [[-o]] to temporarily execute the command as an op and [[-p]] to run the command as the clicking player instead of the server.<br>To give the player temporary permissions instead of op, use [[/npc command permissions]].<br>Set the cost of each click with [[/npc command cost/expcost/itemcost]].<br>Commands can be executed one by one instead of all at once by using [[/npc command sequential]] or [[/npc command cycle]].",
|
||||
"citizens.commands.npc.command.hide-error-messages-set" : "Now hiding error messages.",
|
||||
"citizens.commands.npc.command.hide-error-messages-unset" : "No longer hiding error messages.",
|
||||
"citizens.commands.npc.command.individual-cost-set" : "Set cost per click to [[{0}]] for command id [[{1}]].",
|
||||
|
Loading…
Reference in New Issue
Block a user