finish the ender crates

This commit is contained in:
Ellpeck 2019-02-18 19:30:35 +01:00
parent 1502348da8
commit c97a13f737
13 changed files with 235 additions and 17 deletions

View file

@ -140,7 +140,7 @@ public final class NaturesAuraAPI {
/** /**
* The capability that any world has to store Nature's Aura specific data in * 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 * 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) @CapabilityInject(IWorldData.class)
public static Capability<IWorldData> capWorldData; public static Capability<IWorldData> capWorldData;

View file

@ -24,4 +24,6 @@ public interface IWorldData extends ICapabilityProvider, INBTSerializable<NBTTag
} }
IItemHandlerModifiable getEnderStorage(String name); IItemHandlerModifiable getEnderStorage(String name);
boolean isEnderStorageLocked(String name);
} }

View file

@ -1,32 +1,107 @@
package de.ellpeck.naturesaura.blocks; package de.ellpeck.naturesaura.blocks;
import de.ellpeck.naturesaura.NaturesAura; import de.ellpeck.naturesaura.NaturesAura;
import de.ellpeck.naturesaura.api.misc.IWorldData;
import de.ellpeck.naturesaura.blocks.tiles.TileEntityEnderCrate; import de.ellpeck.naturesaura.blocks.tiles.TileEntityEnderCrate;
import de.ellpeck.naturesaura.blocks.tiles.render.RenderEnderCrate; import de.ellpeck.naturesaura.blocks.tiles.render.RenderEnderCrate;
import de.ellpeck.naturesaura.items.ModItems;
import de.ellpeck.naturesaura.reg.ITESRProvider; import de.ellpeck.naturesaura.reg.ITESRProvider;
import net.minecraft.block.BlockAnvil;
import net.minecraft.block.SoundType; import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material; import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer;
import net.minecraft.client.resources.I18n;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
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.tileentity.TileEntity;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand; import net.minecraft.util.EnumHand;
import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.Tuple; import net.minecraft.util.Tuple;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.AnvilUpdateEvent;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly; import net.minecraftforge.fml.relauncher.SideOnly;
import javax.annotation.Nullable;
import java.lang.ref.WeakReference;
import java.util.List;
import java.util.Random; import java.util.Random;
public class BlockEnderCrate extends BlockContainerImpl implements ITESRProvider { public class BlockEnderCrate extends BlockContainerImpl implements ITESRProvider {
// This is terrible but I can't see a better solution right now so oh well
private static final ThreadLocal<WeakReference<World>> CACHED_WORLD = new ThreadLocal<>();
public BlockEnderCrate() { public BlockEnderCrate() {
super(Material.ROCK, "ender_crate", TileEntityEnderCrate.class, "ender_crate"); super(Material.ROCK, "ender_crate", TileEntityEnderCrate.class, "ender_crate");
this.setSoundType(SoundType.STONE); this.setSoundType(SoundType.STONE);
this.setHardness(5F); this.setHardness(5F);
this.setLightLevel(0.75F); 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<String> 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> 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 @Override
@ -36,7 +111,7 @@ public class BlockEnderCrate extends BlockContainerImpl implements ITESRProvider
if (tile instanceof TileEntityEnderCrate) { if (tile instanceof TileEntityEnderCrate) {
TileEntityEnderCrate crate = (TileEntityEnderCrate) tile; TileEntityEnderCrate crate = (TileEntityEnderCrate) tile;
if (crate.canOpen()) { if (crate.canOpen()) {
crate.drainAura(5000); crate.drainAura(10000);
playerIn.openGui(NaturesAura.MOD_ID, 0, worldIn, pos.getX(), pos.getY(), pos.getZ()); 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; return true;
} }
@Override
@SideOnly(Side.CLIENT)
public void addInformation(ItemStack stack, @Nullable World worldIn, List<String> tooltip, ITooltipFlag flagIn) {
addEnderNameInfo(stack, tooltip);
}
@Override @Override
@SideOnly(Side.CLIENT) @SideOnly(Side.CLIENT)
public void randomDisplayTick(IBlockState stateIn, World worldIn, BlockPos pos, Random rand) { public void randomDisplayTick(IBlockState stateIn, World worldIn, BlockPos pos, Random rand) {

View file

@ -1,7 +1,9 @@
package de.ellpeck.naturesaura.blocks.tiles; package de.ellpeck.naturesaura.blocks.tiles;
import de.ellpeck.naturesaura.NaturesAura;
import de.ellpeck.naturesaura.api.aura.chunk.IAuraChunk; import de.ellpeck.naturesaura.api.aura.chunk.IAuraChunk;
import de.ellpeck.naturesaura.api.misc.IWorldData; import de.ellpeck.naturesaura.api.misc.IWorldData;
import de.ellpeck.naturesaura.blocks.BlockEnderCrate;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagCompound;
@ -35,7 +37,7 @@ public class TileEntityEnderCrate extends TileEntityImpl {
public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) { public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) {
ItemStack remain = this.getStorage().insertItem(slot, stack, simulate); ItemStack remain = this.getStorage().insertItem(slot, stack, simulate);
if (!simulate) if (!simulate)
TileEntityEnderCrate.this.drainAura((stack.getCount() - remain.getCount()) * 200); TileEntityEnderCrate.this.drainAura((stack.getCount() - remain.getCount()) * 500);
return remain; return remain;
} }
@ -44,7 +46,7 @@ public class TileEntityEnderCrate extends TileEntityImpl {
public ItemStack extractItem(int slot, int amount, boolean simulate) { public ItemStack extractItem(int slot, int amount, boolean simulate) {
ItemStack extracted = this.getStorage().extractItem(slot, amount, simulate); ItemStack extracted = this.getStorage().extractItem(slot, amount, simulate);
if (!simulate) if (!simulate)
TileEntityEnderCrate.this.drainAura(extracted.getCount() * 200); TileEntityEnderCrate.this.drainAura(extracted.getCount() * 500);
return extracted; return extracted;
} }
@ -77,16 +79,22 @@ public class TileEntityEnderCrate extends TileEntityImpl {
@Override @Override
public ItemStack getDrop(IBlockState state, int fortune) { public ItemStack getDrop(IBlockState state, int fortune) {
ItemStack drop = super.getDrop(state, fortune); ItemStack drop = super.getDrop(state, fortune);
if (this.name != null) if (this.name != null) {
drop.setStackDisplayName(this.name); if (!drop.hasTagCompound())
drop.setTagCompound(new NBTTagCompound());
drop.getTagCompound().setString(NaturesAura.MOD_ID + ":ender_name", this.name);
}
return drop; return drop;
} }
@Override @Override
public void loadDataOnPlace(ItemStack stack) { public void loadDataOnPlace(ItemStack stack) {
super.loadDataOnPlace(stack); super.loadDataOnPlace(stack);
if (!this.world.isRemote && stack.hasDisplayName()) if (!this.world.isRemote) {
this.name = stack.getDisplayName(); String name = BlockEnderCrate.getEnderName(stack);
if (name != null && !name.isEmpty())
this.name = name;
}
} }
@Override @Override

View file

@ -2,6 +2,7 @@ package de.ellpeck.naturesaura.gui;
import de.ellpeck.naturesaura.NaturesAura; import de.ellpeck.naturesaura.NaturesAura;
import de.ellpeck.naturesaura.api.misc.IWorldData; import de.ellpeck.naturesaura.api.misc.IWorldData;
import de.ellpeck.naturesaura.blocks.BlockEnderCrate;
import de.ellpeck.naturesaura.blocks.tiles.TileEntityEnderCrate; import de.ellpeck.naturesaura.blocks.tiles.TileEntityEnderCrate;
import de.ellpeck.naturesaura.items.ModItems; import de.ellpeck.naturesaura.items.ModItems;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
@ -32,8 +33,11 @@ public class GuiHandler implements IGuiHandler {
} }
} else if (id == 1) { } else if (id == 1) {
ItemStack stack = player.getHeldItemMainhand(); ItemStack stack = player.getHeldItemMainhand();
if (stack.getItem() == ModItems.ENDER_ACCESS && stack.hasDisplayName()) if (stack.getItem() == ModItems.ENDER_ACCESS) {
return new ContainerEnderCrate(player, IWorldData.getOverworldData(world).getEnderStorage(stack.getDisplayName())); String name = BlockEnderCrate.getEnderName(stack);
if (name != null && !name.isEmpty())
return new ContainerEnderCrate(player, IWorldData.getOverworldData(world).getEnderStorage(name));
}
} }
return null; return null;
} }
@ -50,9 +54,10 @@ public class GuiHandler implements IGuiHandler {
} }
} else if (id == 1) { } else if (id == 1) {
ItemStack stack = player.getHeldItemMainhand(); ItemStack stack = player.getHeldItemMainhand();
if (stack.getItem() == ModItems.ENDER_ACCESS && stack.hasDisplayName()) { if (stack.getItem() == ModItems.ENDER_ACCESS) {
String name = stack.getDisplayName(); String name = BlockEnderCrate.getEnderName(stack);
return new GuiEnderCrate(player, IWorldData.getOverworldData(world).getEnderStorage(name), "ender_access", name); if (name != null && !name.isEmpty())
return new GuiEnderCrate(player, IWorldData.getOverworldData(world).getEnderStorage(name), "ender_access", name);
} }
} }
return null; return null;

View file

@ -1,13 +1,21 @@
package de.ellpeck.naturesaura.items; package de.ellpeck.naturesaura.items;
import com.google.common.base.Strings;
import de.ellpeck.naturesaura.NaturesAura; import de.ellpeck.naturesaura.NaturesAura;
import de.ellpeck.naturesaura.api.NaturesAuraAPI; 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.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult; import net.minecraft.util.ActionResult;
import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumHand; import net.minecraft.util.EnumHand;
import net.minecraft.world.World; 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 class ItemEnderAccess extends ItemImpl {
public ItemEnderAccess() { public ItemEnderAccess() {
@ -19,12 +27,17 @@ public class ItemEnderAccess extends ItemImpl {
if (handIn != EnumHand.MAIN_HAND) if (handIn != EnumHand.MAIN_HAND)
return new ActionResult<>(EnumActionResult.PASS, playerIn.getHeldItem(handIn)); return new ActionResult<>(EnumActionResult.PASS, playerIn.getHeldItem(handIn));
ItemStack stack = playerIn.getHeldItemMainhand(); ItemStack stack = playerIn.getHeldItemMainhand();
if (stack.hasDisplayName()) { if (!Strings.isNullOrEmpty(BlockEnderCrate.getEnderName(stack))) {
if (!worldIn.isRemote && NaturesAuraAPI.instance().extractAuraFromPlayer(playerIn, 5000, false)) { 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); 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.SUCCESS, stack);
} }
return new ActionResult<>(EnumActionResult.FAIL, stack); return new ActionResult<>(EnumActionResult.FAIL, stack);
} }
@Override
@SideOnly(Side.CLIENT)
public void addInformation(ItemStack stack, @Nullable World worldIn, List<String> tooltip, ITooltipFlag flagIn) {
BlockEnderCrate.addEnderNameInfo(stack, tooltip);
}
} }

View file

@ -4,6 +4,8 @@ import de.ellpeck.naturesaura.Helper;
import de.ellpeck.naturesaura.api.NaturesAuraAPI; import de.ellpeck.naturesaura.api.NaturesAuraAPI;
import de.ellpeck.naturesaura.api.misc.IWorldData; import de.ellpeck.naturesaura.api.misc.IWorldData;
import de.ellpeck.naturesaura.blocks.tiles.ItemStackHandlerNA; 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.NBTBase;
import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList; import net.minecraft.nbt.NBTTagList;
@ -68,4 +70,15 @@ public class WorldData implements IWorldData {
public ItemStackHandlerNA getEnderStorage(String name) { public ItemStackHandlerNA getEnderStorage(String name) {
return this.enderStorages.computeIfAbsent(name, n -> new ItemStackHandlerNA(27)); 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;
}
} }

View file

@ -108,6 +108,8 @@ info.naturesaura.stored_pos_gone=Your notes seem out of date...
info.naturesaura.empty=Empty info.naturesaura.empty=Empty
info.naturesaura.ender_crate=Ender Crate: %s info.naturesaura.ender_crate=Ender Crate: %s
info.naturesaura.ender_access=Ender Ocular: %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=Nature's Aura
advancement.naturesaura.root.desc=Becoming a magical botanist advancement.naturesaura.root.desc=Becoming a magical botanist

View file

@ -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"
}
]
}

View file

@ -40,7 +40,8 @@
{ {
"type": "naturesaura:offering", "type": "naturesaura:offering",
"text": "Exchanging the $(item)Token of Fear$() for a much stronger version, the $(item)Token of Terror$()", "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", "type": "naturesaura:offering",

View file

@ -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"
}
]
}

View file

@ -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"
}
}

View file

@ -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"
}
}