Skip to content

Commit

Permalink
Add crafter gui
Browse files Browse the repository at this point in the history
  • Loading branch information
stefvanschie committed Jan 4, 2024
1 parent 076a981 commit 287c93b
Show file tree
Hide file tree
Showing 2 changed files with 327 additions and 1 deletion.
2 changes: 1 addition & 1 deletion IF/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.19.4-R0.1-SNAPSHOT</version>
<version>1.20.3-R0.1-SNAPSHOT</version>
<scope>provided</scope>
<exclusions>
<!-- Provided, but not accessible -->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,326 @@
package com.github.stefvanschie.inventoryframework.gui.type;

import com.github.stefvanschie.inventoryframework.HumanEntityCache;
import com.github.stefvanschie.inventoryframework.adventuresupport.TextHolder;
import com.github.stefvanschie.inventoryframework.exception.XMLLoadException;
import com.github.stefvanschie.inventoryframework.gui.InventoryComponent;
import com.github.stefvanschie.inventoryframework.gui.type.util.InventoryBased;
import com.github.stefvanschie.inventoryframework.gui.type.util.NamedGui;
import org.bukkit.entity.HumanEntity;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
* Represents a gui in the form of a crafter.
*
* @since 0.10.13
*/
public class CrafterGui extends NamedGui implements InventoryBased {

/**
* Represents the inventory component for the input
*/
@NotNull
private InventoryComponent inputComponent = new InventoryComponent(3, 3);

/**
* Represents the inventory component for the player inventory
*/
@NotNull
private InventoryComponent playerInventoryComponent = new InventoryComponent(9, 4);

/**
* Constructs a new crafter gui.
*
* @param title the title/name of this gui
* @since 0.10.13
*/
public CrafterGui(@NotNull String title) {
super(title);
}

/**
* Constructs a new crafter gui.
*
* @param title the title/name of this gui
* @since 0.10.13
*/
public CrafterGui(@NotNull TextHolder title) {
super(title);
}

/**
* Constructs a new crafter gui for the given {@code plugin}.
*
* @param title the title/name of this gui
* @param plugin the owning plugin of this gui
* @see #CrafterGui(String)
* @since 0.10.13
*/
public CrafterGui(@NotNull String title, @NotNull Plugin plugin) {
super(title, plugin);
}

/**
* Constructs a new crafter gui for the given {@code plugin}.
*
* @param title the title/name of this gui
* @param plugin the owning plugin of this gui
* @see #CrafterGui(TextHolder)
* @since 0.10.13
*/
public CrafterGui(@NotNull TextHolder title, @NotNull Plugin plugin) {
super(title, plugin);
}

@Override
public void show(@NotNull HumanEntity humanEntity) {
if (isDirty()) {
this.inventory = createInventory();
markChanges();
}

getInventory().clear();

getInputComponent().display(getInventory(), 0);
getPlayerInventoryComponent().display();

if (getPlayerInventoryComponent().hasItem()) {
HumanEntityCache humanEntityCache = getHumanEntityCache();

if (!humanEntityCache.contains(humanEntity)) {
humanEntityCache.storeAndClear(humanEntity);
}

getPlayerInventoryComponent().placeItems(humanEntity.getInventory(), 0);
}

humanEntity.openInventory(getInventory());
}

@NotNull
@Contract(pure = true)
@Override
public CrafterGui copy() {
CrafterGui gui = new CrafterGui(getTitleHolder(), super.plugin);

gui.inputComponent = inputComponent.copy();
gui.playerInventoryComponent = playerInventoryComponent.copy();

gui.setOnTopClick(this.onTopClick);
gui.setOnBottomClick(this.onBottomClick);
gui.setOnGlobalClick(this.onGlobalClick);
gui.setOnOutsideClick(this.onOutsideClick);
gui.setOnClose(this.onClose);

return gui;
}

@Override
public void click(@NotNull InventoryClickEvent event) {
int rawSlot = event.getRawSlot();

if (rawSlot >= 0 && rawSlot <= 8) {
getInputComponent().click(this, event, rawSlot);
} else {
getPlayerInventoryComponent().click(this, event, rawSlot - 9);
}
}

@NotNull
@Override
public Inventory getInventory() {
if (this.inventory == null) {
this.inventory = createInventory();
}

return inventory;
}

@Contract(pure = true)
@Override
public boolean isPlayerInventoryUsed() {
return getPlayerInventoryComponent().hasItem();
}

@NotNull
@Contract(pure = true)
@Override
public Inventory createInventory() {
//noinspection UnstableApiUsage
Inventory inventory = getTitleHolder().asInventoryTitle(this, InventoryType.CRAFTER);

addInventory(inventory, this);

return inventory;
}

@Contract(pure = true)
@Override
public int getViewerCount() {
return getInventory().getViewers().size();
}

@NotNull
@Contract(pure = true)
@Override
public List<HumanEntity> getViewers() {
return new ArrayList<>(getInventory().getViewers());
}

/**
* Gets the inventory component representing the input.
*
* @return the input component
* @since 0.10.13
*/
@NotNull
@Contract(pure = true)
public InventoryComponent getInputComponent() {
return inputComponent;
}

/**
* Gets the inventory component representing the player inventory.
*
* @return the player inventory component
* @since 0.10.13
*/
@NotNull
@Contract(pure = true)
public InventoryComponent getPlayerInventoryComponent() {
return playerInventoryComponent;
}

/**
* Loads a crafter gui from an XML file.
*
* @param instance the instance on which to reference fields and methods
* @param inputStream the input stream containing the XML data
* @param plugin the plugin that will be the owner of the created gui
* @return the loaded crafter gui
* @see #load(Object, InputStream)
* @since 0.10.13
*/
@Nullable
@Contract(pure = true)
public static CrafterGui load(@NotNull Object instance, @NotNull InputStream inputStream,
@NotNull Plugin plugin) {
try {
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(inputStream);
Element documentElement = document.getDocumentElement();

documentElement.normalize();

return load(instance, documentElement, plugin);
} catch (SAXException | ParserConfigurationException | IOException e) {
e.printStackTrace();
return null;
}
}

/**
* Loads a crafter gui from the specified element, applying code references to the provided instance.
*
* @param instance the instance on which to reference fields and methods
* @param element the element to load the gui from
* @param plugin the plugin that will be the owner of the created gui
* @return the loaded crafter gui
* @since 0.10.13
*/
@NotNull
public static CrafterGui load(@NotNull Object instance, @NotNull Element element, @NotNull Plugin plugin) {
if (!element.hasAttribute("title")) {
throw new XMLLoadException("Provided XML element's gui tag doesn't have the mandatory title attribute set");
}

CrafterGui crafterGui = new CrafterGui(element.getAttribute("title"), plugin);
crafterGui.initializeOrThrow(instance, element);

if (element.hasAttribute("populate")) {
return crafterGui;
}

NodeList childNodes = element.getChildNodes();

for (int index = 0; index < childNodes.getLength(); index++) {
Node item = childNodes.item(index);

if (item.getNodeType() != Node.ELEMENT_NODE) {
continue;
}

Element componentElement = (Element) item;

if (!componentElement.getTagName().equalsIgnoreCase("component")) {
throw new XMLLoadException("Gui element contains non-component tags");
}

if (!componentElement.hasAttribute("name")) {
throw new XMLLoadException("Component tag does not have a name specified");
}

InventoryComponent component;

switch (componentElement.getAttribute("name")) {
case "input":
component = crafterGui.getInputComponent();
break;
case "player-inventory":
component = crafterGui.getPlayerInventoryComponent();
break;
default:
throw new XMLLoadException("Unknown component name");
}

component.load(instance, componentElement, plugin);
}

return crafterGui;
}

/**
* Loads a crafter gui from an XML file.
*
* @param instance the instance on which to reference fields and methods
* @param inputStream the input stream containing the XML data
* @return the loaded crafter gui
* @since 0.10.13
*/
@Nullable
@Contract(pure = true)
public static CrafterGui load(@NotNull Object instance, @NotNull InputStream inputStream) {
return load(instance, inputStream, JavaPlugin.getProvidingPlugin(CrafterGui.class));
}

/**
* Loads a crafter gui from the specified element, applying code references to the provided instance.
*
* @param instance the instance on which to reference fields and methods
* @param element the element to load the gui from
* @return the loaded crafting table gui
* @since 0.10.13
*/
@NotNull
public static CrafterGui load(@NotNull Object instance, @NotNull Element element) {
return load(instance, element, JavaPlugin.getProvidingPlugin(CrafterGui.class));
}
}

0 comments on commit 287c93b

Please sign in to comment.