Last active
February 23, 2021 08:03
-
-
Save Oskang09/b0e34fb081a9de7906c24b432b7bc08a to your computer and use it in GitHub Desktop.
Minecraft Inventory UI API inspired by React
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package me.ms.plugin.inventory; | |
public class ExampleInventory extends InventoryUI<ExampleInventory.Props, ExampleInventory.State> { | |
protected ExampleInventory(Props props) { | |
super("ExampleInventory", 54, props, null); | |
} | |
public class Props { | |
} | |
public class State { | |
} | |
@Override | |
protected InventoryOptions options() { | |
return InventoryOptions.DEFAULT; | |
} | |
@Override | |
protected State initialState() { | |
return new State(); | |
} | |
@Override | |
protected void disposeState() { | |
} | |
@Override | |
protected void render() { | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package me.ms.plugin.inventory; | |
import org.bukkit.entity.Player; | |
import org.bukkit.event.EventHandler; | |
import org.bukkit.event.EventPriority; | |
import org.bukkit.event.Listener; | |
import org.bukkit.event.inventory.InventoryClickEvent; | |
import org.bukkit.event.inventory.InventoryCloseEvent; | |
import org.bukkit.plugin.java.JavaPlugin; | |
import java.util.HashMap; | |
import java.util.LinkedList; | |
import java.util.Map; | |
public class InventoryListener implements Listener { | |
private static Map<String, LinkedList<InventoryUI>> inventories; | |
private static boolean registered; | |
protected static void register(JavaPlugin plugin) { | |
registered = true; | |
inventories = new HashMap<>(); | |
plugin.getServer().getPluginManager().registerEvents(new InventoryListener(), plugin); | |
} | |
protected static boolean isRegistered() { | |
return registered; | |
} | |
protected static void replace(Player player, InventoryUI inventoryUI) { | |
String uuid = player.getUniqueId().toString(); | |
LinkedList<InventoryUI> lists = new LinkedList<>(); | |
InventoryUI instance = inventoryUI; | |
if (!instance.options().isGlobalSharedInventory) { | |
instance = inventoryUI.clone(); | |
} | |
lists.addFirst(instance); | |
player.closeInventory(); | |
inventories.replace(uuid, lists); | |
player.openInventory(instance.getInventory()); | |
instance.render(); | |
} | |
protected static void push(Player player, InventoryUI inventoryUI) { | |
String uuid = player.getUniqueId().toString(); | |
inventories.compute(uuid, (__, lists) -> { | |
if (lists == null) { | |
lists = new LinkedList<>(); | |
} | |
InventoryUI instance = inventoryUI; | |
if (!instance.options().isGlobalSharedInventory) { | |
instance = inventoryUI.clone(); | |
} | |
lists.addFirst(instance); | |
player.closeInventory(); | |
player.openInventory(instance.getInventory()); | |
instance.render(); | |
return lists; | |
}); | |
} | |
protected static void pop(Player player) { | |
String uuid = player.getUniqueId().toString(); | |
inventories.compute(uuid, (__, lists) -> { | |
InventoryUI last = lists.removeFirst(); | |
player.closeInventory(); | |
last.disposeState(); | |
if (lists.size() == 0) { | |
return null; | |
} | |
InventoryUI instance = lists.getFirst(); | |
if (instance.options().refreshStateWhenGoBack) { | |
instance.state = instance.initialState(); | |
} | |
player.openInventory(instance.getInventory()); | |
if (instance.options().renderWhenGoBack) { | |
instance.render(); | |
} | |
return lists; | |
}); | |
} | |
private InventoryListener() {} | |
@EventHandler(priority = EventPriority.MONITOR) | |
public void onClick(InventoryClickEvent event) { | |
String uuid = event.getWhoClicked().getUniqueId().toString(); | |
LinkedList<InventoryUI> inventoryList = inventories.getOrDefault(uuid, null); | |
if (inventoryList == null || inventoryList.size() == 0) { | |
return; | |
} | |
InventoryUI inventory = inventoryList.getFirst(); | |
if (event.getClickedInventory() == inventory.getInventory()) { | |
event.setCancelled(!inventory.options().clickableByDefault); | |
inventory.click(event); | |
} | |
} | |
@EventHandler(priority = EventPriority.MONITOR) | |
public void onClose(InventoryCloseEvent event) { | |
Player player = (Player) event.getPlayer(); | |
String uuid = event.getPlayer().getUniqueId().toString(); | |
LinkedList<InventoryUI> inventoryList = inventories.getOrDefault(uuid, null); | |
if (inventoryList == null || inventoryList.size() == 0) { | |
return; | |
} | |
InventoryUI inventory = inventoryList.getFirst(); | |
if (inventory.options().closableByEvent) { | |
pop(player); | |
return; | |
} | |
player.openInventory(inventory.getInventory()); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package me.ms.plugin.inventory; | |
public class InventoryOptions { | |
public static InventoryOptions DEFAULT = new InventoryOptions(); | |
public boolean clickableByDefault; | |
public boolean closableByEvent; | |
public boolean refreshStateWhenGoBack; | |
public boolean renderWhenGoBack; | |
public boolean isGlobalSharedInventory; | |
public InventoryOptions() { | |
clickableByDefault = false; | |
closableByEvent = true; | |
refreshStateWhenGoBack = false; | |
renderWhenGoBack = false; | |
isGlobalSharedInventory = false; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package me.ms.plugin.inventory; | |
import lombok.Getter; | |
import org.bukkit.Bukkit; | |
import org.bukkit.entity.Player; | |
import org.bukkit.event.inventory.InventoryClickEvent; | |
import org.bukkit.event.inventory.InventoryType; | |
import org.bukkit.inventory.Inventory; | |
import org.bukkit.inventory.ItemStack; | |
import org.bukkit.plugin.java.JavaPlugin; | |
import java.util.HashMap; | |
import java.util.Map; | |
import java.util.function.Consumer; | |
import java.util.function.Function; | |
public abstract class InventoryUI<P, S> implements Cloneable { | |
public static void register(JavaPlugin plugin) { | |
InventoryListener.register(plugin); | |
} | |
@Getter | |
protected Inventory inventory; | |
private final Map<Integer, Consumer<InventoryClickEvent>> actions; | |
@Getter | |
protected S state; | |
@Getter | |
protected P props; | |
protected abstract InventoryOptions options(); | |
protected abstract S initialState(); | |
protected abstract void render(); | |
protected abstract void disposeState(); | |
protected void setState(Function<S,S> update) { | |
setState(update.apply(this.state)); | |
} | |
protected void setState(S state) { | |
this.state = state; | |
this.render(); | |
} | |
protected void set(int index, ItemStack item) { | |
this.set(index, item, null); | |
} | |
protected void set(int index, ItemStack item, Consumer<InventoryClickEvent> action) { | |
this.inventory.setItem(index, item); | |
if (action != null) { | |
this.actions.put(index, action); | |
} | |
} | |
protected void set(int[] index, ItemStack item) { | |
this.set(index, item, null); | |
} | |
protected void set(int[] index, ItemStack item, Consumer<InventoryClickEvent> action) { | |
for ( int i = 0; i < index.length; i++) { | |
this.inventory.setItem(i, item); | |
if (action != null) { | |
this.actions.put(i, action); | |
} | |
} | |
} | |
protected void push(Player player, InventoryUI inventoryUI) { | |
InventoryListener.push(player, inventoryUI); | |
} | |
protected void pop(Player player) { | |
InventoryListener.pop(player); | |
} | |
void click(InventoryClickEvent event) { | |
Consumer<InventoryClickEvent> action = this.actions.getOrDefault(event.getSlot(), null); | |
if (action != null) { | |
action.accept(event); | |
} | |
} | |
protected InventoryUI(P props, S state) { | |
if (!InventoryListener.isRegistered()) { | |
throw new IllegalStateException("Disabling InventoryUI because InventoryListener hasn't registered."); | |
} | |
this.actions = new HashMap<>(); | |
this.props = props; | |
this.state = state; | |
if (state == null) { | |
this.state = initialState(); | |
} | |
} | |
public InventoryUI(InventoryType type, String title, P props, S state) { | |
this(props, state); | |
this.inventory = Bukkit.createInventory(null, type, title); | |
} | |
public InventoryUI(InventoryType type, P props, S state) { | |
this(props, state); | |
this.inventory = Bukkit.createInventory(null, type); | |
} | |
public InventoryUI(String title, int size, P props, S state) { | |
this(props, state); | |
this.inventory = Bukkit.createInventory(null, size, title); | |
} | |
@Override | |
protected InventoryUI clone() { | |
try { | |
return (InventoryUI) super.clone(); | |
} catch (CloneNotSupportedException e) { | |
e.printStackTrace(); | |
} | |
return null; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment