2013-01-12 15:12:12 +01:00
package com.earth2me.essentials ;
2013-03-16 10:16:33 +01:00
import com.earth2me.essentials.textreader.BookInput ;
import com.earth2me.essentials.textreader.BookPager ;
import com.earth2me.essentials.textreader.IText ;
2018-12-09 13:16:15 +01:00
import com.earth2me.essentials.utils.EnumUtil ;
2013-06-08 23:31:19 +02:00
import com.earth2me.essentials.utils.FormatUtil ;
2018-12-09 13:16:15 +01:00
import com.earth2me.essentials.utils.MaterialUtil ;
2013-06-08 23:31:19 +02:00
import com.earth2me.essentials.utils.NumberUtil ;
2021-10-24 16:12:20 +02:00
import com.earth2me.essentials.utils.VersionUtil ;
2014-01-20 14:54:48 +01:00
import com.google.common.base.Joiner ;
2013-10-11 04:44:41 +02:00
import net.ess3.api.IEssentials ;
2024-02-03 21:38:14 +01:00
import net.ess3.api.TranslatableException ;
2013-01-13 05:44:28 +01:00
import org.bukkit.Color ;
2013-01-15 00:11:19 +01:00
import org.bukkit.DyeColor ;
import org.bukkit.FireworkEffect ;
2013-01-12 15:12:12 +01:00
import org.bukkit.Material ;
2016-07-25 13:06:24 +02:00
import org.bukkit.block.Banner ;
2015-04-21 01:04:09 +02:00
import org.bukkit.block.banner.PatternType ;
2013-01-12 15:12:12 +01:00
import org.bukkit.enchantments.Enchantment ;
2018-01-18 09:25:19 +01:00
import org.bukkit.inventory.ItemFlag ;
2013-01-12 15:12:12 +01:00
import org.bukkit.inventory.ItemStack ;
2020-10-03 19:46:05 +02:00
import org.bukkit.inventory.meta.BannerMeta ;
import org.bukkit.inventory.meta.BlockStateMeta ;
import org.bukkit.inventory.meta.BookMeta ;
import org.bukkit.inventory.meta.EnchantmentStorageMeta ;
2021-01-19 13:30:09 +01:00
import org.bukkit.inventory.meta.FireworkEffectMeta ;
2020-10-03 19:46:05 +02:00
import org.bukkit.inventory.meta.FireworkMeta ;
import org.bukkit.inventory.meta.ItemMeta ;
import org.bukkit.inventory.meta.LeatherArmorMeta ;
import org.bukkit.inventory.meta.PotionMeta ;
import org.bukkit.inventory.meta.SkullMeta ;
2015-10-28 15:59:11 +01:00
import org.bukkit.potion.Potion ;
2013-03-16 10:16:33 +01:00
import org.bukkit.potion.PotionEffect ;
import org.bukkit.potion.PotionEffectType ;
2013-01-12 15:12:12 +01:00
2020-10-03 19:46:05 +02:00
import java.util.ArrayList ;
import java.util.Arrays ;
import java.util.HashMap ;
import java.util.List ;
import java.util.Locale ;
import java.util.Map ;
2020-04-25 14:08:57 +02:00
import java.util.logging.Level ;
import java.util.regex.Pattern ;
2015-04-15 06:06:16 +02:00
public class MetaItemStack {
2018-01-19 02:52:44 +01:00
private static final Map < String , DyeColor > colorMap = new HashMap < > ( ) ;
private static final Map < String , FireworkEffect . Type > fireworkShape = new HashMap < > ( ) ;
2020-10-03 19:46:05 +02:00
private static boolean useNewSkullMethod = true ;
2015-04-15 06:06:16 +02:00
static {
2020-10-03 19:46:05 +02:00
for ( final DyeColor color : DyeColor . values ( ) ) {
2015-04-15 06:06:16 +02:00
colorMap . put ( color . name ( ) , color ) ;
}
2020-10-03 19:46:05 +02:00
for ( final FireworkEffect . Type type : FireworkEffect . Type . values ( ) ) {
2015-04-15 06:06:16 +02:00
fireworkShape . put ( type . name ( ) , type ) ;
}
}
2021-01-19 13:30:09 +01:00
private static final transient Pattern splitPattern = Pattern . compile ( " [:+',;.] " ) ;
private static final transient Pattern hexPattern = Pattern . compile ( " #([0-9a-fA-F]{6}) " ) ;
2015-04-15 06:06:16 +02:00
private ItemStack stack ;
private FireworkEffect . Builder builder = FireworkEffect . builder ( ) ;
private PotionEffectType pEffectType ;
private PotionEffect pEffect ;
private boolean validFirework = false ;
2021-01-19 13:30:09 +01:00
private boolean validFireworkCharge = false ;
2015-04-15 06:06:16 +02:00
private boolean validPotionEffect = false ;
private boolean validPotionDuration = false ;
private boolean validPotionPower = false ;
2015-10-28 15:59:11 +01:00
private boolean isSplashPotion = false ;
2015-04-15 06:06:16 +02:00
private boolean completePotion = false ;
private int power = 1 ;
private int duration = 120 ;
public MetaItemStack ( final ItemStack stack ) {
this . stack = stack . clone ( ) ;
}
2020-10-03 19:46:05 +02:00
private static void setSkullOwner ( final IEssentials ess , final ItemStack stack , final String owner ) {
if ( ! ( stack . getItemMeta ( ) instanceof SkullMeta ) ) return ;
final SkullMeta meta = ( SkullMeta ) stack . getItemMeta ( ) ;
if ( useNewSkullMethod ) {
try {
meta . setOwningPlayer ( ess . getServer ( ) . getOfflinePlayer ( owner ) ) ;
stack . setItemMeta ( meta ) ;
return ;
} catch ( final NoSuchMethodError e ) {
useNewSkullMethod = false ;
}
}
meta . setOwner ( owner ) ;
stack . setItemMeta ( meta ) ;
}
2015-04-15 06:06:16 +02:00
public ItemStack getItemStack ( ) {
return stack ;
}
public boolean isValidFirework ( ) {
return validFirework ;
}
public boolean isValidPotion ( ) {
return validPotionEffect & & validPotionDuration & & validPotionPower ;
}
public FireworkEffect . Builder getFireworkBuilder ( ) {
return builder ;
}
public PotionEffect getPotionEffect ( ) {
return pEffect ;
}
public boolean completePotion ( ) {
return completePotion ;
}
private void resetPotionMeta ( ) {
pEffect = null ;
pEffectType = null ;
validPotionEffect = false ;
validPotionDuration = false ;
validPotionPower = false ;
2015-10-28 15:59:11 +01:00
isSplashPotion = false ;
2015-04-15 06:06:16 +02:00
completePotion = true ;
}
public boolean canSpawn ( final IEssentials ess ) {
try {
2015-06-04 19:18:47 +02:00
ess . getServer ( ) . getUnsafe ( ) . modifyItemStack ( stack . clone ( ) , " {} " ) ;
2015-04-15 06:06:16 +02:00
return true ;
2020-10-03 19:46:05 +02:00
} catch ( final NoSuchMethodError nsme ) {
2015-04-15 06:06:16 +02:00
return true ;
2020-10-03 19:46:05 +02:00
} catch ( final Throwable npe ) {
2015-04-15 06:06:16 +02:00
if ( ess . getSettings ( ) . isDebug ( ) ) {
2020-04-25 14:08:57 +02:00
ess . getLogger ( ) . log ( Level . INFO , " Itemstack is invalid " , npe ) ;
2015-04-15 06:06:16 +02:00
}
return false ;
}
}
2020-10-03 19:46:05 +02:00
public void parseStringMeta ( final CommandSource sender , final boolean allowUnsafe , final String [ ] string , final int fromArg , final IEssentials ess ) throws Exception {
2015-04-15 06:06:16 +02:00
if ( string [ fromArg ] . startsWith ( " { " ) & & hasMetaPermission ( sender , " vanilla " , false , true , ess ) ) {
try {
stack = ess . getServer ( ) . getUnsafe ( ) . modifyItemStack ( stack , Joiner . on ( ' ' ) . join ( Arrays . asList ( string ) . subList ( fromArg , string . length ) ) ) ;
2020-10-03 19:46:05 +02:00
} catch ( final NullPointerException npe ) {
2015-04-15 06:06:16 +02:00
if ( ess . getSettings ( ) . isDebug ( ) ) {
ess . getLogger ( ) . log ( Level . INFO , " Itemstack is invalid " , npe ) ;
}
2020-10-03 19:46:05 +02:00
} catch ( final NoSuchMethodError nsme ) {
2024-02-03 21:38:14 +01:00
throw new TranslatableException ( nsme , " noMetaJson " ) ;
2020-10-03 19:46:05 +02:00
} catch ( final Throwable throwable ) {
2015-04-15 06:06:16 +02:00
throw new Exception ( throwable . getMessage ( ) , throwable ) ;
}
} else {
for ( int i = fromArg ; i < string . length ; i + + ) {
addStringMeta ( sender , allowUnsafe , string [ i ] , ess ) ;
}
if ( validFirework ) {
if ( ! hasMetaPermission ( sender , " firework " , true , true , ess ) ) {
2024-02-03 21:38:14 +01:00
throw new TranslatableException ( " noMetaFirework " ) ;
2015-04-15 06:06:16 +02:00
}
2020-10-03 19:46:05 +02:00
final FireworkEffect effect = builder . build ( ) ;
final FireworkMeta fmeta = ( FireworkMeta ) stack . getItemMeta ( ) ;
2015-04-15 06:06:16 +02:00
fmeta . addEffect ( effect ) ;
if ( fmeta . getEffects ( ) . size ( ) > 1 & & ! hasMetaPermission ( sender , " firework-multiple " , true , true , ess ) ) {
2024-02-03 21:38:14 +01:00
throw new TranslatableException ( " multipleCharges " ) ;
2015-04-15 06:06:16 +02:00
}
stack . setItemMeta ( fmeta ) ;
}
2021-01-19 13:30:09 +01:00
if ( validFireworkCharge ) {
if ( ! hasMetaPermission ( sender , " firework " , true , true , ess ) ) {
2024-02-03 21:38:14 +01:00
throw new TranslatableException ( " noMetaFirework " ) ;
2021-01-19 13:30:09 +01:00
}
final FireworkEffect effect = builder . build ( ) ;
final FireworkEffectMeta meta = ( FireworkEffectMeta ) stack . getItemMeta ( ) ;
meta . setEffect ( effect ) ;
stack . setItemMeta ( meta ) ;
}
2015-04-15 06:06:16 +02:00
}
}
public void addStringMeta ( final CommandSource sender , final boolean allowUnsafe , final String string , final IEssentials ess ) throws Exception {
final String [ ] split = splitPattern . split ( string , 2 ) ;
if ( split . length < 1 ) {
return ;
}
2020-10-03 19:46:05 +02:00
final Material WRITTEN_BOOK = EnumUtil . getMaterial ( " WRITTEN_BOOK " ) ;
2016-02-06 12:24:36 +01:00
2015-04-15 06:06:16 +02:00
if ( split . length > 1 & & split [ 0 ] . equalsIgnoreCase ( " name " ) & & hasMetaPermission ( sender , " name " , false , true , ess ) ) {
2023-05-27 03:51:11 +02:00
final String displayName = FormatUtil . replaceFormat ( split [ 1 ] . replaceAll ( " (?<! \\ \\ )_ " , " " ) . replace ( " \\ _ " , " _ " ) ) ;
2015-04-15 06:06:16 +02:00
final ItemMeta meta = stack . getItemMeta ( ) ;
meta . setDisplayName ( displayName ) ;
stack . setItemMeta ( meta ) ;
} else if ( split . length > 1 & & ( split [ 0 ] . equalsIgnoreCase ( " lore " ) | | split [ 0 ] . equalsIgnoreCase ( " desc " ) ) & & hasMetaPermission ( sender , " lore " , false , true , ess ) ) {
2020-04-25 14:08:57 +02:00
final List < String > lore = new ArrayList < > ( ) ;
2020-10-03 19:46:05 +02:00
for ( final String line : split [ 1 ] . split ( " (?<! \\ \\ ) \\ | " ) ) {
2023-05-27 03:51:11 +02:00
lore . add ( FormatUtil . replaceFormat ( line . replaceAll ( " (?<! \\ \\ )_ " , " " ) . replace ( " \\ _ " , " _ " ) . replace ( " \\ | " , " | " ) ) ) ;
2015-04-15 06:06:16 +02:00
}
final ItemMeta meta = stack . getItemMeta ( ) ;
meta . setLore ( lore ) ;
stack . setItemMeta ( meta ) ;
2023-08-06 01:38:43 +02:00
} else if ( ( split [ 0 ] . equalsIgnoreCase ( " custom-model-data " ) | | split [ 0 ] . equalsIgnoreCase ( " cmd " ) ) & & hasMetaPermission ( sender , " custom-model-data " , false , true , ess ) ) {
if ( VersionUtil . getServerBukkitVersion ( ) . isHigherThanOrEqualTo ( VersionUtil . v1_14_R01 ) ) {
final int value = split . length < = 1 ? 0 : Integer . parseInt ( split [ 1 ] ) ;
final ItemMeta meta = stack . getItemMeta ( ) ;
meta . setCustomModelData ( value ) ;
stack . setItemMeta ( meta ) ;
}
2017-08-07 15:01:49 +02:00
} else if ( split [ 0 ] . equalsIgnoreCase ( " unbreakable " ) & & hasMetaPermission ( sender , " unbreakable " , false , true , ess ) ) {
2020-10-03 19:46:05 +02:00
final boolean value = split . length < = 1 | | Boolean . parseBoolean ( split [ 1 ] ) ;
2021-10-24 16:17:06 +02:00
setUnbreakable ( ess , stack , value ) ;
2018-12-09 13:16:15 +01:00
} else if ( split . length > 1 & & ( split [ 0 ] . equalsIgnoreCase ( " player " ) | | split [ 0 ] . equalsIgnoreCase ( " owner " ) ) & & hasMetaPermission ( sender , " head " , false , true , ess ) ) {
2022-02-13 21:33:51 +01:00
if ( MaterialUtil . isPlayerHead ( stack ) ) {
2015-04-15 06:06:16 +02:00
final String owner = split [ 1 ] ;
2019-08-24 11:05:26 +02:00
setSkullOwner ( ess , stack , owner ) ;
2015-04-15 06:06:16 +02:00
} else {
2024-02-03 21:38:14 +01:00
throw new TranslatableException ( " onlyPlayerSkulls " ) ;
2015-04-15 06:06:16 +02:00
}
2023-08-08 21:46:07 +02:00
} else if ( split . length > 1 & & split [ 0 ] . equalsIgnoreCase ( " book " ) & & MaterialUtil . isEditableBook ( stack . getType ( ) ) & & ( hasMetaPermission ( sender , " book " , true , true , ess ) | | hasMetaPermission ( sender , " chapter- " + split [ 1 ] . toLowerCase ( Locale . ENGLISH ) , true , true , ess ) ) ) {
2015-04-15 06:06:16 +02:00
final BookMeta meta = ( BookMeta ) stack . getItemMeta ( ) ;
final IText input = new BookInput ( " book " , true , ess ) ;
final BookPager pager = new BookPager ( input ) ;
2023-08-08 21:46:07 +02:00
// This fix only applies to written books - which require an author and a title. https://bugs.mojang.com/browse/MC-59153
if ( stack . getType ( ) = = WRITTEN_BOOK ) {
if ( ! meta . hasAuthor ( ) ) {
// The sender can be null when this method is called from {@link com.earth2me.essentials.signs.EssentialsSign#getItemMeta(ItemStack, String, IEssentials)}
meta . setAuthor ( sender = = null ? Console . getInstance ( ) . getDisplayName ( ) : sender . getPlayer ( ) . getName ( ) ) ;
}
if ( ! meta . hasTitle ( ) ) {
final String title = FormatUtil . replaceFormat ( split [ 1 ] . replace ( '_' , ' ' ) ) ;
meta . setTitle ( title . length ( ) > 32 ? title . substring ( 0 , 32 ) : title ) ;
}
}
2020-10-03 19:46:05 +02:00
final List < String > pages = pager . getPages ( split [ 1 ] ) ;
2015-04-15 06:06:16 +02:00
meta . setPages ( pages ) ;
stack . setItemMeta ( meta ) ;
2018-12-09 13:16:15 +01:00
} else if ( split . length > 1 & & split [ 0 ] . equalsIgnoreCase ( " author " ) & & stack . getType ( ) = = WRITTEN_BOOK & & hasMetaPermission ( sender , " author " , false , true , ess ) ) {
2015-04-15 06:06:16 +02:00
final String author = FormatUtil . replaceFormat ( split [ 1 ] ) ;
final BookMeta meta = ( BookMeta ) stack . getItemMeta ( ) ;
meta . setAuthor ( author ) ;
stack . setItemMeta ( meta ) ;
2018-12-09 13:16:15 +01:00
} else if ( split . length > 1 & & split [ 0 ] . equalsIgnoreCase ( " title " ) & & stack . getType ( ) = = WRITTEN_BOOK & & hasMetaPermission ( sender , " title " , false , true , ess ) ) {
2023-05-27 03:51:11 +02:00
final String title = FormatUtil . replaceFormat ( split [ 1 ] . replaceAll ( " (?<! \\ \\ )_ " , " " ) . replace ( " \\ _ " , " _ " ) ) ;
2015-04-15 06:06:16 +02:00
final BookMeta meta = ( BookMeta ) stack . getItemMeta ( ) ;
meta . setTitle ( title ) ;
stack . setItemMeta ( meta ) ;
2021-05-28 19:52:18 +02:00
} else if ( split . length > 1 & & split [ 0 ] . startsWith ( " page " ) & & split [ 0 ] . length ( ) > 4 & & MaterialUtil . isEditableBook ( stack . getType ( ) ) & & hasMetaPermission ( sender , " page " , false , true , ess ) ) {
final int page = NumberUtil . isInt ( split [ 0 ] . substring ( 4 ) ) ? ( Integer . parseInt ( split [ 0 ] . substring ( 4 ) ) - 1 ) : 0 ;
final BookMeta meta = ( BookMeta ) stack . getItemMeta ( ) ;
final List < String > pages = meta . hasPages ( ) ? new ArrayList < > ( meta . getPages ( ) ) : new ArrayList < > ( ) ;
final List < String > lines = new ArrayList < > ( ) ;
for ( final String line : split [ 1 ] . split ( " (?<! \\ \\ ) \\ | " ) ) {
2023-05-27 03:51:11 +02:00
lines . add ( FormatUtil . replaceFormat ( line . replaceAll ( " (?<! \\ \\ )_ " , " " ) . replace ( " \\ _ " , " _ " ) . replace ( " \\ | " , " | " ) ) ) ;
2021-05-28 19:52:18 +02:00
}
final String content = String . join ( " \ n " , lines ) ;
if ( page > = pages . size ( ) ) {
for ( int i = 0 ; i < = page - pages . size ( ) ; i + + ) {
pages . add ( " " ) ;
}
}
pages . set ( page , content ) ;
meta . setPages ( pages ) ;
stack . setItemMeta ( meta ) ;
2020-10-03 19:46:05 +02:00
} else if ( split . length > 1 & & split [ 0 ] . equalsIgnoreCase ( " power " ) & & MaterialUtil . isFirework ( stack . getType ( ) ) & & hasMetaPermission ( sender , " firework-power " , false , true , ess ) ) {
2015-04-15 06:06:16 +02:00
final int power = NumberUtil . isInt ( split [ 1 ] ) ? Integer . parseInt ( split [ 1 ] ) : 0 ;
final FireworkMeta meta = ( FireworkMeta ) stack . getItemMeta ( ) ;
meta . setPower ( power > 3 ? 4 : power ) ;
stack . setItemMeta ( meta ) ;
2018-01-18 09:25:19 +01:00
} else if ( split . length > 1 & & split [ 0 ] . equalsIgnoreCase ( " itemflags " ) & & hasMetaPermission ( sender , " itemflags " , false , true , ess ) ) {
addItemFlags ( string ) ;
2019-05-12 14:50:35 +02:00
} else if ( MaterialUtil . isFirework ( stack . getType ( ) ) ) {
2021-06-11 17:13:43 +02:00
if ( ! parseEnchantmentStrings ( sender , allowUnsafe , split , ess ) ) {
//WARNING - Meta for fireworks will be ignored after this point.
addFireworkMeta ( sender , false , string , ess ) ;
}
2021-01-19 13:30:09 +01:00
} else if ( MaterialUtil . isFireworkCharge ( stack . getType ( ) ) ) {
2021-06-11 17:13:43 +02:00
if ( ! parseEnchantmentStrings ( sender , allowUnsafe , split , ess ) ) {
//WARNING - Meta for fireworks will be ignored after this point.
addChargeMeta ( sender , false , string , ess ) ;
}
2019-05-12 14:50:35 +02:00
} else if ( MaterialUtil . isPotion ( stack . getType ( ) ) ) {
2021-06-11 17:13:43 +02:00
if ( split [ 0 ] . equalsIgnoreCase ( " power " ) | | ! parseEnchantmentStrings ( sender , allowUnsafe , split , ess ) ) {
//WARNING - Meta for potions will be ignored after this point.
addPotionMeta ( sender , false , string , ess ) ;
}
2018-12-09 13:16:15 +01:00
} else if ( MaterialUtil . isBanner ( stack . getType ( ) ) ) {
2021-06-11 17:13:43 +02:00
if ( ! parseEnchantmentStrings ( sender , allowUnsafe , split , ess ) ) {
2019-05-12 14:50:35 +02:00
//WARNING - Meta for banners will be ignored after this point.
addBannerMeta ( sender , false , string , ess ) ;
}
2018-12-09 13:16:15 +01:00
} else if ( split . length > 1 & & ( split [ 0 ] . equalsIgnoreCase ( " color " ) | | split [ 0 ] . equalsIgnoreCase ( " colour " ) ) & & MaterialUtil . isLeatherArmor ( stack . getType ( ) ) ) {
2021-06-11 17:13:43 +02:00
final String [ ] color = split [ 1 ] . split ( " [|,] " ) ;
2018-12-09 13:16:15 +01:00
if ( color . length = = 1 & & ( NumberUtil . isInt ( color [ 0 ] ) | | color [ 0 ] . startsWith ( " # " ) ) ) {
// Either integer or hexadecimal
2015-10-08 20:14:04 +02:00
final LeatherArmorMeta meta = ( LeatherArmorMeta ) stack . getItemMeta ( ) ;
2020-10-03 19:46:05 +02:00
final String input = color [ 0 ] ;
2018-12-09 13:16:15 +01:00
if ( input . startsWith ( " # " ) ) { // Hex
2015-10-08 20:33:14 +02:00
meta . setColor ( Color . fromRGB (
Integer . valueOf ( input . substring ( 1 , 3 ) , 16 ) ,
Integer . valueOf ( input . substring ( 3 , 5 ) , 16 ) ,
Integer . valueOf ( input . substring ( 5 , 7 ) , 16 ) ) ) ;
2018-12-09 13:16:15 +01:00
} else { // Int
2015-10-08 20:33:14 +02:00
meta . setColor ( Color . fromRGB ( Integer . parseInt ( input ) ) ) ;
}
2015-10-08 20:14:04 +02:00
stack . setItemMeta ( meta ) ;
} else if ( color . length = = 3 ) { // r,g,b
2015-04-15 06:06:16 +02:00
final int red = NumberUtil . isInt ( color [ 0 ] ) ? Integer . parseInt ( color [ 0 ] ) : 0 ;
final int green = NumberUtil . isInt ( color [ 1 ] ) ? Integer . parseInt ( color [ 1 ] ) : 0 ;
final int blue = NumberUtil . isInt ( color [ 2 ] ) ? Integer . parseInt ( color [ 2 ] ) : 0 ;
final LeatherArmorMeta meta = ( LeatherArmorMeta ) stack . getItemMeta ( ) ;
meta . setColor ( Color . fromRGB ( red , green , blue ) ) ;
stack . setItemMeta ( meta ) ;
} else {
2024-02-03 21:38:14 +01:00
throw new TranslatableException ( " leatherSyntax " ) ;
2015-04-15 06:06:16 +02:00
}
} else {
parseEnchantmentStrings ( sender , allowUnsafe , split , ess ) ;
}
}
2018-01-18 09:25:19 +01:00
public void addItemFlags ( final String string ) throws Exception {
2020-10-03 19:46:05 +02:00
final String [ ] separate = splitPattern . split ( string , 2 ) ;
2018-01-23 01:37:01 +01:00
if ( separate . length ! = 2 ) {
2024-02-03 21:38:14 +01:00
throw new TranslatableException ( " invalidItemFlagMeta " , string ) ;
2018-01-18 09:25:19 +01:00
}
2020-10-03 19:46:05 +02:00
final String [ ] split = separate [ 1 ] . split ( " , " ) ;
final ItemMeta meta = stack . getItemMeta ( ) ;
2018-01-18 09:25:19 +01:00
2020-10-03 19:46:05 +02:00
for ( final String s : split ) {
for ( final ItemFlag flag : ItemFlag . values ( ) ) {
2018-01-18 09:25:19 +01:00
if ( s . equalsIgnoreCase ( flag . name ( ) ) ) {
meta . addItemFlags ( flag ) ;
}
}
}
if ( meta . getItemFlags ( ) . isEmpty ( ) ) {
2024-02-03 21:38:14 +01:00
throw new TranslatableException ( " invalidItemFlagMeta " , string ) ;
2018-01-18 09:25:19 +01:00
}
stack . setItemMeta ( meta ) ;
}
2021-01-19 13:30:09 +01:00
private void addChargeMeta ( final CommandSource sender , final boolean allowShortName , final String string , final IEssentials ess ) throws Exception {
final String [ ] split = splitPattern . split ( string , 2 ) ;
if ( split . length < 2 ) {
return ;
}
if ( split [ 0 ] . equalsIgnoreCase ( " color " ) | | split [ 0 ] . equalsIgnoreCase ( " colour " ) | | ( allowShortName & & split [ 0 ] . equalsIgnoreCase ( " c " ) ) ) {
final List < Color > primaryColors = new ArrayList < > ( ) ;
final String [ ] colors = split [ 1 ] . split ( " , " ) ;
for ( final String color : colors ) {
if ( colorMap . containsKey ( color . toUpperCase ( ) ) ) {
validFireworkCharge = true ;
primaryColors . add ( colorMap . get ( color . toUpperCase ( ) ) . getFireworkColor ( ) ) ;
} else if ( hexPattern . matcher ( color ) . matches ( ) ) {
validFireworkCharge = true ;
primaryColors . add ( Color . fromRGB ( Integer . decode ( color ) ) ) ;
} else {
2024-02-03 21:38:14 +01:00
throw new TranslatableException ( " invalidFireworkFormat " , split [ 1 ] , split [ 0 ] ) ;
2021-01-19 13:30:09 +01:00
}
}
builder . withColor ( primaryColors ) ;
} else if ( split [ 0 ] . equalsIgnoreCase ( " shape " ) | | split [ 0 ] . equalsIgnoreCase ( " type " ) | | ( allowShortName & & ( split [ 0 ] . equalsIgnoreCase ( " s " ) | | split [ 0 ] . equalsIgnoreCase ( " t " ) ) ) ) {
FireworkEffect . Type finalEffect = null ;
split [ 1 ] = split [ 1 ] . equalsIgnoreCase ( " large " ) ? " BALL_LARGE " : split [ 1 ] ;
if ( fireworkShape . containsKey ( split [ 1 ] . toUpperCase ( ) ) ) {
finalEffect = fireworkShape . get ( split [ 1 ] . toUpperCase ( ) ) ;
} else {
2024-02-03 21:38:14 +01:00
throw new TranslatableException ( " invalidFireworkFormat " , split [ 1 ] , split [ 0 ] ) ;
2021-01-19 13:30:09 +01:00
}
if ( finalEffect ! = null ) {
builder . with ( finalEffect ) ;
}
} else if ( split [ 0 ] . equalsIgnoreCase ( " fade " ) | | ( allowShortName & & split [ 0 ] . equalsIgnoreCase ( " f " ) ) ) {
final List < Color > fadeColors = new ArrayList < > ( ) ;
final String [ ] colors = split [ 1 ] . split ( " , " ) ;
for ( final String color : colors ) {
if ( colorMap . containsKey ( color . toUpperCase ( ) ) ) {
fadeColors . add ( colorMap . get ( color . toUpperCase ( ) ) . getFireworkColor ( ) ) ;
} else if ( hexPattern . matcher ( color ) . matches ( ) ) {
fadeColors . add ( Color . fromRGB ( Integer . decode ( color ) ) ) ;
} else {
2024-02-03 21:38:14 +01:00
throw new TranslatableException ( " invalidFireworkFormat " , split [ 1 ] , split [ 0 ] ) ;
2021-01-19 13:30:09 +01:00
}
}
if ( ! fadeColors . isEmpty ( ) ) {
builder . withFade ( fadeColors ) ;
}
} else if ( split [ 0 ] . equalsIgnoreCase ( " effect " ) | | ( allowShortName & & split [ 0 ] . equalsIgnoreCase ( " e " ) ) ) {
final String [ ] effects = split [ 1 ] . split ( " , " ) ;
for ( final String effect : effects ) {
if ( effect . equalsIgnoreCase ( " twinkle " ) ) {
builder . flicker ( true ) ;
} else if ( effect . equalsIgnoreCase ( " trail " ) ) {
builder . trail ( true ) ;
} else {
2024-02-03 21:38:14 +01:00
throw new TranslatableException ( " invalidFireworkFormat " , split [ 1 ] , split [ 0 ] ) ;
2021-01-19 13:30:09 +01:00
}
}
}
}
2015-04-15 06:06:16 +02:00
public void addFireworkMeta ( final CommandSource sender , final boolean allowShortName , final String string , final IEssentials ess ) throws Exception {
2020-10-03 19:46:05 +02:00
if ( MaterialUtil . isFirework ( stack . getType ( ) ) ) {
2015-04-15 06:06:16 +02:00
final String [ ] split = splitPattern . split ( string , 2 ) ;
if ( split . length < 2 ) {
return ;
}
if ( split [ 0 ] . equalsIgnoreCase ( " color " ) | | split [ 0 ] . equalsIgnoreCase ( " colour " ) | | ( allowShortName & & split [ 0 ] . equalsIgnoreCase ( " c " ) ) ) {
if ( validFirework ) {
if ( ! hasMetaPermission ( sender , " firework " , true , true , ess ) ) {
2024-02-03 21:38:14 +01:00
throw new TranslatableException ( " noMetaFirework " ) ;
2015-04-15 06:06:16 +02:00
}
2020-10-03 19:46:05 +02:00
final FireworkEffect effect = builder . build ( ) ;
final FireworkMeta fmeta = ( FireworkMeta ) stack . getItemMeta ( ) ;
2015-04-15 06:06:16 +02:00
fmeta . addEffect ( effect ) ;
if ( fmeta . getEffects ( ) . size ( ) > 1 & & ! hasMetaPermission ( sender , " firework-multiple " , true , true , ess ) ) {
2024-02-03 21:38:14 +01:00
throw new TranslatableException ( " multipleCharges " ) ;
2015-04-15 06:06:16 +02:00
}
stack . setItemMeta ( fmeta ) ;
builder = FireworkEffect . builder ( ) ;
}
2020-10-03 19:46:05 +02:00
final List < Color > primaryColors = new ArrayList < > ( ) ;
final String [ ] colors = split [ 1 ] . split ( " , " ) ;
for ( final String color : colors ) {
2015-04-15 06:06:16 +02:00
if ( colorMap . containsKey ( color . toUpperCase ( ) ) ) {
validFirework = true ;
primaryColors . add ( colorMap . get ( color . toUpperCase ( ) ) . getFireworkColor ( ) ) ;
2021-01-19 13:30:09 +01:00
} else if ( hexPattern . matcher ( color ) . matches ( ) ) {
validFirework = true ;
primaryColors . add ( Color . fromRGB ( Integer . decode ( color ) ) ) ;
2015-04-15 06:06:16 +02:00
} else {
2024-02-03 21:38:14 +01:00
throw new TranslatableException ( " invalidFireworkFormat " , split [ 1 ] , split [ 0 ] ) ;
2015-04-15 06:06:16 +02:00
}
}
builder . withColor ( primaryColors ) ;
} else if ( split [ 0 ] . equalsIgnoreCase ( " shape " ) | | split [ 0 ] . equalsIgnoreCase ( " type " ) | | ( allowShortName & & ( split [ 0 ] . equalsIgnoreCase ( " s " ) | | split [ 0 ] . equalsIgnoreCase ( " t " ) ) ) ) {
FireworkEffect . Type finalEffect = null ;
2020-10-03 19:46:05 +02:00
split [ 1 ] = split [ 1 ] . equalsIgnoreCase ( " large " ) ? " BALL_LARGE " : split [ 1 ] ;
2015-04-15 06:06:16 +02:00
if ( fireworkShape . containsKey ( split [ 1 ] . toUpperCase ( ) ) ) {
finalEffect = fireworkShape . get ( split [ 1 ] . toUpperCase ( ) ) ;
} else {
2024-02-03 21:38:14 +01:00
throw new TranslatableException ( " invalidFireworkFormat " , split [ 1 ] , split [ 0 ] ) ;
2015-04-15 06:06:16 +02:00
}
if ( finalEffect ! = null ) {
builder . with ( finalEffect ) ;
}
} else if ( split [ 0 ] . equalsIgnoreCase ( " fade " ) | | ( allowShortName & & split [ 0 ] . equalsIgnoreCase ( " f " ) ) ) {
2020-10-03 19:46:05 +02:00
final List < Color > fadeColors = new ArrayList < > ( ) ;
final String [ ] colors = split [ 1 ] . split ( " , " ) ;
for ( final String color : colors ) {
2015-04-15 06:06:16 +02:00
if ( colorMap . containsKey ( color . toUpperCase ( ) ) ) {
fadeColors . add ( colorMap . get ( color . toUpperCase ( ) ) . getFireworkColor ( ) ) ;
2021-01-19 13:30:09 +01:00
} else if ( hexPattern . matcher ( color ) . matches ( ) ) {
fadeColors . add ( Color . fromRGB ( Integer . decode ( color ) ) ) ;
2015-04-15 06:06:16 +02:00
} else {
2024-02-03 21:38:14 +01:00
throw new TranslatableException ( " invalidFireworkFormat " , split [ 1 ] , split [ 0 ] ) ;
2015-04-15 06:06:16 +02:00
}
}
if ( ! fadeColors . isEmpty ( ) ) {
builder . withFade ( fadeColors ) ;
}
} else if ( split [ 0 ] . equalsIgnoreCase ( " effect " ) | | ( allowShortName & & split [ 0 ] . equalsIgnoreCase ( " e " ) ) ) {
2020-10-03 19:46:05 +02:00
final String [ ] effects = split [ 1 ] . split ( " , " ) ;
for ( final String effect : effects ) {
2015-04-15 06:06:16 +02:00
if ( effect . equalsIgnoreCase ( " twinkle " ) ) {
builder . flicker ( true ) ;
} else if ( effect . equalsIgnoreCase ( " trail " ) ) {
builder . trail ( true ) ;
} else {
2024-02-03 21:38:14 +01:00
throw new TranslatableException ( " invalidFireworkFormat " , split [ 1 ] , split [ 0 ] ) ;
2015-04-15 06:06:16 +02:00
}
}
}
}
}
public void addPotionMeta ( final CommandSource sender , final boolean allowShortName , final String string , final IEssentials ess ) throws Exception {
2018-12-09 13:16:15 +01:00
if ( MaterialUtil . isPotion ( stack . getType ( ) ) ) {
2015-04-15 06:06:16 +02:00
final String [ ] split = splitPattern . split ( string , 2 ) ;
if ( split . length < 2 ) {
return ;
}
if ( split [ 0 ] . equalsIgnoreCase ( " effect " ) | | ( allowShortName & & split [ 0 ] . equalsIgnoreCase ( " e " ) ) ) {
pEffectType = Potions . getByName ( split [ 1 ] ) ;
if ( pEffectType ! = null & & pEffectType . getName ( ) ! = null ) {
if ( hasMetaPermission ( sender , " potions. " + pEffectType . getName ( ) . toLowerCase ( Locale . ENGLISH ) , true , false , ess ) ) {
validPotionEffect = true ;
} else {
2024-02-03 21:38:14 +01:00
throw new TranslatableException ( " noPotionEffectPerm " , pEffectType . getName ( ) . toLowerCase ( Locale . ENGLISH ) ) ;
2015-04-15 06:06:16 +02:00
}
} else {
2024-02-03 21:38:14 +01:00
throw new TranslatableException ( " invalidPotionMeta " , split [ 1 ] ) ;
2015-04-15 06:06:16 +02:00
}
} else if ( split [ 0 ] . equalsIgnoreCase ( " power " ) | | ( allowShortName & & split [ 0 ] . equalsIgnoreCase ( " p " ) ) ) {
if ( NumberUtil . isInt ( split [ 1 ] ) ) {
validPotionPower = true ;
power = Integer . parseInt ( split [ 1 ] ) ;
if ( power > 0 & & power < 4 ) {
power - = 1 ;
}
} else {
2024-02-03 21:38:14 +01:00
throw new TranslatableException ( " invalidPotionMeta " , split [ 1 ] ) ;
2020-08-22 18:40:40 +02:00
}
} else if ( split [ 0 ] . equalsIgnoreCase ( " amplifier " ) | | ( allowShortName & & split [ 0 ] . equalsIgnoreCase ( " a " ) ) ) {
if ( NumberUtil . isInt ( split [ 1 ] ) ) {
validPotionPower = true ;
power = Integer . parseInt ( split [ 1 ] ) ;
} else {
2024-02-03 21:38:14 +01:00
throw new TranslatableException ( " invalidPotionMeta " , split [ 1 ] ) ;
2015-04-15 06:06:16 +02:00
}
} else if ( split [ 0 ] . equalsIgnoreCase ( " duration " ) | | ( allowShortName & & split [ 0 ] . equalsIgnoreCase ( " d " ) ) ) {
if ( NumberUtil . isInt ( split [ 1 ] ) ) {
validPotionDuration = true ;
duration = Integer . parseInt ( split [ 1 ] ) * 20 ; //Duration is in ticks by default, converted to seconds
} else {
2024-02-03 21:38:14 +01:00
throw new TranslatableException ( " invalidPotionMeta " , split [ 1 ] ) ;
2015-04-15 06:06:16 +02:00
}
2015-10-29 21:42:19 +01:00
} else if ( split [ 0 ] . equalsIgnoreCase ( " splash " ) | | ( allowShortName & & split [ 0 ] . equalsIgnoreCase ( " s " ) ) ) {
2020-04-25 14:08:57 +02:00
isSplashPotion = Boolean . parseBoolean ( split [ 1 ] ) ;
2015-04-15 06:06:16 +02:00
}
if ( isValidPotion ( ) ) {
2020-10-03 19:46:05 +02:00
final PotionMeta pmeta = ( PotionMeta ) stack . getItemMeta ( ) ;
2015-04-15 06:06:16 +02:00
pEffect = pEffectType . createEffect ( duration , power ) ;
if ( pmeta . getCustomEffects ( ) . size ( ) > 1 & & ! hasMetaPermission ( sender , " potions.multiple " , true , false , ess ) ) {
2024-02-03 21:38:14 +01:00
throw new TranslatableException ( " multiplePotionEffects " ) ;
2015-04-15 06:06:16 +02:00
}
pmeta . addCustomEffect ( pEffect , true ) ;
stack . setItemMeta ( pmeta ) ;
2021-10-24 16:12:20 +02:00
if ( VersionUtil . getServerBukkitVersion ( ) . isHigherThanOrEqualTo ( VersionUtil . v1_9_R01 ) ) {
2024-02-04 02:12:35 +01:00
if ( isSplashPotion & & stack . getType ( ) = = Material . POTION ) {
2018-01-07 03:18:59 +01:00
stack . setType ( Material . SPLASH_POTION ) ;
2024-02-04 02:12:35 +01:00
} else if ( ! isSplashPotion & & stack . getType ( ) = = Material . SPLASH_POTION ) {
2018-01-07 03:18:59 +01:00
stack . setType ( Material . POTION ) ;
}
} else {
2021-10-24 16:12:20 +02:00
final Potion potion = Potion . fromDamage ( stack . getDurability ( ) ) ;
2018-01-07 03:18:59 +01:00
potion . setSplash ( isSplashPotion ) ;
potion . apply ( stack ) ;
}
2015-04-15 06:06:16 +02:00
resetPotionMeta ( ) ;
}
}
}
2021-06-11 17:13:43 +02:00
private boolean parseEnchantmentStrings ( final CommandSource sender , final boolean allowUnsafe , final String [ ] split , final IEssentials ess ) throws Exception {
2015-04-15 06:06:16 +02:00
final Enchantment enchantment = Enchantments . getByName ( split [ 0 ] ) ;
2021-06-11 17:13:43 +02:00
if ( enchantment = = null ) {
return false ;
2015-04-15 06:06:16 +02:00
}
2021-06-11 17:13:43 +02:00
if ( hasMetaPermission ( sender , " enchantments. " + enchantment . getName ( ) . toLowerCase ( Locale . ENGLISH ) , false , false , ess ) ) {
int level = - 1 ;
if ( split . length > 1 ) {
try {
level = Integer . parseInt ( split [ 1 ] ) ;
} catch ( final NumberFormatException ex ) {
level = - 1 ;
}
2015-04-15 06:06:16 +02:00
}
2021-06-11 17:13:43 +02:00
if ( level < 0 | | ( ! allowUnsafe & & level > enchantment . getMaxLevel ( ) ) ) {
level = enchantment . getMaxLevel ( ) ;
}
addEnchantment ( sender , allowUnsafe , enchantment , level ) ;
2015-04-15 06:06:16 +02:00
}
2021-06-11 17:13:43 +02:00
return true ;
2015-04-15 06:06:16 +02:00
}
public void addEnchantment ( final CommandSource sender , final boolean allowUnsafe , final Enchantment enchantment , final int level ) throws Exception {
if ( enchantment = = null ) {
2024-02-03 21:38:14 +01:00
throw new TranslatableException ( " enchantmentNotFound " ) ;
2015-04-15 06:06:16 +02:00
}
try {
if ( stack . getType ( ) . equals ( Material . ENCHANTED_BOOK ) ) {
2020-10-03 19:46:05 +02:00
final EnchantmentStorageMeta meta = ( EnchantmentStorageMeta ) stack . getItemMeta ( ) ;
2015-04-15 06:06:16 +02:00
if ( level = = 0 ) {
meta . removeStoredEnchant ( enchantment ) ;
} else {
meta . addStoredEnchant ( enchantment , level , allowUnsafe ) ;
}
stack . setItemMeta ( meta ) ;
2020-10-03 19:46:05 +02:00
} else { // all other material types besides ENCHANTED_BOOK
2015-04-15 06:06:16 +02:00
if ( level = = 0 ) {
stack . removeEnchantment ( enchantment ) ;
} else {
if ( allowUnsafe ) {
stack . addUnsafeEnchantment ( enchantment , level ) ;
} else {
stack . addEnchantment ( enchantment , level ) ;
}
}
}
2020-10-03 19:46:05 +02:00
} catch ( final Exception ex ) {
2015-04-15 06:06:16 +02:00
throw new Exception ( " Enchantment " + enchantment . getName ( ) + " : " + ex . getMessage ( ) , ex ) ;
}
}
public Enchantment getEnchantment ( final User user , final String name ) throws Exception {
final Enchantment enchantment = Enchantments . getByName ( name ) ;
if ( enchantment = = null ) {
return null ;
}
final String enchantmentName = enchantment . getName ( ) . toLowerCase ( Locale . ENGLISH ) ;
if ( ! hasMetaPermission ( user , " enchantments. " + enchantmentName , true , false ) ) {
2024-02-03 21:38:14 +01:00
throw new TranslatableException ( " enchantmentPerm " , enchantmentName ) ;
2015-04-15 06:06:16 +02:00
}
return enchantment ;
}
2015-04-21 01:04:09 +02:00
public void addBannerMeta ( final CommandSource sender , final boolean allowShortName , final String string , final IEssentials ess ) throws Exception {
2018-12-09 14:47:52 +01:00
if ( MaterialUtil . isBanner ( stack . getType ( ) ) & & ! stack . getType ( ) . toString ( ) . equals ( " SHIELD " ) & & string ! = null ) {
2015-04-21 01:04:09 +02:00
final String [ ] split = splitPattern . split ( string , 2 ) ;
if ( split . length < 2 ) {
2024-02-03 21:38:14 +01:00
throw new TranslatableException ( " invalidBanner " , split [ 1 ] ) ;
2015-04-21 01:04:09 +02:00
}
2018-08-25 12:33:17 +02:00
2016-07-26 23:03:33 +02:00
PatternType patternType = null ;
try {
2024-03-04 19:49:30 +01:00
patternType = PatternType . getByIdentifier ( split [ 0 ] ) ;
2020-10-03 19:46:05 +02:00
} catch ( final Exception ignored ) {
}
2015-04-21 01:04:09 +02:00
final BannerMeta meta = ( BannerMeta ) stack . getItemMeta ( ) ;
if ( split [ 0 ] . equalsIgnoreCase ( " basecolor " ) ) {
2020-10-03 19:46:05 +02:00
final Color color = Color . fromRGB ( Integer . parseInt ( split [ 1 ] ) ) ;
2015-04-21 01:04:09 +02:00
meta . setBaseColor ( DyeColor . getByColor ( color ) ) ;
2016-07-26 23:03:33 +02:00
} else if ( patternType ! = null ) {
2024-03-04 19:49:30 +01:00
final PatternType type = PatternType . getByIdentifier ( split [ 0 ] ) ;
2020-10-03 19:46:05 +02:00
final DyeColor color = DyeColor . getByColor ( Color . fromRGB ( Integer . parseInt ( split [ 1 ] ) ) ) ;
final org . bukkit . block . banner . Pattern pattern = new org . bukkit . block . banner . Pattern ( color , type ) ;
2015-04-21 01:04:09 +02:00
meta . addPattern ( pattern ) ;
}
2016-07-25 13:06:24 +02:00
stack . setItemMeta ( meta ) ;
2018-12-09 14:47:52 +01:00
} else if ( stack . getType ( ) . toString ( ) . equals ( " SHIELD " ) & & string ! = null ) {
2016-07-25 13:06:24 +02:00
final String [ ] split = splitPattern . split ( string , 2 ) ;
if ( split . length < 2 ) {
2024-02-03 21:38:14 +01:00
throw new TranslatableException ( " invalidBanner " , split [ 1 ] ) ;
2016-07-25 13:06:24 +02:00
}
2016-07-26 23:03:33 +02:00
PatternType patternType = null ;
try {
2024-03-04 19:49:30 +01:00
patternType = PatternType . getByIdentifier ( split [ 0 ] ) ;
2020-10-03 19:46:05 +02:00
} catch ( final Exception ignored ) {
}
2016-07-26 23:03:33 +02:00
2016-07-25 13:06:24 +02:00
// Hacky fix for accessing Shield meta - https://github.com/drtshock/Essentials/pull/745#issuecomment-234843795
2020-10-03 19:46:05 +02:00
final BlockStateMeta meta = ( BlockStateMeta ) stack . getItemMeta ( ) ;
final Banner banner = ( Banner ) meta . getBlockState ( ) ;
2016-07-25 13:06:24 +02:00
if ( split [ 0 ] . equalsIgnoreCase ( " basecolor " ) ) {
2020-10-03 19:46:05 +02:00
final Color color = Color . fromRGB ( Integer . parseInt ( split [ 1 ] ) ) ;
2016-07-25 13:06:24 +02:00
banner . setBaseColor ( DyeColor . getByColor ( color ) ) ;
2016-07-26 23:03:33 +02:00
} else if ( patternType ! = null ) {
2024-03-04 19:49:30 +01:00
final PatternType type = PatternType . getByIdentifier ( split [ 0 ] ) ;
2020-10-03 19:46:05 +02:00
final DyeColor color = DyeColor . getByColor ( Color . fromRGB ( Integer . parseInt ( split [ 1 ] ) ) ) ;
final org . bukkit . block . banner . Pattern pattern = new org . bukkit . block . banner . Pattern ( color , type ) ;
2016-07-25 13:06:24 +02:00
banner . addPattern ( pattern ) ;
}
banner . update ( ) ;
meta . setBlockState ( banner ) ;
2015-04-21 01:04:09 +02:00
stack . setItemMeta ( meta ) ;
}
}
2015-04-15 06:06:16 +02:00
private boolean hasMetaPermission ( final CommandSource sender , final String metaPerm , final boolean graceful , final boolean includeBase , final IEssentials ess ) throws Exception {
final User user = sender ! = null & & sender . isPlayer ( ) ? ess . getUser ( sender . getPlayer ( ) ) : null ;
return hasMetaPermission ( user , metaPerm , graceful , includeBase ) ;
}
private boolean hasMetaPermission ( final User user , final String metaPerm , final boolean graceful , final boolean includeBase ) throws Exception {
final String permBase = includeBase ? " essentials.itemspawn.meta- " : " essentials. " ;
if ( user = = null | | user . isAuthorized ( permBase + metaPerm ) ) {
return true ;
}
if ( graceful ) {
return false ;
} else {
2024-02-03 21:38:14 +01:00
throw new TranslatableException ( " noMetaPerm " , metaPerm ) ;
2015-04-15 06:06:16 +02:00
}
}
2016-03-02 02:16:13 +01:00
2021-10-24 16:17:06 +02:00
private void setUnbreakable ( final IEssentials ess , final ItemStack is , final boolean unbreakable ) {
2020-10-03 19:46:05 +02:00
final ItemMeta meta = is . getItemMeta ( ) ;
2021-10-24 16:17:06 +02:00
ess . getItemUnbreakableProvider ( ) . setUnbreakable ( meta , unbreakable ) ;
is . setItemMeta ( meta ) ;
2016-03-02 02:16:13 +01:00
}
2013-01-12 15:12:12 +01:00
}