Skip to content
This repository was archived by the owner on Aug 12, 2025. It is now read-only.

Commit f7c6900

Browse files
authored
Merge pull request #9 from NextForge-Development/create-textblockitemdisplay-package
Implement basic hologram API
2 parents 5072379 + e98077f commit f7c6900

14 files changed

Lines changed: 594 additions & 0 deletions

‎build.gradle‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ dependencies {
2121
implementation "org.mozilla:rhino:1.7.14"
2222
implementation "com.google.code.gson:gson:2.10.1"
2323
implementation "org.bstats:bstats-bukkit:3.0.2"
24+
testImplementation "org.junit.jupiter:junit-jupiter:5.9.3"
25+
testImplementation "org.mockito:mockito-core:5.5.0"
2426
}
2527

2628
subprojects {
@@ -72,6 +74,10 @@ tasks {
7274
options.encoding = "UTF-8"
7375
}
7476

77+
test {
78+
useJUnitPlatform()
79+
}
80+
7581
// Haupt-Versionserweiterung für plugin.yml
7682
processResources {
7783
filesMatching("plugin.yml") {

‎src/main/java/gg/nextforge/NextCorePlugin.java‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ public void enable(boolean isReload) {
4848

4949
new NextCoreCommand(this);
5050
new NPCCommand(this, getNpcManager());
51+
new gg.nextforge.textblockitemdisplay.HologramCommand(this, getHologramManager());
5152

5253
ConsoleHeader.send(this);
5354

‎src/main/java/gg/nextforge/plugin/NextForgePlugin.java‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import gg.nextforge.protocol.ProtocolManager;
88
import gg.nextforge.scheduler.CoreScheduler;
99
import gg.nextforge.text.TextManager;
10+
import gg.nextforge.textblockitemdisplay.HologramManager;
1011
import lombok.Getter;
1112
import org.bstats.bukkit.Metrics;
1213
import org.bukkit.plugin.Plugin;
@@ -25,6 +26,7 @@ public abstract class NextForgePlugin extends JavaPlugin {
2526
CommandManager commandManager;
2627
TextManager textManager;
2728
NPCManager npcManager;
29+
HologramManager hologramManager;
2830
ProtocolManager protocolManager;
2931
Metrics metrics;
3032

@@ -60,6 +62,7 @@ public void onEnable() {
6062
this.commandManager = new CommandManager(this);
6163
this.textManager = new TextManager(this);
6264
this.npcManager = new NPCManager(this);
65+
this.hologramManager = new HologramManager();
6366
this.protocolManager = new ProtocolManager(this);
6467

6568
boolean isReload = getServer().getPluginManager().isPluginEnabled("NextForge");
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package gg.nextforge.textblockitemdisplay;
2+
3+
import org.bukkit.Material;
4+
5+
/**
6+
* Represents a hologram displaying a block.
7+
*/
8+
public interface BlockHologram extends Hologram {
9+
/**
10+
* @return block type displayed by this hologram.
11+
*/
12+
Material getBlockType();
13+
14+
/**
15+
* Sets block type.
16+
*
17+
* @param material material to display
18+
*/
19+
void setBlockType(Material material);
20+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package gg.nextforge.textblockitemdisplay;
2+
3+
import org.bukkit.Location;
4+
5+
/**
6+
* Base interface for all hologram types.
7+
*/
8+
public interface Hologram {
9+
/**
10+
* @return name of the hologram.
11+
*/
12+
String getName();
13+
14+
/**
15+
* Get the current location of the hologram.
16+
*
17+
* @return hologram location
18+
*/
19+
Location getLocation();
20+
21+
/**
22+
* Sets the location of this hologram.
23+
*
24+
* @param location new location
25+
*/
26+
void setLocation(Location location);
27+
28+
/**
29+
* Spawns the hologram.
30+
*/
31+
void spawn();
32+
33+
/**
34+
* Removes the hologram from the world.
35+
*/
36+
void despawn();
37+
38+
/**
39+
* @return whether the hologram is currently spawned
40+
*/
41+
boolean isSpawned();
42+
}
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
package gg.nextforge.textblockitemdisplay;
2+
3+
import gg.nextforge.NextCorePlugin;
4+
import gg.nextforge.command.CommandContext;
5+
import gg.nextforge.command.CommandManager;
6+
import gg.nextforge.text.TextManager;
7+
import org.bukkit.Location;
8+
import org.bukkit.Material;
9+
import org.bukkit.entity.Player;
10+
import org.bukkit.inventory.ItemStack;
11+
12+
/**
13+
* Command handling for hologram operations.
14+
*/
15+
public class HologramCommand {
16+
private final NextCorePlugin plugin;
17+
private final HologramManager manager;
18+
private final TextManager text;
19+
20+
public HologramCommand(NextCorePlugin plugin, HologramManager manager) {
21+
this.plugin = plugin;
22+
this.manager = manager;
23+
this.text = plugin.getTextManager();
24+
register();
25+
}
26+
27+
private void register() {
28+
CommandManager cm = plugin.getCommandManager();
29+
cm.command("hologram")
30+
.permission("nextforge.command.hologram")
31+
.description("Manage holograms")
32+
.executor(this::handleHelp)
33+
.subcommand("help", this::handleHelp)
34+
.subcommand("list", this::handleList)
35+
.subcommand("nearby", this::handleNearby)
36+
.subcommand("create", this::handleCreate)
37+
.subcommand("remove", this::handleRemove)
38+
.subcommand("copy", this::handleCopy)
39+
.subcommand("info", this::handleInfo)
40+
.register();
41+
}
42+
43+
private void handleHelp(CommandContext ctx) {
44+
text.send(ctx.sender(), "<gray>/hologram list</gray> - list holograms");
45+
text.send(ctx.sender(), "<gray>/hologram create (type) (name)</gray>");
46+
}
47+
48+
private void handleList(CommandContext ctx) {
49+
for (Hologram h : manager.getHolograms()) {
50+
text.send(ctx.sender(), " - " + h.getName());
51+
}
52+
}
53+
54+
private void handleNearby(CommandContext ctx) {
55+
if (!(ctx.sender() instanceof Player player)) {
56+
text.send(ctx.sender(), "Only players");
57+
return;
58+
}
59+
double range = 10;
60+
if (ctx.args().length > 0) {
61+
try {
62+
range = Double.parseDouble(ctx.args()[0]);
63+
} catch (NumberFormatException e) {
64+
text.send(ctx.sender(), "Invalid range. Please provide a valid number.");
65+
return;
66+
}
67+
}
68+
Location loc = player.getLocation();
69+
for (Hologram h : manager.getHolograms()) {
70+
if (h.getLocation().getWorld().equals(loc.getWorld()) &&
71+
h.getLocation().distance(loc) <= range) {
72+
text.send(player, " - " + h.getName());
73+
}
74+
}
75+
}
76+
77+
private void handleCreate(CommandContext ctx) {
78+
if (!(ctx.sender() instanceof Player player)) {
79+
text.send(ctx.sender(), "Only players");
80+
return;
81+
}
82+
if (ctx.args().length < 2) {
83+
text.send(ctx.sender(), "Usage: /hologram create (type) (name)");
84+
return;
85+
}
86+
String type = ctx.args()[0].toLowerCase();
87+
String name = ctx.args()[1];
88+
Location loc = player.getLocation();
89+
switch (type) {
90+
case "text" -> manager.createTextHologram(name, loc);
91+
case "item" -> manager.createItemHologram(name, loc, player.getInventory().getItemInMainHand());
92+
case "block" -> manager.createBlockHologram(name, loc, Material.STONE);
93+
default -> {
94+
text.send(ctx.sender(), "Unknown type");
95+
return;
96+
}
97+
}
98+
text.send(ctx.sender(), "Created hologram " + name);
99+
}
100+
101+
private void handleRemove(CommandContext ctx) {
102+
if (ctx.args().length < 1) {
103+
text.send(ctx.sender(), "Usage: /hologram remove (name)");
104+
return;
105+
}
106+
manager.remove(ctx.args()[0]);
107+
text.send(ctx.sender(), "Removed hologram");
108+
}
109+
110+
private void handleCopy(CommandContext ctx) {
111+
if (ctx.args().length < 2) {
112+
text.send(ctx.sender(), "Usage: /hologram copy (src) (dest)");
113+
return;
114+
}
115+
Hologram src = manager.get(ctx.args()[0]);
116+
if (src == null) {
117+
text.send(ctx.sender(), "Not found");
118+
return;
119+
}
120+
Location loc = src.getLocation();
121+
if (src instanceof TextHologram th) {
122+
TextHologram nh = manager.createTextHologram(ctx.args()[1], loc);
123+
th.getLines().forEach(nh::addLine);
124+
} else if (src instanceof ItemHologram ih) {
125+
manager.createItemHologram(ctx.args()[1], loc, ih.getItem());
126+
} else if (src instanceof BlockHologram bh) {
127+
manager.createBlockHologram(ctx.args()[1], loc, bh.getBlockType());
128+
}
129+
text.send(ctx.sender(), "Copied hologram");
130+
}
131+
132+
private void handleInfo(CommandContext ctx) {
133+
if (ctx.args().length < 1) {
134+
text.send(ctx.sender(), "Usage: /hologram info (name)");
135+
return;
136+
}
137+
Hologram h = manager.get(ctx.args()[0]);
138+
if (h == null) {
139+
text.send(ctx.sender(), "Not found");
140+
return;
141+
}
142+
text.send(ctx.sender(), "Name: " + h.getName());
143+
text.send(ctx.sender(), "Location: " + h.getLocation().toVector());
144+
if (h instanceof TextHologram th) {
145+
text.send(ctx.sender(), "Lines: " + th.getLines().size());
146+
}
147+
if (h instanceof ItemHologram ih) {
148+
ItemStack item = ih.getItem();
149+
text.send(ctx.sender(), "Item: " + item.getType());
150+
}
151+
if (h instanceof BlockHologram bh) {
152+
text.send(ctx.sender(), "Block: " + bh.getBlockType());
153+
}
154+
}
155+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package gg.nextforge.textblockitemdisplay;
2+
3+
import gg.nextforge.textblockitemdisplay.impl.SimpleBlockHologram;
4+
import gg.nextforge.textblockitemdisplay.impl.SimpleItemHologram;
5+
import gg.nextforge.textblockitemdisplay.impl.SimpleTextHologram;
6+
import org.bukkit.Location;
7+
import org.bukkit.Material;
8+
import org.bukkit.inventory.ItemStack;
9+
10+
import java.util.ArrayList;
11+
import java.util.List;
12+
import java.util.Map;
13+
import java.util.concurrent.ConcurrentHashMap;
14+
15+
/**
16+
* Manager responsible for creating and storing holograms.
17+
*/
18+
public class HologramManager {
19+
private final Map<String, Hologram> holograms = new ConcurrentHashMap<>();
20+
21+
/**
22+
* Creates a text hologram.
23+
*
24+
* @param name hologram name
25+
* @param location spawn location
26+
* @return created hologram
27+
*/
28+
public TextHologram createTextHologram(String name, Location location) {
29+
TextHologram holo = new SimpleTextHologram(name, location);
30+
holograms.put(name.toLowerCase(), holo);
31+
return holo;
32+
}
33+
34+
/**
35+
* Creates an item hologram.
36+
*
37+
* @param name hologram name
38+
* @param location spawn location
39+
* @param item item to display
40+
* @return created hologram
41+
*/
42+
public ItemHologram createItemHologram(String name, Location location, ItemStack item) {
43+
ItemHologram holo = new SimpleItemHologram(name, location, item);
44+
holograms.put(name.toLowerCase(), holo);
45+
return holo;
46+
}
47+
48+
/**
49+
* Creates a block hologram.
50+
*
51+
* @param name hologram name
52+
* @param location spawn location
53+
* @param material block material
54+
* @return created hologram
55+
*/
56+
public BlockHologram createBlockHologram(String name, Location location, Material material) {
57+
BlockHologram holo = new SimpleBlockHologram(name, location, material);
58+
holograms.put(name.toLowerCase(), holo);
59+
return holo;
60+
}
61+
62+
/**
63+
* Removes a hologram by name.
64+
*
65+
* @param name the name of the hologram to remove
66+
* If no hologram exists with the given name, no action is taken.
67+
*/
68+
public void remove(String name) {
69+
Hologram h = holograms.remove(name.toLowerCase());
70+
if (h != null) {
71+
h.despawn();
72+
}
73+
}
74+
75+
/**
76+
* Retrieves a hologram by its name.
77+
*
78+
* @param name the name of the hologram to retrieve
79+
* @return the hologram associated with the given name, or {@code null} if no such hologram exists
80+
*/
81+
public Hologram get(String name) {
82+
return holograms.get(name.toLowerCase());
83+
}
84+
85+
/**
86+
* @return list of all holograms.
87+
*/
88+
public List<Hologram> getHolograms() {
89+
return new ArrayList<>(holograms.values());
90+
}
91+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package gg.nextforge.textblockitemdisplay;
2+
3+
import org.bukkit.inventory.ItemStack;
4+
5+
/**
6+
* Represents a hologram displaying an item.
7+
*/
8+
public interface ItemHologram extends Hologram {
9+
/**
10+
* @return item displayed by the hologram.
11+
*/
12+
ItemStack getItem();
13+
14+
/**
15+
* Sets the item to display.
16+
*
17+
* @param item new item
18+
*/
19+
void setItem(ItemStack item);
20+
}

0 commit comments

Comments
 (0)