mirror of
https://github.com/CitizensDev/Citizens2.git
synced 2024-12-26 19:18:37 +01:00
Add rudimentary /npc undo, some misc cleanup
This commit is contained in:
parent
984ce6d9e7
commit
aacff7b45a
@ -45,7 +45,9 @@ import org.json.simple.parser.JSONParser;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.ListMultimap;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import net.citizensnpcs.Citizens;
|
||||
@ -83,6 +85,9 @@ import net.citizensnpcs.api.util.Messaging;
|
||||
import net.citizensnpcs.api.util.Paginator;
|
||||
import net.citizensnpcs.api.util.SpigotUtil;
|
||||
import net.citizensnpcs.commands.gui.NPCConfigurator;
|
||||
import net.citizensnpcs.commands.history.CommandHistoryItem;
|
||||
import net.citizensnpcs.commands.history.CreateNPCHistoryItem;
|
||||
import net.citizensnpcs.commands.history.RemoveNPCHistoryItem;
|
||||
import net.citizensnpcs.npc.EntityControllers;
|
||||
import net.citizensnpcs.npc.NPCSelector;
|
||||
import net.citizensnpcs.npc.Template;
|
||||
@ -131,6 +136,7 @@ import net.citizensnpcs.util.Util;
|
||||
|
||||
@Requirements(selected = true, ownership = true)
|
||||
public class NPCCommands {
|
||||
private final ListMultimap<UUID, CommandHistoryItem> history = ArrayListMultimap.create();
|
||||
private final NPCSelector selector;
|
||||
private final NPCRegistry temporaryRegistry;
|
||||
|
||||
@ -139,6 +145,10 @@ public class NPCCommands {
|
||||
temporaryRegistry = CitizensAPI.createCitizensBackedNPCRegistry(new MemoryNPCDataStore());
|
||||
}
|
||||
|
||||
private void addCommandHistory(CommandSender sender, CommandHistoryItem item) {
|
||||
history.put(sender instanceof Entity ? ((Entity) sender).getUniqueId() : null, item);
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "npc" },
|
||||
usage = "age [age] (-l)",
|
||||
@ -378,7 +388,7 @@ public class NPCCommands {
|
||||
} else if (args.getString(1).equalsIgnoreCase("remove")) {
|
||||
if (args.argsLength() == 2)
|
||||
throw new CommandUsageException();
|
||||
int id = args.getInteger(2);
|
||||
int id = args.getInteger(2, -1);
|
||||
if (!commands.hasCommandId(id))
|
||||
throw new CommandException(Messages.COMMAND_UNKNOWN_COMMAND_ID, id);
|
||||
commands.removeCommandById(id);
|
||||
@ -479,6 +489,7 @@ public class NPCCommands {
|
||||
|
||||
Messaging.sendTr(sender, Messages.NPC_COPIED, npc.getName());
|
||||
selector.select(sender, copy);
|
||||
addCommandHistory(sender, new CreateNPCHistoryItem(copy));
|
||||
}
|
||||
|
||||
@Command(
|
||||
@ -615,6 +626,7 @@ public class NPCCommands {
|
||||
npc.getOrAddTrait(Age.class).setAge(age);
|
||||
}
|
||||
selector.select(sender, npc);
|
||||
addCommandHistory(sender, new CreateNPCHistoryItem(npc));
|
||||
Messaging.send(sender, msg + '.');
|
||||
}
|
||||
|
||||
@ -1734,6 +1746,7 @@ public class NPCCommands {
|
||||
Collection<NPC> npcs = Lists.newArrayList(CitizensAPI.getNPCRegistry());
|
||||
for (NPC o : npcs) {
|
||||
if (o.getOrAddTrait(Owner.class).isOwnedBy(owner)) {
|
||||
addCommandHistory(sender, new RemoveNPCHistoryItem(o));
|
||||
o.destroy(sender);
|
||||
}
|
||||
}
|
||||
@ -1743,6 +1756,7 @@ public class NPCCommands {
|
||||
if (args.hasValueFlag("eid")) {
|
||||
Entity entity = Bukkit.getServer().getEntity(UUID.fromString(args.getFlag("eid")));
|
||||
if (entity != null && (npc = CitizensAPI.getNPCRegistry().getNPC(entity)) != null) {
|
||||
addCommandHistory(sender, new RemoveNPCHistoryItem(npc));
|
||||
npc.destroy(sender);
|
||||
Messaging.sendTr(sender, Messages.NPC_REMOVED, npc.getName());
|
||||
return;
|
||||
@ -1755,7 +1769,10 @@ public class NPCCommands {
|
||||
if (args.getString(1).equalsIgnoreCase("all")) {
|
||||
if (!sender.hasPermission("citizens.admin.remove.all") && !sender.hasPermission("citizens.admin"))
|
||||
throw new NoPermissionsException();
|
||||
CitizensAPI.getNPCRegistry().deregisterAll();
|
||||
for (NPC rem : CitizensAPI.getNPCRegistry()) {
|
||||
addCommandHistory(sender, new RemoveNPCHistoryItem(rem));
|
||||
rem.destroy();
|
||||
}
|
||||
Messaging.sendTr(sender, Messages.REMOVED_ALL_NPCS);
|
||||
return;
|
||||
} else {
|
||||
@ -1769,6 +1786,7 @@ public class NPCCommands {
|
||||
throw new CommandException(Messages.COMMAND_MUST_BE_OWNER);
|
||||
if (!sender.hasPermission("citizens.npc.remove") && !sender.hasPermission("citizens.admin"))
|
||||
throw new NoPermissionsException();
|
||||
addCommandHistory(sender, new RemoveNPCHistoryItem(npc));
|
||||
npc.destroy(sender);
|
||||
Messaging.sendTr(sender, Messages.NPC_REMOVED, npc.getName());
|
||||
}
|
||||
@ -1784,6 +1802,7 @@ public class NPCCommands {
|
||||
throw new CommandException(Messages.COMMAND_MUST_BE_OWNER);
|
||||
if (!sender.hasPermission("citizens.npc.remove") && !sender.hasPermission("citizens.admin"))
|
||||
throw new NoPermissionsException();
|
||||
addCommandHistory(sender, new RemoveNPCHistoryItem(npc));
|
||||
npc.destroy(sender);
|
||||
Messaging.sendTr(sender, Messages.NPC_REMOVED, npc.getName());
|
||||
}
|
||||
@ -2504,6 +2523,36 @@ public class NPCCommands {
|
||||
Messaging.sendTr(sender, Messages.ENTITY_TYPE_SET, npc.getName(), args.getString(1));
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "npc" },
|
||||
usage = "undo (all)",
|
||||
desc = "Undoes the last action (currently only create/remove supported)",
|
||||
modifiers = { "undo" },
|
||||
min = 1,
|
||||
max = 2,
|
||||
permission = "citizens.npc.undo")
|
||||
@Requirements
|
||||
public void undo(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
|
||||
if (args.argsLength() > 1 && args.getString(1).equals("all")) {
|
||||
while (undoLastAction(sender)) {
|
||||
}
|
||||
} else if (undoLastAction(sender)) {
|
||||
Messaging.sendTr(sender, Messages.UNDO_SUCCESSFUL);
|
||||
} else {
|
||||
Messaging.sendTr(sender, Messages.UNDO_UNSUCCESSFUL);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean undoLastAction(CommandSender sender) {
|
||||
UUID uuid = sender instanceof Entity ? ((Entity) sender).getUniqueId() : null;
|
||||
List<CommandHistoryItem> hist = history.get(uuid);
|
||||
if (hist.size() == 0)
|
||||
return false;
|
||||
CommandHistoryItem item = hist.remove(hist.size() - 1);
|
||||
item.undo(sender, selector);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "npc" },
|
||||
usage = "useitem (-o(ffhand))",
|
||||
|
@ -0,0 +1,9 @@
|
||||
package net.citizensnpcs.commands.history;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import net.citizensnpcs.api.npc.NPCSelector;
|
||||
|
||||
public interface CommandHistoryItem {
|
||||
void undo(CommandSender sender, NPCSelector selector);
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package net.citizensnpcs.commands.history;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import net.citizensnpcs.api.CitizensAPI;
|
||||
import net.citizensnpcs.api.npc.NPC;
|
||||
import net.citizensnpcs.api.npc.NPCSelector;
|
||||
|
||||
public class CreateNPCHistoryItem implements CommandHistoryItem {
|
||||
private final UUID uuid;
|
||||
|
||||
public CreateNPCHistoryItem(NPC npc) {
|
||||
this.uuid = npc.getUniqueId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undo(CommandSender sender, NPCSelector selector) {
|
||||
NPC npc = CitizensAPI.getNPCRegistry().getByUniqueIdGlobal(uuid);
|
||||
if (npc != null) {
|
||||
npc.destroy();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package net.citizensnpcs.commands.history;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.EntityType;
|
||||
|
||||
import net.citizensnpcs.api.CitizensAPI;
|
||||
import net.citizensnpcs.api.npc.NPC;
|
||||
import net.citizensnpcs.api.npc.NPCSelector;
|
||||
import net.citizensnpcs.api.trait.trait.MobType;
|
||||
import net.citizensnpcs.api.util.DataKey;
|
||||
import net.citizensnpcs.api.util.MemoryDataKey;
|
||||
|
||||
public class RemoveNPCHistoryItem implements CommandHistoryItem {
|
||||
private final int id;
|
||||
private final DataKey key;
|
||||
private final EntityType type;
|
||||
private final UUID uuid;
|
||||
|
||||
public RemoveNPCHistoryItem(NPC from) {
|
||||
this.key = new MemoryDataKey();
|
||||
from.save(key);
|
||||
this.type = from.getOrAddTrait(MobType.class).getType();
|
||||
this.uuid = from.getUniqueId();
|
||||
this.id = from.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undo(CommandSender sender, NPCSelector selector) {
|
||||
NPC npc = CitizensAPI.getNPCRegistry().createNPC(type, uuid, id, key.getString("name"));
|
||||
npc.load(key);
|
||||
selector.select(sender, npc);
|
||||
}
|
||||
}
|
@ -385,6 +385,8 @@ public class Messages {
|
||||
public static final String TROPICALFISH_BODY_COLOR_SET = "citizens.commands.npc.tropicalfish.body-color-set";
|
||||
public static final String TROPICALFISH_PATTERN_COLOR_SET = "citizens.commands.npc.tropicalfish.pattern-color-set";
|
||||
public static final String TROPICALFISH_PATTERN_SET = "citizens.commands.npc.tropicalfish.pattern-set";
|
||||
public static final String UNDO_SUCCESSFUL = "citizens.commands.npc.undo.successful";
|
||||
public static final String UNDO_UNSUCCESSFUL = "citizens.commands.npc.undo.unsuccessful";
|
||||
public static final String UNKNOWN_COMMAND = "citizens.commands.unknown-command";
|
||||
public static final String UNKNOWN_MATERIAL = "citizens.commands.npc.item.unknown-material";
|
||||
public static final String USING_MINECRAFT_AI = "citizens.commands.npc.ai.started";
|
||||
|
@ -254,6 +254,8 @@ citizens.commands.npc.wolf.collar-color-unsupported=[[{0}]] is not a RGB color c
|
||||
citizens.commands.npc.villager.level-set=Level set to [[{0}]].
|
||||
citizens.commands.npc.villager.invalid-type=Invalid villager type. Valid types are: [[{0}]].
|
||||
citizens.commands.npc.villager.type-set=Type set to [[{0}]].
|
||||
citizens.commands.npc.undo.successful=Undo successful
|
||||
citizens.commands.npc.undo.unsuccessful=No commands to undo
|
||||
citizens.commands.npc.zombiemod.villager-set=[[{0}]] is now a villager.
|
||||
citizens.commands.npc.zombiemod.villager-unset=[[{0}]] is no longer a villager.
|
||||
citizens.commands.npc.zombiemod.baby-set=[[{0}]] is now a baby.
|
||||
|
@ -183,8 +183,8 @@ public class EntityHumanNPC extends ServerPlayer implements NPCHolder, Skinnable
|
||||
}
|
||||
|
||||
if (navigating) {
|
||||
if (!NMSImpl.isNavigationFinished(navigation)) {
|
||||
NMSImpl.updateNavigation(navigation);
|
||||
if (!navigation.isDone()) {
|
||||
navigation.tick();
|
||||
}
|
||||
moveOnCurrentHeading();
|
||||
}
|
||||
|
@ -645,7 +645,7 @@ public class NMSImpl implements NMSBridge {
|
||||
((Mob) raw).setPathfindingMalus(BlockPathTypes.WATER, oldWater);
|
||||
}
|
||||
}
|
||||
stopNavigation(navigation);
|
||||
navigation.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -680,7 +680,7 @@ public class NMSImpl implements NMSBridge {
|
||||
}
|
||||
lastSpeed = params.speed();
|
||||
}
|
||||
if (params.debug() && !NMSImpl.isNavigationFinished(navigation)) {
|
||||
if (params.debug() && !navigation.isDone()) {
|
||||
BlockData data = Material.DANDELION.createBlockData();
|
||||
Path path = getPathEntity(navigation);
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
@ -691,7 +691,7 @@ public class NMSImpl implements NMSBridge {
|
||||
}
|
||||
}
|
||||
navigation.setSpeedModifier(params.speed());
|
||||
return NMSImpl.isNavigationFinished(navigation);
|
||||
return navigation.isDone();
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -1417,12 +1417,12 @@ public class NMSImpl implements NMSBridge {
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
stopNavigation(navigation);
|
||||
navigation.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
updateNavigation(navigation);
|
||||
navigation.tick();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1694,10 +1694,6 @@ public class NMSImpl implements NMSBridge {
|
||||
network.address = socketAddress;
|
||||
}
|
||||
|
||||
public static boolean isNavigationFinished(PathNavigation navigation) {
|
||||
return navigation.isDone();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static void minecartItemLogic(AbstractMinecart minecart) {
|
||||
NPC npc = ((NPCHolder) minecart).getNPC();
|
||||
@ -1848,15 +1844,11 @@ public class NMSImpl implements NMSBridge {
|
||||
}
|
||||
}
|
||||
|
||||
public static void stopNavigation(PathNavigation navigation) {
|
||||
navigation.stop();
|
||||
}
|
||||
|
||||
public static void updateAI(LivingEntity entity) {
|
||||
if (entity instanceof Mob) {
|
||||
Mob handle = (Mob) entity;
|
||||
handle.getSensing().tick();
|
||||
NMSImpl.updateNavigation(handle.getNavigation());
|
||||
handle.getNavigation().tick();
|
||||
handle.getMoveControl().tick();
|
||||
handle.getLookControl().tick();
|
||||
handle.getJumpControl().tick();
|
||||
@ -1885,10 +1877,6 @@ public class NMSImpl implements NMSBridge {
|
||||
}
|
||||
}
|
||||
|
||||
public static void updateNavigation(PathNavigation navigation) {
|
||||
navigation.tick();
|
||||
}
|
||||
|
||||
private static final MethodHandle ADVANCEMENTS_PLAYER_FIELD = NMS.getFinalSetter(ServerPlayer.class, "cr");
|
||||
|
||||
private static final Set<EntityType> BAD_CONTROLLER_LOOK = EnumSet.of(EntityType.POLAR_BEAR, EntityType.BEE,
|
||||
|
@ -22,7 +22,7 @@ public class PlayerLookControl {
|
||||
}
|
||||
|
||||
public void a() {
|
||||
if (!NMSImpl.isNavigationFinished(this.a.getNavigation())) {
|
||||
if (!this.a.getNavigation().isDone()) {
|
||||
// TODO: use Citizens AI?
|
||||
// this.a.yHeadRot = Mth.rotateIfNecessary(this.a.yHeadRot, this.a.yBodyRot, 75);
|
||||
return;
|
||||
|
@ -184,8 +184,8 @@ public class EntityHumanNPC extends ServerPlayer implements NPCHolder, Skinnable
|
||||
}
|
||||
|
||||
if (navigating) {
|
||||
if (!NMSImpl.isNavigationFinished(navigation)) {
|
||||
NMSImpl.updateNavigation(navigation);
|
||||
if (!navigation.isDone()) {
|
||||
navigation.tick();
|
||||
}
|
||||
moveOnCurrentHeading();
|
||||
}
|
||||
|
@ -649,7 +649,7 @@ public class NMSImpl implements NMSBridge {
|
||||
((Mob) raw).setPathfindingMalus(BlockPathTypes.WATER, oldWater);
|
||||
}
|
||||
}
|
||||
stopNavigation(navigation);
|
||||
navigation.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -684,7 +684,7 @@ public class NMSImpl implements NMSBridge {
|
||||
}
|
||||
lastSpeed = params.speed();
|
||||
}
|
||||
if (params.debug() && !NMSImpl.isNavigationFinished(navigation)) {
|
||||
if (params.debug() && !navigation.isDone()) {
|
||||
BlockData data = Material.DANDELION.createBlockData();
|
||||
Path path = getPathEntity(navigation);
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
@ -695,7 +695,7 @@ public class NMSImpl implements NMSBridge {
|
||||
}
|
||||
}
|
||||
navigation.setSpeedModifier(params.speed());
|
||||
return NMSImpl.isNavigationFinished(navigation);
|
||||
return navigation.isDone();
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -1421,12 +1421,12 @@ public class NMSImpl implements NMSBridge {
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
stopNavigation(navigation);
|
||||
navigation.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
updateNavigation(navigation);
|
||||
navigation.tick();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1698,10 +1698,6 @@ public class NMSImpl implements NMSBridge {
|
||||
network.address = socketAddress;
|
||||
}
|
||||
|
||||
public static boolean isNavigationFinished(PathNavigation navigation) {
|
||||
return navigation.isDone();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static void minecartItemLogic(AbstractMinecart minecart) {
|
||||
NPC npc = ((NPCHolder) minecart).getNPC();
|
||||
@ -1732,7 +1728,7 @@ public class NMSImpl implements NMSBridge {
|
||||
int i = 0;
|
||||
for (GoalSelector selector : goalSelectors) {
|
||||
try {
|
||||
Collection list = selector.getAvailableGoals();
|
||||
Collection<?> list = selector.getAvailableGoals();
|
||||
list.clear();
|
||||
|
||||
Collection old = npc.data().get("selector" + i);
|
||||
@ -1852,10 +1848,6 @@ public class NMSImpl implements NMSBridge {
|
||||
}
|
||||
}
|
||||
|
||||
public static void stopNavigation(PathNavigation navigation) {
|
||||
navigation.stop();
|
||||
}
|
||||
|
||||
public static Entity teleportAcrossWorld(Entity entity, ServerLevel worldserver, BlockPos location) {
|
||||
if (FIND_DIMENSION_ENTRY_POINT == null || entity.isRemoved())
|
||||
return null;
|
||||
@ -1888,7 +1880,7 @@ public class NMSImpl implements NMSBridge {
|
||||
if (entity instanceof Mob) {
|
||||
Mob handle = (Mob) entity;
|
||||
handle.getSensing().tick();
|
||||
NMSImpl.updateNavigation(handle.getNavigation());
|
||||
handle.getNavigation().tick();
|
||||
handle.getMoveControl().tick();
|
||||
handle.getLookControl().tick();
|
||||
handle.getJumpControl().tick();
|
||||
@ -1917,10 +1909,6 @@ public class NMSImpl implements NMSBridge {
|
||||
}
|
||||
}
|
||||
|
||||
public static void updateNavigation(PathNavigation navigation) {
|
||||
navigation.tick();
|
||||
}
|
||||
|
||||
private static final MethodHandle ADVANCEMENTS_PLAYER_FIELD = NMS.getFinalSetter(ServerPlayer.class, "cs");
|
||||
private static final Set<EntityType> BAD_CONTROLLER_LOOK = EnumSet.of(EntityType.POLAR_BEAR, EntityType.BEE,
|
||||
EntityType.SILVERFISH, EntityType.SHULKER, EntityType.ENDERMITE, EntityType.ENDER_DRAGON, EntityType.BAT,
|
||||
|
@ -22,7 +22,7 @@ public class PlayerLookControl {
|
||||
}
|
||||
|
||||
public void a() {
|
||||
if (!NMSImpl.isNavigationFinished(this.a.getNavigation())) {
|
||||
if (!this.a.getNavigation().isDone()) {
|
||||
// TODO: use Citizens AI?
|
||||
// this.a.yHeadRot = Mth.rotateIfNecessary(this.a.yHeadRot, this.a.yBodyRot, 75);
|
||||
return;
|
||||
|
Loading…
Reference in New Issue
Block a user