From 7f2318f89c3556e621d477b6526e776944f88bd6 Mon Sep 17 00:00:00 2001 From: zeng-git <95841646+zeng-github01@users.noreply.github.com> Date: Fri, 29 Nov 2024 13:06:55 +0800 Subject: [PATCH] Add Annihilation Plane enchantment support, deprecate Identity (#510) --- .../appeng/core/localization/GuiText.java | 6 +- .../appeng/core/localization/WailaText.java | 4 +- .../modules/waila/PartWailaDataProvider.java | 3 +- .../part/AnnihilationPlaneDataProvider.java | 47 ++++++ src/main/java/appeng/items/AEBaseItem.java | 5 - .../java/appeng/items/parts/ItemPart.java | 53 ++++++- src/main/java/appeng/parts/AEBasePart.java | 19 ++- .../automation/PartAnnihilationPlane.java | 142 ++++++++++++++++-- .../PartIdentityAnnihilationPlane.java | 30 ++-- .../java/appeng/parts/misc/PartInterface.java | 4 +- .../java/appeng/util/EnchantmentUtil.java | 74 +++++++++ src/main/java/appeng/util/Platform.java | 10 +- .../appliedenergistics2/lang/en_us.lang | 5 + .../appliedenergistics2/lang/zh_cn.lang | 5 + .../parts/planes_annihilatition_identity.json | 36 ----- 15 files changed, 365 insertions(+), 78 deletions(-) create mode 100644 src/main/java/appeng/integration/modules/waila/part/AnnihilationPlaneDataProvider.java create mode 100644 src/main/java/appeng/util/EnchantmentUtil.java delete mode 100644 src/main/resources/assets/appliedenergistics2/recipes/network/parts/planes_annihilatition_identity.json diff --git a/src/main/java/appeng/core/localization/GuiText.java b/src/main/java/appeng/core/localization/GuiText.java index c03fb6d932f..67f2eeb203f 100644 --- a/src/main/java/appeng/core/localization/GuiText.java +++ b/src/main/java/appeng/core/localization/GuiText.java @@ -209,7 +209,11 @@ public enum GuiText { // Used in Crafting Toasts CraftingToastDone, - CraftingToastCancelled; + CraftingToastCancelled, + + CanBeEnchanted, + IncreasedEnergyUseFromEnchants, + Deprecated; private final String root; diff --git a/src/main/java/appeng/core/localization/WailaText.java b/src/main/java/appeng/core/localization/WailaText.java index 89109d88c80..888b58ade37 100644 --- a/src/main/java/appeng/core/localization/WailaText.java +++ b/src/main/java/appeng/core/localization/WailaText.java @@ -41,7 +41,9 @@ public enum WailaText { Showing, Contains, - Channels; + Channels, + EnchantedWith, + IdentityDeprecated; private final String root; diff --git a/src/main/java/appeng/integration/modules/waila/PartWailaDataProvider.java b/src/main/java/appeng/integration/modules/waila/PartWailaDataProvider.java index b21e96b05eb..bd8a4fbd757 100644 --- a/src/main/java/appeng/integration/modules/waila/PartWailaDataProvider.java +++ b/src/main/java/appeng/integration/modules/waila/PartWailaDataProvider.java @@ -69,8 +69,9 @@ public PartWailaDataProvider() { final IPartWailaDataProvider powerState = new PowerStateWailaDataProvider(); final IPartWailaDataProvider p2pState = new P2PStateWailaDataProvider(); final IPartWailaDataProvider partStack = new PartStackWailaDataProvider(); + final IPartWailaDataProvider annihilationPlane = new AnnihilationPlaneDataProvider(); - this.providers = Lists.newArrayList(channel, storageMonitor, powerState, partStack, p2pState); + this.providers = Lists.newArrayList(channel, storageMonitor, powerState, partStack, p2pState, annihilationPlane); } @Override diff --git a/src/main/java/appeng/integration/modules/waila/part/AnnihilationPlaneDataProvider.java b/src/main/java/appeng/integration/modules/waila/part/AnnihilationPlaneDataProvider.java new file mode 100644 index 00000000000..5219d54b37d --- /dev/null +++ b/src/main/java/appeng/integration/modules/waila/part/AnnihilationPlaneDataProvider.java @@ -0,0 +1,47 @@ +package appeng.integration.modules.waila.part; + +import appeng.api.parts.IPart; +import appeng.core.localization.WailaText; +import appeng.parts.automation.PartAnnihilationPlane; +import appeng.parts.automation.PartIdentityAnnihilationPlane; +import appeng.util.EnchantmentUtil; +import mcp.mobius.waila.api.IWailaConfigHandler; +import mcp.mobius.waila.api.IWailaDataAccessor; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import java.util.List; +import java.util.Map; + +public class AnnihilationPlaneDataProvider extends BasePartWailaDataProvider { + @Override + public List getWailaBody(IPart part, List currentToolTip, IWailaDataAccessor accessor, IWailaConfigHandler config) { + if (part instanceof PartIdentityAnnihilationPlane) { + currentToolTip.add(WailaText.IdentityDeprecated.getLocal()); + } else if (part instanceof PartAnnihilationPlane plane) { + NBTTagCompound nbtData = accessor.getNBTData(); + Map enchantments = EnchantmentUtil.getEnchantments(nbtData); + if (!enchantments.isEmpty()) { + currentToolTip.add(WailaText.EnchantedWith.getLocal()); + for (var enchantment : enchantments.keySet()) { + currentToolTip.add(enchantment.getTranslatedName(enchantments.get(enchantment))); + } + } + } + + return currentToolTip; + } + + @Override + public NBTTagCompound getNBTData(EntityPlayerMP player, IPart part, TileEntity te, NBTTagCompound tag, World world, BlockPos pos) { + if (part instanceof PartAnnihilationPlane plane) { + plane.writeEnchantments(tag); + } + + return tag; + } +} diff --git a/src/main/java/appeng/items/AEBaseItem.java b/src/main/java/appeng/items/AEBaseItem.java index dc9ef83c364..a2bfa5eb782 100644 --- a/src/main/java/appeng/items/AEBaseItem.java +++ b/src/main/java/appeng/items/AEBaseItem.java @@ -57,11 +57,6 @@ public final void getSubItems(final CreativeTabs creativeTab, final NonNullList< } } - @Override - public boolean isBookEnchantable(final ItemStack itemstack1, final ItemStack itemstack2) { - return false; - } - @SideOnly(Side.CLIENT) protected void addCheckedInformation(final ItemStack stack, final World world, final List lines, final ITooltipFlag advancedTooltips) { super.addInformation(stack, world, lines, advancedTooltips); diff --git a/src/main/java/appeng/items/parts/ItemPart.java b/src/main/java/appeng/items/parts/ItemPart.java index ebf9864ccf1..64fa91e15cf 100644 --- a/src/main/java/appeng/items/parts/ItemPart.java +++ b/src/main/java/appeng/items/parts/ItemPart.java @@ -30,8 +30,12 @@ import appeng.items.AEBaseItem; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableSet; +import net.minecraft.client.util.ITooltipFlag; import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Enchantments; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumFacing; @@ -133,10 +137,20 @@ public int getDamageByType(final PartType t) { @Override public EnumActionResult onItemUse(final EntityPlayer player, final World w, final BlockPos pos, final EnumHand hand, final EnumFacing side, final float hitX, final float hitY, final float hitZ) { - if (this.getTypeByStack(player.getHeldItem(hand)) == PartType.INVALID_TYPE) { + ItemStack heldItem = player.getHeldItem(hand); + PartType typeByStack = getTypeByStack(heldItem); + if (typeByStack == PartType.INVALID_TYPE) { return EnumActionResult.FAIL; } + if (player.isSneaking() && typeByStack == PartType.IDENTITY_ANNIHILATION_PLANE) { + ItemStack newPlane = new ItemStack(this, heldItem.getCount(), PartType.ANNIHILATION_PLANE.getBaseDamage()); + newPlane.addEnchantment(Enchantments.SILK_TOUCH,1); + + player.setHeldItem(hand, newPlane); + return EnumActionResult.SUCCESS; + } + return AEApi.instance().partHelper().placeBus(player.getHeldItem(hand), pos, side, player, hand, w); } @@ -178,6 +192,43 @@ protected void getCheckedSubItems(final CreativeTabs creativeTab, final NonNullL } } + @Override + protected void addCheckedInformation(ItemStack stack, World world, List lines, ITooltipFlag advancedTooltips) { + if (getTypeByStack(stack) == PartType.ANNIHILATION_PLANE) { + var enchantments = EnchantmentHelper.getEnchantments(stack); + if (enchantments.isEmpty()) { + lines.add(GuiText.CanBeEnchanted.getLocal()); + } + else { + lines.add(GuiText.IncreasedEnergyUseFromEnchants.getLocal()); + } + } + + if (getTypeByStack(stack) == PartType.IDENTITY_ANNIHILATION_PLANE) { + lines.add(GuiText.Deprecated.getLocal()); + } + } + + @Override + public int getItemEnchantability() { + return 10; + } + + @Override + public boolean isEnchantable(ItemStack stack) { + return getTypeByStack(stack) == PartType.ANNIHILATION_PLANE; + } + + @Override + public boolean canApplyAtEnchantingTable(ItemStack stack, Enchantment enchantment) { + return enchantment == Enchantments.UNBREAKING || enchantment == Enchantments.FORTUNE || enchantment == Enchantments.SILK_TOUCH || enchantment == Enchantments.EFFICIENCY; + } + + @Override + public boolean isBookEnchantable(ItemStack stack, ItemStack book) { + return getTypeByStack(stack) == PartType.ANNIHILATION_PLANE; + } + @Nonnull public PartType getTypeByStack(final ItemStack is) { Preconditions.checkNotNull(is); diff --git a/src/main/java/appeng/parts/AEBasePart.java b/src/main/java/appeng/parts/AEBasePart.java index b7a69df38bd..b6113299752 100644 --- a/src/main/java/appeng/parts/AEBasePart.java +++ b/src/main/java/appeng/parts/AEBasePart.java @@ -359,8 +359,19 @@ public void uploadSettings(final SettingsFrom from, final NBTTagCompound compoun * @param from source of settings * @return compound of source */ + @Deprecated protected NBTTagCompound downloadSettings(final SettingsFrom from) { - final NBTTagCompound output = new NBTTagCompound(); + NBTTagCompound compound = downloadSettings(from, new NBTTagCompound()); + return compound.isEmpty() ? null : compound; + } + + /** + * Exports settings for attaching it to a memory card or item stack. + * + * @param from The purpose to export settings for. + * @param output The tag to write the settings to. + */ + protected NBTTagCompound downloadSettings(final SettingsFrom from, final NBTTagCompound output) { final IConfigManager cm = this.getConfigManager(); if (cm != null) { @@ -392,7 +403,7 @@ protected NBTTagCompound downloadSettings(final SettingsFrom from) { } } - return output.isEmpty() ? null : output; + return output; } public boolean useStandardMemoryCard() { @@ -419,8 +430,8 @@ private boolean useMemoryCard(final EntityPlayer player) { final String name = is.getTranslationKey(); if (player.isSneaking()) { - final NBTTagCompound data = this.downloadSettings(SettingsFrom.MEMORY_CARD); - if (data != null) { + final NBTTagCompound data = this.downloadSettings(SettingsFrom.MEMORY_CARD, new NBTTagCompound()); + if (!data.isEmpty()) { memoryCard.setMemoryCardContents(memCardIS, name, data); memoryCard.notifyUser(player, MemoryCardMessages.SETTINGS_SAVED); } diff --git a/src/main/java/appeng/parts/automation/PartAnnihilationPlane.java b/src/main/java/appeng/parts/automation/PartAnnihilationPlane.java index 48daee9fce2..9e357025322 100644 --- a/src/main/java/appeng/parts/automation/PartAnnihilationPlane.java +++ b/src/main/java/appeng/parts/automation/PartAnnihilationPlane.java @@ -48,25 +48,39 @@ import appeng.me.GridAccessException; import appeng.me.helpers.MachineSource; import appeng.parts.PartBasicState; +import appeng.util.EnchantmentUtil; import appeng.util.IWorldCallable; import appeng.util.Platform; +import appeng.util.SettingsFrom; import appeng.util.item.AEItemStack; import com.google.common.collect.Lists; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.entity.Entity; import net.minecraft.entity.item.EntityItem; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; +import net.minecraft.init.Enchantments; +import net.minecraft.init.Items; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; import net.minecraft.world.WorldServer; +import net.minecraftforge.common.util.FakePlayer; +import net.minecraftforge.common.util.FakePlayerFactory; +import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; +import java.util.concurrent.ThreadLocalRandom; public class PartAnnihilationPlane extends PartBasicState implements IGridTickable, IWorldCallable { @@ -82,6 +96,12 @@ public static List getModels() { private boolean isAccepting = true; private boolean breaking = false; + /** + * Enchantments found on the plane when it was placed will be used to enchant the fake tool used for picking up + * blocks. + */ + private Map enchantments = new LinkedHashMap<>(); + public PartAnnihilationPlane(final ItemStack is) { super(is); } @@ -92,6 +112,7 @@ public TickRateModulation call(final World world) throws Exception { return this.breakBlock(true); } + @Override public void getBoxes(final IPartCollisionHelper bch) { int minX = 1; @@ -422,14 +443,38 @@ private boolean canHandleBlock(final WorldServer w, final BlockPos pos) { } protected List obtainBlockDrops(final WorldServer w, final BlockPos pos) { - final ItemStack[] out = Platform.getBlockDrops(w, pos); - return Lists.newArrayList(out); + final FakePlayer fakePlayer = FakePlayerFactory.getMinecraft(w); + final IBlockState state = w.getBlockState(pos); + + if (state.getBlock().canSilkHarvest(w, pos, state, fakePlayer) && enchantments.containsKey(Enchantments.SILK_TOUCH)) { + final List out = new ArrayList<>(1); + final Item item = Item.getItemFromBlock(state.getBlock()); + + if (item != Items.AIR) { + int meta = 0; + if (item.getHasSubtypes()) { + meta = state.getBlock().getMetaFromState(state); + } + final ItemStack itemstack = new ItemStack(item, 1, meta); + out.add(itemstack); + } + return out; + } else { + if (enchantments.containsKey(Enchantments.FORTUNE)) { + final ItemStack[] out = Platform.getBlockDrops(w, pos, enchantments.get(Enchantments.FORTUNE)); + return Lists.newArrayList(out); + } else { + ItemStack[] blockDrops = Platform.getBlockDrops(w, pos); + return Lists.newArrayList(blockDrops); + } + } } /** * Checks if this plane can handle the block at the specific coordinates. */ protected float calculateEnergyUsage(final WorldServer w, final BlockPos pos, final List items) { + boolean useEnergy = true; final IBlockState state = w.getBlockState(pos); final float hardness = state.getBlockHardness(w, pos); @@ -438,7 +483,25 @@ protected float calculateEnergyUsage(final WorldServer w, final BlockPos pos, fi requiredEnergy += is.getCount(); } - return requiredEnergy; + if (!enchantments.isEmpty()) { + var efficiencyFactor = 1f; + var efficiencyLevel = 0; + if (enchantments.containsKey(Enchantments.EFFICIENCY)) { + // Reduce total energy usage incurred by other enchantments by 15% per Efficiency level. + efficiencyLevel = enchantments.get(Enchantments.EFFICIENCY); + efficiencyFactor *= Math.pow(0.85, efficiencyLevel); + } + if (enchantments.containsKey(Enchantments.UNBREAKING)) { + // Give plane only a (100 / (level + 1))% chance to use energy. + // This is similar to vanilla Unbreaking behaviour for tools. + int randomNumber = ThreadLocalRandom.current().nextInt(enchantments.get(Enchantments.UNBREAKING) + 1); + useEnergy = randomNumber == 0; + } + var levelSum = enchantments.values().stream().reduce(0, Integer::sum) - efficiencyLevel; + requiredEnergy *= 8 * levelSum * efficiencyFactor; + } + + return useEnergy ? requiredEnergy : 0; } /** @@ -447,10 +510,10 @@ protected float calculateEnergyUsage(final WorldServer w, final BlockPos pos, fi * It also sets isAccepting to false, if the item can not be stored. * * @param itemStacks an array of {@link ItemStack} to test - * @return true, if the network can store at least a single item of all drops or no drops are reported + * @return true, if the network can store all drops or no drops are reported */ private boolean canStoreItemStacks(final List itemStacks) { - boolean canStore = itemStacks.isEmpty(); + boolean canStore = true; try { final IStorageGrid storage = this.getProxy().getStorage(); @@ -459,8 +522,8 @@ private boolean canStoreItemStacks(final List itemStacks) { final IAEItemStack itemToTest = AEItemStack.fromItemStack(itemStack); final IAEItemStack overflow = storage.getInventory(AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class)) .injectItems(itemToTest, Actionable.SIMULATE, this.mySrc); - if (overflow == null || itemToTest.getStackSize() > overflow.getStackSize()) { - canStore = true; + if (overflow != null) { + canStore = false; } } } catch (final GridAccessException e) { @@ -472,15 +535,20 @@ private boolean canStoreItemStacks(final List itemStacks) { } private void breakBlockAndStoreItems(final WorldServer w, final BlockPos pos) { - w.destroyBlock(pos, true); + final List items = this.obtainBlockDrops(w, pos); - final AxisAlignedBB box = new AxisAlignedBB(pos).grow(0.2); - for (final Object ei : w.getEntitiesWithinAABB(EntityItem.class, box)) { - if (ei instanceof EntityItem) { - final EntityItem entityItem = (EntityItem) ei; - this.storeEntityItem(entityItem); + try { + final IStorageGrid storage = this.getProxy().getStorage(); + for (ItemStack itemStack : items) { + final IAEItemStack aeItemStack = AEItemStack.fromItemStack(itemStack); + storage.getInventory(AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class)) + .injectItems(aeItemStack, Actionable.MODULATE, this.mySrc); } + } catch (GridAccessException e) { + } + + w.destroyBlock(pos, false); } private void refresh() { @@ -498,4 +566,50 @@ public IPartModel getStaticModels() { return MODELS.getModel(this.getConnections(), this.isPowered(), this.isActive()); } + @Override + protected NBTTagCompound downloadSettings(SettingsFrom from, NBTTagCompound output) { + super.downloadSettings(from, output); + // Save enchants only when the actual plane is dismantled + if (from == SettingsFrom.DISMANTLE_ITEM) { + writeEnchantments(output); + } + + return output; + } + + @Override + public void uploadSettings(SettingsFrom from, NBTTagCompound output, EntityPlayer player) { + super.uploadSettings(from, output, player); + // Import enchants only when the plan is placed, not from memory cards + if (from == SettingsFrom.DISMANTLE_ITEM) { + readEnchantments(output); + } + } + + public void readEnchantments(NBTTagCompound data) { + enchantments = EnchantmentUtil.getEnchantments(data); + EnchantmentHelper.setEnchantments(enchantments, getItemStack()); + } + + public void writeEnchantments(NBTTagCompound data) { + EnchantmentUtil.setEnchantments(data, enchantments); + } + + @Override + public void readFromNBT(NBTTagCompound data) { + super.readFromNBT(data); + readEnchantments(data); + } + + @Override + public void writeToNBT(NBTTagCompound data) { + super.writeToNBT(data); + writeEnchantments(data); + } + + @Override + public void addToWorld() { + super.addToWorld(); + enchantments = EnchantmentHelper.getEnchantments(getItemStack()); + } } diff --git a/src/main/java/appeng/parts/automation/PartIdentityAnnihilationPlane.java b/src/main/java/appeng/parts/automation/PartIdentityAnnihilationPlane.java index 13170a8630b..10eb549ef83 100644 --- a/src/main/java/appeng/parts/automation/PartIdentityAnnihilationPlane.java +++ b/src/main/java/appeng/parts/automation/PartIdentityAnnihilationPlane.java @@ -19,17 +19,20 @@ package appeng.parts.automation; -import appeng.api.parts.IPart; +import appeng.api.AEApi; import appeng.api.parts.IPartHost; import appeng.api.parts.IPartModel; -import appeng.api.util.AEPartLocation; import appeng.items.parts.PartModels; import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Enchantments; import net.minecraft.init.Items; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.WorldServer; import net.minecraftforge.common.util.FakePlayer; import net.minecraftforge.common.util.FakePlayerFactory; @@ -53,15 +56,6 @@ public PartIdentityAnnihilationPlane(final ItemStack is) { super(is); } - @Override - protected boolean isAnnihilationPlane(final TileEntity blockTileEntity, final AEPartLocation side) { - if (blockTileEntity instanceof IPartHost) { - final IPart p = ((IPartHost) blockTileEntity).getPart(side); - return p != null && p.getClass() == this.getClass(); - } - return false; - } - @Override protected float calculateEnergyUsage(final WorldServer w, final BlockPos pos, final List items) { final float requiredEnergy = super.calculateEnergyUsage(w, pos, items); @@ -92,6 +86,20 @@ protected List obtainBlockDrops(final WorldServer w, final BlockPos p } } + @Override + public boolean onPartShiftActivate(EntityPlayer player, EnumHand hand, Vec3d pos) { + TileEntity tile = getTile(); + if (tile instanceof IPartHost host) { + host.removePart(getSide(), false); + ItemStack itemStack = AEApi.instance().definitions().parts().annihilationPlane().maybeStack(1).orElse(ItemStack.EMPTY); + itemStack.addEnchantment(Enchantments.SILK_TOUCH, 1); + host.addPart(itemStack, getSide(), player, hand); + return true; + } + + return false; + } + @Override public IPartModel getStaticModels() { return MODELS.getModel(this.getConnections(), this.isPowered(), this.isActive()); diff --git a/src/main/java/appeng/parts/misc/PartInterface.java b/src/main/java/appeng/parts/misc/PartInterface.java index b33dc836b9b..ef18769df5e 100644 --- a/src/main/java/appeng/parts/misc/PartInterface.java +++ b/src/main/java/appeng/parts/misc/PartInterface.java @@ -299,8 +299,8 @@ public GuiBridge getGuiBridge() { } @Override - public NBTTagCompound downloadSettings(SettingsFrom from) { - NBTTagCompound output = super.downloadSettings(from); + public NBTTagCompound downloadSettings(SettingsFrom from, NBTTagCompound compound) { + NBTTagCompound output = super.downloadSettings(from, compound); if (from == SettingsFrom.MEMORY_CARD) { final IItemHandler inv = this.getInventoryByName("patterns"); if (inv instanceof AppEngInternalInventory) { diff --git a/src/main/java/appeng/util/EnchantmentUtil.java b/src/main/java/appeng/util/EnchantmentUtil.java new file mode 100644 index 00000000000..af41410cc78 --- /dev/null +++ b/src/main/java/appeng/util/EnchantmentUtil.java @@ -0,0 +1,74 @@ +package appeng.util; + +import com.google.common.collect.Maps; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; + +import java.util.HashMap; +import java.util.Map; + +public final class EnchantmentUtil { + private EnchantmentUtil() { + } + + private static Map deserializeEnchantments(NBTTagList tagList) { + Map map = Maps.newLinkedHashMap(); + + for(int i = 0; i < tagList.tagCount(); ++i) { + NBTTagCompound compoundtag = tagList.getCompoundTagAt(i); + Enchantment enchantmentByID = Enchantment.getEnchantmentByID(getEnchantmentId(compoundtag)); + if (enchantmentByID != null) { + map.put(enchantmentByID, getEnchantmentLevel(compoundtag)); + } + } + + return map; + } + + private static int getEnchantmentId(NBTTagCompound tagCompound) { + return tagCompound.getInteger("id"); + } + + private static int getEnchantmentLevel(NBTTagCompound tagCompound) { + return Math.max(0, Math.min(255, tagCompound.getInteger("lvl"))); + } + + private static NBTTagCompound storeEnchantment(int id, int level) { + NBTTagCompound compoundtag = new NBTTagCompound(); + compoundtag.setShort("id",(short) id); + compoundtag.setShort("lvl", ((short) level)); + return compoundtag; + } + /** + * Read enchants written using {@link #setEnchantments} or added to an itemstack's tag using normal enchanting. + */ + public static Map getEnchantments(NBTTagCompound data) { + if (data.hasKey("Enchantments",9)) { + var list = data.getTagList("Enchantments",10); + var enchants = deserializeEnchantments(list); + if (!enchants.isEmpty()) { + return enchants; + } + } + return new HashMap<>(); + } + + /** + * Writes a list of enchantments to the given tag the same way as + * {@link EnchantmentHelper#setEnchantments(Map, ItemStack)} would. + */ + public static void setEnchantments(NBTTagCompound tag, Map enchantments) { + NBTTagList enchantList = new NBTTagList(); + for (Map.Entry entry : enchantments.entrySet()) { + Enchantment enchantment = entry.getKey(); + if (enchantment == null) + continue; + int level = entry.getValue(); + enchantList.appendTag(storeEnchantment(Enchantment.getEnchantmentID(enchantment), level)); + } + tag.setTag("Enchantments", enchantList); + } +} diff --git a/src/main/java/appeng/util/Platform.java b/src/main/java/appeng/util/Platform.java index 4d69f11b277..8abb776ae4c 100644 --- a/src/main/java/appeng/util/Platform.java +++ b/src/main/java/appeng/util/Platform.java @@ -430,15 +430,21 @@ public static boolean isBlockAir(final World w, final BlockPos pos) { } } + + public static ItemStack[] getBlockDrops(final World w, final BlockPos pos) { + return getBlockDrops(w, pos,0); + } + + public static ItemStack[] getBlockDrops(final World w, final BlockPos pos, int fortune) { List out = new ArrayList<>(); final IBlockState state = w.getBlockState(pos); if (state != null) { - out = state.getBlock().getDrops(w, pos, state, 0); + out = state.getBlock().getDrops(w, pos, state, fortune); } - if (out == null) { + if (out == null || out.isEmpty()) { return new ItemStack[0]; } return out.toArray(new ItemStack[out.size()]); diff --git a/src/main/resources/assets/appliedenergistics2/lang/en_us.lang b/src/main/resources/assets/appliedenergistics2/lang/en_us.lang index 0710950fd4b..adc60d7eebc 100644 --- a/src/main/resources/assets/appliedenergistics2/lang/en_us.lang +++ b/src/main/resources/assets/appliedenergistics2/lang/en_us.lang @@ -258,6 +258,9 @@ gui.appliedenergistics2.CraftingToastDone=Crafting Done! gui.appliedenergistics2.CraftingToastCancelled=Crafting Cancelled! gui.appliedenergistics2.Sticky=Sticky gui.appliedenergistics2.FluidTerminal=Fluid Terminal +gui.appliedenergistics2.CanBeEnchanted=Can be enchanted +gui.appliedenergistics2.IncreasedEnergyUseFromEnchants=Enchants increase energy use +gui.appliedenergistics2.Deprecated=Deprecated // GUI Tooltips gui.tooltips.appliedenergistics2.Stash=Store Items @@ -441,6 +444,8 @@ waila.appliedenergistics2.p2p_input_many_outputs=Linked (Input Side) - §4%d§r waila.appliedenergistics2.p2p_output_one_input=Linked (Output Side) - 1 Input waila.appliedenergistics2.p2p_output_many_inputs=Linked (Output Side) - §2%d§r Inputs waila.appliedenergistics2.P2POutput=Linked (Output Side) +waila.appliedenergistics2.EnchantedWith=Enchanted with: +waila.appliedenergistics2.IdentityDeprecated=Deprecated. Convert with SHIFT + RIGHT-CLICK // TheOneProbe theoneprobe.appliedenergistics2.crafting=Crafting: §2%1$s§r diff --git a/src/main/resources/assets/appliedenergistics2/lang/zh_cn.lang b/src/main/resources/assets/appliedenergistics2/lang/zh_cn.lang index 58cc6f20151..8f867d8cb9a 100644 --- a/src/main/resources/assets/appliedenergistics2/lang/zh_cn.lang +++ b/src/main/resources/assets/appliedenergistics2/lang/zh_cn.lang @@ -258,6 +258,9 @@ gui.appliedenergistics2.CraftingToastDone=合成已完成! gui.appliedenergistics2.CraftingToastCancelled=合成已取消! gui.appliedenergistics2.Sticky=粘滞 gui.appliedenergistics2.FluidTerminal=流体终端 +gui.appliedenergistics2.CanBeEnchanted=可被附魔 +gui.appliedenergistics2.IncreasedEnergyUseFromEnchants=附魔会增加能耗 +gui.appliedenergistics2.Deprecated=已弃用 // GUI Tooltips gui.tooltips.appliedenergistics2.Stash=存储物品 @@ -442,6 +445,8 @@ waila.appliedenergistics2.p2p_input_many_outputs=已连接(输入端)- §4%d waila.appliedenergistics2.p2p_output_one_input=已连接(输出端)- 1输入 waila.appliedenergistics2.p2p_output_many_inputs=已连接(输出端)- §2%d§r输入 waila.appliedenergistics2.P2POutput=已连接(输出端) +waila.appliedenergistics2.EnchantedWith=已附魔: +waila.appliedenergistics2.IdentityDeprecated=已弃用。 使用SHIFT + 右键来转换 // TheOneProbe theoneprobe.appliedenergistics2.crafting=合成中:§2%1$s§r diff --git a/src/main/resources/assets/appliedenergistics2/recipes/network/parts/planes_annihilatition_identity.json b/src/main/resources/assets/appliedenergistics2/recipes/network/parts/planes_annihilatition_identity.json deleted file mode 100644 index 3353edf0853..00000000000 --- a/src/main/resources/assets/appliedenergistics2/recipes/network/parts/planes_annihilatition_identity.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "conditions": [ - { - "type": "forge:and", - "values": [ - { - "type": "appliedenergistics2:part_exists", - "part": "part.identity_annihilation_plane" - }, - { - "type": "appliedenergistics2:part_exists", - "part": "part.annihilation_plane" - }, - { - "type": "appliedenergistics2:material_exists", - "material": "material.fluix_pearl" - } - ] - } - ], - "result": { - "type": "appliedenergistics2:part", - "part": "part.identity_annihilation_plane" - }, - "type": "appliedenergistics2:part_shapeless", - "ingredients": [ - { - "type": "appliedenergistics2:part", - "part": "part.annihilation_plane" - }, - { - "type": "appliedenergistics2:part", - "part": "material.fluix_pearl" - } - ] -}