Skip to content

Commit 1cfdea4

Browse files
committed
9.0.0-SNAPSHOT (BestTool)
1 parent 123f169 commit 1cfdea4

File tree

5 files changed

+343
-3
lines changed

5 files changed

+343
-3
lines changed

TODO.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Todo
2-
2+
## Auto updater
3+
Automatically use latest version
34
## StackableItems
45
Make it configurable whether ItemStacks > 64 items will stay unsorted, or sorted and reverted back to stacks of 64 items
56
-> https://www.spigotmc.org/threads/1-8-1-15-chestsort-api.334121/page-19#post-3821591

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<name>ChestSort</name>
1010
<url>https://www.chestsort.de</url>
1111
<description>Automatically sorts your chests!</description>
12-
<version>8.14.2</version>
12+
<version>9.0.0-SNAPSHOT</version>
1313
<packaging>jar</packaging>
1414

1515
<properties>

src/main/java/de/jeff_media/ChestSort/ChestSortPlugin.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,7 @@ void load(boolean reload) {
462462
sortingMethod = getConfig().getString("sorting-method");
463463
getServer().getPluginManager().registerEvents(listener, this);
464464
getServer().getPluginManager().registerEvents(settingsGUI, this);
465+
getServer().getPluginManager().registerEvents(new ToolUtils(), this);
465466
ChestSortChestSortCommand chestsortCommandExecutor = new ChestSortChestSortCommand(this);
466467
ChestSortTabCompleter tabCompleter = new ChestSortTabCompleter();
467468
this.getCommand("sort").setExecutor(chestsortCommandExecutor);
Lines changed: 338 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,338 @@
1+
package de.jeff_media.ChestSort;
2+
3+
import org.bukkit.Material;
4+
import org.bukkit.Tag;
5+
import org.bukkit.block.Block;
6+
import org.bukkit.event.EventHandler;
7+
import org.bukkit.event.Listener;
8+
import org.bukkit.event.block.Action;
9+
import org.bukkit.event.player.PlayerInteractEvent;
10+
import org.bukkit.inventory.ItemStack;
11+
import org.bukkit.inventory.PlayerInventory;
12+
import org.bukkit.inventory.meta.Damageable;
13+
import org.bukkit.inventory.meta.ItemMeta;
14+
import org.jetbrains.annotations.NotNull;
15+
import org.jetbrains.annotations.Nullable;
16+
17+
import java.util.ArrayList;
18+
import java.util.HashMap;
19+
import java.util.Objects;
20+
import java.util.Set;
21+
22+
public class ToolUtils implements Listener {
23+
24+
// Configurable
25+
boolean hotbarOnly = false;
26+
27+
static int hotbarSize = 9;
28+
static int inventorySize = 36;
29+
static int favoriteSlot = hotbarSize-1;
30+
31+
HashMap<Material,Tool> toolMap = new HashMap<>();
32+
ArrayList<Tag> usedTags = new ArrayList<>();
33+
final Material[] pickaxes = {
34+
Material.NETHERITE_PICKAXE,
35+
Material.DIAMOND_PICKAXE,
36+
Material.IRON_PICKAXE,
37+
Material.STONE_PICKAXE,
38+
Material.WOODEN_PICKAXE};
39+
final Material[] axes = {
40+
Material.NETHERITE_AXE,
41+
Material.DIAMOND_AXE,
42+
Material.IRON_AXE,
43+
Material.STONE_AXE,
44+
Material.WOODEN_AXE};
45+
final Material[] shovels = {
46+
Material.NETHERITE_SHOVEL,
47+
Material.DIAMOND_SHOVEL,
48+
Material.IRON_SHOVEL,
49+
Material.STONE_SHOVEL,
50+
Material.WOODEN_SHOVEL};
51+
52+
final Material[] hoes = {
53+
Material.NETHERITE_HOE,
54+
Material.DIAMOND_HOE,
55+
Material.IRON_HOE,
56+
Material.STONE_HOE,
57+
Material.WOODEN_HOE};
58+
59+
ToolUtils() {
60+
initMap();
61+
}
62+
63+
enum Tool {
64+
PICKAXE,
65+
SHOVEL,
66+
SHEARS,
67+
AXE,
68+
HOE,
69+
NONE
70+
}
71+
72+
private void initMap() {
73+
long startTime = System.nanoTime();
74+
tagToMap(Tag.ANVIL,Tool.PICKAXE);
75+
tagToMap(Tag.BEEHIVES,Tool.AXE);
76+
tagToMap(Tag.CRIMSON_STEMS,Tool.AXE);
77+
tagToMap(Tag.BAMBOO_PLANTABLE_ON,Tool.SHOVEL);
78+
tagToMap(Tag.ICE,Tool.PICKAXE);
79+
tagToMap(Tag.LOGS,Tool.AXE);
80+
tagToMap(Tag.PLANKS,Tool.AXE);
81+
tagToMap(Tag.RAILS,Tool.PICKAXE);
82+
tagToMap(Tag.SIGNS,Tool.AXE);
83+
84+
tagToMap(Tag.WALLS,Tool.PICKAXE);
85+
tagToMap(Tag.WOOL,Tool.SHEARS);
86+
87+
tagToMap(Tag.CROPS,Tool.NONE);
88+
tagToMap(Tag.FENCE_GATES,Tool.AXE);
89+
tagToMap(Tag.FENCES,Tool.AXE);
90+
tagToMap(Tag.FLOWERS,Tool.NONE);
91+
tagToMap(Tag.LEAVES,Tool.SHEARS);
92+
93+
// Order is important
94+
tagToMap(Tag.PRESSURE_PLATES, Tool.PICKAXE);
95+
tagToMap(Tag.WOODEN_PRESSURE_PLATES,Tool.AXE);
96+
tagToMap(Tag.DOORS,Tool.AXE);
97+
tagToMap(Tag.DOORS,Tool.PICKAXE,"IRON");
98+
tagToMap(Tag.TRAPDOORS,Tool.AXE);
99+
tagToMap(Tag.TRAPDOORS,Tool.PICKAXE,"IRON");
100+
tagToMap(Tag.BUTTONS,Tool.AXE);
101+
tagToMap(Tag.BUTTONS,Tool.PICKAXE,"STONE");
102+
103+
tagToMap(Tag.SAND,Tool.SHOVEL);
104+
tagToMap(Tag.SHULKER_BOXES,Tool.PICKAXE);
105+
tagToMap(Tag.STONE_BRICKS,Tool.PICKAXE);
106+
107+
addToMap(Material.VINE,Tool.SHEARS);
108+
long endTime = System.nanoTime();
109+
printMap();
110+
System.out.println(String.format("Building the map took %d ms",(endTime-startTime)/1000000));
111+
}
112+
113+
private void printMap() {
114+
toolMap.forEach((mat, tool) -> System.out.println(String.format("%0$30s -> %s", mat.name(), tool.name())));
115+
}
116+
117+
private void addToMap(Material mat, Tool tool) {
118+
toolMap.put(mat, tool);
119+
}
120+
121+
private void tagToMap(Tag<Material> tag, Tool tool) {
122+
/*for(Material mat : tag.getValues() ) {
123+
addToMap(mat,tool);
124+
}*/
125+
tagToMap(tag,tool,null);
126+
}
127+
128+
private void tagToMap(Tag<Material> tag, Tool tool, @Nullable String match) {
129+
for(Material mat : tag.getValues()) {
130+
if(match==null) {
131+
addToMap(mat,tool);
132+
} else {
133+
if (mat.name().contains(match)) {
134+
addToMap(mat,tool);
135+
}
136+
}
137+
}
138+
usedTags.add(tag);
139+
}
140+
141+
/**
142+
* Gets the best tool type for a material
143+
* @param mat The block's material
144+
* @return Best tool type for that material
145+
*/
146+
@NotNull
147+
Tool getBestToolType(Material mat) {
148+
Tool bestTool = toolMap.get(mat);
149+
if(bestTool == null) bestTool = Tool.NONE;
150+
System.out.println("Best ToolType for "+mat+" is "+bestTool.name());
151+
return bestTool;
152+
}
153+
154+
/**
155+
* Searches through and array and returns the ItemStack that matches this material
156+
* @param mat Material to look for
157+
* @param items Player's items (whole inventory or hotbar)
158+
* @return Matching ItemStack
159+
*/
160+
@Nullable
161+
ItemStack getItemStackFromArray(Material mat, ItemStack[] items) {
162+
for(ItemStack item : items) {
163+
if(item==null) continue;
164+
if(item.getType()==mat) return item;
165+
}
166+
return null;
167+
}
168+
169+
/**
170+
* Searches the player's inventory for the best matching tool and returns its ItemStack
171+
* @param type Tool type
172+
* @param items Player's items (whole inventory or hotbar)
173+
* @return
174+
*/
175+
@Nullable
176+
ItemStack typeToItem(Tool type, ItemStack[] items) {
177+
178+
Objects.requireNonNull(type,"type cannot be null.");
179+
180+
switch(type) {
181+
182+
case PICKAXE:
183+
for(Material pickaxe : pickaxes) {
184+
ItemStack itemStack = getItemStackFromArray(pickaxe, items);
185+
if(itemStack != null) return itemStack;
186+
}
187+
return null;
188+
189+
case AXE:
190+
for(Material axe : axes) {
191+
ItemStack itemStack = getItemStackFromArray(axe, items);
192+
if(itemStack != null) return itemStack;
193+
}
194+
return null;
195+
196+
case SHOVEL:
197+
for(Material shovel : shovels) {
198+
ItemStack itemStack = getItemStackFromArray(shovel, items);
199+
if(itemStack != null) return itemStack;
200+
}
201+
System.out.println("typeToItem -> shovel -> null");
202+
return null;
203+
204+
case HOE:
205+
for(Material hoe : hoes) {
206+
ItemStack itemStack = getItemStackFromArray(hoe, items);
207+
if(itemStack != null) return itemStack;
208+
}
209+
return null;
210+
211+
case SHEARS:
212+
return getItemStackFromArray(Material.SHEARS, items);
213+
214+
default:
215+
return null;
216+
}
217+
}
218+
219+
/**
220+
* Tries to get the ItemStack that is the best for this block
221+
* @param mat The block's material
222+
* @param inv Player's inventory
223+
* @return
224+
*/
225+
@Nullable
226+
ItemStack getBestToolFromInventory(Material mat, PlayerInventory inv) {
227+
ItemStack[] hotbar = new ItemStack[(hotbarOnly ? hotbarSize : inventorySize)];
228+
Tool bestType = getBestToolType(mat);
229+
for(int i = 0; i < (hotbarOnly ? hotbarSize : inventorySize); i++) {
230+
hotbar[i] = inv.getItem(i);
231+
}
232+
ItemStack debug = typeToItem(bestType,hotbar);
233+
if(debug == null) System.out.println("debug == null");
234+
return debug;
235+
}
236+
237+
238+
239+
@EventHandler
240+
public void onPlayerInteract(PlayerInteractEvent event) {
241+
if (event.getAction() != Action.LEFT_CLICK_BLOCK) return;
242+
/*if (event.getHand() != EquipmentSlot.HAND)
243+
return;*/
244+
245+
PlayerInventory inv = event.getPlayer().getInventory();
246+
Block block = event.getClickedBlock();
247+
if (block == null) return;
248+
249+
ItemStack bestTool = getBestToolFromInventory(block.getType(), inv);
250+
if(bestTool == null) {
251+
freeSlot(favoriteSlot,inv);
252+
//System.out.println("Could not find any appropiate tool");
253+
return;
254+
}
255+
int positionInInventory = getPositionInInventory(bestTool,inv) ;
256+
if(positionInInventory != 0) {
257+
moveToolToSlot(positionInInventory,favoriteSlot,inv);
258+
} else {
259+
freeSlot(favoriteSlot,inv);
260+
}
261+
}
262+
263+
/**
264+
* Gets the slot number of a given ItemStack
265+
* @param item ItemStack that we need the slot number of
266+
* @param inv Player's inventory
267+
* @return
268+
*/
269+
int getPositionInInventory(ItemStack item, PlayerInventory inv) {
270+
for(int i = 0; i < inv.getSize(); i++) {
271+
ItemStack currentItem = inv.getItem(i);
272+
if(currentItem==null) continue;
273+
if(currentItem.equals(item)) {
274+
System.out.println(String.format("Found perfect tool %s at slot %d",currentItem.getType().name(),i));
275+
return i;
276+
}
277+
}
278+
return 0;
279+
}
280+
281+
/**
282+
* Moves a tool to the given slot
283+
* @param source Slot where the tool is
284+
* @param dest Slot where the tool should be
285+
* @param inv Player's inventory
286+
*/
287+
private void moveToolToSlot(int source, int dest, PlayerInventory inv) {
288+
System.out.println(String.format("Moving item from slot %d to %d",source,dest));
289+
inv.setHeldItemSlot(dest);
290+
if(source==dest) return;
291+
ItemStack sourceItem = inv.getItem(source);
292+
ItemStack destItem = inv.getItem(dest);
293+
if(source < hotbarSize) {
294+
inv.setHeldItemSlot(source);
295+
return;
296+
}
297+
if(destItem == null) {
298+
inv.setItem(dest,sourceItem);
299+
inv.setItem(source,null);
300+
} else {
301+
inv.setItem(source, destItem);
302+
inv.setItem(dest, sourceItem);
303+
}
304+
}
305+
306+
/**
307+
* Tries to free the slot if it is occupied with a damageable item
308+
* @param source Slot to free
309+
* @param inv Player's inventory
310+
*/
311+
private void freeSlot(int source, PlayerInventory inv) {
312+
System.out.println(String.format("Trying to free slot %d",source));
313+
ItemStack item = inv.getItem(source);
314+
315+
// If current slot is empty, we don't have to change it
316+
if(item == null) return;
317+
318+
// If the item is not damageable, we don't have to move it
319+
ItemMeta meta = item.getItemMeta();
320+
if(!(meta instanceof Damageable)) return;
321+
322+
// Try to combine the item with existing stacks
323+
inv.setItem(source, null);
324+
inv.addItem(item);
325+
326+
// If the item was moved to the same slot, we have to move it somewhere else
327+
if(inv.getItem(source)==null) return;
328+
for(int i = source; i < inventorySize; i++) {
329+
if(inv.getItem(i)==null) {
330+
inv.setItem(i,item);
331+
inv.setItem(source,null);
332+
return;
333+
}
334+
}
335+
// TODO: If all of that didn't work, change to some block that is not damageable
336+
}
337+
338+
}

src/main/resources/plugin.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
main: de.jeff_media.ChestSort.ChestSortPlugin
22
name: ChestSort
3-
version: 8.14.2
3+
version: 9.0.0-SNAPSHOT
44
api-version: "1.13"
55
description: Allows automatic chest sorting
66
author: mfnalex

0 commit comments

Comments
 (0)