Skip to content

Commit

Permalink
v13.0.0
Browse files Browse the repository at this point in the history
* Added XProxifier for XReflection IV
* **[XReflection]** Using the suffix support for JetBrains `@Language` annotation, we no longer need to add semicolons or `{}`
  at the end of string APIs. Other than the readability improvement, this results in a slight performance
  improvement as well, since fewer characters are needed for parsing.
* Improved Unit Tests.
* Added `@Contract` annotations to most APIs.
* **[XTag]** Fixed `INVENTORY_NOT_DISPLAYABLE` for wheat.
  • Loading branch information
CryptoMorin committed Jan 2, 2025
1 parent 79dc6f9 commit ee8f5f9
Show file tree
Hide file tree
Showing 36 changed files with 1,122 additions and 123 deletions.
42 changes: 38 additions & 4 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ This file simply highlighs things that need to be done in future releases or oth
solution is yet to be found. It's also a simple list of planned decisions for the future of the project that other
developers can see and perhaps give suggestions about. Anyone is welcome to complete any of the listed issues.

* **[XMaterial]** We have to convert this into a XModule/XRegistry class soon. Wait and see what Spigot/Pape does first.

* **[Unit Tests]** Improve Maven's unit testing (Read #149 issue for more info.)

* **[XReflectASM/ReflectiveProxy]** Add more benchmarking for XReflection Stage III & IV with different method
Expand All @@ -22,6 +24,39 @@ developers can see and perhaps give suggestions about. Anyone is welcome to comp
of using the annotations. This is useful for situations where annotations will seem bulky or the data is more complex
and must be calculated during runtime.

* **[ReflectiveProxyObject]** Add a way to ignore certain methods if they're not supported in a specific
version instead of throwing an error (related to the issue below)

* **[ReflectiveProxyObject]** Add some sort of `boolean isSupported(String method, MethodType type)` to
**ReflectiveProxyObject**. So we can test whether a method is supported in the current version or not.
If we could make the method signature more simple, that'd be nice as well. For example, we could take the
string approach and do `boolean isSupported(String signature)` to be used
like `isSupported("private method(int a, String b, ...)")` that could work. A more strict approach using the
already existing interface would've been nicer. For example, in JavaScript we could reference the method
itself and add properties to it. I guess an ideal approach would be how you link methods in javadocs.

* **[ReflectiveProxyObject]** Add a simple enum class scanner that uses `@Proxify` and `@ReflectName` annotations to
parse an enum class and map the correct values to field. How this value gets saved should be handled by
an interface class like `interface A { void mapValue(Object) }` which our enum implements. Then we could
also add a parent interface for **ReflectiveProxyObject** that enums also share, allowing us to use its
`instance()` method. Which also means that we can use our enum class in other proxy methods.

* **[ReflectiveProxyObject]** Add interface inheritance support. (This might already be a thing, we just need to test)

* **[ReflectiveProxyObject]** Add support for inner classes.

* **[ReflectiveProxyObject]** Create a Maven and Gradle plugin for real class support that remaps fields, constructors
and static member accesses to proxy access.

* **[XProxifier]** Implement configurable settings. (Read the TODO list inside that class for more info.)

* **[XProxifier]** Turn this into an IntelliJ plugin that allows proxifying any compiled file. Will probably
need ASM to read the class file due to class loader issues? Not sure, needs to be tested.

* **[XProxifier]** Add a way to automatically generate mappings for different versions of a proxified class.
We might define download links to mapping files, download the needed mapping, parse it and generate a class
container for it?

* **[XTag]** Inline all fields. Using a `static {}` block is unnecessary and makes things really hard to track.
Currently, this is not possible using IntelliJ's `Refactor -> Inline Field` feature, because you'll get a
`No initializer present for the field` error. Not sure if this is a bug or some sort of tricky feature.
Expand All @@ -33,6 +68,7 @@ developers can see and perhaps give suggestions about. Anyone is welcome to comp
including the current version and methods to enable/disable certain features that are currently handled by system
properties? One thing we could do is to add an option to enable debug mode, certain exceptions that are normally
suppressed are printed.

* **[General]** Don't forget to remove pre-12.0.0 deprecated codes in MC v1.22

* **[General]** Add a guide for Maven and Gradle users on how to properly exclude XSeries XReflection's III and IV proxy
Expand All @@ -44,7 +80,5 @@ developers can see and perhaps give suggestions about. Anyone is welcome to comp
have to spend a lot of time to design one.

* **[Documentation]** While the javadocs are pretty comprehensive for most classes, they're mostly flooded with small
and
technical details that most developers don't have to be concerned about. We should make a guide on the wiki with
screenshots
and a general overview of all the features which makes it much easier for developers to get started.
and technical details that most developers don't have to be concerned about. We should make a guide on the wiki with
screenshots and a general overview of all the features which makes it much easier for developers to get started.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>com.github.cryptomorin</groupId>
<artifactId>XSeries</artifactId>
<version>12.1.0</version>
<version>13.0.0</version>

<name>XSeries</name>
<description>A set of utilities for Minecraft plugins</description>
Expand Down
58 changes: 53 additions & 5 deletions src/main/java/com/cryptomorin/xseries/XItemStack.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,7 @@
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.entity.TropicalFish;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.*;
import org.bukkit.inventory.meta.*;
import org.bukkit.inventory.meta.trim.ArmorTrim;
import org.bukkit.inventory.meta.trim.TrimMaterial;
Expand All @@ -55,8 +52,10 @@
import org.bukkit.material.SpawnEgg;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionType;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.Range;

import java.util.*;
import java.util.function.BiPredicate;
Expand All @@ -77,7 +76,7 @@
* <a href="https://hub.spigotmc.org/javadocs/spigot/org/bukkit/inventory/ItemStack.html">ItemStack</a>
*
* @author Crypto Morin
* @version 7.5.1
* @version 7.5.2
* @see XMaterial
* @see XPotion
* @see XSkull
Expand Down Expand Up @@ -1236,6 +1235,7 @@ public static Color parseColor(@Nullable String str) {
* @since 2.0.1
*/
@NotNull
@Contract(mutates = "param1")
public static List<ItemStack> giveOrDrop(@NotNull Player player, @Nullable ItemStack... items) {
return giveOrDrop(player, false, items);
}
Expand All @@ -1250,6 +1250,7 @@ public static List<ItemStack> giveOrDrop(@NotNull Player player, @Nullable ItemS
* @since 2.0.1
*/
@NotNull
@Contract(mutates = "param1")
public static List<ItemStack> giveOrDrop(@NotNull Player player, boolean split, @Nullable ItemStack... items) {
if (items == null || items.length == 0) return new ArrayList<>();
List<ItemStack> leftOvers = addItems(player.getInventory(), split, items);
Expand All @@ -1260,6 +1261,7 @@ public static List<ItemStack> giveOrDrop(@NotNull Player player, boolean split,
return leftOvers;
}

@Contract(mutates = "param1")
public static List<ItemStack> addItems(@NotNull Inventory inventory, boolean split, @NotNull ItemStack... items) {
return addItems(inventory, split, null, items);
}
Expand All @@ -1277,7 +1279,9 @@ public static List<ItemStack> addItems(@NotNull Inventory inventory, boolean spl
* @return items that didn't fit in the inventory.
* @since 4.0.0
*/

@NotNull
@Contract(mutates = "param1")
public static List<ItemStack> addItems(@NotNull Inventory inventory, boolean split,
@Nullable Predicate<Integer> modifiableSlots, @NotNull ItemStack... items) {
Objects.requireNonNull(inventory, "Cannot add items to null inventory");
Expand Down Expand Up @@ -1344,6 +1348,9 @@ public static List<ItemStack> addItems(@NotNull Inventory inventory, boolean spl
return leftOvers;
}

@NotNull
@Contract(pure = true)
@Range(from = -1, to = Integer.MAX_VALUE)
public static int firstPartial(@NotNull Inventory inventory, @Nullable ItemStack item, int beginIndex) {
return firstPartial(inventory, item, beginIndex, null);
}
Expand All @@ -1361,6 +1368,9 @@ public static int firstPartial(@NotNull Inventory inventory, @Nullable ItemStack
* @throws IndexOutOfBoundsException if the beginning index is less than 0 or greater than the inventory storage size.
* @since 4.0.0
*/
@NotNull
@Contract(pure = true)
@Range(from = -1, to = Integer.MAX_VALUE)
public static int firstPartial(@NotNull Inventory inventory, @Nullable ItemStack item, int beginIndex, @Nullable Predicate<Integer> modifiableSlots) {
if (item != null) {
ItemStack[] items = getStorageContents(inventory);
Expand All @@ -1378,6 +1388,8 @@ public static int firstPartial(@NotNull Inventory inventory, @Nullable ItemStack
return -1;
}

@NotNull
@Contract(pure = true)
public static List<ItemStack> stack(@NotNull Collection<ItemStack> items) {
return stack(items, ItemStack::isSimilar);
}
Expand All @@ -1396,6 +1408,7 @@ public static List<ItemStack> stack(@NotNull Collection<ItemStack> items) {
* @since 4.0.0
*/
@NotNull
@Contract(pure = true)
public static List<ItemStack> stack(@NotNull Collection<ItemStack> items, @NotNull BiPredicate<ItemStack, ItemStack> similarity) {
Objects.requireNonNull(items, "Cannot stack null items");
Objects.requireNonNull(similarity, "Similarity check cannot be null");
Expand All @@ -1418,6 +1431,8 @@ public static List<ItemStack> stack(@NotNull Collection<ItemStack> items, @NotNu
return stacked;
}

@Contract(pure = true)
@Range(from = -1, to = Integer.MAX_VALUE)
public static int firstEmpty(@NotNull Inventory inventory, int beginIndex) {
return firstEmpty(inventory, beginIndex, null);
}
Expand All @@ -1434,6 +1449,8 @@ public static int firstEmpty(@NotNull Inventory inventory, int beginIndex) {
* @throws IndexOutOfBoundsException if the beginning index is less than 0 or greater than the inventory storage size.
* @since 4.0.0
*/
@Contract(pure = true)
@Range(from = -1, to = Integer.MAX_VALUE)
public static int firstEmpty(@NotNull Inventory inventory, int beginIndex, @Nullable Predicate<Integer> modifiableSlots) {
ItemStack[] items = getStorageContents(inventory);
int invSize = items.length;
Expand All @@ -1458,6 +1475,8 @@ public static int firstEmpty(@NotNull Inventory inventory, int beginIndex, @Null
* @see #firstPartial(Inventory, ItemStack, int)
* @since 4.2.0
*/
@Contract(pure = true)
@Range(from = -1, to = Integer.MAX_VALUE)
public static int firstPartialOrEmpty(@NotNull Inventory inventory, @Nullable ItemStack item, int beginIndex) {
if (item != null) {
ItemStack[] items = getStorageContents(inventory);
Expand All @@ -1474,6 +1493,10 @@ public static int firstPartialOrEmpty(@NotNull Inventory inventory, @Nullable It
return -1;
}

/**
* Cross-version compatible version of {@link Inventory#getStorageContents()}.
*/
@Contract(pure = true)
public static ItemStack[] getStorageContents(Inventory inventory) {
// Mojang divides player inventory like this:
// public final ItemStack[] items = new ItemStack[36];
Expand All @@ -1489,6 +1512,31 @@ public static ItemStack[] getStorageContents(Inventory inventory) {
}
}

/**
* @see #isEmpty(ItemStack)
* @since 7.5.2
*/
@Contract(pure = true)
public static boolean notEmpty(@Nullable ItemStack item) {
return !isEmpty(item);
}

/**
* Checks if this item is {@code null} or {@link Material#AIR}.
* The latter can only happen in the following situations:
* <ul>
* <li>{@link PlayerInventory#getItemInMainHand()}</li>
* <li>{@link PlayerInventory#getItemInOffHand()}</li>
* </ul>
*
* @see #notEmpty(ItemStack)
* @since 7.5.2
*/
@Contract(pure = true)
public static boolean isEmpty(@Nullable ItemStack item) {
return item == null || item.getType() == Material.AIR;
}

public static class MaterialCondition extends RuntimeException {
protected XMaterial solution;

Expand Down
4 changes: 2 additions & 2 deletions src/main/java/com/cryptomorin/xseries/XPotion.java
Original file line number Diff line number Diff line change
Expand Up @@ -333,8 +333,8 @@ private static List<String> split(@NotNull String str, @SuppressWarnings("SamePa
* Format: <b>Potion, Duration (in seconds), Amplifier (level) [%chance]</b>
* <pre>
* WEAKNESS, 30, 1
* SLOWNESS 200 10
* 1, 10000, 100 %50
* SLOWNESS, 200, 10
* 1, 10000, 100, %50
* </pre>
* The last argument can also include a chance (written in percent) which if not met, returns null.
*
Expand Down
6 changes: 4 additions & 2 deletions src/main/java/com/cryptomorin/xseries/XTag.java
Original file line number Diff line number Diff line change
Expand Up @@ -2436,8 +2436,10 @@ public final class XTag<T extends XBase<?, ?>> {
)
.inheritFrom(
AIR, CAVE_VINES, FILLED_CAULDRONS, FIRE, FLUID, PORTALS,
WALL_SIGNS, WALL_HANGING_SIGNS, WALL_TORCHES, ALIVE_CORAL_WALL_FANS, DEAD_CORAL_WALL_FANS, WALL_HEADS,
CANDLE_CAKES, WALL_BANNERS, FLOWER_POTS.without(XMaterial.FLOWER_POT), CROPS.without(XMaterial.WHEAT)
WALL_SIGNS, WALL_HANGING_SIGNS, WALL_TORCHES, ALIVE_CORAL_WALL_FANS,
DEAD_CORAL_WALL_FANS, WALL_HEADS, CANDLE_CAKES, WALL_BANNERS,
FLOWER_POTS.without(XMaterial.FLOWER_POT),
CROPS.without(XMaterial.WHEAT_SEEDS, XMaterial.WHEAT)
).build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public final class XSkull {
* @return A {@link ProfileInstruction} that sets the profile for the generated {@link ItemStack}.
*/
@NotNull
@Contract(pure = true)
@Contract(value = "-> new", pure = true)
public static ProfileInstruction<ItemStack> createItem() {
return of(XMaterial.PLAYER_HEAD.parseItem());
}
Expand All @@ -97,7 +97,7 @@ public static ProfileInstruction<ItemStack> createItem() {
* @return A {@link ProfileInstruction} that sets the profile for the given {@link ItemStack}.
*/
@NotNull
@Contract(pure = true)
@Contract(value = "_ -> new", pure = true)
public static ProfileInstruction<ItemStack> of(@NotNull ItemStack stack) {
return new ProfileInstruction<>(new ProfileContainer.ItemStackProfileContainer(stack));
}
Expand All @@ -109,7 +109,7 @@ public static ProfileInstruction<ItemStack> of(@NotNull ItemStack stack) {
* @return An {@link ProfileInstruction} that sets the profile for the given {@link ItemMeta}.
*/
@NotNull
@Contract(pure = true)
@Contract(value = "_ -> new", pure = true)
public static ProfileInstruction<ItemMeta> of(@NotNull ItemMeta meta) {
return new ProfileInstruction<>(new ProfileContainer.ItemMetaProfileContainer((SkullMeta) meta));
}
Expand All @@ -121,7 +121,7 @@ public static ProfileInstruction<ItemMeta> of(@NotNull ItemMeta meta) {
* @return An {@link ProfileInstruction} that sets the profile for the given {@link Block}.
*/
@NotNull
@Contract(pure = true)
@Contract(value = "_ -> new", pure = true)
public static ProfileInstruction<Block> of(@NotNull Block block) {
return new ProfileInstruction<>(new ProfileContainer.BlockProfileContainer(block));
}
Expand All @@ -133,7 +133,7 @@ public static ProfileInstruction<Block> of(@NotNull Block block) {
* @return An {@link ProfileInstruction} that sets the profile for the given {@link BlockState}.
*/
@NotNull
@Contract(pure = true)
@Contract(value = "_ -> new", pure = true)
public static ProfileInstruction<Skull> of(@NotNull BlockState state) {
return new ProfileInstruction<>(new ProfileContainer.BlockStateProfileContainer((Skull) state));
}
Expand All @@ -156,7 +156,7 @@ public static ProfileInstruction<Skull> of(@NotNull BlockState state) {
* @return A clone of the default {@link GameProfile}.
*/
@NotNull
@Contract(pure = true)
@Contract(value = "-> new", pure = true)
protected static Profileable getDefaultProfile() {
// We copy this just in case something changes the GameProfile properties.
GameProfile clone = PlayerProfiles.createGameProfile(DEFAULT_PROFILE.getId(), DEFAULT_PROFILE.getName());
Expand Down
Loading

0 comments on commit ee8f5f9

Please sign in to comment.