-
-
Notifications
You must be signed in to change notification settings - Fork 371
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Changeable Max Stack Size for Items and Inventory (#6698)
* Changeable max stack size for item and inventory * Changeable max stack size for item and inventory * Fix required plugins versioning * Fix human error and removing redundant debug message * Fix breaking change to inventory max stack size in 1.20.5 * Requested changes * Annotation correction * More tests * Check for ItemType#getRandom() nullability * Check for ItemType#getRandom() nullability * Remove license header (#6684) * Java 17 and some code optimisations * Requested changes * Improve examples * Requested changes * Minor logic change for changer * chezburger simplified --------- Co-authored-by: Moderocky <[email protected]> Co-authored-by: sovdee <[email protected]>
- Loading branch information
1 parent
59b1ff4
commit 541dc12
Showing
2 changed files
with
152 additions
and
38 deletions.
There are no files selected for viewing
128 changes: 91 additions & 37 deletions
128
src/main/java/ch/njol/skript/expressions/ExprMaxStack.java
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,62 +1,116 @@ | ||
/** | ||
* This file is part of Skript. | ||
* | ||
* Skript is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation, either version 3 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* Skript is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with Skript. If not, see <http://www.gnu.org/licenses/>. | ||
* | ||
* Copyright Peter Güttinger, SkriptLang team and contributors | ||
*/ | ||
package ch.njol.skript.expressions; | ||
|
||
import org.bukkit.Bukkit; | ||
import org.bukkit.Material; | ||
import org.bukkit.event.Event; | ||
import org.bukkit.inventory.Inventory; | ||
import org.bukkit.inventory.ItemStack; | ||
import org.bukkit.inventory.meta.ItemMeta; | ||
import org.jetbrains.annotations.Nullable; | ||
|
||
import ch.njol.skript.Skript; | ||
import ch.njol.skript.aliases.ItemType; | ||
import ch.njol.skript.classes.Changer.ChangeMode; | ||
import ch.njol.skript.doc.Description; | ||
import ch.njol.skript.doc.Examples; | ||
import ch.njol.skript.doc.Name; | ||
import ch.njol.skript.doc.RequiredPlugins; | ||
import ch.njol.skript.doc.Since; | ||
import ch.njol.skript.expressions.base.SimplePropertyExpression; | ||
import org.bukkit.Material; | ||
import org.bukkit.inventory.ItemStack; | ||
import ch.njol.util.Math2; | ||
import ch.njol.util.coll.CollectionUtils; | ||
|
||
/** | ||
* @author joeuguce99 | ||
*/ | ||
@Name("Maximum Stack Size") | ||
@Description("The maximum stack size of the specified material, e.g. 64 for torches, 16 for buckets, and 1 for swords.") | ||
@Examples("send \"You can only pick up %max stack size of player's tool% of %type of (player's tool)%\" to player") | ||
@Since("2.1") | ||
public class ExprMaxStack extends SimplePropertyExpression<ItemType, Long> { | ||
@Description({ | ||
"The maximum stack size of an item (e.g. 64 for torches, 16 for buckets, 1 for swords, etc.) or inventory.", | ||
"In 1.20.5+, the maximum stack size of items can be changed to any integer from 1 to 99, and stacked up to the maximum stack size of the inventory they're in." | ||
}) | ||
@Examples({ | ||
"send \"You can hold %max stack size of player's tool% of %type of player's tool% in a slot.\" to player", | ||
"set the maximum stack size of inventory of all players to 16", | ||
"add 8 to the maximum stack size of player's tool", | ||
"reset the maximum stack size of {_gui}" | ||
}) | ||
@Since("2.1, INSERT VERSION (changeable, inventories)") | ||
@RequiredPlugins("Spigot 1.20.5+ (changeable)") | ||
public class ExprMaxStack extends SimplePropertyExpression<Object, Integer> { | ||
|
||
static { | ||
register(ExprMaxStack.class, Long.class, "max[imum] stack[[ ]size]", "itemtype"); | ||
register(ExprMaxStack.class, Integer.class, "max[imum] stack[[ ]size]", "itemtypes/inventories"); | ||
} | ||
|
||
@SuppressWarnings("null") | ||
|
||
private static final boolean CHANGEABLE_ITEM_STACK_SIZE = Skript.methodExists(ItemMeta.class, "setMaxStackSize", Integer.class); | ||
|
||
@Override | ||
public Long convert(ItemType itemType) { | ||
Object random = itemType.getRandomStackOrMaterial(); | ||
if (random instanceof Material) | ||
return (long) ((Material) random).getMaxStackSize(); | ||
return (long) ((ItemStack) random).getMaxStackSize(); | ||
public @Nullable Integer convert(Object from) { | ||
if (from instanceof ItemType itemType) | ||
return getMaxStackSize(itemType); | ||
if (from instanceof Inventory inventory) | ||
return inventory.getMaxStackSize(); | ||
return null; | ||
} | ||
|
||
@Override | ||
public Class<? extends Long> getReturnType() { | ||
return Long.class; | ||
public @Nullable Class<?>[] acceptChange(ChangeMode mode) { | ||
return switch (mode) { | ||
case ADD, REMOVE, RESET, SET -> { | ||
if (!CHANGEABLE_ITEM_STACK_SIZE && ItemType.class.isAssignableFrom(getExpr().getReturnType())) { | ||
Skript.error("Changing the maximum stack size of items requires Minecraft 1.20.5 or newer!"); | ||
yield null; | ||
} | ||
yield CollectionUtils.array(Integer.class); | ||
} | ||
default -> null; | ||
}; | ||
} | ||
|
||
@Override | ||
public void change(Event event, Object @Nullable [] delta, ChangeMode mode) { | ||
int change = delta == null ? 0 : ((Number) delta[0]).intValue(); | ||
for (Object source : getExpr().getArray(event)) { | ||
if (source instanceof ItemType itemType) { | ||
if (!CHANGEABLE_ITEM_STACK_SIZE) | ||
continue; | ||
int size = getMaxStackSize(itemType); | ||
switch (mode) { | ||
case ADD -> size += change; | ||
case SET -> size = change; | ||
case REMOVE -> size -= change; | ||
} | ||
ItemMeta meta = itemType.getItemMeta(); | ||
// Minecraft only accepts stack size from 1 to 99 | ||
meta.setMaxStackSize(mode != ChangeMode.RESET ? Math2.fit(1, size, 99) : null); | ||
itemType.setItemMeta(meta); | ||
} else if (source instanceof Inventory inventory) { | ||
int size = inventory.getMaxStackSize(); | ||
switch (mode) { | ||
case ADD -> size += change; | ||
case SET -> size = change; | ||
case REMOVE -> size -= change; | ||
case RESET -> size = Bukkit.createInventory(null, inventory.getType()).getMaxStackSize(); | ||
} | ||
inventory.setMaxStackSize(size); | ||
} | ||
} | ||
} | ||
|
||
@Override | ||
public Class<? extends Integer> getReturnType() { | ||
return Integer.class; | ||
} | ||
|
||
@Override | ||
protected String getPropertyName() { | ||
return "maximum stack size"; | ||
} | ||
|
||
private static int getMaxStackSize(ItemType itemType) { | ||
Object item = itemType.getRandomStackOrMaterial(); | ||
if (item instanceof ItemStack stack) | ||
return stack.getMaxStackSize(); | ||
if (item instanceof Material material) | ||
return material.getMaxStackSize(); | ||
throw new UnsupportedOperationException(); | ||
} | ||
|
||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,64 @@ | ||
test "max stack": | ||
test "max stack - itemtype": | ||
assert max stack size of diamond sword is 1 with "diamond sword max stack size failed" | ||
assert max stack size of bucket is 16 with "bucket max stack size failed" | ||
assert max stack size of dirt is 64 with "dirt max stack size failed" | ||
|
||
# edge case | ||
assert max stack size of {_null} is not set with "max stack size of non itemtype expected to fail ##1" | ||
assert max stack size of {_null} is 0 to fail with "max stack size of non itemtype expected to fail ##2" | ||
assert max stack size of diamond and diamond sword is 64 and 1 with "max stack size of itemtypes 'and' case failed" | ||
assert max stack size of diamond or diamond sword is 64 or 1 with "max stack size of itemtypes 'or' case failed" | ||
loop any log and any wool: | ||
assert max stack size of loop-value is 64 with "max stack size of category itemtypes (%loop-value%) failed" | ||
|
||
test "max stack override - itemtype" when running minecraft "1.20.5": | ||
set {_item} to diamond | ||
set max stack size of {_item} to 32 | ||
assert max stack size of {_item} is 32 with "diamond should have max stack size of 32" | ||
add 2 to max stack size of {_item} | ||
assert max stack size of {_item} is 34 with "diamond should have max stack size of 34" | ||
remove 4 from max stack size of {_item} | ||
assert max stack size of {_item} is 30 with "diamond should have max stack size of 30" | ||
reset max stack size of {_item} | ||
assert max stack size of {_item} is 64 with "diamond should have max stack size of 64" | ||
|
||
set {_item} to bucket | ||
set max stack size of {_item} to 24 | ||
assert max stack size of {_item} is 24 with "bucket should have max stack size of 24" | ||
add 2 to max stack size of {_item} | ||
assert max stack size of {_item} is 26 with "bucket should have max stack size of 26" | ||
remove 4 from max stack size of {_item} | ||
assert max stack size of {_item} is 22 with "bucket should have max stack size of 22" | ||
reset max stack size of {_item} | ||
assert max stack size of {_item} is 16 with "bucket should have max stack size of 16" | ||
|
||
set {_item} to diamond sword | ||
set max stack size of {_item} to 16 | ||
assert max stack size of {_item} is 16 with "diamond sword should have max stack size of 16" | ||
add 2 to max stack size of {_item} | ||
assert max stack size of {_item} is 18 with "diamond sword should have max stack size of 18" | ||
remove 4 from max stack size of {_item} | ||
assert max stack size of {_item} is 14 with "diamond sword should have max stack size of 14" | ||
reset max stack size of {_item} | ||
assert max stack size of {_item} is 1 with "diamond sword should have max stack size of 1" | ||
|
||
# edge case | ||
loop any log and any wool: | ||
set {_edge} to loop-value | ||
set max stack size of {_edge} to 1 | ||
assert max stack size of {_edge} is 1 with "max stack size override of category itemtypes (%{_edge}%) failed" | ||
|
||
test "max stack override - inventory": | ||
set {_default} to 99 # 1.20.5 and newer | ||
if running below minecraft "1.20.5": | ||
set {_default} to 64 | ||
set {_inv} to a new chest inventory with 1 rows | ||
assert max stack size of {_inv} is {_default} with "inventory should have max stack size of %{_default}%" | ||
set max stack size of {_inv} to 32 | ||
assert max stack size of {_inv} is 32 with "inventory should have max stack size of 32" | ||
add 2 to max stack size of {_inv} | ||
assert max stack size of {_inv} is 34 with "inventory should have max stack size of 34" | ||
remove 4 from max stack size of {_inv} | ||
assert max stack size of {_inv} is 30 with "inventory should have max stack size of 30" | ||
reset max stack size of {_inv} | ||
assert max stack size of {_inv} is {_default} with "inventory should have factory max stack size of %{_default}%" |