Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

import java.util.Objects;
import java.util.Optional;
import java.util.regex.Pattern;

public class HologramData implements YamlData {

Expand All @@ -28,6 +29,7 @@ public class HologramData implements YamlData {
private Visibility visibility = DEFAULT_VISIBILITY;
private boolean persistent = DEFAULT_PERSISTENCE;
private String linkedNpcName;
private String worldPattern;

/**
* @param name Name of hologram
Expand Down Expand Up @@ -134,6 +136,23 @@ public HologramData setLinkedNpcName(String linkedNpcName) {
return this;
}

public String getWorldPattern() {
return worldPattern;
}

public HologramData setWorldPattern(String worldPattern) {
this.worldPattern = worldPattern;
return this;
}

public boolean matchesWorld(World world) {
if (worldPattern == null || !worldPattern.contains("*") && !worldPattern.contains("?") && !worldPattern.contains("[") && !worldPattern.contains("{")) {
return location.getWorld().equals(world);
}
Pattern pattern = Pattern.compile(worldPattern.replace("*", ".*").replace("?", "."));
return pattern.matcher(world.getName()).matches();
}

@Override
public boolean read(ConfigurationSection section, String name) {
String worldName = section.getString("location.world", "world");
Expand All @@ -143,13 +162,30 @@ public boolean read(ConfigurationSection section, String name) {
float yaw = (float) section.getDouble("location.yaw", 0);
float pitch = (float) section.getDouble("location.pitch", 0);

World world = Bukkit.getWorld(worldName);
if (world == null) {
FancyHologramsPlugin.get().getFancyLogger().warn("Could not load hologram '" + name + "', because the world '" + worldName + "' is not loaded");
return false;
if (worldName.contains("*") || worldName.contains("?") || worldName.contains("[") || worldName.contains("{")) {
this.worldPattern = worldName;
World firstMatchingWorld = null;
Pattern pattern = Pattern.compile(worldName.replace("*", ".*").replace("?", "."));
for (World w : Bukkit.getWorlds()) {
if (pattern.matcher(w.getName()).matches()) {
firstMatchingWorld = w;
break;
}
}
if (firstMatchingWorld == null) {
FancyHologramsPlugin.get().getFancyLogger().warn("Could not load hologram '" + name + "', because no world matching pattern '" + worldName + "' is loaded");
return false;
}
location = new Location(firstMatchingWorld, x, y, z, yaw, pitch);
} else {
World world = Bukkit.getWorld(worldName);
if (world == null) {
FancyHologramsPlugin.get().getFancyLogger().warn("Could not load hologram '" + name + "', because the world '" + worldName + "' is not loaded");
return false;
}
location = new Location(world, x, y, z, yaw, pitch);
}

location = new Location(world, x, y, z, yaw, pitch);
visibilityDistance = section.getInt("visibility_distance", DEFAULT_VISIBILITY_DISTANCE);
visibility = Optional.ofNullable(section.getString("visibility"))
.flatMap(Visibility::byString)
Expand All @@ -165,7 +201,7 @@ public boolean read(ConfigurationSection section, String name) {
@Override
public boolean write(ConfigurationSection section, String name) {
section.set("type", type.name());
section.set("location.world", location.getWorld().getName());
section.set("location.world", worldPattern != null ? worldPattern : location.getWorld().getName());
section.set("location.x", location.x());
section.set("location.y", location.y());
section.set("location.z", location.z());
Expand All @@ -185,6 +221,7 @@ public HologramData copy(String name) {
.setVisibilityDistance(this.getVisibilityDistance())
.setVisibility(this.getVisibility())
.setPersistent(this.isPersistent())
.setLinkedNpcName(this.getLinkedNpcName());
.setLinkedNpcName(this.getLinkedNpcName())
.setWorldPattern(this.getWorldPattern());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -273,11 +273,11 @@ public boolean meetsVisibilityConditions(@NotNull final Player player) {
}

public boolean isWithinVisibilityDistance(@NotNull final Player player) {
final var location = getData().getLocation();
if (!location.getWorld().equals(player.getWorld())) {
if (!data.matchesWorld(player.getWorld())) {
return false;
}

final var location = getData().getLocation();
int visibilityDistance = data.getVisibilityDistance();
double distanceSquared = location.distanceSquared(player.getLocation());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ public boolean show(@NotNull final Player player) {
return false; // could not be created, nothing to show
}

if (!data.getLocation().getWorld().getName().equals(player.getLocation().getWorld().getName())) {
if (!data.matchesWorld(player.getWorld())) {
return false;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.regex.Pattern;

public class NpcManagerImpl implements NpcManager {

Expand Down Expand Up @@ -248,28 +249,6 @@ public void loadNpcs() {
logger.warn("Could not load location for npc '" + id + "'");
}

if (location == null) {
String worldName = npcConfig.getString("npcs." + id + ".location.world");
World world = Bukkit.getWorld(worldName);

if (world == null) {
world = (!ServerSoftware.isFolia()) ? new WorldCreator(worldName).createWorld() : null;
}

if (world == null) {
logger.info("Could not load npc '" + id + "', because the world '" + worldName + "' is not loaded");
continue;
}

double x = npcConfig.getDouble("npcs." + id + ".location.x");
double y = npcConfig.getDouble("npcs." + id + ".location.y");
double z = npcConfig.getDouble("npcs." + id + ".location.z");
float yaw = (float) npcConfig.getDouble("npcs." + id + ".location.yaw");
float pitch = (float) npcConfig.getDouble("npcs." + id + ".location.pitch");

location = new Location(world, x, y, z, yaw, pitch);
}

SkinData skin = null;
String skinIdentifier = npcConfig.getString("npcs." + id + ".skin.identifier", npcConfig.getString("npcs." + id + ".skin.uuid", ""));
String skinVariantStr = npcConfig.getString("npcs." + id + ".skin.variant", SkinData.SkinVariant.AUTO.name());
Expand Down Expand Up @@ -310,6 +289,89 @@ public void loadNpcs() {
boolean turnToPlayer = npcConfig.getBoolean("npcs." + id + ".turnToPlayer");
int turnToPlayerDistance = npcConfig.getInt("npcs." + id + ".turnToPlayerDistance", -1);

if (location == null) {
String worldName = npcConfig.getString("npcs." + id + ".location.world");

List<World> matchingWorlds = new ArrayList<>();
if (worldName.contains("*") || worldName.contains("?") || worldName.contains("[") || worldName.contains("{")) {
Pattern worldPattern = Pattern.compile(worldName.replace("*", ".*").replace("?", "."));
for (World w : Bukkit.getWorlds()) {
if (worldPattern.matcher(w.getName()).matches()) {
matchingWorlds.add(w);
}
}
} else {
World world = Bukkit.getWorld(worldName);
if (world == null) {
world = (!ServerSoftware.isFolia()) ? new WorldCreator(worldName).createWorld() : null;
}
if (world != null) {
matchingWorlds.add(world);
}
}

if (matchingWorlds.isEmpty()) {
logger.info("Could not load npc '" + id + "', because no world matching '" + worldName + "' is loaded");
continue;
}

double x = npcConfig.getDouble("npcs." + id + ".location.x");
double y = npcConfig.getDouble("npcs." + id + ".location.y");
double z = npcConfig.getDouble("npcs." + id + ".location.z");
float yaw = (float) npcConfig.getDouble("npcs." + id + ".location.yaw");
float pitch = (float) npcConfig.getDouble("npcs." + id + ".location.pitch");

for (World world : matchingWorlds) {
Location loc = new Location(world, x, y, z, yaw, pitch);

Map<ActionTrigger, List<NpcAction.NpcActionData>> actionsForWorld = new ConcurrentHashMap<>();
for (Map.Entry<ActionTrigger, List<NpcAction.NpcActionData>> entry : actions.entrySet()) {
actionsForWorld.put(entry.getKey(), new ArrayList<>(entry.getValue()));
}

Map<NpcAttribute, String> attributesForWorld = new HashMap<>(attributes);

NpcData data = new NpcData(
matchingWorlds.size() > 1 ? id + "_" + world.getName() : id,
name,
creator,
displayName,
skin,
loc,
showInTab,
spawnEntity,
collidable,
glowing,
glowingColor,
type,
new HashMap<>(),
turnToPlayer,
turnToPlayerDistance,
null,
actionsForWorld,
interactionCooldown,
scale,
visibilityDistance,
attributesForWorld,
mirrorSkin
);

Npc npc = npcAdapter.apply(data);

if (npcConfig.isConfigurationSection("npcs." + id + ".equipment")) {
for (String equipmentSlotStr : npcConfig.getConfigurationSection("npcs." + id + ".equipment").getKeys(false)) {
NpcEquipmentSlot equipmentSlot = NpcEquipmentSlot.parse(equipmentSlotStr);
ItemStack item = npcConfig.getItemStack("npcs." + id + ".equipment." + equipmentSlotStr);
npc.getData().addEquipment(equipmentSlot, item);
}
}

npc.create();
registerNpc(npc);
}
continue;
}

Map<ActionTrigger, List<NpcAction.NpcActionData>> actions = new ConcurrentHashMap<>();

//TODO: remove these fields next version
Expand Down