├── META-INF
└── MANIFEST.MF
├── src
└── main
│ └── java
│ └── com
│ └── codehusky
│ └── huskyui
│ ├── states
│ ├── element
│ │ ├── package-info.java
│ │ ├── Element.java
│ │ └── ActionableElement.java
│ ├── action
│ │ ├── runnable
│ │ │ ├── package-info.java
│ │ │ ├── UIRunnable.java
│ │ │ └── RunnableAction.java
│ │ ├── package-info.java
│ │ ├── ActionType.java
│ │ ├── CommandAction.java
│ │ └── Action.java
│ ├── package-info.java
│ ├── State.java
│ └── Page.java
│ ├── package-info.java
│ ├── InventoryUtil.java
│ ├── StateContainer.java
│ ├── ElementRegistry.java
│ └── HuskyUI.java
├── .gitignore
├── pom.xml
├── README.md
└── LICENSE
/META-INF/MANIFEST.MF:
--------------------------------------------------------------------------------
1 | Manifest-Version: 1.0
2 |
3 |
--------------------------------------------------------------------------------
/src/main/java/com/codehusky/huskyui/states/element/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Contains the types of {@link com.codehusky.huskyui.states.element.Element}s
3 | * to be used in a {@link com.codehusky.huskyui.states.Page}.
4 | */
5 | package com.codehusky.huskyui.states.element;
--------------------------------------------------------------------------------
/src/main/java/com/codehusky/huskyui/states/action/runnable/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * When {@link com.codehusky.huskyui.states.action.Action}s just aren't enough,
3 | * and developers wanna perform neat actions when their GUIs are used.
4 | */
5 | package com.codehusky.huskyui.states.action.runnable;
--------------------------------------------------------------------------------
/src/main/java/com/codehusky/huskyui/states/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Contains the {@link com.codehusky.huskyui.states.State} and
3 | * {@link com.codehusky.huskyui.states.Page} classes, meant to
4 | * facilitate data to a player in the form of a chest-based GUI.
5 | */
6 | package com.codehusky.huskyui.states;
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.class
2 |
3 | # Mobile Tools for Java (J2ME)
4 | .mtj.tmp/
5 |
6 | # Package Files #
7 | *.jar
8 | *.war
9 | *.ear
10 |
11 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
12 | hs_err_pid*
13 | .idea/
14 | *.iml
15 | target/
16 |
17 | # gradle
18 | .gradle/
19 | build/
--------------------------------------------------------------------------------
/src/main/java/com/codehusky/huskyui/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Main package for HuskyUI.
3 | *
4 | *
Contains the main {@link org.spongepowered.api.plugin.Plugin}
5 | * annotated class for loading by Sponge. Also contains the container
6 | * for {@link com.codehusky.huskyui.states.State}s.
7 | */
8 | package com.codehusky.huskyui;
--------------------------------------------------------------------------------
/src/main/java/com/codehusky/huskyui/states/action/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Actions, primarily, are the tool to move {@link org.spongepowered.api.entity.living.player.Player}s
3 | * throughout the GUI interface. Those actions are defined in this package.
4 | *
5 | *
Notice {@link com.codehusky.huskyui.states.action.runnable.RunnableAction} in the child
6 | * package of this one, where other, developer-defined actions can be determined based on
7 | * a Player's selection.
8 | */
9 | package com.codehusky.huskyui.states.action;
--------------------------------------------------------------------------------
/src/main/java/com/codehusky/huskyui/InventoryUtil.java:
--------------------------------------------------------------------------------
1 | package com.codehusky.huskyui;
2 |
3 | import org.spongepowered.api.entity.living.player.Player;
4 | import org.spongepowered.api.item.inventory.Inventory;
5 | import org.spongepowered.api.scheduler.Task;
6 |
7 | public class InventoryUtil {
8 | public static void close(Player player) {
9 | Task.builder().execute(()->
10 | player.closeInventory()
11 | ).delayTicks(1).submit(HuskyUI.getInstance());
12 | }
13 |
14 | public static void open(Player player, Inventory inventory) {
15 | Task.builder().execute(()-> {
16 | player.openInventory(inventory);
17 | }).delayTicks(1).submit(HuskyUI.getInstance());
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/com/codehusky/huskyui/states/action/runnable/UIRunnable.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HuskyUI.
3 | *
4 | * HuskyUI is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HuskyUI is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with HuskyUI. If not, see .
16 | */
17 |
18 | package com.codehusky.huskyui.states.action.runnable;
19 |
20 | import javax.annotation.Nonnull;
21 |
22 | /**
23 | * A pre-determined action to be run when interfacing with a Page.
24 | */
25 | public interface UIRunnable {
26 |
27 | /**
28 | * The additional actions to be run when interfacing with a Page.
29 | *
30 | * @param context the RunnableAction that relates to this runnable
31 | */
32 | void run(@Nonnull final RunnableAction context);
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/com/codehusky/huskyui/states/action/ActionType.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HuskyUI.
3 | *
4 | * HuskyUI is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HuskyUI is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with HuskyUI. If not, see .
16 | */
17 |
18 | package com.codehusky.huskyui.states.action;
19 |
20 | /**
21 | * The type of {@link Action} to be performed.
22 | */
23 | public enum ActionType {
24 |
25 | /**
26 | * Triggered if a {@link org.spongepowered.api.entity.living.player.Player}
27 | * is going "Back" to the parent.
28 | */
29 | BACK,
30 |
31 | /**
32 | * Triggered if a {@link org.spongepowered.api.entity.living.player.Player}
33 | * is closing the {@link org.spongepowered.api.item.inventory.Inventory}.
34 | */
35 | CLOSE,
36 |
37 | /**
38 | * Triggered for a normal action, usually forward.
39 | */
40 | NORMAL,
41 |
42 | REFRESH,
43 |
44 | /**
45 | * This is a false flag operation. We've been swindled!
46 | * Quick, scramble the jets!
47 | */
48 | NONE
49 | }
50 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.codehusky
8 | HuskyUI
9 | 0.6.0PRE3
10 |
11 |
12 |
13 | sponge
14 | http://repo.spongepowered.org/maven
15 |
16 |
17 |
18 |
19 |
20 | org.spongepowered
21 | spongeapi
22 | 7.0.0-SNAPSHOT
23 |
24 | provided
25 |
26 |
27 | org.apache.maven.plugins
28 | maven-javadoc-plugin
29 | 3.0.0
30 | maven-plugin
31 |
32 |
33 |
34 | 1.8
35 | 1.8
36 |
37 |
38 |
39 |
40 |
41 | org.apache.maven.plugins
42 | maven-javadoc-plugin
43 | 3.0.0
44 |
45 |
46 | https://jd.spongepowered.org/7.0.0/
47 |
48 |
49 | **/Metrics.java
50 |
51 |
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/src/main/java/com/codehusky/huskyui/states/element/Element.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HuskyUI.
3 | *
4 | * HuskyUI is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HuskyUI is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with HuskyUI. If not, see .
16 | */
17 |
18 | package com.codehusky.huskyui.states.element;
19 |
20 | import com.codehusky.huskyui.StateContainer;
21 | import org.spongepowered.api.item.inventory.ItemStack;
22 | import javax.annotation.Nonnull;
23 |
24 | /**
25 | * A basic Element is, essentially, a simple wrapper for
26 | * an {@link ItemStack} and serves no purpose.
27 | */
28 | public class Element {
29 |
30 | /**
31 | * The {@link ItemStack} being wrapped.
32 | */
33 | @Nonnull private final ItemStack item;
34 |
35 | /**
36 | * Constructs a new Element.
37 | *
38 | * @param item the {@link ItemStack} to be wrapped
39 | */
40 | public Element(@Nonnull final ItemStack item) {
41 | this.item = item;
42 | }
43 |
44 | /**
45 | * Gets the {@link ItemStack} being wrapped.
46 | *
47 | * @return the wrapped ItemStack
48 | */
49 | @Nonnull
50 | public ItemStack getItem() {
51 | return this.item;
52 | }
53 |
54 | /**
55 | * Creates a copy of this Element.
56 | *
57 | * @param newContainer the {@link StateContainer} now
58 | * responsible for this Element
59 | * @return a copy of this Element
60 | */
61 | @Nonnull
62 | public Element copy(@Nonnull final StateContainer newContainer) { // We don't use this on purpose.
63 | return new Element(this.item.copy());
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/java/com/codehusky/huskyui/states/element/ActionableElement.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HuskyUI.
3 | *
4 | * HuskyUI is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HuskyUI is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with HuskyUI. If not, see .
16 | */
17 |
18 | package com.codehusky.huskyui.states.element;
19 |
20 | import com.codehusky.huskyui.StateContainer;
21 | import com.codehusky.huskyui.states.action.Action;
22 | import com.codehusky.huskyui.states.action.CommandAction;
23 | import org.spongepowered.api.item.inventory.ItemStack;
24 | import javax.annotation.Nonnull;
25 |
26 | /**
27 | * An extension of {@link Element} that also wraps
28 | * an {@link Action} to be used, typically, by an event.
29 | */
30 | public class ActionableElement extends Element {
31 |
32 | /**
33 | * The {@link Action} to be performed on
34 | * on this Element.
35 | */
36 | @Nonnull private Action action;
37 |
38 | /**
39 | * Constructs a new ActionableElement.
40 | *
41 | * @param action the {@link Action} to be performed
42 | * @param item the {@link ItemStack} this {@link Element} wraps
43 | */
44 | public ActionableElement(@Nonnull final Action action, @Nonnull final ItemStack item) {
45 | super(item);
46 | this.action = action;
47 | }
48 |
49 | /**
50 | * Gets the {@link Action} to be performed on this Element.
51 | *
52 | * @return the Action to be performed on this Element
53 | */
54 | @Nonnull
55 | public Action getAction() {
56 | return this.action;
57 | }
58 |
59 | /**
60 | * Creates a copy of this ActionableElement.
61 | *
62 | * @param newContainer the {@link StateContainer} now
63 | * responsible for this ActionableElement
64 | * @return a copy of this ActionableElement
65 | */
66 | @Nonnull
67 | @Override
68 | public ActionableElement copy(@Nonnull final StateContainer newContainer) {
69 | return new ActionableElement(this.action.copy(newContainer), this.getItem().copy());
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/main/java/com/codehusky/huskyui/states/action/CommandAction.java:
--------------------------------------------------------------------------------
1 | package com.codehusky.huskyui.states.action;
2 |
3 | import com.codehusky.huskyui.StateContainer;
4 | import com.codehusky.huskyui.states.State;
5 | import org.spongepowered.api.Sponge;
6 | import org.spongepowered.api.item.inventory.Inventory;
7 |
8 | import javax.annotation.Nonnull;
9 | /**
10 | * This class is used to handle situations requiring command execution by an item.
11 | * You should not use this class to open another UI state container, use a {@link com.codehusky.huskyui.states.action.runnable.RunnableAction} for that.
12 | */
13 | public class CommandAction extends Action {
14 | @Nonnull private final String command;
15 | @Nonnull private CommandReceiver receiver;
16 |
17 | /**
18 | * Constructs a CommandAction.
19 | *
20 | * @param container the {@link StateContainer} that is responsible for this Action
21 | * @param type the type of Action taking place
22 | * @param goalState the intended {@link State}
23 | * @param command The command intended to run
24 | */
25 | public CommandAction(@Nonnull StateContainer container, @Nonnull ActionType type, @Nonnull String goalState, @Nonnull final String command) {
26 | super(container, type, goalState);
27 | this.command = command;
28 | this.receiver = CommandReceiver.SERVER;
29 | }
30 |
31 | /**
32 | * Constructs a CommandAction.
33 | *
34 | * @param container the {@link StateContainer} that is responsible for this Action
35 | * @param type the type of Action taking place
36 | * @param goalState the intended {@link State}
37 | * @param command the command intended to run
38 | * @param receiver the {@link CommandReceiver} intended to run the command
39 | */
40 | public CommandAction(@Nonnull StateContainer container, @Nonnull ActionType type, @Nonnull String goalState,
41 | @Nonnull final String command, @Nonnull CommandReceiver receiver) {
42 | super(container, type, goalState);
43 | this.command = command;
44 | this.receiver = receiver;
45 | }
46 |
47 | @Override
48 | public void runAction(@Nonnull String currentState, Inventory inventory) {
49 | Sponge.getCommandManager().process(this.receiver == CommandReceiver.SERVER ?
50 | Sponge.getServer().getConsole() : getObserver(), this.command);
51 | super.runAction(currentState,inventory);
52 | }
53 |
54 | @Nonnull
55 | public String getCommand() {
56 | return command;
57 | }
58 |
59 | @Nonnull
60 | public CommandReceiver getReceiver() {
61 | return receiver;
62 | }
63 |
64 | /**
65 | * Set the {@link CommandReceiver} of the CommandAction
66 | *
67 | * @param receiver the {@link CommandReceiver} that will replace the previously specified one.
68 | */
69 | public void setReceiver(@Nonnull CommandReceiver receiver) {
70 | this.receiver = receiver;
71 | }
72 |
73 | public enum CommandReceiver {
74 | PLAYER,
75 | SERVER
76 | }
77 |
78 | /**
79 | * Creates a copy of this CommandAction.
80 | *
81 | * @param newContainer the new {@link StateContainer} to be responsible for this new Action
82 | * @return a copy of this Action
83 | */
84 | @Nonnull
85 | public Action copy(@Nonnull final StateContainer newContainer) {
86 | return new CommandAction(newContainer, this.getType(), this.getGoalState(),command,receiver);
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/src/main/java/com/codehusky/huskyui/states/action/runnable/RunnableAction.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HuskyUI.
3 | *
4 | * HuskyUI is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HuskyUI is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with HuskyUI. If not, see .
16 | */
17 |
18 | package com.codehusky.huskyui.states.action.runnable;
19 |
20 | import com.codehusky.huskyui.StateContainer;
21 | import com.codehusky.huskyui.states.action.Action;
22 | import com.codehusky.huskyui.states.action.ActionType;
23 | import org.spongepowered.api.item.inventory.Inventory;
24 | import org.spongepowered.api.text.Text;
25 | import org.spongepowered.api.text.format.TextColors;
26 |
27 | import javax.annotation.Nonnull;
28 | import javax.annotation.Nullable;
29 |
30 | /**
31 | * A separate type of {@link Action} which performs developer-defined
32 | * actions separate from navigating the GUI.
33 | */
34 | public class RunnableAction extends Action {
35 |
36 | /**
37 | * The UIRunnable that determines this action to be taken.
38 | */
39 | @Nullable private UIRunnable runnable;
40 |
41 | /**
42 | * Constructs a new RunnableAction without a pre-determined action.
43 | *
44 | * @param container the {@link StateContainer} responsible for this RunnableAction
45 | * @param type the type of {@link Action} being performed
46 | * @param goalState the destination for a {@link org.spongepowered.api.entity.living.player.Player}
47 | * after this Action is completed
48 | */
49 | public RunnableAction(@Nonnull final StateContainer container,
50 | @Nonnull final ActionType type,
51 | @Nonnull final String goalState) {
52 | this(container, type, goalState, null);
53 | }
54 |
55 | /**
56 | * Constructs a new RunnableAction with a pre-determined action.
57 | *
58 | * @param container the {@link StateContainer} responsible for this RunnableAction
59 | * @param type the type of {@link Action} being performed
60 | * @param goalState the destination for a {@link org.spongepowered.api.entity.living.player.Player}
61 | * after this Action is completed
62 | * @param runnable the additional Action to be performed
63 | */
64 | public RunnableAction(@Nonnull final StateContainer container,
65 | @Nonnull final ActionType type,
66 | @Nonnull final String goalState,
67 | @Nullable final UIRunnable runnable) {
68 | super(container, type, goalState);
69 | this.runnable = runnable;
70 | }
71 |
72 | /**
73 | * Gets the additional action to be performed.
74 | *
75 | * @return the additional actions to be performed
76 | */
77 | @Nullable
78 | public UIRunnable getRunnable() {
79 | return this.runnable;
80 | }
81 |
82 | /**
83 | * Sets the additional actions to be performed.
84 | *
85 | * @param runnable the additional actions to be performed
86 | */
87 | public void setRunnable(@Nonnull final UIRunnable runnable) {
88 | this.runnable = runnable;
89 | }
90 |
91 | /**
92 | * Runs the additional actions.
93 | *
94 | * @param currentState the current State before the Action is performed
95 | */
96 | @Override
97 | public void runAction(@Nonnull final String currentState, Inventory inventory) {
98 | if (this.runnable != null) {
99 | this.runnable.run(this);
100 | } else {
101 | this.getObserver().sendMessage(Text.of(TextColors.RED, "Cannot run a null action!"));
102 | }
103 | super.runAction(currentState,inventory);
104 | }
105 |
106 | /**
107 | * Creates a copy of this RunnableAction.
108 | *
109 | * @param newContainer the new {@link StateContainer} to be responsible for this new Action
110 | * @return a copy of this RunnableAction
111 | */
112 | @Nonnull
113 | @Override
114 | public RunnableAction copy(@Nonnull final StateContainer newContainer) {
115 | // UIRunnable doesn't need to be copied - it's just an action.
116 | return new RunnableAction(newContainer, this.getType(), this.getGoalState(), this.runnable);
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # HuskyUI
2 | A simple, lightweight UI system for, as of right now, chest GUIs.
3 |
4 | **[Java Docs](http://jd.codehusky.com/huskyui/)**
5 |
6 | **[Forum Topic](https://forums.spongepowered.org/t/huskyui-a-simple-fast-ui-system-for-plugins/19557/4)**
7 |
8 | **[HuskyUI Wiki](https://github.com/codeHusky/HuskyUI-Plugin/wiki)**
9 |
10 | # Implementation Examples
11 |
12 | ### Hotbar Compass using ElementRegistry
13 |
14 | ```java
15 | RunnableAction testAction = new RunnableAction(registry, ActionType.NONE,"");
16 | testAction.setRunnable(context -> {
17 | StateContainer container = new StateContainer();
18 | Page testPage = Page.builder()
19 | .setTitle(Text.of(TextColors.GOLD,"Navigator"))
20 | .setAutoPaging(true)
21 | .addElement(new Element(
22 | ItemStack.builder()
23 | .itemType(ItemTypes.DIAMOND)
24 | .add(Keys.DISPLAY_NAME,Text.of(TextColors.BLUE,"Diamond Rush"))
25 | .build()
26 | ))
27 | .addElement(new Element(
28 | ItemStack.builder()
29 | .itemType(ItemTypes.FIREWORKS)
30 | .add(Keys.DISPLAY_NAME,Text.of(TextColors.RED,"Fireworks Palooza"))
31 | .build()
32 | ))
33 | .addElement(new Element(
34 | ItemStack.builder()
35 | .itemType(ItemTypes.MINECART)
36 | .add(Keys.DISPLAY_NAME,Text.of(TextColors.GRAY,"Roller Coasters"))
37 | .build()
38 | ))
39 | .build("testpage");
40 | container.setInitialState(testPage);
41 | container.launchFor(context.getObserver());
42 | });
43 | ActionableElement testElement = new ActionableElement(
44 | testAction,
45 | ItemStack.builder()
46 | .itemType(ItemTypes.COMPASS)
47 | .add(Keys.DISPLAY_NAME, Text.of(TextColors.GOLD,"Navigator"))
48 | .build());
49 |
50 | HuskyUI.getElementRegistry().registerAutoElement(4,testElement);
51 | ItemStack litMC = ItemStack.builder()
52 | .itemType(ItemTypes.REDSTONE_TORCH)
53 | .add(Keys.DISPLAY_NAME,Text.of(TextColors.RED,"LitMC"))
54 | .build();
55 | HuskyUI.getElementRegistry().registerAutoElement(0,new Element(litMC));
56 | HuskyUI.getElementRegistry().registerAutoElement(8,new Element(litMC));
57 |
58 | HuskyUI.getElementRegistry().registerAutoElement(new Element(ItemStack.builder().itemType(ItemTypes.MINECART).add(Keys.DISPLAY_NAME,Text.of("movable 1")).build()));
59 | HuskyUI.getElementRegistry().registerAutoElement(new Element(ItemStack.builder().itemType(ItemTypes.MINECART).add(Keys.DISPLAY_NAME,Text.of("movable 2")).build()));
60 | HuskyUI.getElementRegistry().registerAutoElement(new Element(ItemStack.builder().itemType(ItemTypes.MINECART).add(Keys.DISPLAY_NAME,Text.of("movable 3")).build()));
61 | ```
62 | **Result** (with some movement of the movable carts.)
63 |
64 | 
65 |
66 | ### Generic Example
67 | ```java
68 | StateContainer container = new StateContainer();
69 | container.addState(
70 | Page.builder()
71 | .setUpdatable(true)
72 | .setUpdater(page -> {
73 | int count = 0;
74 | for(Inventory slot: page.getPageView().slots()){
75 |
76 | if(!slot.peek().isPresent() && count == page.getTicks()%page.getPageView().capacity()){
77 | slot.set(ItemStack.of(ItemTypes.STAINED_GLASS_PANE,count));
78 | }else{
79 | if(slot.peek().isPresent()) {
80 | ItemStack stack = slot.peek().get();
81 | if (stack.getType() == ItemTypes.STAINED_GLASS_PANE) {
82 | slot.set(ItemStack.empty());
83 | }
84 | }
85 | }
86 | count++;
87 | }
88 | })
89 | .setUpdateTickRate(20)
90 | .setTitle(Text.of(TextColors.RED,"BLARG"))
91 | .addElement(new ActionableElement(new Action(container,ActionType.NORMAL,"test2"),ItemStack.builder().
92 | itemType(ItemTypes.COOKIE)
93 | .build()))
94 | .build("test")
95 | );
96 | container.addState(
97 | Page.builder()
98 | .setUpdatable(false)
99 | .setTitle(Text.of(TextColors.GREEN,"alt"))
100 | .addElement(new ActionableElement(new Action(container,ActionType.BACK,"test"),ItemStack.builder().
101 | itemType(ItemTypes.COOKIE)
102 | .build()))
103 | .setParent("test")
104 | .build("test2")
105 | );
106 | container.launchFor(plr);
107 | ```
108 |
--------------------------------------------------------------------------------
/src/main/java/com/codehusky/huskyui/states/State.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HuskyUI.
3 | *
4 | * HuskyUI is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HuskyUI is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with HuskyUI. If not, see .
16 | */
17 |
18 | package com.codehusky.huskyui.states;
19 |
20 | import com.codehusky.huskyui.StateContainer;
21 | import org.spongepowered.api.entity.living.player.Player;
22 | import javax.annotation.Nonnull;
23 |
24 | /**
25 | * A State in the GUI process. Typically extended by {@link Page}.
26 | */
27 | public class State {
28 |
29 | /**
30 | * The ID of this State.
31 | */
32 | private final String id;
33 |
34 | /**
35 | * The ID of the parent to this State.
36 | */
37 | private String parent;
38 |
39 | /**
40 | * The {@link StateContainer} responsible for this State.
41 | */
42 | private StateContainer container;
43 |
44 | /**
45 | * The {@link Player}, if applicable, currently viewing this GUI.
46 | */
47 | private Player observer;
48 |
49 | /**
50 | * An easily created way to construct a State.
51 | *
52 | *
This constructor will assume that the ID is "null",
53 | * and should really only be used for testing purposes.
54 | */
55 | public State() {
56 | this("null");
57 | }
58 |
59 | /**
60 | * A State constructor. Creates a State to be, typically,
61 | * stored in a {@link StateContainer}.
62 | *
63 | * @param id the ID of this State
64 | */
65 | public State(@Nonnull final String id) {
66 | this.id = id;
67 | this.parent = null;
68 | this.container = null;
69 | this.observer = null;
70 | }
71 |
72 | /**
73 | * Gets the ID of this State.
74 | *
75 | * @return the ID of this State
76 | */
77 | public String getId() {
78 | return this.id;
79 | }
80 |
81 | /**
82 | * Gets the ID of the parent to this State.
83 | *
84 | * @return the ID of the parent to this State
85 | */
86 | public String getParent() {
87 | return this.parent;
88 | }
89 |
90 | /**
91 | * Determines whether or not this State has a parent.
92 | *
93 | * @return true if this State has a parent; false otherwise
94 | */
95 | public boolean hasParent() {
96 | return this.parent != null;
97 | }
98 |
99 | /**
100 | * Sets the ID of the parent to this State.
101 | *
102 | * @param parent the ID of the parent to this State
103 | */
104 | public void setParent(final String parent) {
105 | if(parent == null) return;
106 | this.parent = parent;
107 | }
108 |
109 | /**
110 | * Gets the {@link StateContainer} responsible for this State.
111 | *
112 | * @return the StateContainer responsible for this State
113 | */
114 | public StateContainer getContainer() {
115 | return this.container;
116 | }
117 |
118 | /**
119 | * Sets the {@link StateContainer} responsible for this State.
120 | *
121 | * @param container the StateContainer responsible for this State
122 | */
123 | public void setContainer(@Nonnull final StateContainer container) {
124 | this.container = container;
125 | }
126 |
127 | /**
128 | * Determines whether or not this State has a {@link StateContainer}.
129 | *
130 | *
Typically this would always be false, but people are crazy
131 | * so I dunno.
132 | *
133 | * @return true if this State has a StateContainer; false otherwise
134 | */
135 | public boolean isHeadless() {
136 | return this.container == null;
137 | }
138 |
139 | /**
140 | * Gets the {@link Player} currently viewing this State, if applicable.
141 | *
142 | * @return the {@link Player} currently viewing this State
143 | */
144 | public Player getObserver() {
145 | return this.observer;
146 | }
147 |
148 | /**
149 | * Determines whether or not this State is being viewed.
150 | *
151 | * @return true if this State is being viewed; false otherwise
152 | */
153 | public boolean hasObserver() {
154 | return this.observer != null;
155 | }
156 |
157 | /**
158 | * Sets the {@link Player} who is viewing this State.
159 | *
160 | * @param observer the Player viewing this State
161 | */
162 | public void setObserver(final Player observer) {
163 | this.observer = observer;
164 | }
165 |
166 | /**
167 | * Creates a copy of this State.
168 | *
169 | * @param newContainer the {@link StateContainer} that will be taking
170 | * responsibility for this State.
171 | * @return a copy of this State
172 | */
173 | @Nonnull
174 | public State copy(@Nonnull final StateContainer newContainer) {
175 | final State state = new State(this.id);
176 |
177 | state.setContainer(newContainer);
178 | state.setObserver(this.observer);
179 | state.setParent(this.parent);
180 |
181 | return state;
182 | }
183 | }
184 |
--------------------------------------------------------------------------------
/src/main/java/com/codehusky/huskyui/states/action/Action.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HuskyUI.
3 | *
4 | * HuskyUI is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HuskyUI is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with HuskyUI. If not, see .
16 | */
17 |
18 | package com.codehusky.huskyui.states.action;
19 |
20 | import com.codehusky.huskyui.InventoryUtil;
21 | import com.codehusky.huskyui.StateContainer;
22 | import com.codehusky.huskyui.states.Page;
23 | import org.spongepowered.api.effect.sound.SoundTypes;
24 | import org.spongepowered.api.entity.living.player.Player;
25 | import org.spongepowered.api.item.inventory.Inventory;
26 | import org.spongepowered.api.text.Text;
27 | import org.spongepowered.api.text.format.TextColors;
28 |
29 | import javax.annotation.Nonnull;
30 | import java.util.function.Consumer;
31 |
32 | /**
33 | * This class' purpose is to be used to determine the movement
34 | * of a user within a GUI.
35 | * @see CommandAction
36 | * @see com.codehusky.huskyui.states.action.runnable.RunnableAction
37 | */
38 | public class Action {
39 |
40 | /**
41 | * The {@link StateContainer} that is responsible for this Action.
42 | */
43 | @Nonnull private final StateContainer container;
44 |
45 | /**
46 | * The {@link Player} observing the {@link com.codehusky.huskyui.states.Page}
47 | * that this action is being performed on.
48 | */
49 | private Player observer = null;
50 |
51 | /**
52 | * The type of Action taking place.
53 | */
54 | @Nonnull private final ActionType type;
55 |
56 | /**
57 | * The intended {@link com.codehusky.huskyui.states.State} that the
58 | * observer should find themselves in when this Action finishes.
59 | */
60 | @Nonnull private final String goalState;
61 |
62 | /**
63 | * Constructs an Action.
64 | *
65 | * @param container the {@link StateContainer} that is responsible for this Action
66 | * @param type the type of Action taking place
67 | * @param goalState the intended {@link com.codehusky.huskyui.states.State}
68 | * for the observer to land
69 | */
70 | public Action(@Nonnull final StateContainer container,
71 | @Nonnull final ActionType type,
72 | @Nonnull final String goalState) {
73 | this.container = container;
74 | this.type = type;
75 | this.goalState = goalState;
76 | }
77 |
78 | /**
79 | * Gets the {@link StateContainer} that is responsible for this Action.
80 | *
81 | * @return the StateContainer responsible for this Action
82 | */
83 | @Nonnull
84 | public StateContainer getContainer() {
85 | return this.container;
86 | }
87 |
88 | /**
89 | * The {@link Player} that is observing this Action.
90 | *
91 | * @return the Player observing this Action
92 | */
93 | public Player getObserver() {
94 | return this.observer;
95 | }
96 |
97 | /**
98 | * Sets the {@link Player} that is observing this Action
99 | *
100 | * @param observer the Player that is observing this Action
101 | */
102 | public void setObserver(Player observer) {
103 | this.observer = observer;
104 | }
105 |
106 | /**
107 | * Gets the type of Action to be performed.
108 | *
109 | * @return the type of Action to be performed
110 | */
111 | @Nonnull
112 | public ActionType getType() {
113 | return this.type;
114 | }
115 |
116 | /**
117 | * Gets the intended {@link com.codehusky.huskyui.states.State} for
118 | * the {@link Player} to end up in after this Action is performed.
119 | *
120 | * @return the intended State for the Player to end up in
121 | */
122 | @Nonnull
123 | public String getGoalState() {
124 | return this.goalState;
125 | }
126 |
127 | /**
128 | * Performs this Action.
129 | *
130 | * @param currentState the current State before the Action is performed
131 | */
132 | public void runAction(@Nonnull final String currentState, final Inventory inventory) {
133 | switch (this.type) {
134 | case CLOSE:
135 | InventoryUtil.close(this.observer);
136 | break;
137 | case BACK:
138 | if (this.container.hasState(currentState)) {
139 | if (this.container.getState(currentState).hasParent()) {
140 | this.container.openState(this.observer, this.container.getState(currentState).getParent());
141 | } else {
142 | this.observer.playSound(SoundTypes.BLOCK_ANVIL_LAND, this.observer.getLocation().getPosition(), 0.5);
143 | InventoryUtil.close(this.observer);
144 | this.observer.sendMessage(Text.of(TextColors.RED, "Impossible BACK action - closing broken State."));
145 | }
146 | }
147 | break;
148 | case NORMAL:
149 | this.container.openState(this.observer, this.goalState);
150 | break;
151 | case NONE:
152 | // do nothing
153 | break;
154 | case REFRESH:
155 | Page page = ((Page)getContainer().getState(currentState));
156 | try {
157 | Consumer goo = page.getUpdateConsumer();
158 | if (goo != null) {
159 | goo.accept(page);
160 | }
161 | }catch (Exception e){
162 | this.observer.sendMessage(Text.of(TextColors.RED, "Impossible refresh action - closing broken State."));
163 | }
164 | break;
165 | default:
166 | this.observer.sendMessage(Text.of("??"));
167 | break;
168 | }
169 | }
170 |
171 | /**
172 | * Creates a copy of this Action.
173 | *
174 | * @param newContainer the new {@link StateContainer} to be responsible for this new Action
175 | * @return a copy of this Action
176 | */
177 | @Nonnull
178 | public Action copy(@Nonnull final StateContainer newContainer) {
179 | return new Action(newContainer, this.type, this.goalState);
180 | }
181 | }
182 |
--------------------------------------------------------------------------------
/src/main/java/com/codehusky/huskyui/StateContainer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HuskyUI.
3 | *
4 | * HuskyUI is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HuskyUI is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with HuskyUI. If not, see .
16 | */
17 |
18 | package com.codehusky.huskyui;
19 |
20 | import com.codehusky.huskyui.states.Page;
21 | import com.codehusky.huskyui.states.State;
22 | import com.google.common.collect.Maps;
23 | import org.spongepowered.api.entity.living.player.Player;
24 | import org.spongepowered.api.item.inventory.Inventory;
25 | import org.spongepowered.api.text.Text;
26 | import org.spongepowered.api.text.format.TextColors;
27 |
28 | import javax.annotation.Nonnull;
29 | import javax.annotation.Nullable;
30 | import java.util.Map;
31 |
32 | /**
33 | * The StateContainer's purpose is to be the gateway for information
34 | * regarding any active GUI. It can also be easily copied, with the
35 | * purpose of assigning a separate container for each user accessing
36 | * the GUI, allowing extensible on a per-user basis.
37 | */
38 | public class StateContainer {
39 |
40 | /**
41 | * Contains the {@link State}s in use by this container, sorted
42 | * by that State's ID.
43 | */
44 | @Nonnull private final Map states;
45 |
46 | /**
47 | * References the ID of the {@link State} which has been
48 | * deemed as the "default" State.
49 | *
50 | *
When the GUI is initially opened, for instance, this
51 | * ID should reference which State to be loaded first.
52 | */
53 | @Nullable private String initialState;
54 |
55 | /**
56 | * A StateContainer constructor. Left empty to pass equally
57 | * empty data to the other constructor.
58 | */
59 | public StateContainer() {
60 | this(Maps.newHashMap());
61 | }
62 |
63 | /**
64 | * A StateContainer constructor. Passed to it are the current
65 | * {@link State}s that this GUI can expect to contain.
66 | *
67 | * @param states the current States for this GUI
68 | */
69 | public StateContainer(@Nonnull final Map states) {
70 | this.states = states;
71 | this.initialState = null;
72 | }
73 |
74 | /**
75 | * A StateContainer constructor. Passed to it are the current
76 | * {@link State}s that this GUI can expect to contain.
77 | *
78 | *
Also requires an initial State to be defined.
79 | *
80 | * @param states the current States for this GUI
81 | * @param initialState the initial State
82 | */
83 | public StateContainer(@Nonnull final Map states, @Nonnull final String initialState) {
84 | this.states = states;
85 | this.initialState = initialState;
86 | }
87 |
88 | /**
89 | * Gets the current {@link State}s in use by this GUI.
90 | *
91 | * @return the current States in use by this GUI
92 | */
93 | @Nonnull
94 | public Map getStates() {
95 | return this.states;
96 | }
97 |
98 | /**
99 | * Gets a specific {@link State} in use by this GUI,
100 | * based on its ID.
101 | *
102 | * @param id the ID of the State being requested
103 | * @return the State being requested; null if non-existent
104 | */
105 | @Nullable
106 | public State getState(@Nonnull final String id) {
107 | return this.states.get(id);
108 | }
109 |
110 | /**
111 | * Determines whether or not the requested {@link State} exists.
112 | *
113 | * @param id the ID of the State being determined
114 | * @return true if the State exists, false otherwise
115 | */
116 | public boolean hasState(@Nonnull final String id) {
117 | return this.getState(id) != null;
118 | }
119 |
120 | /**
121 | * Adds a {@link State} to this GUI.
122 | *
123 | * If no default state has been set, this will also set the default state.
124 | *
125 | * @param state the State to be added
126 | */
127 | public void addState(@Nonnull final State state) {
128 | state.setContainer(this);
129 |
130 | if (this.states.containsKey(state.getId())) {
131 | throw new IllegalStateException("A State with ID \"" + state.getId() + "\" already exists in this container.");
132 | }
133 | if(this.initialState == null){
134 | this.initialState = state.getId();
135 | }
136 |
137 | this.states.put(state.getId(), state);
138 | }
139 |
140 | /**
141 | * Removes a {@link State} from this GUI.
142 | *
143 | * @param id the ID of the State to be removed
144 | */
145 | public void removeState(@Nonnull final String id) {
146 | if (this.initialState != null && this.initialState.equals(id)) {
147 | this.initialState = null;
148 | }
149 |
150 | this.states.remove(id);
151 | }
152 |
153 | /**
154 | * Removes a {@link State} from this GUI.
155 | *
156 | * @param state the State object itself to be removed
157 | */
158 | public void removeState(@Nonnull final State state) {
159 | if (this.hasState(state.getId())) {
160 | this.removeState(state.getId());
161 | }
162 | }
163 |
164 |
165 | /**
166 | * Sets the initial {@link State} to be displayed when
167 | * the GUI is opened.
168 | *
169 | * @param state the State to be displayed when the GUI is opened
170 | */
171 | public void setInitialState(@Nonnull final State state) {
172 | this.initialState = state.getId();
173 |
174 | if (!this.states.containsKey(state.getId())) {
175 | this.addState(state);
176 | }
177 | }
178 |
179 | /**
180 | * Opens a specific {@link State} for a {@link Player},
181 | * based on the expected ID of the State.
182 | *
183 | * @param player the Player to display the State to
184 | * @param id the ID of the State being requested
185 | */
186 | public void openState(@Nonnull final Player player, @Nonnull final String id) {
187 | int pagenum = 0;
188 | String pageID = id;
189 | if(id.contains("#")){
190 | try {
191 | pagenum = Integer.valueOf(id.split("#")[1]);
192 | pageID=id.split("#")[0];
193 | }catch(Exception e){
194 | fail(player, "Attempted to open an invalid pagenum!");
195 | }
196 | }
197 | State state = this.states.get(pageID);
198 |
199 | if (state == null) {
200 | fail(player, "Attempted to open a nonexistent state!");
201 | fail(player, "Invalid ID: " + id);
202 | InventoryUtil.close(player);
203 | return;
204 | }
205 | state = state.copy(this);
206 |
207 | state.setObserver(player);
208 |
209 | if (state instanceof Page) {
210 | //InventoryUtil.close(player);
211 | Page page = (Page) state;
212 | Inventory toShow = page.getPageView(pagenum);
213 | InventoryUtil.open(player, toShow);
214 |
215 | return;
216 | }
217 |
218 | InventoryUtil.close(player);
219 | fail(player, "Attempted to open an invalid or incomplete state!");
220 | fail(player, "Invalid ID: " + id);
221 | }
222 |
223 |
224 | /**
225 | * Opens the initial {@link State} for the {@link Player}.
226 | *
227 | * @param player the Player to show the initial State to
228 | */
229 | public void launchFor(@Nonnull final Player player) {
230 | if (this.initialState == null) {
231 | fail(player, "Attempted to open a container without an initial state!");
232 | return;
233 | }
234 |
235 | this.openState(player, this.initialState);
236 | }
237 |
238 | /**
239 | * Creates a copy of this StateContainer.
240 | *
241 | * @return a copy of this StateContainer
242 | */
243 | @Nonnull
244 | public StateContainer copy() {
245 | final StateContainer container = new StateContainer();
246 |
247 | for (final State state : this.states.values()) {
248 | container.addState(state.copy(container));
249 | }
250 |
251 | if (this.initialState != null) {
252 | container.setInitialState(states.get(this.initialState));
253 | }
254 |
255 | return container;
256 | }
257 |
258 | /**
259 | * A simple convenience method to send failures to
260 | * {@link Player}s; added by a misguided, lazy developer.
261 | *
262 | * @param player the Player to send the message to
263 | * @param message the message to be sent to the Player
264 | */
265 | private static void fail(@Nonnull final Player player, @Nonnull final String message) {
266 | player.sendMessage(Text.of(TextColors.RED, message));
267 | }
268 | }
269 |
--------------------------------------------------------------------------------
/src/main/java/com/codehusky/huskyui/ElementRegistry.java:
--------------------------------------------------------------------------------
1 | package com.codehusky.huskyui;
2 |
3 | import com.codehusky.huskyui.states.element.ActionableElement;
4 | import com.codehusky.huskyui.states.element.Element;
5 | import org.spongepowered.api.data.DataQuery;
6 | import org.spongepowered.api.item.ItemTypes;
7 | import org.spongepowered.api.item.inventory.ItemStack;
8 |
9 | import java.util.ArrayList;
10 | import java.util.HashMap;
11 | import java.util.Optional;
12 |
13 | /**
14 | * ElementRegistry is a class only meant for use inside of HuskyUI to register elements with the plugin.
15 | * Using it for any other purpose is not advised.
16 | * This is for messing with Elements within player inventories.
17 | *
18 | * Auto-Inv and methods referencing Auto are talking about Auto-Inventory Delivery of the element.
19 | * Elements delivered to player inventories will be placed in the first available slot unless specified otherwise.
20 | *
21 | *
!! WARNING !!
22 | * Enforcing a slot id for an auto element will result on player's inventories being cleared every time they log in.
23 | * Please use this feature with care! By default, you should not do this. Make it controlled via config (default off) or be very explicit in disclosure of this feature.
24 | * Improper warning of this feature could be disastrous for some servers.
25 | *
26 | */
27 | public class ElementRegistry extends StateContainer {
28 |
29 | private HashMap elements;
30 |
31 | //position, element id
32 | private HashMap autoInvLocations;
33 | private ArrayList autoInvElements;
34 |
35 | private int elementIncrement = 0;
36 |
37 | /**
38 | * Initialization for Registry.
39 | * For use only by the HuskyUI main class.
40 | */
41 | ElementRegistry() {
42 | elements = new HashMap<>();
43 | autoInvLocations = new HashMap<>();
44 | autoInvElements = new ArrayList<>();
45 | }
46 |
47 |
48 | /**
49 | * Register an element to HuskyUI's Element Registry.
50 | *
51 | * @param element Element to register
52 | * @return elementID of registered element
53 | */
54 | public int registerElement(Element element){
55 | int key = elementIncrement;
56 | elements.put(key,element);
57 | elementIncrement++;
58 | return key;
59 | }
60 |
61 | /**
62 | * Unregister an element from the Registry.
63 | * Note that this will not remove an item from a player registered to this ID, so use of this method is heavily discouraged.
64 | *
65 | * @param id Element to unregister
66 | */
67 | public void unregisterElement(int id){
68 | if(elements.containsKey(id)){
69 | elements.remove(id);
70 | if(autoInvElements.contains(id)){
71 | autoInvElements.remove(id);
72 | if(autoInvLocations.values().contains(id)){
73 | autoInvLocations.values().removeIf(val -> id == val);
74 | }
75 | }
76 | }else{
77 | throw new RuntimeException("Cannot unregister element: Element id \"" + id + "\" is not registered.");
78 | }
79 | }
80 |
81 | /**
82 | * Register an element to the Registry and also the auto-deployment system.
83 | * Items registered in this way will be given to the player when they log into the server.
84 | *
85 | * @param element Element to register
86 | * @return elementID of registered element.
87 | */
88 | public int registerAutoElement(Element element){
89 | int id = registerElement(element);
90 | autoInvElements.add(id);
91 | return id;
92 | }
93 |
94 | /**
95 | * Register an existing element to the ElementRegistry
96 | * @param elementID ElementID to register with auto-inv delivery enabled
97 | */
98 | public void registerAutoElement(int elementID){
99 | if(!elements.containsKey(elementID)){
100 | throw new RuntimeException("Cannot register element as auto: Element id \"" + elementID + "\" is not registered.");
101 | }
102 | if(autoInvElements.contains(elementID)) return;
103 | autoInvElements.add(elementID);
104 | }
105 |
106 | /**
107 | * Registers an element at a given fixed slot position.
108 | * WARNING: Adding anything to a fixed slot ID will result in the removal of all user items on their spawn.
109 | * Please make use of this method configurable in your plugin, with it being disabled by default. Thanks!
110 | *
111 | * @param slotID SlotID to associate element with
112 | * @param element Element to register
113 | * @return ElementID
114 | */
115 | public int registerAutoElement(int slotID, Element element){
116 | int id = registerElement(element);
117 | autoInvLocations.put(slotID,id);
118 | autoInvElements.add(id);
119 | return id;
120 | }
121 |
122 | /**
123 | * Associates an existing element to a given fixed slot position.
124 | * WARNING: Adding anything to a fixed slot ID will result in the removal of all user items on their spawn.
125 | * Please make use of this method configurable in your plugin, with it being disabled by default. Thanks!
126 | *
127 | * @param slotID SlotID to associate element with
128 | * @param elementID ElementID to bind to slot.
129 | */
130 | public void registerAutoElement(int slotID, int elementID){
131 | if(!elements.containsKey(elementID)){
132 | throw new RuntimeException("Cannot register element as auto: Element id \"" + elementID + "\" is not registered.");
133 | }
134 | autoInvLocations.put(slotID,elementID);
135 |
136 | if(!autoInvElements.contains(elementID))
137 | autoInvElements.add(elementID);
138 | }
139 |
140 | /**
141 | * Get all auto-given items (placed in user inventory on login)
142 | * @return HashMap of ElementIDs to Element itemstacks.
143 | */
144 | public HashMap getAutoItems() {
145 | HashMap stacks = new HashMap<>();
146 | for(int i : autoInvElements){
147 | stacks.put(i,getItemStackForElement(i));
148 | }
149 | return stacks;
150 | }
151 |
152 | /**
153 | * Get all fixed locations of auto items.
154 | * If this hashmap is empty, inventories are NOT reset on login.
155 | *
156 | * @return HashMap containing SlotIDs to ElementIDs
157 | */
158 | public HashMap getAutoItemLocations() {
159 | return autoInvLocations;
160 | }
161 |
162 | /**
163 | * Convert an ItemStack into an Element
164 | *
165 | * @param stack ItemStack to pull Element from
166 | * @return Element, if it exists with that item.
167 | */
168 | public Optional getElementFromItemStack(ItemStack stack){
169 | Optional optID = getElementIDFromItemStack(stack);
170 | if(optID.isPresent()){
171 | if(elements.containsKey(optID.get())){
172 | return Optional.of(elements.get(optID.get()));
173 | }
174 | }
175 | return Optional.empty();
176 | }
177 |
178 | /**
179 | * Convert an ItemStack into an ElementID
180 | *
181 | * @param stack ItemStack to pull ElementID from
182 | * @return ElementID, if it exists. This ID may not actually be associated with an Element, so please verify that before use with {@link #elementExists(int)}.
183 | */
184 | public Optional getElementIDFromItemStack(ItemStack stack){
185 | if(stack.getType() == ItemTypes.AIR || stack.getType() == ItemTypes.NONE) return Optional.empty();
186 | Optional