diff --git a/src/main/java/de/ellpeck/naturesaura/Helper.java b/src/main/java/de/ellpeck/naturesaura/Helper.java index 4dafd711..14ce0919 100644 --- a/src/main/java/de/ellpeck/naturesaura/Helper.java +++ b/src/main/java/de/ellpeck/naturesaura/Helper.java @@ -37,6 +37,7 @@ import net.minecraftforge.common.capabilities.CapabilityManager; import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandlerModifiable; import org.lwjgl.opengl.GL11; @@ -315,4 +316,11 @@ public final class Helper { } return false; } + + public static boolean isEmpty(IItemHandler handler) { + for (int i = 0; i < handler.getSlots(); i++) + if (!handler.getStackInSlot(i).isEmpty()) + return false; + return true; + } } diff --git a/src/main/java/de/ellpeck/naturesaura/NaturesAura.java b/src/main/java/de/ellpeck/naturesaura/NaturesAura.java index fad82208..f7617413 100644 --- a/src/main/java/de/ellpeck/naturesaura/NaturesAura.java +++ b/src/main/java/de/ellpeck/naturesaura/NaturesAura.java @@ -4,6 +4,7 @@ import de.ellpeck.naturesaura.api.NaturesAuraAPI; import de.ellpeck.naturesaura.api.aura.chunk.IAuraChunk; import de.ellpeck.naturesaura.api.aura.container.IAuraContainer; import de.ellpeck.naturesaura.api.aura.item.IAuraRecharge; +import de.ellpeck.naturesaura.api.misc.IWorldData; import de.ellpeck.naturesaura.blocks.ModBlocks; import de.ellpeck.naturesaura.blocks.multi.Multiblocks; import de.ellpeck.naturesaura.chunk.effect.DrainSpotEffects; @@ -11,6 +12,7 @@ import de.ellpeck.naturesaura.commands.CommandAura; import de.ellpeck.naturesaura.compat.Compat; import de.ellpeck.naturesaura.entities.ModEntities; import de.ellpeck.naturesaura.events.CommonEvents; +import de.ellpeck.naturesaura.gui.GuiHandler; import de.ellpeck.naturesaura.items.ModItems; import de.ellpeck.naturesaura.items.OreDict; import de.ellpeck.naturesaura.packet.PacketHandler; @@ -62,6 +64,7 @@ public final class NaturesAura { Helper.registerCap(IAuraContainer.class); Helper.registerCap(IAuraRecharge.class); Helper.registerCap(IAuraChunk.class); + Helper.registerCap(IWorldData.class); new ModBlocks(); new ModItems(); @@ -85,6 +88,7 @@ public final class NaturesAura { ModRegistry.init(event); DrainSpotEffects.init(); OreDict.init(); + new GuiHandler(); proxy.init(event); } diff --git a/src/main/java/de/ellpeck/naturesaura/api/NaturesAuraAPI.java b/src/main/java/de/ellpeck/naturesaura/api/NaturesAuraAPI.java index af9d512f..a7e6fdb8 100644 --- a/src/main/java/de/ellpeck/naturesaura/api/NaturesAuraAPI.java +++ b/src/main/java/de/ellpeck/naturesaura/api/NaturesAuraAPI.java @@ -9,6 +9,7 @@ import de.ellpeck.naturesaura.api.aura.item.IAuraRecharge; import de.ellpeck.naturesaura.api.aura.type.BasicAuraType; import de.ellpeck.naturesaura.api.aura.type.IAuraType; import de.ellpeck.naturesaura.api.internal.StubHooks; +import de.ellpeck.naturesaura.api.misc.IWorldData; import de.ellpeck.naturesaura.api.multiblock.IMultiblock; import de.ellpeck.naturesaura.api.multiblock.Matcher; import de.ellpeck.naturesaura.api.recipes.AltarRecipe; @@ -136,6 +137,13 @@ public final class NaturesAuraAPI { */ @CapabilityInject(IAuraChunk.class) public static Capability capAuraChunk; + /** + * 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()}. + */ + @CapabilityInject(IWorldData.class) + public static Capability capWorldData; /** * This method returns the active {@link IInternalHooks} instance which can diff --git a/src/main/java/de/ellpeck/naturesaura/api/misc/IWorldData.java b/src/main/java/de/ellpeck/naturesaura/api/misc/IWorldData.java new file mode 100644 index 00000000..f2f50a50 --- /dev/null +++ b/src/main/java/de/ellpeck/naturesaura/api/misc/IWorldData.java @@ -0,0 +1,27 @@ +package de.ellpeck.naturesaura.api.misc; + +import de.ellpeck.naturesaura.api.NaturesAuraAPI; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.world.DimensionType; +import net.minecraft.world.World; +import net.minecraftforge.common.DimensionManager; +import net.minecraftforge.common.capabilities.ICapabilityProvider; +import net.minecraftforge.common.util.INBTSerializable; +import net.minecraftforge.items.IItemHandlerModifiable; + +public interface IWorldData extends ICapabilityProvider, INBTSerializable { + + static IWorldData getWorldData(World world) { + if (world.hasCapability(NaturesAuraAPI.capWorldData, null)) + return world.getCapability(NaturesAuraAPI.capWorldData, null); + return null; + } + + static IWorldData getOverworldData(World world) { + if (!world.isRemote) + return getWorldData(DimensionManager.getWorld(DimensionType.OVERWORLD.getId())); + return getWorldData(world); + } + + IItemHandlerModifiable getEnderStorage(String name); +} diff --git a/src/main/java/de/ellpeck/naturesaura/blocks/BlockEnderCrate.java b/src/main/java/de/ellpeck/naturesaura/blocks/BlockEnderCrate.java new file mode 100644 index 00000000..eeb70f91 --- /dev/null +++ b/src/main/java/de/ellpeck/naturesaura/blocks/BlockEnderCrate.java @@ -0,0 +1,34 @@ +package de.ellpeck.naturesaura.blocks; + +import de.ellpeck.naturesaura.NaturesAura; +import de.ellpeck.naturesaura.blocks.tiles.TileEntityEnderCrate; +import net.minecraft.block.SoundType; +import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public class BlockEnderCrate extends BlockContainerImpl { + public BlockEnderCrate() { + super(Material.ROCK, "ender_crate", TileEntityEnderCrate.class, "ender_crate"); + this.setSoundType(SoundType.STONE); + this.setHardness(5F); + } + + @Override + public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) { + if (!worldIn.isRemote) { + TileEntity tile = worldIn.getTileEntity(pos); + if (tile instanceof TileEntityEnderCrate) { + TileEntityEnderCrate crate = (TileEntityEnderCrate) tile; + if (crate.canOpen()) + playerIn.openGui(NaturesAura.MOD_ID, 0, worldIn, pos.getX(), pos.getY(), pos.getZ()); + } + } + return true; + } +} diff --git a/src/main/java/de/ellpeck/naturesaura/blocks/ModBlocks.java b/src/main/java/de/ellpeck/naturesaura/blocks/ModBlocks.java index 578570ea..e31dc15b 100644 --- a/src/main/java/de/ellpeck/naturesaura/blocks/ModBlocks.java +++ b/src/main/java/de/ellpeck/naturesaura/blocks/ModBlocks.java @@ -48,5 +48,6 @@ public final class ModBlocks { public static final Block RF_CONVERTER = ModConfig.enabledFeatures.rfConverter ? new BlockRFConverter() : null; public static final Block MOSS_GENERATOR = new BlockMossGenerator(); public static final Block TIME_CHANGER = new BlockTimeChanger(); - public static final Block GENERATOR_LIMIT_REMOVER = new BlockImpl("generator_limit_remover",Material.ROCK).setSoundType(SoundType.STONE).setHardness(2F); + public static final Block GENERATOR_LIMIT_REMOVER = new BlockImpl("generator_limit_remover", Material.ROCK).setSoundType(SoundType.STONE).setHardness(2F); + public static final Block ENDER_CRATE = new BlockEnderCrate(); } diff --git a/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityEnderCrate.java b/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityEnderCrate.java new file mode 100644 index 00000000..53d3ec49 --- /dev/null +++ b/src/main/java/de/ellpeck/naturesaura/blocks/tiles/TileEntityEnderCrate.java @@ -0,0 +1,61 @@ +package de.ellpeck.naturesaura.blocks.tiles; + +import de.ellpeck.naturesaura.api.misc.IWorldData; +import net.minecraft.block.state.IBlockState; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumFacing; +import net.minecraftforge.items.IItemHandlerModifiable; + +public class TileEntityEnderCrate extends TileEntityImpl { + + public String name; + + @Override + public IItemHandlerModifiable getItemHandler(EnumFacing facing) { + if (this.canOpen()) + return IWorldData.getOverworldData(this.world).getEnderStorage(this.name); + return null; + } + + public boolean canOpen() { + return this.name != null; + } + + @Override + public void dropInventory() { + } + + @Override + public ItemStack getDrop(IBlockState state, int fortune) { + ItemStack drop = super.getDrop(state, fortune); + if (this.name != null) + drop.setStackDisplayName(this.name); + return drop; + } + + @Override + public void loadDataOnPlace(ItemStack stack) { + super.loadDataOnPlace(stack); + if (!this.world.isRemote && stack.hasDisplayName()) + this.name = stack.getDisplayName(); + } + + @Override + public void writeNBT(NBTTagCompound compound, SaveType type) { + super.writeNBT(compound, type); + if (type != SaveType.BLOCK) { + if (this.name != null) + compound.setString("name", this.name); + } + } + + @Override + public void readNBT(NBTTagCompound compound, SaveType type) { + super.readNBT(compound, type); + if (type != SaveType.BLOCK) { + if (compound.hasKey("name")) + this.name = compound.getString("name"); + } + } +} diff --git a/src/main/java/de/ellpeck/naturesaura/events/CommonEvents.java b/src/main/java/de/ellpeck/naturesaura/events/CommonEvents.java index dc9c63e2..aff02d31 100644 --- a/src/main/java/de/ellpeck/naturesaura/events/CommonEvents.java +++ b/src/main/java/de/ellpeck/naturesaura/events/CommonEvents.java @@ -7,8 +7,10 @@ import de.ellpeck.naturesaura.api.NaturesAuraAPI; import de.ellpeck.naturesaura.api.aura.chunk.IAuraChunk; import de.ellpeck.naturesaura.api.aura.type.IAuraType; import de.ellpeck.naturesaura.chunk.AuraChunk; +import de.ellpeck.naturesaura.misc.WorldData; import de.ellpeck.naturesaura.packet.PacketHandler; import net.minecraft.util.ResourceLocation; +import net.minecraft.world.World; import net.minecraft.world.WorldServer; import net.minecraft.world.chunk.Chunk; import net.minecraftforge.common.config.Config; @@ -30,6 +32,12 @@ public class CommonEvents { event.addCapability(new ResourceLocation(NaturesAura.MOD_ID, "aura"), new AuraChunk(chunk, type)); } + @SubscribeEvent + public void onWorldCapsAttach(AttachCapabilitiesEvent event) { + World world = event.getObject(); + event.addCapability(new ResourceLocation(NaturesAura.MOD_ID, "data"), new WorldData(world)); + } + @SubscribeEvent public void onWorldTick(TickEvent.WorldTickEvent event) { if (!event.world.isRemote && event.phase == TickEvent.Phase.END) { diff --git a/src/main/java/de/ellpeck/naturesaura/gui/ContainerEnderCrate.java b/src/main/java/de/ellpeck/naturesaura/gui/ContainerEnderCrate.java new file mode 100644 index 00000000..ff2e0e8a --- /dev/null +++ b/src/main/java/de/ellpeck/naturesaura/gui/ContainerEnderCrate.java @@ -0,0 +1,57 @@ +package de.ellpeck.naturesaura.gui; + +import de.ellpeck.naturesaura.blocks.tiles.TileEntityEnderCrate; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.SlotItemHandler; + +public class ContainerEnderCrate extends Container { + private final TileEntityEnderCrate crate; + + public ContainerEnderCrate(EntityPlayer player, TileEntityEnderCrate crate) { + this.crate = crate; + IItemHandler handler = this.crate.getItemHandler(null); + + int i = (3 - 4) * 18; + for (int j = 0; j < 3; ++j) + for (int k = 0; k < 9; ++k) + this.addSlotToContainer(new SlotItemHandler(handler, k + j * 9, 8 + k * 18, 18 + j * 18)); + for (int l = 0; l < 3; ++l) + for (int j1 = 0; j1 < 9; ++j1) + this.addSlotToContainer(new Slot(player.inventory, j1 + l * 9 + 9, 8 + j1 * 18, 103 + l * 18 + i)); + for (int i1 = 0; i1 < 9; ++i1) + this.addSlotToContainer(new Slot(player.inventory, i1, 8 + i1 * 18, 161 + i)); + } + + @Override + public boolean canInteractWith(EntityPlayer playerIn) { + return !this.crate.isInvalid(); + } + + @Override + public ItemStack transferStackInSlot(EntityPlayer playerIn, int index) { + ItemStack itemstack = ItemStack.EMPTY; + Slot slot = this.inventorySlots.get(index); + + if (slot != null && slot.getHasStack()) { + ItemStack itemstack1 = slot.getStack(); + itemstack = itemstack1.copy(); + + if (index < 3 * 9) { + if (!this.mergeItemStack(itemstack1, 3 * 9, this.inventorySlots.size(), true)) + return ItemStack.EMPTY; + } else if (!this.mergeItemStack(itemstack1, 0, 3 * 9, false)) + return ItemStack.EMPTY; + + if (itemstack1.isEmpty()) + slot.putStack(ItemStack.EMPTY); + else + slot.onSlotChanged(); + } + + return itemstack; + } +} diff --git a/src/main/java/de/ellpeck/naturesaura/gui/GuiEnderCrate.java b/src/main/java/de/ellpeck/naturesaura/gui/GuiEnderCrate.java new file mode 100644 index 00000000..93ab1090 --- /dev/null +++ b/src/main/java/de/ellpeck/naturesaura/gui/GuiEnderCrate.java @@ -0,0 +1,51 @@ +package de.ellpeck.naturesaura.gui; + +import de.ellpeck.naturesaura.NaturesAura; +import de.ellpeck.naturesaura.blocks.tiles.TileEntityEnderCrate; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.resources.I18n; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.text.TextFormatting; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +@SideOnly(Side.CLIENT) +public class GuiEnderCrate extends GuiContainer { + private static final ResourceLocation CHEST_GUI_TEXTURE = new ResourceLocation("textures/gui/container/generic_54.png"); + private final EntityPlayer player; + private final TileEntityEnderCrate crate; + + public GuiEnderCrate(EntityPlayer player, TileEntityEnderCrate crate) { + super(new ContainerEnderCrate(player, crate)); + this.player = player; + this.crate = crate; + this.allowUserInput = false; + this.ySize = 114 + 3 * 18; + } + + @Override + public void drawScreen(int mouseX, int mouseY, float partialTicks) { + this.drawDefaultBackground(); + super.drawScreen(mouseX, mouseY, partialTicks); + this.renderHoveredToolTip(mouseX, mouseY); + } + + @Override + protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) { + String display = I18n.format("info." + NaturesAura.MOD_ID + ".ender_crate", TextFormatting.ITALIC + this.crate.name + TextFormatting.RESET); + this.fontRenderer.drawString(display, 8, 6, 4210752); + this.fontRenderer.drawString(this.player.inventory.getDisplayName().getFormattedText(), 8, this.ySize - 96 + 2, 4210752); + } + + @Override + protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) { + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + this.mc.getTextureManager().bindTexture(CHEST_GUI_TEXTURE); + int i = (this.width - this.xSize) / 2; + int j = (this.height - this.ySize) / 2; + this.drawTexturedModalRect(i, j, 0, 0, this.xSize, 3 * 18 + 17); + this.drawTexturedModalRect(i, j + 3 * 18 + 17, 0, 126, this.xSize, 96); + } +} \ No newline at end of file diff --git a/src/main/java/de/ellpeck/naturesaura/gui/GuiHandler.java b/src/main/java/de/ellpeck/naturesaura/gui/GuiHandler.java new file mode 100644 index 00000000..bb90b105 --- /dev/null +++ b/src/main/java/de/ellpeck/naturesaura/gui/GuiHandler.java @@ -0,0 +1,47 @@ +package de.ellpeck.naturesaura.gui; + +import de.ellpeck.naturesaura.NaturesAura; +import de.ellpeck.naturesaura.blocks.tiles.TileEntityEnderCrate; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraftforge.fml.common.network.IGuiHandler; +import net.minecraftforge.fml.common.network.NetworkRegistry; + +import javax.annotation.Nullable; + +public class GuiHandler implements IGuiHandler { + + public GuiHandler() { + NetworkRegistry.INSTANCE.registerGuiHandler(NaturesAura.MOD_ID, this); + } + + @Nullable + @Override + public Object getServerGuiElement(int id, EntityPlayer player, World world, int x, int y, int z) { + if (id == 0) { + TileEntity tile = world.getTileEntity(new BlockPos(x, y, z)); + if (tile instanceof TileEntityEnderCrate) { + TileEntityEnderCrate crate = (TileEntityEnderCrate) tile; + if (crate.canOpen()) + return new ContainerEnderCrate(player, crate); + } + } + return null; + } + + @Nullable + @Override + public Object getClientGuiElement(int id, EntityPlayer player, World world, int x, int y, int z) { + if (id == 0) { + TileEntity tile = world.getTileEntity(new BlockPos(x, y, z)); + if (tile instanceof TileEntityEnderCrate) { + TileEntityEnderCrate crate = (TileEntityEnderCrate) tile; + if (crate.canOpen()) + return new GuiEnderCrate(player, crate); + } + } + return null; + } +} diff --git a/src/main/java/de/ellpeck/naturesaura/misc/WorldData.java b/src/main/java/de/ellpeck/naturesaura/misc/WorldData.java new file mode 100644 index 00000000..eaea99ef --- /dev/null +++ b/src/main/java/de/ellpeck/naturesaura/misc/WorldData.java @@ -0,0 +1,71 @@ +package de.ellpeck.naturesaura.misc; + +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 net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.World; +import net.minecraftforge.common.capabilities.Capability; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.HashMap; +import java.util.Map; + +public class WorldData implements IWorldData { + private final World world; + private final Map enderStorages = new HashMap<>(); + + public WorldData(World world) { + this.world = world; + } + + @Override + public boolean hasCapability(@Nonnull Capability capability, @Nullable EnumFacing facing) { + return capability == NaturesAuraAPI.capWorldData; + } + + @Nullable + @Override + public T getCapability(@Nonnull Capability capability, @Nullable EnumFacing facing) { + return capability == NaturesAuraAPI.capWorldData ? (T) this : null; + } + + @Override + public NBTTagCompound serializeNBT() { + NBTTagCompound compound = new NBTTagCompound(); + + NBTTagList storages = new NBTTagList(); + for (Map.Entry entry : this.enderStorages.entrySet()) { + ItemStackHandlerNA handler = entry.getValue(); + if (Helper.isEmpty(handler)) + continue; + NBTTagCompound storageComp = handler.serializeNBT(); + storageComp.setString("name", entry.getKey()); + storages.appendTag(storageComp); + } + compound.setTag("storages", storages); + + return compound; + } + + @Override + public void deserializeNBT(NBTTagCompound compound) { + this.enderStorages.clear(); + NBTTagList storages = compound.getTagList("storages", 10); + for (NBTBase base : storages) { + NBTTagCompound storageComp = (NBTTagCompound) base; + ItemStackHandlerNA storage = this.getEnderStorage(storageComp.getString("name")); + storage.deserializeNBT(storageComp); + } + } + + @Override + public ItemStackHandlerNA getEnderStorage(String name) { + return this.enderStorages.computeIfAbsent(name, n -> new ItemStackHandlerNA(27)); + } +} diff --git a/src/main/resources/assets/naturesaura/lang/en_US.lang b/src/main/resources/assets/naturesaura/lang/en_US.lang index 6682b0c6..c3dfc545 100644 --- a/src/main/resources/assets/naturesaura/lang/en_US.lang +++ b/src/main/resources/assets/naturesaura/lang/en_US.lang @@ -45,6 +45,7 @@ tile.naturesaura.rf_converter.name=Energetic Aura Forge tile.naturesaura.moss_generator.name=Swamp Homi tile.naturesaura.time_changer.name=Shifting Sundial tile.naturesaura.generator_limit_remover.name=Creational Catalyst +tile.naturesaura.ender_crate.name=Ender Crate item.naturesaura.eye.name=Environmental Eye item.naturesaura.eye_improved.name=Environmental Ocular @@ -104,6 +105,7 @@ info.naturesaura.same_position=This seems to be the position from your notes... info.naturesaura.too_far=The distance seems too great... info.naturesaura.stored_pos_gone=Your notes seem out of date... info.naturesaura.empty=Empty +info.naturesaura.ender_crate=Ender Crate (%s) advancement.naturesaura.root=Nature's Aura advancement.naturesaura.root.desc=Becoming a magical botanist