Makes some lookclose situations work, and updates documentation
All checks were successful
KnarCraft/BlacksmithVisuals/pipeline/head This commit looks good

This commit is contained in:
Kristian Knarvik 2024-08-04 02:17:30 +02:00
parent ae2ce0c7d6
commit 891330af4a
3 changed files with 55 additions and 4 deletions

View File

@ -2,4 +2,32 @@
This plugin adds additional visual and audial details to blacksmiths while they are working, so it's easier to see if This plugin adds additional visual and audial details to blacksmiths while they are working, so it's easier to see if
they are working or not. It is recommended to put a mace or other hammer-like item in the NPC's off-hand for full they are working or not. It is recommended to put a mace or other hammer-like item in the NPC's off-hand for full
effect. effect.
## FAQ
### Citizens lookclose makes NPC rotate weirdly
It has been found that with some options, lookclose can still be used. An example of a working lookclose setup is:
`/npc lookclose --linkedbody false --disablewhennavigating true --perplayer true --range 3 --targetnpcs false --headonly true --linkedbody false -r false`
Some other options might work as well, but a lot of options won't, as it messes with manual NPC rotation. Keep that in
mind.
### NPCs teleport part of the way while walking to or from a crafting station
This behavior is inevitable. As Citizens pathing is not very accurate (as described in Citizens' FAQ), the NPC must be
teleported to end up in the correct spot.
## Commands
| Command | Options | Description |
|-------------------------------------|--------------------------------------------------------------------------|----------------------------------------------------------------------------------------------|
| /reload (/blacksmithvisuals:reload) | | Reloads the plugin |
| /setNPCPosition <positionType> | idle, netherite-workstation, reforging-workstation, crafting-workstation | Sets an idle or working position for an NPC to the current location of the executing player. |
## Permissions
| Permission | Description |
|-------------------------------|---------------------------------------------|
| blacksmithvisuals.reload | Gives access to the reload command |
| blacksmithvisuals.setposition | Gives access to the /setNPCPosition command |

View File

@ -5,6 +5,7 @@ import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.ProtocolManager; import com.comphenix.protocol.ProtocolManager;
import com.comphenix.protocol.events.PacketContainer; import com.comphenix.protocol.events.PacketContainer;
import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.trait.LookClose;
import net.knarcraft.blacksmith.event.ActionStartEvent; import net.knarcraft.blacksmith.event.ActionStartEvent;
import net.knarcraft.blacksmith.event.BlacksmithReforgeFailEvent; import net.knarcraft.blacksmith.event.BlacksmithReforgeFailEvent;
import net.knarcraft.blacksmith.event.BlacksmithReforgeStartEvent; import net.knarcraft.blacksmith.event.BlacksmithReforgeStartEvent;
@ -27,11 +28,15 @@ import org.bukkit.entity.Entity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.scheduler.BukkitScheduler; import org.bukkit.scheduler.BukkitScheduler;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.Map;
import java.util.Random; import java.util.Random;
import java.util.UUID;
import java.util.logging.Level; import java.util.logging.Level;
/** /**
@ -41,6 +46,7 @@ public class BlacksmithListener implements Listener {
private final Random random; private final Random random;
private final ConfigurationManager configurationManager; private final ConfigurationManager configurationManager;
private final Map<UUID, Double> oldLookRanges;
/** /**
* Instantiates a new blacksmith listener * Instantiates a new blacksmith listener
@ -50,6 +56,7 @@ public class BlacksmithListener implements Listener {
public BlacksmithListener(@NotNull ConfigurationManager configurationManager) { public BlacksmithListener(@NotNull ConfigurationManager configurationManager) {
this.random = new Random(); this.random = new Random();
this.configurationManager = configurationManager; this.configurationManager = configurationManager;
this.oldLookRanges = new HashMap<>();
} }
@EventHandler @EventHandler
@ -101,6 +108,11 @@ public class BlacksmithListener implements Listener {
NPC npc = event.getNpc(); NPC npc = event.getNpc();
long delay = moveToWorkingPosition(npc, NPCPosition.getFromMaterial(event.getCraftingStation())); long delay = moveToWorkingPosition(npc, NPCPosition.getFromMaterial(event.getCraftingStation()));
if (npc.hasTrait(LookClose.class)) {
LookClose trait = npc.getTraitNullable(LookClose.class);
this.oldLookRanges.put(npc.getUniqueId(), trait.getRange());
trait.setRange(0);
}
long finishTime = event.getActionDurationTicks() - (2 * delay); long finishTime = event.getActionDurationTicks() - (2 * delay);
scheduler.scheduleSyncDelayedTask(instance, () -> startWorkAnimation(npc.getEntity(), scheduler.scheduleSyncDelayedTask(instance, () -> startWorkAnimation(npc.getEntity(),
@ -130,6 +142,14 @@ public class BlacksmithListener implements Listener {
return; return;
} }
if (npc.hasTrait(LookClose.class)) {
LookClose trait = npc.getTraitNullable(LookClose.class);
Double oldRange = oldLookRanges.remove(npc.getUniqueId());
if (oldRange != null) {
trait.setRange(oldRange);
}
}
Bukkit.getScheduler().scheduleSyncDelayedTask(BlacksmithVisuals.getInstance(), () -> Bukkit.getScheduler().scheduleSyncDelayedTask(BlacksmithVisuals.getInstance(), () ->
npc.getEntity().teleport(targetLocation), getWalkTime(npc.getEntity().getLocation(), targetLocation)); npc.getEntity().teleport(targetLocation), getWalkTime(npc.getEntity().getLocation(), targetLocation));
npc.getNavigator().setTarget(targetLocation); npc.getNavigator().setTarget(targetLocation);
@ -165,13 +185,16 @@ public class BlacksmithListener implements Listener {
npc.getName() + " is unreachable!"); npc.getName() + " is unreachable!");
return 0; return 0;
} }
Location finalTargetLocation = targetLocation;
// Move NPC using Citizens path-finding // Move NPC using Citizens path-finding
npc.getNavigator().setTarget(targetLocation); Location current = npc.getEntity().getLocation().clone();
npc.teleport(current.setDirection(targetLocation.toVector().subtract(current.toVector())), PlayerTeleportEvent.TeleportCause.PLUGIN);
Bukkit.getScheduler().scheduleSyncDelayedTask(BlacksmithVisuals.getInstance(), () -> npc.getNavigator().setTarget(finalTargetLocation), 2);
// Teleport the NPC tp get it in the exact final location // Teleport the NPC tp get it in the exact final location
long walkTime = getWalkTime(npc.getEntity().getLocation(), targetLocation); long walkTime = getWalkTime(npc.getEntity().getLocation(), targetLocation);
Location finalTargetLocation = targetLocation;
Bukkit.getScheduler().scheduleSyncDelayedTask(BlacksmithVisuals.getInstance(), () -> Bukkit.getScheduler().scheduleSyncDelayedTask(BlacksmithVisuals.getInstance(), () ->
npc.getEntity().teleport(finalTargetLocation), walkTime); npc.getEntity().teleport(finalTargetLocation), walkTime);
return walkTime; return walkTime;

View File

@ -31,5 +31,5 @@ permissions:
description: Allows reloading the plugin description: Allows reloading the plugin
default: false default: false
blacksmithvisuals.setposition: blacksmithvisuals.setposition:
description: Allows use of the /setIdlePosition and /setWorkingPosition commands description: Allows use of the /setNPCPosition command
default: false default: false