Enhance NPC Text script with MiniMessage support and refactor spawn logic
All checks were successful
Build JStom / build (push) Successful in 1m54s

This commit is contained in:
2026-01-27 01:40:37 +00:00
parent 676857d650
commit c3b043c59e
2 changed files with 71 additions and 23 deletions

View File

@@ -23,6 +23,9 @@ dependencies {
// Logging // Logging
implementation("org.slf4j:slf4j-simple:2.0.9") implementation("org.slf4j:slf4j-simple:2.0.9")
// Adventure MiniMessage
implementation("net.kyori:adventure-text-minimessage:4.17.0")
// Config // Config
implementation("org.yaml:snakeyaml:2.2") implementation("org.yaml:snakeyaml:2.2")
} }

View File

@@ -5,57 +5,102 @@ var Component = Java.type('net.kyori.adventure.text.Component');
var NamedTextColor = Java.type('net.kyori.adventure.text.format.NamedTextColor'); var NamedTextColor = Java.type('net.kyori.adventure.text.format.NamedTextColor');
var BillboardConstraints = Java.type('net.minestom.server.entity.metadata.display.AbstractDisplayMeta.BillboardConstraints'); var BillboardConstraints = Java.type('net.minestom.server.entity.metadata.display.AbstractDisplayMeta.BillboardConstraints');
var MinecraftServer = Java.type('net.minestom.server.MinecraftServer'); var MinecraftServer = Java.type('net.minestom.server.MinecraftServer');
var MiniMessage = Java.type('net.kyori.adventure.text.minimessage.MiniMessage');
server.log("NPC Text script initializing..."); server.log("NPC Text script initializing...");
function spawnFixedNPC() { const pos = [
[49.5, 63, -75.5],
[35.5, 63, -75.5],
[48.5, 63, -70.5],
[36.5, 63, -70.5],
[47.5, 63, -65.5],
[37.5, 63, -65.5],
[42.5, 63, -64.5]
];
const text = [
"<#bb00ff>&lGHAST &r&7(1.21+)",
"&7idk",
"&7",
"<#bb00ff>⏩ Line 1",
"<#bb00ff>⏩ Line 2",
"&7",
"&7(Click me to join <#bb00ff>&n0&r&7 others&r&7)"
];
// Join all lines with newline for the display
var fullDisplayText = text.join("\n");
// Run sequentially to prevent race conditions
function spawnNext(index) {
if (index >= pos.length) {
server.log("All NPCs spawned.");
return;
}
var loc = pos[index];
var x = loc[0];
var y = loc[1];
var z = loc[2];
// Use the full text for every NPC
var displayString = fullDisplayText;
var instanceManager = MinecraftServer.getInstanceManager(); var instanceManager = MinecraftServer.getInstanceManager();
var instances = instanceManager.getInstances(); var instances = instanceManager.getInstances();
if (instances.isEmpty()) { if (instances.isEmpty()) {
server.log("No instances found to spawn NPC!"); server.log("No instances found!");
return; return;
} }
var instance = instances.iterator().next(); var instance = instances.iterator().next();
var pos = new Pos(45.5, 65.0, -80.5); var position = new Pos(x, y, z);
// Retrieve EntityTypes via Java helper // Retrieve EntityTypes
var HUSK = server.getEntityType('HUSK'); var HUSK = server.getEntityType('HUSK');
var TEXT_DISPLAY = server.getEntityType('TEXT_DISPLAY'); var TEXT_DISPLAY = server.getEntityType('TEXT_DISPLAY');
if (HUSK == null || TEXT_DISPLAY == null) { // 1. Create the "NPC" (Host)
server.log("Failed to resolve EntityTypes! HUSK=" + HUSK + ", TEXT_DISPLAY=" + TEXT_DISPLAY);
return;
}
// 1. Create the "NPC" (Host) - Husk
var npc = new Entity(HUSK); var npc = new Entity(HUSK);
npc.setNoGravity(true);
// 2. Create the TextDisplay (Passenger) // 2. Create the TextDisplay (Passenger)
var textDisplay = new Entity(TEXT_DISPLAY); var textDisplay = new Entity(TEXT_DISPLAY);
textDisplay.setNoGravity(true); // Ensure text doesn't fall
var meta = textDisplay.getEntityMeta(); var meta = textDisplay.getEntityMeta();
// Configure the text display meta.setText(MiniMessage.miniMessage().deserialize(displayString));
meta.setText(Component.text("I am a fixed NPC!").color(NamedTextColor.YELLOW));
meta.setBillboardRenderConstraints(BillboardConstraints.CENTER); meta.setBillboardRenderConstraints(BillboardConstraints.CENTER);
meta.setScale(new Vec(1.0, 1.0, 1.0)); meta.setScale(new Vec(1.0, 1.0, 1.0));
meta.setBackgroundColor(0); // Transparent meta.setBackgroundColor(0);
// 3. Spawn entities // 3. Spawn entities
npc.setInstance(instance, pos).thenAccept(function() { server.log("Spawning NPC " + (index + 1) + "/" + pos.length + " at " + x + "," + y + "," + z + "...");
textDisplay.setInstance(instance, pos.add(0, 2.5, 0)).thenAccept(function() {
// 4. Make the TextDisplay ride the NPC npc.setInstance(instance, position).thenAccept(function() {
npc.addPassenger(textDisplay); textDisplay.setInstance(instance, position.add(0, 2.5, 0)).thenAccept(function() {
server.log("Spawned fixed NPC at " + pos); try {
npc.addPassenger(textDisplay);
server.log("Successfully spawned NPC + Text at " + x + "," + y + "," + z);
} catch (e) {
server.log("Error adding passenger: " + e);
}
// Spawn next
spawnNext(index + 1);
}).exceptionally(function(e) {
server.log("TextDisplay spawn failed: " + e);
spawnNext(index + 1); // Continue anyway
return null;
}); });
}).exceptionally(function(e) {
server.log("NPC spawn failed: " + e);
spawnNext(index + 1); // Continue anyway
return null;
}); });
} }
// Run immediately
try { try {
spawnFixedNPC(); spawnNext(0);
} catch (e) { } catch (e) {
server.log("Error spawning NPC: " + e); server.log("Error starting spawn loop: " + e);
e.printStackTrace();
} }