diff --git a/src/main/java/de/ellpeck/naturesaura/api/NaturesAuraAPI.java b/src/main/java/de/ellpeck/naturesaura/api/NaturesAuraAPI.java index a7e6fdb8..58d27d78 100644 --- a/src/main/java/de/ellpeck/naturesaura/api/NaturesAuraAPI.java +++ b/src/main/java/de/ellpeck/naturesaura/api/NaturesAuraAPI.java @@ -140,7 +140,7 @@ public final class NaturesAuraAPI { /** * The capability that any world has to store Nature's Aura specific data in * it. To retrieve this capability from any world, use the helper methods - * {@link IWorldData#getWorldData(World)} or {@link IWorldData#getOverworldData()}. + * {@link IWorldData#getWorldData(World)} or {@link IWorldData#getOverworldData(World)}. */ @CapabilityInject(IWorldData.class) public static Capability capWorldData; diff --git a/src/main/java/de/ellpeck/naturesaura/api/misc/IWorldData.java b/src/main/java/de/ellpeck/naturesaura/api/misc/IWorldData.java index f2f50a50..09da5c2c 100644 --- a/src/main/java/de/ellpeck/naturesaura/api/misc/IWorldData.java +++ b/src/main/java/de/ellpeck/naturesaura/api/misc/IWorldData.java @@ -24,4 +24,6 @@ public interface IWorldData extends ICapabilityProvider, INBTSerializable> CACHED_WORLD = new ThreadLocal<>(); + public BlockEnderCrate() { super(Material.ROCK, "ender_crate", TileEntityEnderCrate.class, "ender_crate"); this.setSoundType(SoundType.STONE); this.setHardness(5F); this.setLightLevel(0.75F); + + MinecraftForge.EVENT_BUS.register(this); + } + + public static String getEnderName(ItemStack stack) { + if (!stack.hasTagCompound()) + return ""; + NBTTagCompound compound = stack.getTagCompound(); + return compound.getString(NaturesAura.MOD_ID + ":ender_name"); + } + + @SideOnly(Side.CLIENT) + public static void addEnderNameInfo(ItemStack stack, List tooltip) { + String name = getEnderName(stack); + if (name != null && !name.isEmpty()) + tooltip.add(TextFormatting.DARK_PURPLE + I18n.format("info." + NaturesAura.MOD_ID + ".ender_name", + TextFormatting.ITALIC + name + TextFormatting.RESET)); + else + tooltip.add(TextFormatting.DARK_PURPLE + I18n.format("info." + NaturesAura.MOD_ID + ".ender_name.missing")); + } + + @SubscribeEvent + public void onRightClick(PlayerInteractEvent.RightClickBlock event) { + World world = event.getWorld(); + BlockPos pos = event.getPos(); + IBlockState state = world.getBlockState(pos); + if (state.getBlock() instanceof BlockAnvil) { + CACHED_WORLD.set(new WeakReference<>(world)); + } + } + + @SubscribeEvent + public void onAnvilUpdate(AnvilUpdateEvent event) { + WeakReference world = CACHED_WORLD.get(); + if (world == null || world.get() == null) + return; + ItemStack stack = event.getLeft(); + if (stack.getItem() != Item.getItemFromBlock(this) && stack.getItem() != ModItems.ENDER_ACCESS) + return; + ItemStack second = event.getRight(); + if (second.getItem() != Items.ENDER_EYE || second.getCount() < stack.getCount()) + return; + String name = event.getName(); + if (name == null || name.isEmpty()) + return; + if (IWorldData.getOverworldData(world.get()).isEnderStorageLocked(name)) + return; + ItemStack output = stack.copy(); + if (!output.hasTagCompound()) + output.setTagCompound(new NBTTagCompound()); + output.getTagCompound().setString(NaturesAura.MOD_ID + ":ender_name", name); + event.setOutput(output); + event.setMaterialCost(stack.getCount()); + event.setCost(1); } @Override @@ -36,7 +111,7 @@ public class BlockEnderCrate extends BlockContainerImpl implements ITESRProvider if (tile instanceof TileEntityEnderCrate) { TileEntityEnderCrate crate = (TileEntityEnderCrate) tile; if (crate.canOpen()) { - crate.drainAura(5000); + crate.drainAura(10000); playerIn.openGui(NaturesAura.MOD_ID, 0, worldIn, pos.getX(), pos.getY(), pos.getZ()); } } @@ -44,6 +119,12 @@ public class BlockEnderCrate extends BlockContainerImpl implements ITESRProvider return true; } + @Override + @SideOnly(Side.CLIENT) + public void addInformation(ItemStack stack, @Nullable World worldIn, List tooltip, ITooltipFlag flagIn) { + addEnderNameInfo(stack, tooltip); + } + @Override @SideOnly(Side.CLIENT) public void randomDisplayTick(IBlockState stateIn, World worldIn, BlockPos pos, Random rand) { diff --git a/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityEnderCrate.java b/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityEnderCrate.java index 953491e2..2257087f 100644 --- a/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityEnderCrate.java +++ b/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityEnderCrate.java @@ -1,7 +1,9 @@ package de.ellpeck.naturesaura.blocks.tiles; +import de.ellpeck.naturesaura.NaturesAura; import de.ellpeck.naturesaura.api.aura.chunk.IAuraChunk; import de.ellpeck.naturesaura.api.misc.IWorldData; +import de.ellpeck.naturesaura.blocks.BlockEnderCrate; import net.minecraft.block.state.IBlockState; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; @@ -35,7 +37,7 @@ public class TileEntityEnderCrate extends TileEntityImpl { public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) { ItemStack remain = this.getStorage().insertItem(slot, stack, simulate); if (!simulate) - TileEntityEnderCrate.this.drainAura((stack.getCount() - remain.getCount()) * 200); + TileEntityEnderCrate.this.drainAura((stack.getCount() - remain.getCount()) * 500); return remain; } @@ -44,7 +46,7 @@ public class TileEntityEnderCrate extends TileEntityImpl { public ItemStack extractItem(int slot, int amount, boolean simulate) { ItemStack extracted = this.getStorage().extractItem(slot, amount, simulate); if (!simulate) - TileEntityEnderCrate.this.drainAura(extracted.getCount() * 200); + TileEntityEnderCrate.this.drainAura(extracted.getCount() * 500); return extracted; } @@ -77,16 +79,22 @@ public class TileEntityEnderCrate extends TileEntityImpl { @Override public ItemStack getDrop(IBlockState state, int fortune) { ItemStack drop = super.getDrop(state, fortune); - if (this.name != null) - drop.setStackDisplayName(this.name); + if (this.name != null) { + if (!drop.hasTagCompound()) + drop.setTagCompound(new NBTTagCompound()); + drop.getTagCompound().setString(NaturesAura.MOD_ID + ":ender_name", this.name); + } return drop; } @Override public void loadDataOnPlace(ItemStack stack) { super.loadDataOnPlace(stack); - if (!this.world.isRemote && stack.hasDisplayName()) - this.name = stack.getDisplayName(); + if (!this.world.isRemote) { + String name = BlockEnderCrate.getEnderName(stack); + if (name != null && !name.isEmpty()) + this.name = name; + } } @Override diff --git a/src/main/java/de/ellpeck/naturesaura/gui/GuiHandler.java b/src/main/java/de/ellpeck/naturesaura/gui/GuiHandler.java index e7a1a2e8..88542c7c 100644 --- a/src/main/java/de/ellpeck/naturesaura/gui/GuiHandler.java +++ b/src/main/java/de/ellpeck/naturesaura/gui/GuiHandler.java @@ -2,6 +2,7 @@ package de.ellpeck.naturesaura.gui; import de.ellpeck.naturesaura.NaturesAura; import de.ellpeck.naturesaura.api.misc.IWorldData; +import de.ellpeck.naturesaura.blocks.BlockEnderCrate; import de.ellpeck.naturesaura.blocks.tiles.TileEntityEnderCrate; import de.ellpeck.naturesaura.items.ModItems; import net.minecraft.entity.player.EntityPlayer; @@ -32,8 +33,11 @@ public class GuiHandler implements IGuiHandler { } } else if (id == 1) { ItemStack stack = player.getHeldItemMainhand(); - if (stack.getItem() == ModItems.ENDER_ACCESS && stack.hasDisplayName()) - return new ContainerEnderCrate(player, IWorldData.getOverworldData(world).getEnderStorage(stack.getDisplayName())); + if (stack.getItem() == ModItems.ENDER_ACCESS) { + String name = BlockEnderCrate.getEnderName(stack); + if (name != null && !name.isEmpty()) + return new ContainerEnderCrate(player, IWorldData.getOverworldData(world).getEnderStorage(name)); + } } return null; } @@ -50,9 +54,10 @@ public class GuiHandler implements IGuiHandler { } } else if (id == 1) { ItemStack stack = player.getHeldItemMainhand(); - if (stack.getItem() == ModItems.ENDER_ACCESS && stack.hasDisplayName()) { - String name = stack.getDisplayName(); - return new GuiEnderCrate(player, IWorldData.getOverworldData(world).getEnderStorage(name), "ender_access", name); + if (stack.getItem() == ModItems.ENDER_ACCESS) { + String name = BlockEnderCrate.getEnderName(stack); + if (name != null && !name.isEmpty()) + return new GuiEnderCrate(player, IWorldData.getOverworldData(world).getEnderStorage(name), "ender_access", name); } } return null; diff --git a/src/main/java/de/ellpeck/naturesaura/items/ItemEnderAccess.java b/src/main/java/de/ellpeck/naturesaura/items/ItemEnderAccess.java index f0f4953e..354bc452 100644 --- a/src/main/java/de/ellpeck/naturesaura/items/ItemEnderAccess.java +++ b/src/main/java/de/ellpeck/naturesaura/items/ItemEnderAccess.java @@ -1,13 +1,21 @@ package de.ellpeck.naturesaura.items; +import com.google.common.base.Strings; import de.ellpeck.naturesaura.NaturesAura; import de.ellpeck.naturesaura.api.NaturesAuraAPI; +import de.ellpeck.naturesaura.blocks.BlockEnderCrate; +import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.util.ActionResult; import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumHand; import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import javax.annotation.Nullable; +import java.util.List; public class ItemEnderAccess extends ItemImpl { public ItemEnderAccess() { @@ -19,12 +27,17 @@ public class ItemEnderAccess extends ItemImpl { if (handIn != EnumHand.MAIN_HAND) return new ActionResult<>(EnumActionResult.PASS, playerIn.getHeldItem(handIn)); ItemStack stack = playerIn.getHeldItemMainhand(); - if (stack.hasDisplayName()) { - if (!worldIn.isRemote && NaturesAuraAPI.instance().extractAuraFromPlayer(playerIn, 5000, false)) { + if (!Strings.isNullOrEmpty(BlockEnderCrate.getEnderName(stack))) { + if (!worldIn.isRemote && NaturesAuraAPI.instance().extractAuraFromPlayer(playerIn, 10000, false)) playerIn.openGui(NaturesAura.MOD_ID, 1, worldIn, (int) playerIn.posX, (int) playerIn.posY, (int) playerIn.posZ); - } return new ActionResult<>(EnumActionResult.SUCCESS, stack); } return new ActionResult<>(EnumActionResult.FAIL, stack); } + + @Override + @SideOnly(Side.CLIENT) + public void addInformation(ItemStack stack, @Nullable World worldIn, List tooltip, ITooltipFlag flagIn) { + BlockEnderCrate.addEnderNameInfo(stack, tooltip); + } } diff --git a/src/main/java/de/ellpeck/naturesaura/misc/WorldData.java b/src/main/java/de/ellpeck/naturesaura/misc/WorldData.java index eaea99ef..6efae3e8 100644 --- a/src/main/java/de/ellpeck/naturesaura/misc/WorldData.java +++ b/src/main/java/de/ellpeck/naturesaura/misc/WorldData.java @@ -4,6 +4,8 @@ import de.ellpeck.naturesaura.Helper; import de.ellpeck.naturesaura.api.NaturesAuraAPI; import de.ellpeck.naturesaura.api.misc.IWorldData; import de.ellpeck.naturesaura.blocks.tiles.ItemStackHandlerNA; +import de.ellpeck.naturesaura.items.ModItems; +import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; @@ -68,4 +70,15 @@ public class WorldData implements IWorldData { public ItemStackHandlerNA getEnderStorage(String name) { return this.enderStorages.computeIfAbsent(name, n -> new ItemStackHandlerNA(27)); } + + @Override + public boolean isEnderStorageLocked(String name) { + ItemStackHandlerNA handler = this.getEnderStorage(name); + for (int i = 0; i < handler.getSlots(); i++) { + ItemStack stack = handler.getStackInSlot(i); + if (!stack.isEmpty() && stack.getItem() == ModItems.TOKEN_TERROR) + return true; + } + return false; + } } diff --git a/src/main/resources/assets/naturesaura/lang/en_US.lang b/src/main/resources/assets/naturesaura/lang/en_US.lang index 0c023f9f..f44a729b 100644 --- a/src/main/resources/assets/naturesaura/lang/en_US.lang +++ b/src/main/resources/assets/naturesaura/lang/en_US.lang @@ -108,6 +108,8 @@ info.naturesaura.stored_pos_gone=Your notes seem out of date... info.naturesaura.empty=Empty info.naturesaura.ender_crate=Ender Crate: %s info.naturesaura.ender_access=Ender Ocular: %s +info.naturesaura.ender_name.missing=No Ender Name +info.naturesaura.ender_name=Ender Name: %s advancement.naturesaura.root=Nature's Aura advancement.naturesaura.root.desc=Becoming a magical botanist diff --git a/src/main/resources/assets/naturesaura/patchouli_books/book/en_us/entries/items/ender_access.json b/src/main/resources/assets/naturesaura/patchouli_books/book/en_us/entries/items/ender_access.json new file mode 100644 index 00000000..6f378b20 --- /dev/null +++ b/src/main/resources/assets/naturesaura/patchouli_books/book/en_us/entries/items/ender_access.json @@ -0,0 +1,17 @@ +{ + "name": "Ender Ocular", + "icon": "naturesaura:ender_access", + "category": "items", + "advancement": "naturesaura:aura_bottle_end", + "pages": [ + { + "type": "text", + "text": "The $(item)Ender Ocular$() is, to put it simply, a handheld version of the $(l:using/ender_crate)Ender Crate$(). After giving it an $(thing)Ender Name$() the exact same way, interacting with it while holding it in one's hand will open the storage then and there. For this, an $(l:items/aura_cache)Aura Cache$() is required that some $(aura) will be drained from." + }, + { + "type": "crafting", + "text": "Creating the $(item)Ender Ocular$()", + "recipe": "naturesaura:ender_access" + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/naturesaura/patchouli_books/book/en_us/entries/practices/offering.json b/src/main/resources/assets/naturesaura/patchouli_books/book/en_us/entries/practices/offering.json index d7f9acf6..bfae7f9d 100644 --- a/src/main/resources/assets/naturesaura/patchouli_books/book/en_us/entries/practices/offering.json +++ b/src/main/resources/assets/naturesaura/patchouli_books/book/en_us/entries/practices/offering.json @@ -40,7 +40,8 @@ { "type": "naturesaura:offering", "text": "Exchanging the $(item)Token of Fear$() for a much stronger version, the $(item)Token of Terror$()", - "recipe": "naturesaura:token_terror" + "recipe": "naturesaura:token_terror", + "anchor": "terror" }, { "type": "naturesaura:offering", diff --git a/src/main/resources/assets/naturesaura/patchouli_books/book/en_us/entries/using/ender_crate.json b/src/main/resources/assets/naturesaura/patchouli_books/book/en_us/entries/using/ender_crate.json new file mode 100644 index 00000000..50614d26 --- /dev/null +++ b/src/main/resources/assets/naturesaura/patchouli_books/book/en_us/entries/using/ender_crate.json @@ -0,0 +1,21 @@ +{ + "name": "Ender Crate", + "icon": "naturesaura:ender_crate", + "category": "using", + "advancement": "naturesaura:aura_bottle_end", + "pages": [ + { + "type": "text", + "text": "$(item)Ender Chests$() are great technology for anyone trying to store items safely, however, they don't provide easy means of $(thing)transportation$() for said items. For this, the $(item)Ender Crate$() is perfect: Two or more of these crates which are linked together share the same inventory, even inter-dimensionally, meaning that they create the possibility of easily transporting items around." + }, + { + "type": "text", + "text": "Of course, some $(aura) is required for each interaction that takes place with the crate.$(br)To link one or more crates, they have to be given an $(item)Ender Name$() by placing them in an $(thing)anvil$() with an $(item)Ender Eye$() and then writing down the desired name.$(br)If the worry exists that other people might call their crates the same name, any name can be $(thing)locked$() from being given simply by placing a $(l:practices/offering#terror)Token of Terror$() inside a crate with that name." + }, + { + "type": "crafting", + "text": "Creating the $(item)Ender Crate$()", + "recipe": "naturesaura:ender_crate" + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/naturesaura/recipes/ender_access.json b/src/main/resources/assets/naturesaura/recipes/ender_access.json new file mode 100644 index 00000000..9d72f130 --- /dev/null +++ b/src/main/resources/assets/naturesaura/recipes/ender_access.json @@ -0,0 +1,26 @@ +{ + "type": "forge:ore_shaped", + "pattern": [ + " Y ", + "DED", + " D " + ], + "key": { + "E": { + "item": "minecraft:ender_chest" + }, + "Y": { + "item": "minecraft:ender_eye" + }, + "D": { + "type": "minecraft:item_nbt", + "item": "naturesaura:aura_bottle", + "nbt": { + "stored_type": "naturesaura:end" + } + } + }, + "result": { + "item": "naturesaura:ender_access" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/naturesaura/recipes/ender_crate.json b/src/main/resources/assets/naturesaura/recipes/ender_crate.json new file mode 100644 index 00000000..4cbc5ade --- /dev/null +++ b/src/main/resources/assets/naturesaura/recipes/ender_crate.json @@ -0,0 +1,29 @@ +{ + "type": "forge:ore_shaped", + "pattern": [ + "OYO", + "DED", + "ODO" + ], + "key": { + "E": { + "item": "minecraft:ender_chest" + }, + "Y": { + "item": "minecraft:ender_eye" + }, + "D": { + "type": "minecraft:item_nbt", + "item": "naturesaura:aura_bottle", + "nbt": { + "stored_type": "naturesaura:end" + } + }, + "O": { + "item": "minecraft:obsidian" + } + }, + "result": { + "item": "naturesaura:ender_crate" + } +} \ No newline at end of file