mirror of
https://github.com/FancyInnovations/FancyPlugins.git
synced 2025-12-06 07:43:36 +00:00
fancynpcs: add turn_to_player_distance and center commands
Co-authored-by: Sadat Sahib <58975768+ssquadteam@users.noreply.github.com>
This commit is contained in:
@@ -20,6 +20,14 @@ public interface FancyNpcsConfig {
|
|||||||
int getNpcUpdateVisibilityInterval();
|
int getNpcUpdateVisibilityInterval();
|
||||||
|
|
||||||
int getTurnToPlayerDistance();
|
int getTurnToPlayerDistance();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the distance at which NPCs turn to the player.
|
||||||
|
*
|
||||||
|
* @param distance The new distance value
|
||||||
|
* @return true if the distance was updated successfully, false otherwise
|
||||||
|
*/
|
||||||
|
boolean setTurnToPlayerDistance(int distance);
|
||||||
|
|
||||||
boolean isTurnToPlayerResetToInitialDirection();
|
boolean isTurnToPlayerResetToInitialDirection();
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ public class NpcData {
|
|||||||
private Consumer<Player> onClick;
|
private Consumer<Player> onClick;
|
||||||
private Map<ActionTrigger, List<NpcAction.NpcActionData>> actions;
|
private Map<ActionTrigger, List<NpcAction.NpcActionData>> actions;
|
||||||
private boolean turnToPlayer;
|
private boolean turnToPlayer;
|
||||||
|
private int turnToPlayerDistance = -1; // -1 means use the default from config
|
||||||
private float interactionCooldown;
|
private float interactionCooldown;
|
||||||
private float scale;
|
private float scale;
|
||||||
private int visibilityDistance;
|
private int visibilityDistance;
|
||||||
@@ -57,6 +58,7 @@ public class NpcData {
|
|||||||
EntityType type,
|
EntityType type,
|
||||||
Map<NpcEquipmentSlot, ItemStack> equipment,
|
Map<NpcEquipmentSlot, ItemStack> equipment,
|
||||||
boolean turnToPlayer,
|
boolean turnToPlayer,
|
||||||
|
int turnToPlayerDistance,
|
||||||
Consumer<Player> onClick,
|
Consumer<Player> onClick,
|
||||||
Map<ActionTrigger, List<NpcAction.NpcActionData>> actions,
|
Map<ActionTrigger, List<NpcAction.NpcActionData>> actions,
|
||||||
float interactionCooldown,
|
float interactionCooldown,
|
||||||
@@ -81,6 +83,7 @@ public class NpcData {
|
|||||||
this.onClick = onClick;
|
this.onClick = onClick;
|
||||||
this.actions = actions;
|
this.actions = actions;
|
||||||
this.turnToPlayer = turnToPlayer;
|
this.turnToPlayer = turnToPlayer;
|
||||||
|
this.turnToPlayerDistance = turnToPlayerDistance;
|
||||||
this.interactionCooldown = interactionCooldown;
|
this.interactionCooldown = interactionCooldown;
|
||||||
this.scale = scale;
|
this.scale = scale;
|
||||||
this.visibilityDistance = visibilityDistance;
|
this.visibilityDistance = visibilityDistance;
|
||||||
@@ -108,6 +111,7 @@ public class NpcData {
|
|||||||
};
|
};
|
||||||
this.actions = new ConcurrentHashMap<>();
|
this.actions = new ConcurrentHashMap<>();
|
||||||
this.turnToPlayer = false;
|
this.turnToPlayer = false;
|
||||||
|
this.turnToPlayerDistance = -1; // Use default from config
|
||||||
this.interactionCooldown = 0;
|
this.interactionCooldown = 0;
|
||||||
this.scale = 1;
|
this.scale = 1;
|
||||||
this.visibilityDistance = -1;
|
this.visibilityDistance = -1;
|
||||||
@@ -321,6 +325,27 @@ public class NpcData {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the turn-to-player distance for this NPC.
|
||||||
|
*
|
||||||
|
* @return the custom distance value, or -1 if using the default from config
|
||||||
|
*/
|
||||||
|
public int getTurnToPlayerDistance() {
|
||||||
|
return turnToPlayerDistance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the turn-to-player distance for this NPC.
|
||||||
|
*
|
||||||
|
* @param distance the custom distance value, or -1 to use the default from config
|
||||||
|
* @return this NpcData instance for method chaining
|
||||||
|
*/
|
||||||
|
public NpcData setTurnToPlayerDistance(int distance) {
|
||||||
|
this.turnToPlayerDistance = distance;
|
||||||
|
isDirty = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public float getInteractionCooldown() {
|
public float getInteractionCooldown() {
|
||||||
return interactionCooldown;
|
return interactionCooldown;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ public class NpcModifyEvent extends Event implements Cancellable {
|
|||||||
SHOW_IN_TAB,
|
SHOW_IN_TAB,
|
||||||
SKIN,
|
SKIN,
|
||||||
TURN_TO_PLAYER,
|
TURN_TO_PLAYER,
|
||||||
|
TURN_TO_PLAYER_DISTANCE,
|
||||||
TYPE,
|
TYPE,
|
||||||
// Messages.
|
// Messages.
|
||||||
MESSAGE_ADD,
|
MESSAGE_ADD,
|
||||||
|
|||||||
@@ -205,6 +205,24 @@ public class FancyNpcsConfigImpl implements FancyNpcsConfig {
|
|||||||
return turnToPlayerDistance;
|
return turnToPlayerDistance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setTurnToPlayerDistance(int distance) {
|
||||||
|
// Validate the input - ensure the distance is positive or -1 for default
|
||||||
|
if (distance <= 0 && distance != -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the config value in memory
|
||||||
|
this.turnToPlayerDistance = distance;
|
||||||
|
|
||||||
|
// Persist to config file
|
||||||
|
FileConfiguration config = FancyNpcs.getInstance().getConfig();
|
||||||
|
config.set("turn_to_player_distance", distance);
|
||||||
|
FancyNpcs.getInstance().saveConfig();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public int getVisibilityDistance() {
|
public int getVisibilityDistance() {
|
||||||
return visibilityDistance;
|
return visibilityDistance;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -393,6 +393,8 @@ public class NpcManagerImpl implements NpcManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int turnToPlayerDistance = (int) npcConfig.getDouble("npcs." + id + ".turnToPlayerDistance", 0);
|
||||||
|
|
||||||
NpcData data = new NpcData(
|
NpcData data = new NpcData(
|
||||||
id,
|
id,
|
||||||
name,
|
name,
|
||||||
@@ -408,6 +410,7 @@ public class NpcManagerImpl implements NpcManager {
|
|||||||
type,
|
type,
|
||||||
new HashMap<>(),
|
new HashMap<>(),
|
||||||
turnToPlayer,
|
turnToPlayer,
|
||||||
|
turnToPlayerDistance,
|
||||||
null,
|
null,
|
||||||
actions,
|
actions,
|
||||||
interactionCooldown,
|
interactionCooldown,
|
||||||
@@ -472,4 +475,4 @@ public class NpcManagerImpl implements NpcManager {
|
|||||||
logger.error("Could not save backup file for NPCs");
|
logger.error("Could not save backup file for NPCs");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -167,6 +167,7 @@ public final class CloudCommandManager {
|
|||||||
*/
|
*/
|
||||||
public @NotNull CloudCommandManager registerCommands() {
|
public @NotNull CloudCommandManager registerCommands() {
|
||||||
annotationParser.parse(AttributeCMD.INSTANCE);
|
annotationParser.parse(AttributeCMD.INSTANCE);
|
||||||
|
annotationParser.parse(CenterCMD.INSTANCE);
|
||||||
annotationParser.parse(CollidableCMD.INSTANCE);
|
annotationParser.parse(CollidableCMD.INSTANCE);
|
||||||
annotationParser.parse(CopyCMD.INSTANCE);
|
annotationParser.parse(CopyCMD.INSTANCE);
|
||||||
annotationParser.parse(CreateCMD.INSTANCE);
|
annotationParser.parse(CreateCMD.INSTANCE);
|
||||||
@@ -187,6 +188,7 @@ public final class CloudCommandManager {
|
|||||||
annotationParser.parse(SkinCMD.INSTANCE);
|
annotationParser.parse(SkinCMD.INSTANCE);
|
||||||
annotationParser.parse(TeleportCMD.INSTANCE);
|
annotationParser.parse(TeleportCMD.INSTANCE);
|
||||||
annotationParser.parse(TurnToPlayerCMD.INSTANCE);
|
annotationParser.parse(TurnToPlayerCMD.INSTANCE);
|
||||||
|
annotationParser.parse(TurnToPlayerDistanceCMD.INSTANCE);
|
||||||
annotationParser.parse(TypeCMD.INSTANCE);
|
annotationParser.parse(TypeCMD.INSTANCE);
|
||||||
annotationParser.parse(ActionCMD.INSTANCE);
|
annotationParser.parse(ActionCMD.INSTANCE);
|
||||||
annotationParser.parse(VisibilityDistanceCMD.INSTANCE);
|
annotationParser.parse(VisibilityDistanceCMD.INSTANCE);
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ public enum CopyCMD {
|
|||||||
npc.getData().getType(),
|
npc.getData().getType(),
|
||||||
new ConcurrentHashMap<>(npc.getData().getEquipment()),
|
new ConcurrentHashMap<>(npc.getData().getEquipment()),
|
||||||
npc.getData().isTurnToPlayer(),
|
npc.getData().isTurnToPlayer(),
|
||||||
|
npc.getData().getTurnToPlayerDistance(),
|
||||||
npc.getData().getOnClick(),
|
npc.getData().getOnClick(),
|
||||||
new ConcurrentHashMap<>(npc.getData().getActions()),
|
new ConcurrentHashMap<>(npc.getData().getActions()),
|
||||||
npc.getData().getInteractionCooldown(),
|
npc.getData().getInteractionCooldown(),
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import de.oliver.fancynpcs.api.events.NpcModifyEvent;
|
|||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.incendo.cloud.annotations.Command;
|
import org.incendo.cloud.annotations.Command;
|
||||||
import org.incendo.cloud.annotations.Permission;
|
import org.incendo.cloud.annotations.Permission;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@@ -23,14 +22,21 @@ public enum TurnToPlayerCMD {
|
|||||||
final @NotNull Npc npc,
|
final @NotNull Npc npc,
|
||||||
final @Nullable Boolean state
|
final @Nullable Boolean state
|
||||||
) {
|
) {
|
||||||
final boolean finalState = (state == null) ? !npc.getData().isTurnToPlayer() : state;
|
if (state != null && npc.getData().isTurnToPlayer() != state) {
|
||||||
// Calling the event and updating the state if not cancelled.
|
if (new NpcModifyEvent(npc, NpcModifyEvent.NpcModification.TURN_TO_PLAYER, state, sender).callEvent()) {
|
||||||
if (new NpcModifyEvent(npc, NpcModifyEvent.NpcModification.TURN_TO_PLAYER, finalState, sender).callEvent()) {
|
npc.getData().setTurnToPlayer(state);
|
||||||
npc.getData().setTurnToPlayer(finalState);
|
translator.translate(state ? "npc_turn_to_player_set_true" : "npc_turn_to_player_set_false")
|
||||||
translator.translate(finalState ? "npc_turn_to_player_set_true" : "npc_turn_to_player_set_false").replace("npc", npc.getData().getName()).send(sender);
|
.replace("npc", npc.getData().getName())
|
||||||
return;
|
.send(sender);
|
||||||
|
} else {
|
||||||
|
translator.translate("command_npc_modification_cancelled").send(sender);
|
||||||
|
}
|
||||||
|
} else if (state == null) {
|
||||||
|
// If no state provided, just display current state
|
||||||
|
boolean currentState = npc.getData().isTurnToPlayer();
|
||||||
|
translator.translate(currentState ? "npc_turn_to_player_status_true" : "npc_turn_to_player_status_false")
|
||||||
|
.replace("npc", npc.getData().getName())
|
||||||
|
.send(sender);
|
||||||
}
|
}
|
||||||
translator.translate("command_npc_modification_cancelled").send(sender);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public class TurnToPlayerTracker implements Runnable {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Collection<Npc> npcs = FancyNpcs.getInstance().getNpcManagerImpl().getAllNpcs();
|
Collection<Npc> npcs = FancyNpcs.getInstance().getNpcManagerImpl().getAllNpcs();
|
||||||
int turnToPlayerDistance = FancyNpcs.getInstance().getFancyNpcConfig().getTurnToPlayerDistance();
|
int defaultTurnToPlayerDistance = FancyNpcs.getInstance().getFancyNpcConfig().getTurnToPlayerDistance();
|
||||||
|
|
||||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||||
Location playerLocation = player.getLocation();
|
Location playerLocation = player.getLocation();
|
||||||
@@ -33,8 +33,12 @@ public class TurnToPlayerTracker implements Runnable {
|
|||||||
if (Double.isNaN(distance)) {
|
if (Double.isNaN(distance)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get NPC-specific turn distance or fall back to default
|
||||||
|
int npcTurnDistance = npcData.getTurnToPlayerDistance();
|
||||||
|
int effectiveTurnDistance = (npcTurnDistance == -1) ? defaultTurnToPlayerDistance : npcTurnDistance;
|
||||||
|
|
||||||
if (npcData.isTurnToPlayer() && distance < turnToPlayerDistance) {
|
if (npcData.isTurnToPlayer() && distance < effectiveTurnDistance) {
|
||||||
Location newLoc = playerLocation.clone();
|
Location newLoc = playerLocation.clone();
|
||||||
newLoc.setDirection(newLoc.subtract(npcLocation).toVector());
|
newLoc.setDirection(newLoc.subtract(npcLocation).toVector());
|
||||||
npc.lookAt(player, newLoc);
|
npc.lookAt(player, newLoc);
|
||||||
|
|||||||
@@ -107,6 +107,7 @@ messages:
|
|||||||
npc_action_set: "<dark_gray>› <gray>Syntax: {primaryColor}/npc action {secondaryColor}(npc) (trigger) {primaryColor}set {secondaryColor}(index) (type) [value]"
|
npc_action_set: "<dark_gray>› <gray>Syntax: {primaryColor}/npc action {secondaryColor}(npc) (trigger) {primaryColor}set {secondaryColor}(index) (type) [value]"
|
||||||
npc_attribute: "<dark_gray>› <gray>Syntax: {primaryColor}/npc attribute {secondaryColor}(npc) {primaryColor}(set | list)"
|
npc_attribute: "<dark_gray>› <gray>Syntax: {primaryColor}/npc attribute {secondaryColor}(npc) {primaryColor}(set | list)"
|
||||||
npc_attribute_set: "<dark_gray>› <gray>Syntax: {primaryColor}/npc attribute {secondaryColor}(npc) {primaryColor}set {secondaryColor}(attribute) (value)"
|
npc_attribute_set: "<dark_gray>› <gray>Syntax: {primaryColor}/npc attribute {secondaryColor}(npc) {primaryColor}set {secondaryColor}(attribute) (value)"
|
||||||
|
npc_center: "<dark_gray>› <gray>Syntax: {primaryColor}/npc center {secondaryColor}(npc)"
|
||||||
npc_collidable: "<dark_gray>› <gray>Syntax: {primaryColor}/npc collidable {secondaryColor}(npc) (state)"
|
npc_collidable: "<dark_gray>› <gray>Syntax: {primaryColor}/npc collidable {secondaryColor}(npc) (state)"
|
||||||
npc_copy: "<dark_gray>› <gray>Syntax: {primaryColor}/npc copy {secondaryColor}(npc) (new_name)"
|
npc_copy: "<dark_gray>› <gray>Syntax: {primaryColor}/npc copy {secondaryColor}(npc) (new_name)"
|
||||||
npc_create: "<dark_gray>› <gray>Syntax: {primaryColor}/npc create {secondaryColor}(npc) [--type] [--position] [--world]"
|
npc_create: "<dark_gray>› <gray>Syntax: {primaryColor}/npc create {secondaryColor}(npc) [--type] [--position] [--world]"
|
||||||
@@ -125,7 +126,7 @@ messages:
|
|||||||
npc_show_in_tab: "<dark_gray>› <gray>Syntax: {primaryColor}/npc show_in_tab {secondaryColor}(npc) (state)"
|
npc_show_in_tab: "<dark_gray>› <gray>Syntax: {primaryColor}/npc show_in_tab {secondaryColor}(npc) (state)"
|
||||||
npc_skin: "<dark_gray>› <gray>Syntax: {primaryColor}/npc skin {secondaryColor}(npc) (@none | @mirror | name | uuid | placeholder | url | file name) [--slim]"
|
npc_skin: "<dark_gray>› <gray>Syntax: {primaryColor}/npc skin {secondaryColor}(npc) (@none | @mirror | name | uuid | placeholder | url | file name) [--slim]"
|
||||||
npc_teleport: "<dark_gray>› <gray>Syntax: {primaryColor}/npc teleport {secondaryColor}(npc)"
|
npc_teleport: "<dark_gray>› <gray>Syntax: {primaryColor}/npc teleport {secondaryColor}(npc)"
|
||||||
npc_turn_to_player: "<dark_gray>› <gray>Syntax: {primaryColor}/npc turn_to_player {secondaryColor}(npc) (state)"
|
npc_turn_to_player: "<dark_gray>› <gray>Syntax: {primaryColor}/npc turn_to_player {secondaryColor}(npc) (state) [distance]"
|
||||||
npc_type: "<dark_gray>› <gray>Syntax: {primaryColor}/npc type {secondaryColor}(npc) (type)"
|
npc_type: "<dark_gray>› <gray>Syntax: {primaryColor}/npc type {secondaryColor}(npc) (type)"
|
||||||
npc_visibility_distance: "<dark_gray>› <gray>Syntax: {primaryColor}/npc visibility_distance {secondaryColor}(npc) (always_visible | default | not_visible | distance)"
|
npc_visibility_distance: "<dark_gray>› <gray>Syntax: {primaryColor}/npc visibility_distance {secondaryColor}(npc) (always_visible | default | not_visible | distance)"
|
||||||
|
|
||||||
@@ -158,6 +159,7 @@ messages:
|
|||||||
- "<dark_gray>› <hover:show_text:'<gray>Lists all modified attributes of the NPC.'>{primaryColor}/npc attribute {secondaryColor}(npc) {primaryColor}list"
|
- "<dark_gray>› <hover:show_text:'<gray>Lists all modified attributes of the NPC.'>{primaryColor}/npc attribute {secondaryColor}(npc) {primaryColor}list"
|
||||||
- "<dark_gray>› <hover:show_text:'<gray>Changes whether the NPC can collide with other entities.'>{primaryColor}/npc collidable {secondaryColor}(npc) [state]"
|
- "<dark_gray>› <hover:show_text:'<gray>Changes whether the NPC can collide with other entities.'>{primaryColor}/npc collidable {secondaryColor}(npc) [state]"
|
||||||
- "<dark_gray>› <hover:show_text:'<gray>Copies (duplicates) specified NPC.'>{primaryColor}/npc copy {secondaryColor}(npc) (new_name)"
|
- "<dark_gray>› <hover:show_text:'<gray>Copies (duplicates) specified NPC.'>{primaryColor}/npc copy {secondaryColor}(npc) (new_name)"
|
||||||
|
- "<dark_gray>› <hover:show_text:'<gray>Centers the NPC on its current block location.'>{primaryColor}/npc center {secondaryColor}(npc)"
|
||||||
- "<dark_gray>› <hover:show_text:'<gray>Creates a new NPC. Can be customized with flags.'>{primaryColor}/npc create {secondaryColor}(npc) [--type] [--location] [--world]"
|
- "<dark_gray>› <hover:show_text:'<gray>Creates a new NPC. Can be customized with flags.'>{primaryColor}/npc create {secondaryColor}(npc) [--type] [--location] [--world]"
|
||||||
- "<dark_gray>› <hover:show_text:'<gray>Changes displayname of the NPC. Supports MiniMessage, PlaceholderAPI and MiniPlaceholders.'>{primaryColor}/npc displayname {secondaryColor}(npc) (name)"
|
- "<dark_gray>› <hover:show_text:'<gray>Changes displayname of the NPC. Supports MiniMessage, PlaceholderAPI and MiniPlaceholders.'>{primaryColor}/npc displayname {secondaryColor}(npc) (name)"
|
||||||
- "<dark_gray>› <hover:show_text:'<gray>Sets equipment slot of the NPC to item currently held in main hand, none or a specific item type.'>{primaryColor}/npc equipment {secondaryColor}(npc) {primaryColor}set {secondaryColor}(slot) (@hand | @none | item)"
|
- "<dark_gray>› <hover:show_text:'<gray>Sets equipment slot of the NPC to item currently held in main hand, none or a specific item type.'>{primaryColor}/npc equipment {secondaryColor}(npc) {primaryColor}set {secondaryColor}(slot) (@hand | @none | item)"
|
||||||
@@ -175,7 +177,7 @@ messages:
|
|||||||
- "<dark_gray>› <hover:show_text:'<gray>Changes whether the NPC is shown in the player-list. This works only on NPCs of PLAYER type.<newline><newline>{errorColor}Re-connecting to the server might be required for changes to take effect.'>{primaryColor}/npc show_in_tab {secondaryColor}(npc) (state)"
|
- "<dark_gray>› <hover:show_text:'<gray>Changes whether the NPC is shown in the player-list. This works only on NPCs of PLAYER type.<newline><newline>{errorColor}Re-connecting to the server might be required for changes to take effect.'>{primaryColor}/npc show_in_tab {secondaryColor}(npc) (state)"
|
||||||
- "<dark_gray>› <hover:show_text:'<gray>Changes skin of the NPC.<newline><gray>Supports PlaceholderAPI and MiniPlaceholders.<newline><newline>{warningColor}@none <dark_gray>- <gray>removes the skin<newline>{warningColor}@mirror <dark_gray>- <gray>mirrors player skin<newline>{warningColor}(name) <dark_gray>- <gray>name of any player<newline>{warningColor}(url) <dark_gray>- <gray>url of the skin texture'>{primaryColor}/npc skin {secondaryColor}(npc) (@none | @mirror | name | url) [--slim]"
|
- "<dark_gray>› <hover:show_text:'<gray>Changes skin of the NPC.<newline><gray>Supports PlaceholderAPI and MiniPlaceholders.<newline><newline>{warningColor}@none <dark_gray>- <gray>removes the skin<newline>{warningColor}@mirror <dark_gray>- <gray>mirrors player skin<newline>{warningColor}(name) <dark_gray>- <gray>name of any player<newline>{warningColor}(url) <dark_gray>- <gray>url of the skin texture'>{primaryColor}/npc skin {secondaryColor}(npc) (@none | @mirror | name | url) [--slim]"
|
||||||
- "<dark_gray>› <hover:show_text:'<gray>Teleports you to the specified NPC.'>{primaryColor}/npc teleport {secondaryColor}(npc)"
|
- "<dark_gray>› <hover:show_text:'<gray>Teleports you to the specified NPC.'>{primaryColor}/npc teleport {secondaryColor}(npc)"
|
||||||
- "<dark_gray>› <hover:show_text:'<gray>Changes whether the NPC should turn to the player when in range.'>{primaryColor}/npc turn_to_player {secondaryColor}(npc) (state)"
|
- "<dark_gray>› <hover:show_text:'<gray>Changes whether the NPC should turn to the player when in range. Optionally specify a custom turn distance.'>{primaryColor}/npc turn_to_player {secondaryColor}(npc) (state) [distance]"
|
||||||
- "<dark_gray>› <hover:show_text:'<gray>Changes the type of the NPC.'>{primaryColor}/npc type {secondaryColor}(npc) (type)"
|
- "<dark_gray>› <hover:show_text:'<gray>Changes the type of the NPC.'>{primaryColor}/npc type {secondaryColor}(npc) (type)"
|
||||||
- "<dark_gray>› <hover:show_text:'<gray>Changes the visibility distance of the NPC.'>{primaryColor}/npc visibility_distance {secondaryColor}(npc) (default | distance | ...)"
|
- "<dark_gray>› <hover:show_text:'<gray>Changes the visibility distance of the NPC.'>{primaryColor}/npc visibility_distance {secondaryColor}(npc) (default | distance | ...)"
|
||||||
|
|
||||||
@@ -322,6 +324,18 @@ messages:
|
|||||||
# Commands (npc turn_to_player)
|
# Commands (npc turn_to_player)
|
||||||
npc_turn_to_player_set_true: "<dark_gray>› <gray>NPC {warningColor}{npc}<gray> is now turning to player."
|
npc_turn_to_player_set_true: "<dark_gray>› <gray>NPC {warningColor}{npc}<gray> is now turning to player."
|
||||||
npc_turn_to_player_set_false: "<dark_gray>› <gray>NPC {warningColor}{npc}<gray> is no longer turning to player."
|
npc_turn_to_player_set_false: "<dark_gray>› <gray>NPC {warningColor}{npc}<gray> is no longer turning to player."
|
||||||
|
npc_turn_to_player_distance_set: "<dark_gray>› <gray>NPC {warningColor}{npc}<gray> will now turn to players within {warningColor}{distance}<gray> blocks."
|
||||||
|
npc_turn_to_player_distance_default: "<dark_gray>› <gray>NPC {warningColor}{npc}<gray> will now use the default distance of {warningColor}{distance}<gray> blocks."
|
||||||
|
npc_turn_to_player_distance_invalid: "<dark_gray>› {errorColor}Invalid distance value. Distance must be -1 (for default) or a positive number."
|
||||||
|
|
||||||
# Commands (npc type)
|
# Commands (npc type)
|
||||||
npc_type_success: "<dark_gray>› <gray>NPC {warningColor}{npc}<gray> type has been changed to {warningColor}{type}<gray>."
|
npc_type_success: "<dark_gray>› <gray>NPC {warningColor}{npc}<gray> type has been changed to {warningColor}{type}<gray>."
|
||||||
|
|
||||||
|
# Commands (npc turn_to_player_distance)
|
||||||
|
turn_to_player_distance_current: "<dark_gray>› <gray>Current turn-to-player distance is: {warningColor}{distance} blocks"
|
||||||
|
turn_to_player_distance_updated: "<dark_gray>› {successColor}Turn-to-player distance has been updated to {warningColor}{distance} blocks"
|
||||||
|
turn_to_player_distance_failed: "<dark_gray>› {errorColor}Failed to update turn-to-player distance."
|
||||||
|
|
||||||
|
# Commands (npc center)
|
||||||
|
npc_center_success: "<dark_gray>› <gray>NPC {warningColor}{npc}<gray> has been centered to {warningColor}{x}<gray>, {warningColor}{y}<gray>, {warningColor}{z}<gray>."
|
||||||
|
npc_center_failure_no_location: "<dark_gray>› {errorColor}NPC {warningColor}{npc}{errorColor} has no valid location."
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package de.oliver.fancynpcs.commands.npc;
|
||||||
|
|
||||||
|
import de.oliver.fancylib.translations.Translator;
|
||||||
|
import de.oliver.fancynpcs.FancyNpcs;
|
||||||
|
import de.oliver.fancynpcs.api.Npc;
|
||||||
|
import de.oliver.fancynpcs.api.NpcData;
|
||||||
|
import de.oliver.fancynpcs.api.events.NpcModifyEvent;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.incendo.cloud.annotations.Command;
|
||||||
|
import org.incendo.cloud.annotations.Permission;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public enum CenterCMD {
|
||||||
|
INSTANCE; // SINGLETON
|
||||||
|
|
||||||
|
private final Translator translator = FancyNpcs.getInstance().getTranslator();
|
||||||
|
|
||||||
|
@Command("npc center <npc>")
|
||||||
|
@Permission("fancynpcs.command.npc.center")
|
||||||
|
public void onCenter(
|
||||||
|
final @NotNull CommandSender sender,
|
||||||
|
final @NotNull Npc npc
|
||||||
|
) {
|
||||||
|
NpcData npcData = npc.getData();
|
||||||
|
Location location = npcData.getLocation();
|
||||||
|
|
||||||
|
if (location == null) {
|
||||||
|
translator.translate("npc_center_failure_no_location").replace("npc", npcData.getName()).send(sender);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Center the NPC on the block
|
||||||
|
Location centeredLocation = location.clone();
|
||||||
|
centeredLocation.setX(centeredLocation.getBlockX() + 0.5);
|
||||||
|
centeredLocation.setY(centeredLocation.getY());
|
||||||
|
centeredLocation.setZ(centeredLocation.getBlockZ() + 0.5);
|
||||||
|
|
||||||
|
// Trigger the modify event
|
||||||
|
if (new NpcModifyEvent(npc, NpcModifyEvent.NpcModification.LOCATION, centeredLocation, sender).callEvent()) {
|
||||||
|
npcData.setLocation(centeredLocation);
|
||||||
|
npc.updateForAll();
|
||||||
|
|
||||||
|
translator.translate("npc_center_success")
|
||||||
|
.replace("npc", npcData.getName())
|
||||||
|
.replace("x", String.format("%.2f", centeredLocation.getX()))
|
||||||
|
.replace("y", String.format("%.2f", centeredLocation.getY()))
|
||||||
|
.replace("z", String.format("%.2f", centeredLocation.getZ()))
|
||||||
|
.send(sender);
|
||||||
|
} else {
|
||||||
|
translator.translate("command_npc_modification_cancelled").send(sender);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
package de.oliver.fancynpcs.commands.npc;
|
||||||
|
|
||||||
|
import de.oliver.fancylib.translations.Translator;
|
||||||
|
import de.oliver.fancynpcs.FancyNpcs;
|
||||||
|
import de.oliver.fancynpcs.api.Npc;
|
||||||
|
import de.oliver.fancynpcs.api.events.NpcModifyEvent;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.incendo.cloud.annotations.Argument;
|
||||||
|
import org.incendo.cloud.annotations.Command;
|
||||||
|
import org.incendo.cloud.annotations.Permission;
|
||||||
|
import org.incendo.cloud.annotations.parser.Parser;
|
||||||
|
import org.incendo.cloud.annotations.suggestion.Suggestions;
|
||||||
|
import org.incendo.cloud.context.CommandContext;
|
||||||
|
import org.incendo.cloud.context.CommandInput;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public enum TurnToPlayerDistanceCMD {
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
|
private final Translator translator = FancyNpcs.getInstance().getTranslator();
|
||||||
|
|
||||||
|
// Storing in a static variable to avoid re-creating the array each time suggestion is requested.
|
||||||
|
private final List<String> DISTANCE_SUGGESTIONS = List.of("default");
|
||||||
|
|
||||||
|
@Command("npc turn_to_player_distance <npc> <distance>")
|
||||||
|
@Permission("fancynpcs.command.npc.turn_to_player_distance")
|
||||||
|
public void onTurnToPlayerDistance(
|
||||||
|
final @NotNull CommandSender sender,
|
||||||
|
final @NotNull Npc npc,
|
||||||
|
final @Argument(parserName = "TurnToPlayerDistanceCMD/distance") int distance
|
||||||
|
) {
|
||||||
|
if (distance < -1) {
|
||||||
|
translator.translate("npc_turn_to_player_distance_invalid").send(sender);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new NpcModifyEvent(npc, NpcModifyEvent.NpcModification.TURN_TO_PLAYER_DISTANCE, distance, sender).callEvent()) {
|
||||||
|
npc.getData().setTurnToPlayerDistance(distance);
|
||||||
|
|
||||||
|
if (distance == -1) {
|
||||||
|
// Using default distance
|
||||||
|
int defaultDistance = FancyNpcs.getInstance().getFancyNpcConfig().getTurnToPlayerDistance();
|
||||||
|
translator.translate("npc_turn_to_player_distance_default")
|
||||||
|
.replace("npc", npc.getData().getName())
|
||||||
|
.replace("distance", String.valueOf(defaultDistance))
|
||||||
|
.send(sender);
|
||||||
|
} else {
|
||||||
|
// Using custom distance
|
||||||
|
translator.translate("npc_turn_to_player_distance_set")
|
||||||
|
.replace("npc", npc.getData().getName())
|
||||||
|
.replace("distance", String.valueOf(distance))
|
||||||
|
.send(sender);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
translator.translate("command_npc_modification_cancelled").send(sender);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PARSERS AND SUGGESTIONS */
|
||||||
|
|
||||||
|
@Parser(name = "TurnToPlayerDistanceCMD/distance", suggestions = "TurnToPlayerDistanceCMD/distance")
|
||||||
|
public @NotNull Integer parse(final CommandContext<CommandSender> context, final CommandInput input) {
|
||||||
|
// If 'default' string is provided, it is being handled as -1.
|
||||||
|
if (input.peekString().equalsIgnoreCase("default")) {
|
||||||
|
input.readString();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// Otherwise, reading next argument as int.
|
||||||
|
return input.readInteger();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suggestions("TurnToPlayerDistanceCMD/distance")
|
||||||
|
public @NotNull List<String> suggest(final CommandContext<CommandSender> context, final CommandInput input) {
|
||||||
|
return DISTANCE_SUGGESTIONS;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user