fancyholograms-v3: Add interaction trait (#53)

* fancyholograms-v3: Add interaction trait

* Calculate height and width

* onModify

* Remove npc when hologram gets unregistered

* Register actions

* formatting
This commit is contained in:
Oliver
2025-05-18 13:34:26 +02:00
committed by GitHub
parent 8c73932fc5
commit a7c3b59165
2 changed files with 166 additions and 0 deletions

View File

@@ -30,6 +30,7 @@ import de.oliver.fancyholograms.storage.StorageMigrator;
import de.oliver.fancyholograms.storage.json.JsonStorage;
import de.oliver.fancyholograms.trait.HologramTraitRegistryImpl;
import de.oliver.fancyholograms.trait.builtin.FileContentTrait;
import de.oliver.fancyholograms.trait.builtin.InteractionTrait;
import de.oliver.fancyholograms.trait.builtin.MultiplePagesTrait;
import de.oliver.fancyholograms.util.PluginUtils;
import de.oliver.fancylib.FancyLib;
@@ -192,6 +193,7 @@ public final class FancyHologramsPlugin extends JavaPlugin implements FancyHolog
traitRegistry.register(MultiplePagesTrait.class);
traitRegistry.register(FileContentTrait.class);
traitRegistry.register(InteractionTrait.class);
new StorageMigrator().migrate();

View File

@@ -0,0 +1,164 @@
package de.oliver.fancyholograms.trait.builtin;
import de.oliver.fancyholograms.api.data.TextHologramData;
import de.oliver.fancyholograms.api.trait.HologramTrait;
import de.oliver.fancyholograms.api.trait.HologramTraitClass;
import de.oliver.fancyholograms.util.PluginUtils;
import de.oliver.fancynpcs.api.FancyNpcsPlugin;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.api.NpcData;
import de.oliver.fancynpcs.api.actions.ActionTrigger;
import de.oliver.fancynpcs.api.actions.NpcAction;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.ApiStatus;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@ApiStatus.Experimental
@HologramTraitClass(traitName = "interaction_trait", defaultTrait = true)
public class InteractionTrait extends HologramTrait {
private static final FancyNpcsPlugin FN = FancyNpcsPlugin.get();
private Configuration config;
private Npc hitbox;
public InteractionTrait() {
if (!PluginUtils.isFancyNpcsEnabled()) {
throw new IllegalStateException("FancyNpcs is not enabled. Please enable it to use InteractionTrait.");
}
}
@Override
public void onAttach() {
this.load();
this.updateHitbox();
}
@Override
public void onSpawn(Player player) {
this.updateHitbox();
}
@Override
public void onDespawn(Player player) {
this.updateHitbox();
}
@Override
public void onModify() {
this.updateHitbox();
}
@Override
public void onUnregister() {
if (this.hitbox != null) {
this.hitbox.removeForAll();
FN.getNpcManager().removeNpc(this.hitbox);
this.hitbox = null;
}
}
@Override
public void save() {
try {
storage.set(hologram.getData().getName(), config);
} catch (Exception e) {
logger.error("Failed to save configuration for InteractionTrait");
logger.error(e);
}
}
@Override
public void load() {
try {
config = storage.get(hologram.getData().getName(), Configuration.class);
} catch (Exception e) {
logger.error("Failed to load configuration for InteractionTrait");
logger.error(e);
}
if (config == null) {
config = new Configuration(List.of(
new ActionConfig("message", "Hi, you just clicked a hologram!")
));
save();
}
}
private void updateHitbox() {
if (FN.getNpcManager().getNpc("hologram_hitbox_for_" + hologram.getData().getName()) == null) {
this.hitbox = FN.getNpcAdapter().apply(new NpcData(
"hologram_hitbox_for_" + hologram.getData().getName(),
UUID.randomUUID(),
hologram.getData().getLocation()
));
this.hitbox.setSaveToFile(false);
this.hitbox.getData().setType(EntityType.INTERACTION);
this.hitbox.getData().setDisplayName("<empty>");
List<NpcAction.NpcActionData> actions = new ArrayList<>();
for (ActionConfig acfg : this.config.actions()) {
NpcAction action = FN.getActionManager().getActionByName(acfg.action());
if (action == null) {
logger.warn("Action " + acfg.action() + " is not registered");
continue;
}
actions.add(new NpcAction.NpcActionData(actions.size(), action, acfg.value()));
}
this.hitbox.getData().getActions().put(ActionTrigger.ANY_CLICK, actions);
this.hitbox.create();
this.hitbox.spawnForAll();
FN.getNpcManager().registerNpc(this.hitbox);
}
this.hitbox.getData().setLocation(hologram.getData().getLocation());
NpcAttribute widthAttr = FN.getAttributeManager().getAttributeByName(EntityType.INTERACTION, "width");
this.hitbox.getData().addAttribute(widthAttr, String.valueOf(calcWidth()));
NpcAttribute heightAttr = FN.getAttributeManager().getAttributeByName(EntityType.INTERACTION, "height");
this.hitbox.getData().addAttribute(heightAttr, String.valueOf(calcHeight()));
this.hitbox.updateForAll();
}
private double calcHeight() {
int lines = ((TextHologramData) hologram.getData()).getText().size();
double heightPerLine = 0.25;
double scale = ((TextHologramData) hologram.getData()).getScale().y;
return lines * heightPerLine * scale;
}
private double calcWidth() {
List<String> lines = ((TextHologramData) hologram.getData()).getText();
double maxCharacters = 0;
for (String line : lines) {
if (line.length() > maxCharacters) {
maxCharacters = line.length();
}
}
double widthPerCharacter = 0.12;
double scale = ((TextHologramData) hologram.getData()).getScale().x;
return maxCharacters * widthPerCharacter * scale;
}
public record ActionConfig(
String action,
String value
) {
}
public record Configuration(
List<ActionConfig> actions
) {
}
}