Skip to content

Commit 941f7f9

Browse files
committed
Implement value request system with multiple input methods
- Added BookInputManager for input via writable books. - Introduced SignInputManager for input through in-game signs. - Created InventoryRequestManager for selecting values via inventory. - Added support for multiple input types: STRING, NUMBER, BOOLEAN. - Implemented PlayerInputManager to manage player-specific input preferences. - Developed ValueRequest class to handle value requests with fallback options.
1 parent 022887b commit 941f7f9

File tree

10 files changed

+1554
-0
lines changed

10 files changed

+1554
-0
lines changed
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package com.bencodez.simpleapi.valuerequest;
2+
3+
import java.util.Map;
4+
import java.util.UUID;
5+
import java.util.concurrent.ConcurrentHashMap;
6+
import java.util.function.Consumer;
7+
8+
import org.bukkit.Bukkit;
9+
import org.bukkit.Material;
10+
import org.bukkit.entity.Player;
11+
import org.bukkit.event.EventHandler;
12+
import org.bukkit.event.Listener;
13+
import org.bukkit.event.player.PlayerEditBookEvent;
14+
import org.bukkit.inventory.ItemStack;
15+
import org.bukkit.plugin.Plugin;
16+
17+
/**
18+
* Handles book based value requests. When a player is asked to provide input via
19+
* a book they are given a writable book. Once the book is signed the input is
20+
* read and passed to the provided callback.
21+
*/
22+
public class BookInputManager implements Listener {
23+
24+
/**
25+
* Flag indicating whether the listener has been registered with the
26+
* server's plugin manager.
27+
*/
28+
private static boolean registered = false;
29+
30+
/**
31+
* The plugin responsible for registering this listener. Stored for future
32+
* requests to ensure correct registration.
33+
*/
34+
private static Plugin plugin;
35+
36+
/**
37+
* Map of player unique identifiers to their pending input callbacks.
38+
*/
39+
private static final Map<UUID, Consumer<String>> callbacks = new ConcurrentHashMap<>();
40+
41+
/**
42+
* Initialise the book input manager. Registers the event listener with the
43+
* plugin manager if it has not already been registered.
44+
*
45+
* @param p the plugin instance used for registration
46+
*/
47+
public static void initialize(Plugin p) {
48+
if (!registered) {
49+
plugin = p;
50+
Bukkit.getPluginManager().registerEvents(new BookInputManager(), p);
51+
registered = true;
52+
}
53+
}
54+
55+
/**
56+
* Prompt a player to provide a value via a writable book. The player will
57+
* receive a book in their inventory. Once the book is edited and signed the
58+
* contents of all pages will be concatenated and delivered to the provided
59+
* callback.
60+
*
61+
* @param player the player who will receive the book and provide input
62+
* @param start the starting value to display in the book (unused in this
63+
* implementation but reserved for future use)
64+
* @param callback the callback to invoke with the input once the player
65+
* finishes editing the book
66+
*/
67+
public static void requestBookInput(Player player, String start, Consumer<String> callback) {
68+
// Ensure the listener is registered with the current plugin
69+
if (!registered && plugin != null) {
70+
initialize(plugin);
71+
}
72+
callbacks.put(player.getUniqueId(), callback);
73+
ItemStack book = new ItemStack(Material.WRITABLE_BOOK);
74+
player.getInventory().addItem(book);
75+
player.sendMessage("Please write your value in the book and sign it to submit.");
76+
}
77+
78+
/**
79+
* Event handler for when a player edits and signs a book. If the player has
80+
* a pending callback in the callbacks map the contents of the book are
81+
* concatenated and supplied to the callback. The callback is then removed.
82+
*
83+
* @param event the book edit event
84+
*/
85+
@EventHandler
86+
public void onPlayerEditBook(PlayerEditBookEvent event) {
87+
Player player = event.getPlayer();
88+
UUID uuid = player.getUniqueId();
89+
if (!callbacks.containsKey(uuid)) {
90+
return;
91+
}
92+
Consumer<String> callback = callbacks.remove(uuid);
93+
if (callback == null) {
94+
return;
95+
}
96+
StringBuilder sb = new StringBuilder();
97+
for (String page : event.getNewBookMeta().getPages()) {
98+
if (page != null) {
99+
sb.append(page);
100+
}
101+
}
102+
callback.accept(sb.toString());
103+
}
104+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.bencodez.simpleapi.valuerequest;
2+
3+
import org.bukkit.entity.Player;
4+
5+
/**
6+
* Callback interface for when a boolean value has been provided by a player.
7+
*/
8+
@FunctionalInterface
9+
public interface BooleanListener {
10+
/**
11+
* Invoked when the player submits a boolean value.
12+
*
13+
* @param player the player who provided the input
14+
* @param value the submitted boolean value
15+
*/
16+
void onInput(Player player, boolean value);
17+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package com.bencodez.simpleapi.valuerequest;
2+
3+
/**
4+
* Represents the different input mechanisms available when requesting a value
5+
* from a player. DIALOG is preferred on modern servers with UniDialog
6+
* support. CHAT falls back to simple chat prompts when no dialog platform
7+
* is available or when running on older versions.
8+
*/
9+
public enum InputMethod {
10+
/**
11+
* Use a UniDialog multi action dialog. This provides a GUI with buttons
12+
* and inputs where available.
13+
*/
14+
DIALOG,
15+
/**
16+
* Use a chat based conversation. Players type their response into chat.
17+
*/
18+
CHAT,
19+
/**
20+
* Use an in-game inventory interface for selecting options. When using this
21+
* method, options are presented as items in a chest-style inventory and a
22+
* player may click to select a value. If custom input is allowed a special
23+
* item will appear that directs the player to the chat input fallback.
24+
*/
25+
INVENTORY,
26+
/**
27+
* Use a writable book and quill for input. When this method is selected the
28+
* player receives a book in their inventory and must write their response
29+
* inside. Once the book is signed the input is captured and processed.
30+
*/
31+
BOOK,
32+
33+
/**
34+
* Use a sign editing interface for input. When selected the player will be
35+
* shown a sign where they can type text across multiple lines. Upon
36+
* confirmation the text from the sign will be passed to the value request
37+
* handler. This method is useful on some server versions that support
38+
* {@link org.bukkit.entity.Player#openSign(org.bukkit.block.Sign)}. It
39+
* behaves similarly to {@link #BOOK} but uses a sign instead of a
40+
* writable book.
41+
*/
42+
SIGN;
43+
44+
/**
45+
* Attempt to parse an input method from a string. If the value is not
46+
* recognised this method returns {@link #DIALOG} by default.
47+
*
48+
* @param method the method name to parse
49+
* @return the resolved input method
50+
*/
51+
public static InputMethod getMethod(String method) {
52+
if (method != null) {
53+
for (InputMethod input : values()) {
54+
if (input.toString().equalsIgnoreCase(method)) {
55+
return input;
56+
}
57+
}
58+
}
59+
return DIALOG;
60+
}
61+
}

0 commit comments

Comments
 (0)