Skip to content

Commit

Permalink
v9.0.0
Browse files Browse the repository at this point in the history
Removed the use of apache commons due to future planned removal of the library.
Removed "unused" package and all its classes.

XMaterial
Fixed a few issues regarding some wood and disc materials.

XItemStack
Custom model data option name is now consistent.

XEnchantment
Removed "ItemStack addEnchantFromString(@nonnull ItemStack item, @nullable String enchantment)" because I believe it's useless and I encourage all devs to make a simple yaml map
based with key as enchant name and value as the level config system instead.
  • Loading branch information
CryptoMorin committed Jul 2, 2022
1 parent 17565da commit b37cf70
Show file tree
Hide file tree
Showing 16 changed files with 290 additions and 1,048 deletions.
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ if it's unrelated to adding support for that version since your changes are like
* Make sure the utility works on different Minecraft server versions.
* Use method and variable names that make sense and are related to the context.
* Don't use Optional everywhere that can return null.
* Using Guava and Apache Commons is a plus, but make sure what you're using is supported in
older versions of Bukkit's libraries.
* Using Google's Guava is a plus, but not always. Make sure what you're using is supported in
older versions of Bukkit's libraries and don't. Don't use other libraries included in Bukkit, specially Apache Commons since it was removed.
* Add JavaDocs with proper formatting. It's also preferred to explain how the complex parts of a method work
inside the method. Use simple English when possible.
* All the functions used in the utilities should be compatible with Bukkit, Spigot and Paper.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
[![Build Status](https://travis-ci.com/CryptoMorin/XSeries.svg?branch=master)](https://travis-ci.com/CryptoMorin/XSeries)
![maven-central](https://img.shields.io/maven-central/v/com.github.cryptomorin/XSeries)

Library mainly designed to provide cross-version support for Minecraft Bukkit servers,
Library mainly designed to provide cross-version support for Minecraft Bukkit plugins,
but it also includes numerous extra methods to help developers design their plugins easier and efficiently.
Some utilities are completely unrelated to cross-version support such as NoteBlockMusic.

Expand Down
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>8.8.0</version>
<version>9.0.0</version>

<name>XSeries</name>
<description>A set of utilities for Minecraft plugins</description>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.mojang.authlib.GameProfile;
import org.apache.commons.lang.Validate;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerJoinEvent;
Expand Down Expand Up @@ -100,7 +99,7 @@ public static String getSkinValue(@Nonnull String id) {

@Nullable
public static String getIdFromUsername(@Nonnull String username) {
Validate.notEmpty(username, "Cannot get UUID of a null or empty username");
if (username == null || username.isEmpty()) throw new IllegalArgumentException("Cannot get UUID of a null or empty username");
int len = username.length();
if (len < 3 || len > 16) throw new IllegalArgumentException("Username cannot be less than 3 and longer than 16 characters: " + username);

Expand Down
3 changes: 1 addition & 2 deletions src/main/java/com/cryptomorin/xseries/SkullUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import com.google.common.collect.Lists;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.inventory.ItemStack;
Expand Down Expand Up @@ -131,7 +130,7 @@ public static SkullMeta applySkin(@Nonnull ItemMeta head, @Nonnull String identi

@Nonnull
protected static SkullMeta getSkullByValue(@Nonnull SkullMeta head, @Nonnull String value) {
Validate.notEmpty(value, "Skull value cannot be null or empty");
if (value == null || value.isEmpty()) throw new IllegalArgumentException("Skull value cannot be null or empty");
GameProfile profile = new GameProfile(UUID.randomUUID(), null);
profile.getProperties().put("textures", new Property("textures", value));

Expand Down
7 changes: 3 additions & 4 deletions src/main/java/com/cryptomorin/xseries/XBiome.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
package com.cryptomorin.xseries;

import com.google.common.base.Enums;
import org.apache.commons.lang.Validate;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.World;
Expand Down Expand Up @@ -240,7 +239,7 @@ private static String format(@Nonnull String name) {
*/
@Nonnull
public static Optional<XBiome> matchXBiome(@Nonnull String biome) {
Validate.notEmpty(biome, "Cannot match XBiome of a null or empty biome name");
if (biome == null || biome.isEmpty()) throw new IllegalArgumentException("Cannot match XBiome of a null or empty biome name");
return Optional.ofNullable(Data.NAMES.get(format(biome)));
}

Expand Down Expand Up @@ -296,7 +295,7 @@ public CompletableFuture<Void> setBiome(@Nonnull Chunk chunk) {
Objects.requireNonNull(biome, () -> "Unsupported biome: " + this.name());
Objects.requireNonNull(chunk, "Cannot set biome of null chunk");
if (!chunk.isLoaded()) {
Validate.isTrue(chunk.load(true), "Could not load chunk at " + chunk.getX() + ", " + chunk.getZ());
if (!chunk.load(true)) throw new IllegalStateException("Could not load chunk at " + chunk.getX() + ", " + chunk.getZ());
}
int heightMax = HORIZONTAL_SUPPORT ? chunk.getWorld().getMaxHeight() : 1;
int heightMin = EXTENDED_MINIMUM ? chunk.getWorld().getMinHeight() : 0;
Expand Down Expand Up @@ -337,7 +336,7 @@ public CompletableFuture<Void> setBiome(@Nonnull Location start, @Nonnull Locati
Objects.requireNonNull(biome, () -> "Unsupported biome: " + this.name());

World world = start.getWorld(); // Avoid getting from weak reference in a loop.
Validate.isTrue(world.getUID().equals(end.getWorld().getUID()), "Location worlds mismatch");
if (!world.getUID().equals(end.getWorld().getUID())) throw new IllegalArgumentException("Location worlds mismatch");
int heightMax = HORIZONTAL_SUPPORT ? world.getMaxHeight() : 1;
int heightMin = EXTENDED_MINIMUM ? world.getMinHeight() : 0;

Expand Down
5 changes: 2 additions & 3 deletions src/main/java/com/cryptomorin/xseries/XBlock.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
*/
package com.cryptomorin.xseries;

import org.apache.commons.lang.Validate;
import org.bukkit.DyeColor;
import org.bukkit.Material;
import org.bukkit.TreeSpecies;
Expand Down Expand Up @@ -486,7 +485,7 @@ public static boolean isOneOf(Block block, Collection<String> blocks) {
}

public static void setCakeSlices(Block block, int amount) {
Validate.isTrue(isCake(block.getType()), "Block is not a cake: " + block.getType());
if (!isCake(block.getType())) throw new IllegalArgumentException("Block is not a cake: " + block.getType());
if (ISFLAT) {
BlockData data = block.getBlockData();
org.bukkit.block.data.type.Cake cake = (org.bukkit.block.data.type.Cake) data;
Expand All @@ -512,7 +511,7 @@ public static void setCakeSlices(Block block, int amount) {
}

public static int addCakeSlices(Block block, int slices) {
Validate.isTrue(isCake(block.getType()), "Block is not a cake: " + block.getType());
if (!isCake(block.getType())) throw new IllegalArgumentException("Block is not a cake: " + block.getType());
if (ISFLAT) {
BlockData data = block.getBlockData();
org.bukkit.block.data.type.Cake cake = (org.bukkit.block.data.type.Cake) data;
Expand Down
54 changes: 5 additions & 49 deletions src/main/java/com/cryptomorin/xseries/XEnchantment.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,17 @@
package com.cryptomorin.xseries;

import com.google.common.base.Enums;
import com.google.common.base.Strings;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.Validate;
import org.apache.commons.lang.WordUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.EntityType;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
import org.bukkit.inventory.meta.ItemMeta;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.*;
import java.util.stream.Collectors;

/**
* Enchantment support with multiple aliases.
Expand Down Expand Up @@ -237,7 +232,7 @@ private static String format(@Nonnull String name) {
*/
@Nonnull
public static Optional<XEnchantment> matchXEnchantment(@Nonnull String enchantment) {
Validate.notEmpty(enchantment, "Enchantment name cannot be null or empty");
if (enchantment == null || enchantment.isEmpty()) throw new IllegalArgumentException("Enchantment name cannot be null or empty");
return Optional.ofNullable(Data.NAMES.get(format(enchantment)));
}

Expand All @@ -258,47 +253,6 @@ public static XEnchantment matchXEnchantment(@Nonnull Enchantment enchantment) {
return Objects.requireNonNull(Data.NAMES.get(enchantment.getName()), () -> "Unsupported enchantment: " + enchantment.getName());
}

/**
* Adds an unsafe enchantment to the given item from a string.
* <p>
* <blockquote><pre>
* ItemStack item = ...;
* addEnchantFromString(item, "unbreaking, 10");
* addEnchantFromString(item, "mending");
* </pre></blockquote>
* <p>
* Note that if you set your item's meta {@link ItemStack#setItemMeta(ItemMeta)} the enchantment
* will be removed.
* You need to use {@link ItemMeta#addEnchant(Enchantment, int, boolean)} instead.
* You can use the {@link #matchXEnchantment(String)} method in this case.
*
* @param item the item to add the enchantment to.
* @param enchantment the enchantment string containing the enchantment name and level (optional)
*
* @return an enchanted {@link ItemStack} or the item itself without enchantment added if enchantment type is null.
* @see #matchXEnchantment(String)
* @since 1.0.0
*/
@Nonnull
public static ItemStack addEnchantFromString(@Nonnull ItemStack item, @Nullable String enchantment) {
Objects.requireNonNull(item, "Cannot add enchantment to null ItemStack");
if (Strings.isNullOrEmpty(enchantment) || enchantment.equalsIgnoreCase("none")) return item;

String[] split = StringUtils.split(StringUtils.deleteWhitespace(enchantment), ',');
if (split.length == 0) split = StringUtils.split(enchantment, ' ');

Optional<XEnchantment> enchantOpt = matchXEnchantment(split[0]);
if (!enchantOpt.isPresent()) return item;
Enchantment enchant = enchantOpt.get().enchantment;
if (enchant == null) return item;

int lvl = 1;
if (split.length > 1) lvl = NumberUtils.toInt(split[1]);

item.addUnsafeEnchantment(enchant, lvl);
return item;
}

/**
* Gets the enchanted book of this enchantment.
*
Expand Down Expand Up @@ -352,7 +306,9 @@ public boolean isSupported() {
@Override
@Nonnull
public String toString() {
return WordUtils.capitalize(this.name().replace('_', ' ').toLowerCase(Locale.ENGLISH));
return Arrays.stream(name().split("_"))
.map(t -> t.charAt(0) + t.substring(1).toLowerCase())
.collect(Collectors.joining(" "));
}

/**
Expand Down
112 changes: 79 additions & 33 deletions src/main/java/com/cryptomorin/xseries/XItemStack.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@
import com.google.common.base.Enums;
import com.google.common.base.Strings;
import com.google.common.collect.Multimap;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.bukkit.*;
import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeModifier;
Expand Down Expand Up @@ -125,7 +123,7 @@ public static void serialize(@Nonnull ItemStack item, @Nonnull ConfigurationSect
if (meta.hasLore()) config.set("lore", meta.getLore()); // TODO Add a method to "untranslate" color codes.

if (supports(14)) {
if (meta.hasCustomModelData()) config.set("custom-model", meta.getCustomModelData());
if (meta.hasCustomModelData()) config.set("custom-model-data", meta.getCustomModelData());
}
if (supports(11)) {
if (meta.isUnbreakable()) config.set("unbreakable", true);
Expand Down Expand Up @@ -436,6 +434,42 @@ public static ItemStack deserialize(@Nonnull Map<String, Object> serializedItem,
return deserialize(mapToConfigSection(serializedItem), translator);
}

private static int toInt(String str, @SuppressWarnings("SameParameterValue") int defaultValue) {
try {
return Integer.parseInt(str);
} catch (NumberFormatException nfe) {
return defaultValue;
}
}

private static List<String> split(@Nonnull String str, @SuppressWarnings("SameParameterValue") char separatorChar) {
List<String> list = new ArrayList<>(5);
boolean match = false, lastMatch = false;
int len = str.length();
int start = 0;

for (int i = 0; i < len; i++) {
if (str.charAt(i) == separatorChar) {
if (match) {
list.add(str.substring(start, i));
match = false;
lastMatch = true;
}

// This is important, it should not be i++
start = i + 1;
continue;
}

lastMatch = false;
match = true;
}

if (match || lastMatch) {
list.add(str.substring(start, len));
}
return list;
}

/**
* Deserialize an ItemStack from the config.
Expand Down Expand Up @@ -539,10 +573,10 @@ public static ItemStack edit(@Nonnull ItemStack item,

String baseEffect = config.getString("base-effect");
if (!Strings.isNullOrEmpty(baseEffect)) {
String[] split = StringUtils.split(baseEffect, ',');
PotionType type = Enums.getIfPresent(PotionType.class, split[0].trim().toUpperCase(Locale.ENGLISH)).or(PotionType.UNCRAFTABLE);
boolean extended = split.length != 1 && Boolean.parseBoolean(split[1].trim());
boolean upgraded = split.length > 2 && Boolean.parseBoolean(split[2].trim());
List<String> split = split(baseEffect, ',');
PotionType type = Enums.getIfPresent(PotionType.class, split.get(0).trim().toUpperCase(Locale.ENGLISH)).or(PotionType.UNCRAFTABLE);
boolean extended = split.size() != 1 && Boolean.parseBoolean(split.get(1).trim());
boolean upgraded = split.size() > 2 && Boolean.parseBoolean(split.get(2).trim());
PotionData potionData = new PotionData(type, extended, upgraded);
potion.setBasePotionData(potionData);
}
Expand All @@ -556,10 +590,10 @@ public static ItemStack edit(@Nonnull ItemStack item,
int level = config.getInt("level");
String baseEffect = config.getString("base-effect");
if (!Strings.isNullOrEmpty(baseEffect)) {
String[] split = StringUtils.split(baseEffect, ',');
PotionType type = Enums.getIfPresent(PotionType.class, split[0].trim().toUpperCase(Locale.ENGLISH)).or(PotionType.SLOWNESS);
boolean extended = split.length != 1 && Boolean.parseBoolean(split[1].trim());
boolean splash = split.length > 2 && Boolean.parseBoolean(split[2].trim());
List<String> split = split(baseEffect, ',');
PotionType type = Enums.getIfPresent(PotionType.class, split.get(0).trim().toUpperCase(Locale.ENGLISH)).or(PotionType.SLOWNESS);
boolean extended = split.size() != 1 && Boolean.parseBoolean(split.get(1).trim());
boolean splash = split.size() > 2 && Boolean.parseBoolean(split.get(2).trim());

item = (new Potion(type, level, splash, extended)).toItemStack(1);
}
Expand All @@ -580,7 +614,7 @@ public static ItemStack edit(@Nonnull ItemStack item,
ShulkerBox box = (ShulkerBox) state;
for (String key : shulkerSection.getKeys(false)) {
ItemStack boxItem = deserialize(shulkerSection.getConfigurationSection(key));
int slot = NumberUtils.toInt(key, 0);
int slot = toInt(key, 0);
box.getInventory().setItem(slot, boxItem);
}
box.update(true);
Expand Down Expand Up @@ -774,35 +808,47 @@ public static ItemStack edit(@Nonnull ItemStack item,

// Custom Model Data
if (supports(14)) {
int modelData = config.getInt("model-data");
int modelData = config.getInt("custom-model-data");
if (modelData != 0) meta.setCustomModelData(modelData);
}

// Lore
List<String> translatedLore;
List<String> lores = config.getStringList("lore");
if (!lores.isEmpty()) {
translatedLore = new ArrayList<>(lores.size());

for (String lore : lores) {
if (lore.isEmpty()) {
translatedLore.add(" ");
continue;
}

for (String singleLore : splitNewLine(lore)) {
if (singleLore.isEmpty()) {
if (config.isSet("lore")) {
List<String> translatedLore;
List<String> lores = config.getStringList("lore");
if (!lores.isEmpty()) {
translatedLore = new ArrayList<>(lores.size());

for (String lore : lores) {
if (lore.isEmpty()) {
translatedLore.add(" ");
continue;
}
translatedLore.add(translator.apply(singleLore));

for (String singleLore : splitNewLine(lore)) {
if (singleLore.isEmpty()) {
translatedLore.add(" ");
continue;
}
translatedLore.add(translator.apply(singleLore));
}
}
} else {
String lore = config.getString("lore");
translatedLore = new ArrayList<>(10);

if (!Strings.isNullOrEmpty(lore)) {
for (String singleLore : splitNewLine(lore)) {
if (singleLore.isEmpty()) {
translatedLore.add(" ");
continue;
}
translatedLore.add(translator.apply(singleLore));
}
}
}

meta.setLore(translatedLore);
} else {
String lore = config.getString("lore");
if (!Strings.isNullOrEmpty(lore)) meta.setLore(Collections.singletonList(translator.apply(lore)));
}

// Enchantments
Expand Down Expand Up @@ -949,9 +995,9 @@ private static Map<String, Object> configSectionToMap(@Nonnull ConfigurationSect
@Nonnull
public static Color parseColor(@Nullable String str) {
if (Strings.isNullOrEmpty(str)) return Color.BLACK;
String[] rgb = StringUtils.split(StringUtils.deleteWhitespace(str), ',');
if (rgb.length < 3) return Color.WHITE;
return Color.fromRGB(NumberUtils.toInt(rgb[0], 0), NumberUtils.toInt(rgb[1], 0), NumberUtils.toInt(rgb[2], 0));
List<String> rgb = split(str.replace(" ", ""), ',');
if (rgb.size() < 3) return Color.WHITE;
return Color.fromRGB(toInt(rgb.get(0), 0), toInt(rgb.get(1), 0), toInt(rgb.get(2), 0));
}

/**
Expand Down
Loading

0 comments on commit b37cf70

Please sign in to comment.