Add perplayer lookclose, rework templates, add message to send on click to shop trait, remove profiler call in player navigation which broke compatibility with certain plugins

This commit is contained in:
fullwall 2022-12-11 21:28:39 +08:00
parent 5254f65945
commit ab0c706da5
11 changed files with 217 additions and 122 deletions

View File

@ -69,6 +69,7 @@ import net.citizensnpcs.editor.Editor;
import net.citizensnpcs.npc.CitizensNPCRegistry;
import net.citizensnpcs.npc.CitizensTraitFactory;
import net.citizensnpcs.npc.NPCSelector;
import net.citizensnpcs.npc.Template;
import net.citizensnpcs.npc.ai.speech.CitizensSpeechFactory;
import net.citizensnpcs.npc.profile.ProfileFetcher;
import net.citizensnpcs.npc.skin.Skin;
@ -363,6 +364,7 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
locationLookup = null;
enabled = false;
saveOnDisable = true;
Template.shutdown();
NMS.shutdown();
CitizensAPI.shutdown();
}
@ -387,6 +389,7 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
Bukkit.getPluginManager().disablePlugin(this);
return;
}
registerScriptHelpers();
saves = createStorage(getDataFolder());
@ -421,6 +424,7 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
registerCommands();
enableSubPlugins();
NMS.load(commands);
Template.migrate();
Bukkit.getMessenger().registerOutgoingPluginChannel(this, "BungeeCord");
commands.registerTabCompletion(this);
@ -478,6 +482,8 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
shops.loadFromDisk();
shops.load();
Template.shutdown();
getServer().getPluginManager().callEvent(new CitizensReloadEvent());
}

View File

@ -1318,7 +1318,8 @@ public class NPCCommands {
@Flag({ "randomlook", "rlook" }) Boolean randomlook, @Flag("range") Double range,
@Flag("randomlookdelay") Integer randomLookDelay, @Flag("randomyawrange") String randomYaw,
@Flag("randompitchrange") String randomPitch, @Flag("randomswitchtargets") Boolean randomSwitchTargets,
@Flag("disablewhennavigating") Boolean disableWhenNavigating) throws CommandException {
@Flag("disablewhennavigating") Boolean disableWhenNavigating, @Flag("perplayer") Boolean perPlayer)
throws CommandException {
boolean toggle = true;
LookClose trait = npc.getOrAddTrait(LookClose.class);
if (randomlook != null) {
@ -1327,6 +1328,12 @@ public class NPCCommands {
npc.getName());
toggle = false;
}
if (perPlayer != null) {
trait.setPerPlayer(perPlayer);
Messaging.sendTr(sender, perPlayer ? Messages.LOOKCLOSE_PERPLAYER_SET : Messages.LOOKCLOSE_PERPLAYER_UNSET,
npc.getName());
toggle = false;
}
if (randomSwitchTargets != null) {
trait.setRandomlySwitchTargets(randomSwitchTargets);
Messaging.sendTr(sender, randomSwitchTargets ? Messages.LOOKCLOSE_RANDOM_TARGET_SWITCH_ENABLED

View File

@ -1,5 +1,6 @@
package net.citizensnpcs.commands;
import java.io.IOException;
import java.util.List;
import javax.annotation.Nullable;
@ -21,7 +22,6 @@ import net.citizensnpcs.api.command.exception.CommandException;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.util.Messaging;
import net.citizensnpcs.npc.Template;
import net.citizensnpcs.npc.Template.TemplateBuilder;
import net.citizensnpcs.util.Messages;
@Requirements(selected = true, ownership = true)
@ -72,7 +72,7 @@ public class TemplateCommands {
@Command(
aliases = { "template", "tpl" },
usage = "create [template name] (-o)",
usage = "create [template name] (-k)",
desc = "Creates a template from the selected NPC",
modifiers = { "create" },
min = 2,
@ -84,8 +84,12 @@ public class TemplateCommands {
if (Template.byName(name) != null)
throw new CommandException(Messages.TEMPLATE_CONFLICT);
TemplateBuilder.create(name).from(npc).override(args.hasFlag('o')).buildAndSave();
Messaging.sendTr(sender, Messages.TEMPLATE_CREATED);
try {
Template.Builder.create(name).from(npc).override(!args.hasFlag('k')).buildAndSave();
Messaging.sendTr(sender, Messages.TEMPLATE_CREATED);
} catch (IOException e) {
Messaging.sendError(sender, "Invalid template filename");
}
}
@Command(
@ -114,7 +118,7 @@ public class TemplateCommands {
permission = "citizens.templates.list")
public void list(CommandContext args, CommandSender sender, NPC npc) throws CommandException {
Messaging.sendTr(sender, Messages.TEMPLATE_LIST_HEADER);
for (Template template : Template.allTemplates()) {
for (Template template : Template.getTemplates()) {
Messaging.send(sender, "[[-]] " + template.getName());
}
}

View File

@ -1,14 +1,16 @@
package net.citizensnpcs.npc;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.io.Files;
import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.event.DespawnReason;
@ -16,6 +18,7 @@ import net.citizensnpcs.api.event.SpawnReason;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.util.DataKey;
import net.citizensnpcs.api.util.MemoryDataKey;
import net.citizensnpcs.api.util.Messaging;
import net.citizensnpcs.api.util.YamlStorage;
import net.citizensnpcs.api.util.YamlStorage.YamlKey;
@ -60,15 +63,62 @@ public class Template {
}
public void delete() {
templates.load();
templates.getKey("").removeKey(name);
templates.save();
new File(getDirectory(), name + ".yml").delete();
}
public String getName() {
return name;
}
public void save() throws IOException {
File file = new File(getDirectory(), name + ".yml");
if (!file.getParentFile().equals(getDirectory()))
throw new IOException();
try {
file.createNewFile();
} catch (IOException e) {
throw e;
}
YamlStorage storage = new YamlStorage(file);
DataKey root = storage.getKey("");
root.setBoolean("override", override);
root.setRaw("replacements", replacements);
storage.save();
}
public static class Builder {
private final String name;
private boolean override = true;
private final Map<String, Object> replacements = Maps.newHashMap();
private Builder(String name) {
this.name = name;
}
public Template buildAndSave() throws IOException {
Template tpl = new Template(name, replacements, override);
tpl.save();
return tpl;
}
public Builder from(NPC npc) {
replacements.clear();
MemoryDataKey key = new MemoryDataKey();
((CitizensNPC) npc).save(key);
replacements.putAll(key.getValuesDeep());
return this;
}
public Builder override(boolean override) {
this.override = override;
return this;
}
public static Builder create(String name) {
return new Builder(name);
}
}
private static class Node {
String headKey;
Map<String, Object> map;
@ -79,69 +129,62 @@ public class Template {
}
}
public static class TemplateBuilder {
private final String name;
private boolean override;
private final Map<String, Object> replacements = Maps.newHashMap();
private TemplateBuilder(String name) {
this.name = name;
}
public Template buildAndSave() {
save();
return new Template(name, replacements, override);
}
public TemplateBuilder from(NPC npc) {
replacements.clear();
MemoryDataKey key = new MemoryDataKey();
((CitizensNPC) npc).save(key);
replacements.putAll(key.getValuesDeep());
return this;
}
public TemplateBuilder override(boolean override) {
this.override = override;
return this;
}
public void save() {
templates.load();
DataKey root = templates.getKey(name);
root.setBoolean("override", override);
root.setRaw("replacements", replacements);
templates.save();
}
public static TemplateBuilder create(String name) {
return new TemplateBuilder(name);
}
}
public static Iterable<Template> allTemplates() {
templates.load();
return Iterables.transform(templates.getKey("").getSubKeys(), new Function<DataKey, Template>() {
@Override
public Template apply(DataKey arg0) {
return Template.byName(arg0.name());
}
});
}
public static Template byName(String name) {
templates.load();
if (!templates.getKey("").keyExists(name))
if (TEMPLATES.containsKey(name))
return TEMPLATES.get(name);
File file = new File(getDirectory(), name + ".yml");
if (!file.exists() || !file.getParentFile().equals(getDirectory()))
return null;
YamlKey key = templates.getKey(name);
boolean override = key.getBoolean("override", false);
YamlStorage storage = new YamlStorage(file);
storage.load();
YamlKey key = storage.getKey("");
boolean override = key.getBoolean("override", true);
Map<String, Object> replacements = key.getRelative("replacements").getValuesDeep();
return new Template(name, replacements, override);
Template res = new Template(name, replacements, override);
TEMPLATES.put(name, res);
return res;
}
private static YamlStorage templates = new YamlStorage(new File(CitizensAPI.getDataFolder(), "templates.yml"));
static {
templates.load();
private static File getDirectory() {
return new File(CitizensAPI.getDataFolder(), "templates");
}
public static Iterable<Template> getTemplates() {
return Arrays.asList(getDirectory().list()).stream().map(f -> new File(getDirectory(), f))
.filter(f -> !f.isDirectory() && Files.getFileExtension(f.getName()).equals(".yml"))
.map(f -> byName(Files.getNameWithoutExtension(f.getName()))).collect(Collectors.toList());
}
public static void migrate() {
File folder = getDirectory();
if (!folder.exists()) {
folder.mkdir();
}
File from = new File(CitizensAPI.getDataFolder(), "templates.yml");
if (from.exists()) {
YamlStorage storage = new YamlStorage(from);
storage.load();
for (DataKey key : storage.getKey("").getSubKeys()) {
String name = key.name();
Map<String, Object> replacements = key.getRelative("replacements").getValuesDeep();
boolean override = key.getBoolean("override", true);
try {
new Template(name, replacements, override).save();
} catch (IOException e) {
Messaging.severe("Unable to migrate template", name, "due to invalid filename");
}
}
try {
Files.move(from, new File(CitizensAPI.getDataFolder(), "templates_migrated.yml"));
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void shutdown() {
TEMPLATES.clear();
}
private static Map<String, Template> TEMPLATES = Maps.newHashMap();
}

View File

@ -1,7 +1,9 @@
package net.citizensnpcs.trait;
import java.util.List;
import java.util.Random;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
@ -12,6 +14,8 @@ import org.bukkit.metadata.MetadataValue;
import org.bukkit.potion.PotionEffectType;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import net.citizensnpcs.Settings.Setting;
import net.citizensnpcs.api.CitizensAPI;
@ -20,6 +24,8 @@ import net.citizensnpcs.api.persistence.Persist;
import net.citizensnpcs.api.trait.Trait;
import net.citizensnpcs.api.trait.TraitName;
import net.citizensnpcs.api.util.DataKey;
import net.citizensnpcs.trait.RotationTrait.PacketRotationSession;
import net.citizensnpcs.trait.RotationTrait.RotationParams;
import net.citizensnpcs.util.NMS;
import net.citizensnpcs.util.Util;
@ -36,6 +42,8 @@ public class LookClose extends Trait implements Toggleable {
@Persist
private boolean enableRandomLook = Setting.DEFAULT_RANDOM_LOOK_CLOSE.asBoolean();
private Player lookingAt;
@Persist("perplayer")
private boolean perPlayer;
@Persist
private int randomLookDelay = Setting.DEFAULT_RANDOM_LOOK_DELAY.asInt();
@Persist
@ -47,6 +55,7 @@ public class LookClose extends Trait implements Toggleable {
private double range = Setting.DEFAULT_LOOK_CLOSE_RANGE.asDouble();
@Persist("realisticlooking")
private boolean realisticLooking = Setting.DEFAULT_REALISTIC_LOOKING.asBoolean();
private final Map<UUID, PacketRotationSession> sessions = Maps.newHashMapWithExpectedSize(4);
private int t;
public LookClose() {
@ -77,6 +86,29 @@ public class LookClose extends Trait implements Toggleable {
* Finds a new look-close target
*/
public void findNewTarget() {
if (perPlayer) {
lookingAt = null;
List<Player> nearbyPlayers = getNearbyPlayers();
Set<UUID> seen = Sets.newHashSet();
for (Player player : nearbyPlayers) {
PacketRotationSession session = sessions.get(player.getUniqueId());
if (session == null) {
sessions.put(player.getUniqueId(), session = npc.getOrAddTrait(RotationTrait.class)
.createPacketSession(new RotationParams().uuidFilter(player.getUniqueId()).persist(true)));
}
session.getSession().rotateToFace(player);
seen.add(player.getUniqueId());
}
for (UUID uuid : Sets.newHashSet(Sets.difference(sessions.keySet(), seen))) {
sessions.remove(uuid).end();
}
} else if (sessions.size() > 0) {
for (PacketRotationSession session : sessions.values()) {
session.end();
}
sessions.clear();
}
if (lookingAt != null && !isValid(lookingAt)) {
NPCLookCloseChangeTargetEvent event = new NPCLookCloseChangeTargetEvent(npc, lookingAt, null);
Bukkit.getPluginManager().callEvent(event);
@ -90,16 +122,7 @@ public class LookClose extends Trait implements Toggleable {
Player old = lookingAt;
if (lookingAt != null) {
if (randomSwitchTargets && t <= 0) {
List<Player> options = Lists.newArrayList();
for (Player player : CitizensAPI.getLocationLookup().getNearbyPlayers(npc.getEntity().getLocation(),
range)) {
if (player == lookingAt || CitizensAPI.getNPCRegistry().getNPC(player) != null) {
continue;
}
if (player.getLocation().getWorld() != NPC_LOCATION.getWorld() || isInvisible(player))
continue;
options.add(player);
}
List<Player> options = getNearbyPlayers();
if (options.size() > 0) {
lookingAt = options.get(Util.getFastRandom().nextInt(options.size()));
t = randomLookDelay;
@ -107,8 +130,7 @@ public class LookClose extends Trait implements Toggleable {
}
} else {
double min = range;
for (Player player : CitizensAPI.getLocationLookup().getNearbyPlayers(npc.getEntity().getLocation(),
range)) {
for (Player player : CitizensAPI.getLocationLookup().getNearbyPlayers(NPC_LOCATION, range)) {
Location location = player.getLocation(CACHE_LOCATION);
if (location.getWorld() != NPC_LOCATION.getWorld())
continue;
@ -130,6 +152,19 @@ public class LookClose extends Trait implements Toggleable {
}
}
private List<Player> getNearbyPlayers() {
List<Player> options = Lists.newArrayList();
for (Player player : CitizensAPI.getLocationLookup().getNearbyPlayers(NPC_LOCATION, range)) {
if (player == lookingAt || CitizensAPI.getNPCRegistry().getNPC(player) != null) {
continue;
}
if (player.getLocation().getWorld() != NPC_LOCATION.getWorld() || isInvisible(player))
continue;
options.add(player);
}
return options;
}
public int getRandomLookDelay() {
return randomLookDelay;
}
@ -202,12 +237,11 @@ public class LookClose extends Trait implements Toggleable {
}
private void randomLook() {
Random rand = new Random();
float pitch = isEqual(randomPitchRange) ? randomPitchRange[0]
: rand.doubles(randomPitchRange[0], randomPitchRange[1]).iterator().next().floatValue();
: Util.getFastRandom().doubles(randomPitchRange[0], randomPitchRange[1]).iterator().next().floatValue();
float yaw = isEqual(randomYawRange) ? randomYawRange[0]
: rand.doubles(randomYawRange[0], randomYawRange[1]).iterator().next().floatValue();
Util.face(npc.getEntity(), yaw, pitch);
: Util.getFastRandom().doubles(randomYawRange[0], randomYawRange[1]).iterator().next().floatValue();
npc.getOrAddTrait(RotationTrait.class).getPhysicalSession().rotateToHave(yaw, pitch);
}
@Override
@ -259,6 +293,10 @@ public class LookClose extends Trait implements Toggleable {
disableWhileNavigating = set;
}
public void setPerPlayer(boolean perPlayer) {
this.perPlayer = perPlayer;
}
/**
* Enables random looking - will look at a random {@link Location} every so often if enabled.
*/

View File

@ -105,13 +105,13 @@ public class RotationTrait extends Trait {
if (!npc.isSpawned())
return;
Set<PacketRotationSession> run = Sets.newHashSet();
Set<PacketRotationSession> ran = Sets.newHashSet();
for (Iterator<PacketRotationSession> itr = Iterables.concat(packetSessions, packetSessionsByUUID.values())
.iterator(); itr.hasNext();) {
PacketRotationSession session = itr.next();
if (run.contains(session))
if (ran.contains(session))
continue;
run.add(session);
ran.add(session);
session.run(npc.getEntity());
if (!session.isActive()) {
itr.remove();

View File

@ -228,10 +228,7 @@ public class ShopTrait extends Trait {
});
edit.setItemStack(new ItemStack(Material.BOOK), "Edit page");
edit.setClickHandler(evt -> {
evt.setCancelled(true);
ctx.getMenu().transition(new NPCShopPageSettings(shop.getOrCreatePage(page)));
});
edit.setClickHandler(evt -> ctx.getMenu().transition(new NPCShopPageSettings(shop.getOrCreatePage(page))));
}
@Override
@ -252,6 +249,8 @@ public class ShopTrait extends Trait {
@Persist
private ItemStack display;
@Persist
private String message;
@Persist
private final List<NPCShopAction> result = Lists.newArrayList();
private void changeAction(List<NPCShopAction> source, Function<NPCShopAction, Boolean> filter,
@ -334,17 +333,20 @@ public class ShopTrait extends Trait {
if (execute(result, action -> action.grant(event.getWhoClicked())) == null) {
take.forEach(a -> a.rollback());
}
if (message != null) {
Messaging.sendColorless(event.getWhoClicked(), message);
}
}
}
@Menu(title = "NPC Shop Item Editor", type = InventoryType.CHEST, dimensions = { 6, 9 })
@MenuSlot(slot = { 3, 4 }, material = Material.DISPENSER, amount = 1, title = "<f>Place display item below")
public static class NPCShopItemEditor extends InventoryMenuPage {
@MenuPattern(
offset = { 0, 6 },
slots = { @MenuSlot(pat = 'x', material = Material.AIR) },
value = "x x\n x \nx x")
private InventoryMenuPattern actionItems;
private NPCShopItem base;
private final Consumer<NPCShopItem> callback;
@MenuPattern(
offset = { 0, 0 },
@ -353,11 +355,10 @@ public class ShopTrait extends Trait {
private InventoryMenuPattern costItems;
private MenuContext ctx;
private final NPCShopItem modified;
private NPCShopItem original;
public NPCShopItemEditor(NPCShopItem item, Consumer<NPCShopItem> consumer) {
this.original = item;
this.modified = original.clone();
this.base = item;
this.modified = base.clone();
this.callback = consumer;
}
@ -367,6 +368,13 @@ public class ShopTrait extends Trait {
if (modified.display != null) {
ctx.getSlot(9 * 4 + 4).setItemStack(modified.display);
}
ctx.getSlot(9 * 3 + 4).setItemStack(new ItemStack(Util.getFallbackMaterial("OAK_SIGN", "SIGN")),
"Set message to send on click, currently:", modified.message);
ctx.getSlot(9 * 3 + 4).setClickHandler(
e -> ctx.getMenu().transition(InputMenus.stringSetter(() -> modified.message, s -> {
modified.message = s;
ctx.getSlot(9 * 3 + 4).setDescription(modified.message);
})));
int pos = 0;
for (GUI template : NPCShopAction.getGUIs()) {
if (template.createMenuItem(null) == null)
@ -390,16 +398,15 @@ public class ShopTrait extends Trait {
@MenuSlot(slot = { 5, 3 }, material = Material.REDSTONE_BLOCK, amount = 1, title = "<7>Cancel")
public void onCancel(InventoryMenuSlot slot, CitizensInventoryClickEvent event) {
event.setCancelled(true);
ctx.getMenu().transitionBack();
}
@Override
public void onClose(HumanEntity who) {
if (original != null && original.display == null) {
original = null;
if (base != null && base.display == null) {
base = null;
}
callback.accept(original);
callback.accept(base);
}
@MenuSlot(slot = { 4, 5 }, material = Material.BOOK, amount = 1, title = "<f>Set description")
@ -444,15 +451,13 @@ public class ShopTrait extends Trait {
@MenuSlot(slot = { 5, 4 }, material = Material.TNT, amount = 1, title = "<c>Remove")
public void onRemove(InventoryMenuSlot slot, CitizensInventoryClickEvent event) {
original = null;
event.setCancelled(true);
base = null;
ctx.getMenu().transitionBack();
}
@MenuSlot(slot = { 5, 5 }, material = Material.EMERALD_BLOCK, amount = 1, title = "<a>Save")
public void onSave(InventoryMenuSlot slot, CitizensInventoryClickEvent event) {
original = modified;
event.setCancelled(true);
base = modified;
ctx.getMenu().transitionBack();
}
}
@ -496,7 +501,6 @@ public class ShopTrait extends Trait {
@MenuSlot(slot = { 0, 4 }, material = Material.FEATHER, amount = 1)
public void editPageTitle(InventoryMenuSlot slot, CitizensInventoryClickEvent event) {
event.setCancelled(true);
ctx.getMenu().transition(InputMenus.stringSetter(() -> page.title, newTitle -> {
page.title = newTitle.isEmpty() ? null : newTitle;
}));
@ -510,7 +514,6 @@ public class ShopTrait extends Trait {
@MenuSlot(slot = { 4, 4 }, material = Material.TNT, amount = 1, title = "<c>Remove page")
public void removePage(InventoryMenuSlot slot, CitizensInventoryClickEvent event) {
event.setCancelled(true);
ctx.data().put("removePage", page.index);
ctx.getMenu().transitionBack();
}
@ -538,19 +541,16 @@ public class ShopTrait extends Trait {
@MenuSlot(slot = { 0, 4 }, material = Material.FEATHER, amount = 1, title = "<f>Edit shop items")
public void onEditItems(InventoryMenuSlot slot, CitizensInventoryClickEvent event) {
event.setCancelled(true);
ctx.getMenu().transition(new NPCShopContentsEditor(shop));
}
@MenuSlot(slot = { 0, 2 }, material = Material.OAK_SIGN, amount = 1)
public void onPermissionChange(InventoryMenuSlot slot, CitizensInventoryClickEvent event) {
event.setCancelled(true);
ctx.getMenu().transition(InputMenus.stringSetter(shop::getRequiredPermission, shop::setPermission));
}
@MenuSlot(slot = { 0, 6 }, material = Material.NAME_TAG, amount = 1)
public void onSetTitle(InventoryMenuSlot slot, CitizensInventoryClickEvent event) {
event.setCancelled(true);
ctx.getMenu().transition(InputMenus.stringSetter(() -> shop.title, newTitle -> {
shop.title = newTitle.isEmpty() ? null : newTitle;
}));
@ -558,7 +558,6 @@ public class ShopTrait extends Trait {
@MenuSlot(slot = { 0, 0 }, material = Material.BOOK, amount = 1, title = "<f>Edit shop type")
public void onShopTypeChange(InventoryMenuSlot slot, CitizensInventoryClickEvent event) {
event.setCancelled(true);
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),

View File

@ -212,6 +212,8 @@ public class Messages {
public static final String LOCALE_NOTIFICATION = "citizens.notifications.locale";
public static final String LOOKCLOSE_DISABLE_WHEN_NAVIGATING = "citizens.commands.npc.lookclose.disable-when-navigating";
public static final String LOOKCLOSE_ENABLE_WHEN_NAVIGATING = "citizens.commands.npc.lookclose.enable-when-navigating";
public static final String LOOKCLOSE_PERPLAYER_SET = "citizens.commands.npc.lookclose.perplayer-set";
public static final String LOOKCLOSE_PERPLAYER_UNSET = "citizens.commands.npc.lookclose.perplayer-unset";
public static final String LOOKCLOSE_RANDOM_DELAY_SET = "citizens.commands.npc.lookclose.random-look-delay-set";
public static final String LOOKCLOSE_RANDOM_PITCH_RANGE_SET = "citizens.commands.npc.lookclose.random-pitch-range-set";
public static final String LOOKCLOSE_RANDOM_SET = "citizens.commands.npc.lookclose.random-set";

View File

@ -148,6 +148,8 @@ citizens.commands.npc.lookclose.random-pitch-range-set=[[{0}]] will now randomly
citizens.commands.npc.lookclose.random-yaw-range-set=[[{0}]] will now randomly choose a yaw in the range [{1}].
citizens.commands.npc.lookclose.random-set=[[{0}]] will now randomly look around.
citizens.commands.npc.lookclose.random-stopped=[[{0}]] will no longer randomly look around.
citizens.commands.npc.lookclose.perplayer-unset=[[{0}]] will no longer use per player looking.
citizens.commands.npc.lookclose.perplayer-set=[[{0}]] will now use per player looking.
citizens.commands.npc.lookclose.error-random-range=Invalid range [[{0}]]. Use the format `min,max`.
citizens.commands.npc.lookclose.set=[[{0}]] will now rotate when players are nearby.
citizens.commands.npc.lookclose.enable-when-navigating=[[{0}]] will now look close when navigating.
@ -295,7 +297,7 @@ citizens.commands.script.compiling=Script compiling...
citizens.commands.script.file-missing=The file [[{0}]] doesn''t exist!
citizens.commands.template.applied=Template applied to [[{0}]] NPCs.
citizens.commands.template.conflict=A template by that name already exists.
citizens.commands.template.created=Template created.
citizens.commands.template.created=Template created. Check your Citizens plugin folder.
citizens.commands.template.missing=Template not found.
citizens.commands.template.delete.deleted=Deleted template [[{0}]].
citizens.commands.template.list.header=]]Available templates[[:]]

View File

@ -148,7 +148,7 @@ public class PlayerNavigation extends PathNavigation {
}
return true;
}
private boolean canWalkOn(int var0, int var1, int var2, int var3, int var4, int var5, Vec3 var6, double var7,
double var9) {
int var11 = var0 - var3 / 2;
@ -226,13 +226,11 @@ public class PlayerNavigation extends PathNavigation {
return null;
if (this.path != null && !this.path.isDone() && var0.contains(this.targetPos))
return this.path;
this.level.getProfiler().push("pathfind");
BlockPos var5 = var2 ? this.mob.blockPosition().above() : this.mob.blockPosition();
int var6 = (int) (var4 + var1);
PathNavigationRegion var7 = new PathNavigationRegion(this.level, var5.offset(-var6, -var6, -var6),
var5.offset(var6, var6, var6));
Path var8 = this.pathFinder.findPath(var7, this.mob, var0, var4, var3, this.maxVisitedNodesMultiplier);
this.level.getProfiler().pop();
if (var8 != null && var8.getTarget() != null) {
this.targetPos = var8.getTarget();
this.reachRange = var3;

View File

@ -16,7 +16,6 @@ import net.citizensnpcs.Settings.Setting;
import net.citizensnpcs.nms.v1_19_R2.entity.EntityHumanNPC;
import net.minecraft.core.BlockPos;
import net.minecraft.util.profiling.ProfilerFiller;
import net.minecraft.util.profiling.metrics.MetricCategory;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.level.PathNavigationRegion;
import net.minecraft.world.level.pathfinder.BinaryHeap;
@ -45,7 +44,7 @@ public class PlayerPathfinder extends PathFinder {
Node var6 = this.nodeEvaluator.getStart();
Map<Target, BlockPos> var7 = var2.stream().collect(
Collectors.toMap(p -> this.nodeEvaluator.getGoal(p.getX(), p.getY(), p.getZ()), Function.identity()));
Path var8 = findPath(var0.getProfiler(), var6, var7, var3, var4, var5);
Path var8 = findPath(null, var6, var7, var3, var4, var5);
this.nodeEvaluator.done();
return var8;
}
@ -57,15 +56,13 @@ public class PlayerPathfinder extends PathFinder {
Node var6 = this.nodeEvaluator.getStart();
Map<Target, BlockPos> var7 = var2.stream().collect(
Collectors.toMap(p -> this.nodeEvaluator.getGoal(p.getX(), p.getY(), p.getZ()), Function.identity()));
Path var8 = findPath(var0.getProfiler(), var6, var7, var3, var4, var5);
Path var8 = findPath(null, var6, var7, var3, var4, var5);
this.nodeEvaluator.done();
return var8;
}
private Path findPath(ProfilerFiller var0, Node var1, Map<Target, BlockPos> var2, float var3, int var4,
float var5) {
var0.push("find_path");
var0.markForCharting(MetricCategory.PATH_FINDING);
Set<Target> var6 = var2.keySet();
var1.g = 0.0F;
var1.h = getBestH(var1, var6);
@ -111,7 +108,6 @@ public class PlayerPathfinder extends PathFinder {
? var9.stream().map(p -> reconstructPath(p.getBestNode(), var2.get(p), true)).min(
Comparator.comparingInt(Path::getNodeCount))
: getFallbackDestinations(var2, var6).findFirst();
var0.pop();
if (!var11.isPresent())
return null;
Path var12 = var11.get();