var Entity = Java.type('net.minestom.server.entity.Entity'); var Pos = Java.type('net.minestom.server.coordinate.Pos'); var Vec = Java.type('net.minestom.server.coordinate.Vec'); var Component = Java.type('net.kyori.adventure.text.Component'); var NamedTextColor = Java.type('net.kyori.adventure.text.format.NamedTextColor'); var BillboardConstraints = Java.type('net.minestom.server.entity.metadata.display.AbstractDisplayMeta.BillboardConstraints'); var MinecraftServer = Java.type('net.minestom.server.MinecraftServer'); var MiniMessage = Java.type('net.kyori.adventure.text.minimessage.MiniMessage'); server.log("NPC Text script initializing..."); 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"); // Helper to convert legacy colors (& and §) to MiniMessage tags function convertLegacyToMiniMessage(text) { if (!text) return text; var legacyMap = { '0': 'black', '1': 'dark_blue', '2': 'dark_green', '3': 'dark_aqua', '4': 'dark_red', '5': 'dark_purple', '6': 'gold', '7': 'gray', '8': 'dark_gray', '9': 'blue', 'a': 'green', 'b': 'aqua', 'c': 'red', 'd': 'light_purple', 'e': 'yellow', 'f': 'white', 'l': 'bold', 'm': 'strikethrough', 'n': 'underlined', 'o': 'italic', 'r': 'reset' }; return text.replace(/[&§]([0-9a-fk-orA-FK-OR])/g, function(match, code) { var tag = legacyMap[code.toLowerCase()]; return tag ? "<" + tag + ">" : match; }); } // 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 instances = instanceManager.getInstances(); if (instances.isEmpty()) { server.log("No instances found!"); return; } var instance = instances.iterator().next(); var position = new Pos(x, y, z); // Retrieve EntityTypes var HUSK = server.getEntityType('HUSK'); var TEXT_DISPLAY = server.getEntityType('TEXT_DISPLAY'); // 1. Create the "NPC" (Host) var npc = new Entity(HUSK); npc.setNoGravity(true); server.track(npc); // 2. Create the TextDisplay (Passenger) var textDisplay = new Entity(TEXT_DISPLAY); textDisplay.setNoGravity(true); // Ensure text doesn't fall server.track(textDisplay); var meta = textDisplay.getEntityMeta(); // Parse both MiniMessage and Legacy var processedText = convertLegacyToMiniMessage(displayString); meta.setText(MiniMessage.miniMessage().deserialize(processedText)); meta.setBillboardRenderConstraints(BillboardConstraints.CENTER); meta.setScale(new Vec(1.0, 1.0, 1.0)); meta.setBackgroundColor(0); meta.setShadow(true); // 3. Spawn entities server.log("Spawning NPC " + (index + 1) + "/" + pos.length + " at " + x + "," + y + "," + z + "..."); npc.setInstance(instance, position).thenAccept(function() { textDisplay.setInstance(instance, position.add(0, 3.0, 0)).thenAccept(function() { 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; }); } try { spawnNext(0); } catch (e) { server.log("Error starting spawn loop: " + e); }