diff --git a/src/main/java/dan200/computercraft/shared/peripheral/generic/data/BlockData.java b/src/main/java/dan200/computercraft/shared/peripheral/generic/data/BlockData.java index d037be6af..13d516c8f 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/generic/data/BlockData.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/generic/data/BlockData.java @@ -13,14 +13,13 @@ import javax.annotation.Nonnull; import java.util.HashMap; import java.util.Map; -import java.util.Objects; public class BlockData { @Nonnull public static > T fill( @Nonnull T data, @Nonnull BlockState state ) { - data.put( "name", Objects.toString( state.getBlock().getRegistryName() ) ); + data.put( "name", DataHelpers.getId( state.getBlock() ) ); Map stateTable = new HashMap<>(); for( ImmutableMap.Entry, ? extends Comparable> entry : state.getValues().entrySet() ) diff --git a/src/main/java/dan200/computercraft/shared/peripheral/generic/data/DataHelpers.java b/src/main/java/dan200/computercraft/shared/peripheral/generic/data/DataHelpers.java index 8ed831dd0..5a3f5c4d0 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/generic/data/DataHelpers.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/generic/data/DataHelpers.java @@ -7,17 +7,31 @@ package dan200.computercraft.shared.peripheral.generic.data; import net.minecraft.util.ResourceLocation; +import net.minecraftforge.registries.IForgeRegistryEntry; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.util.Collection; import java.util.HashMap; import java.util.Map; -public class DataHelpers +public final class DataHelpers { - public static Map getTags( Collection tags ) + private DataHelpers() + { } + + @Nonnull + public static Map getTags( @Nonnull Collection tags ) { Map result = new HashMap<>( tags.size() ); for( ResourceLocation location : tags ) result.put( location.toString(), true ); return result; } + + @Nullable + public static String getId( @Nonnull IForgeRegistryEntry entry ) + { + ResourceLocation id = entry.getRegistryName(); + return id == null ? null : id.toString(); + } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/generic/data/FluidData.java b/src/main/java/dan200/computercraft/shared/peripheral/generic/data/FluidData.java index d4249d733..e5b19af7d 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/generic/data/FluidData.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/generic/data/FluidData.java @@ -10,14 +10,13 @@ import javax.annotation.Nonnull; import java.util.Map; -import java.util.Objects; public class FluidData { @Nonnull public static > T fillBasic( @Nonnull T data, @Nonnull FluidStack stack ) { - data.put( "name", Objects.toString( stack.getFluid().getRegistryName() ) ); + data.put( "name", DataHelpers.getId( stack.getFluid() ) ); data.put( "amount", stack.getAmount() ); return data; } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/generic/data/ItemData.java b/src/main/java/dan200/computercraft/shared/peripheral/generic/data/ItemData.java index 534a10182..1a422487e 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/generic/data/ItemData.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/generic/data/ItemData.java @@ -7,6 +7,9 @@ package dan200.computercraft.shared.peripheral.generic.data; import com.google.gson.JsonParseException; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.item.EnchantedBookItem; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.INBT; @@ -16,8 +19,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; -import java.util.Map; -import java.util.Objects; +import java.util.*; import java.util.stream.Collectors; public class ItemData @@ -25,7 +27,7 @@ public class ItemData @Nonnull public static > T fillBasic( @Nonnull T data, @Nonnull ItemStack stack ) { - data.put( "name", Objects.toString( stack.getItem().getRegistryName() ) ); + data.put( "name", DataHelpers.getId( stack.getItem() ) ); data.put( "count", stack.getCount() ); return data; } @@ -68,6 +70,21 @@ public static > T fill( @Nonnull T data, @ } } + /* + * Used to hide some data from ItemStack tooltip. + * @see https://minecraft.gamepedia.com/Tutorials/Command_NBT_tags + * @see ItemStack#getTooltip + */ + int hideFlags = tag != null ? tag.getInt( "HideFlags" ) : 0; + + List> enchants = getAllEnchants( stack, hideFlags ); + if( !enchants.isEmpty() ) data.put( "enchantments", enchants ); + + if( tag != null && tag.getBoolean( "Unbreakable" ) && (hideFlags & 4) == 0 ) + { + data.put( "unbreakable", true ); + } + return data; } @@ -83,4 +100,59 @@ private static ITextComponent parseTextComponent( @Nonnull INBT x ) return null; } } + + /** + * Retrieve all visible enchantments from given stack. Try to follow all tooltip rules : order and visibility. + * + * @param stack Stack to analyse + * @param hideFlags An int used as bit field to provide visibility rules. + * @return A filled list that contain all visible enchantments. + */ + @Nonnull + private static List> getAllEnchants( @Nonnull ItemStack stack, int hideFlags ) + { + ArrayList> enchants = new ArrayList<>( 0 ); + + if( stack.getItem() instanceof EnchantedBookItem && (hideFlags & 32) == 0 ) + { + addEnchantments( EnchantedBookItem.getEnchantments( stack ), enchants ); + } + + if( stack.isEnchanted() && (hideFlags & 1) == 0 ) + { + /* + * Mimic the EnchantmentHelper.getEnchantments(ItemStack stack) behavior without special case for Enchanted book. + * I'll do that to have the same data than ones displayed in tooltip. + * @see EnchantmentHelper.getEnchantments(ItemStack stack) + */ + addEnchantments( stack.getEnchantmentTagList(), enchants ); + } + + return enchants; + } + + /** + * Converts a Mojang enchant map to a Lua list. + * + * @param rawEnchants The raw NBT list of enchantments + * @param enchants The enchantment map to add it to. + * @see net.minecraft.enchantment.EnchantmentHelper + */ + private static void addEnchantments( @Nonnull ListNBT rawEnchants, @Nonnull ArrayList> enchants ) + { + if( rawEnchants.isEmpty() ) return; + + enchants.ensureCapacity( enchants.size() + rawEnchants.size() ); + + for( Map.Entry entry : EnchantmentHelper.func_226652_a_( rawEnchants ).entrySet() ) + { + Enchantment enchantment = entry.getKey(); + Integer level = entry.getValue(); + HashMap enchant = new HashMap<>( 3 ); + enchant.put( "name", DataHelpers.getId( enchantment ) ); + enchant.put( "level", level ); + enchant.put( "displayName", enchantment.getDisplayName( level ).getString() ); + enchants.add( enchant ); + } + } }