diff --git a/src/main/java/electroblob/wizardry/WizardryGuiHandler.java b/src/main/java/electroblob/wizardry/WizardryGuiHandler.java index 69aa420f..01d8d68a 100644 --- a/src/main/java/electroblob/wizardry/WizardryGuiHandler.java +++ b/src/main/java/electroblob/wizardry/WizardryGuiHandler.java @@ -7,6 +7,7 @@ import electroblob.wizardry.item.ItemSpellBook; import electroblob.wizardry.item.ItemWizardHandbook; import electroblob.wizardry.tileentity.TileEntityArcaneWorkbench; import electroblob.wizardry.tileentity.TileEntityBookshelf; +import electroblob.wizardry.tileentity.TileEntityLectern; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; @@ -23,6 +24,7 @@ public class WizardryGuiHandler implements IGuiHandler { public static final int WIZARD_HANDBOOK = nextGuiId++; public static final int PORTABLE_CRAFTING = nextGuiId++; public static final int BOOKSHELF = nextGuiId++; + public static final int LECTERN = nextGuiId++; @Override public Object getServerGuiElement(int id, EntityPlayer player, World world, int x, int y, int z){ @@ -87,6 +89,14 @@ public class WizardryGuiHandler implements IGuiHandler { (TileEntityBookshelf)tileEntity); } + }else if(id == LECTERN){ + + TileEntity tileEntity = world.getTileEntity(new BlockPos(x, y, z)); + + if(tileEntity instanceof TileEntityLectern){ + return new electroblob.wizardry.client.gui.GuiLectern((TileEntityLectern)tileEntity); + } + } return null; diff --git a/src/main/java/electroblob/wizardry/block/BlockBookshelf.java b/src/main/java/electroblob/wizardry/block/BlockBookshelf.java index 9fc4c90a..ee4de190 100644 --- a/src/main/java/electroblob/wizardry/block/BlockBookshelf.java +++ b/src/main/java/electroblob/wizardry/block/BlockBookshelf.java @@ -13,6 +13,7 @@ import net.minecraft.block.state.BlockStateContainer; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; import net.minecraft.inventory.InventoryHelper; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; @@ -22,8 +23,11 @@ import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; import net.minecraftforge.common.property.IExtendedBlockState; import net.minecraftforge.common.property.Properties; +import org.apache.commons.lang3.ArrayUtils; import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.List; public class BlockBookshelf extends BlockHorizontal implements ITileEntityProvider { @@ -134,4 +138,37 @@ public class BlockBookshelf extends BlockHorizontal implements ITileEntityProvid } } + /** + * Returns a list of nearby bookshelves' inventories, where 'bookshelves' are any tile entities with inventories + * whose blocks are specified in the config file under the {@code bookshelfBlocks} option. + * @param world The world to search in + * @param centre The position to search around + * @param exclude Any tile entities that should be excluded from the returned list + * @return A list of nearby {@link IInventory} objects that count as valid bookshelves + */ + public static List findNearbyBookshelves(World world, BlockPos centre, TileEntity... exclude){ + + List bookshelves = new ArrayList<>(); + + int searchRadius = 4; // TODO: Config option for this + + for(int x = -searchRadius; x <= searchRadius; x++){ + for(int y = -searchRadius; y <= searchRadius; y++){ + for(int z = -searchRadius; z <= searchRadius; z++){ + + BlockPos pos = centre.add(x, y, z); + // TODO: Config option for allowed containers + if(world.getBlockState(pos).getBlock() instanceof BlockBookshelf){ + TileEntity te = world.getTileEntity(pos); + if(te instanceof IInventory && !ArrayUtils.contains(exclude, te)) bookshelves.add((IInventory)te); + } + + } + } + } + + return bookshelves; + + } + } diff --git a/src/main/java/electroblob/wizardry/block/BlockLectern.java b/src/main/java/electroblob/wizardry/block/BlockLectern.java new file mode 100644 index 00000000..922c4118 --- /dev/null +++ b/src/main/java/electroblob/wizardry/block/BlockLectern.java @@ -0,0 +1,122 @@ +package electroblob.wizardry.block; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.WizardryGuiHandler; +import electroblob.wizardry.registry.WizardryTabs; +import electroblob.wizardry.tileentity.TileEntityLectern; +import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.ParticleBuilder.Type; +import net.minecraft.block.BlockHorizontal; +import net.minecraft.block.ITileEntityProvider; +import net.minecraft.block.material.Material; +import net.minecraft.block.state.BlockFaceShape; +import net.minecraft.block.state.BlockStateContainer; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.EntityLivingBase; +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.IBlockAccess; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import javax.annotation.Nullable; +import java.util.Random; + +public class BlockLectern extends BlockHorizontal implements ITileEntityProvider { + + public BlockLectern(){ + super(Material.WOOD); + this.setDefaultState(this.blockState.getBaseState().withProperty(FACING, EnumFacing.NORTH)); + this.setCreativeTab(WizardryTabs.WIZARDRY); + } + + @Override + protected BlockStateContainer createBlockState(){ + return new BlockStateContainer.Builder(this).add(FACING).build(); + } + + @Override + public IBlockState getStateFromMeta(int meta){ + EnumFacing enumfacing = EnumFacing.byIndex(meta); + if(enumfacing.getAxis() == EnumFacing.Axis.Y) enumfacing = EnumFacing.NORTH; + return this.getDefaultState().withProperty(FACING, enumfacing); + } + + @Override + public int getMetaFromState(IBlockState state){ + return state.getValue(FACING).getIndex(); + } + + @Override + @SideOnly(Side.CLIENT) + public void randomDisplayTick(IBlockState state, World world, BlockPos pos, Random rand){ + + EntityPlayer entityplayer = world.getClosestPlayer(pos.getX() + 0.5, pos.getY() + 0.5, + pos.getZ() + 0.5, TileEntityLectern.BOOK_OPEN_DISTANCE, false); + + if(entityplayer != null){ + ParticleBuilder.create(Type.DUST).pos(pos.getX() + rand.nextFloat(), pos.getY() + 1, pos.getZ() + rand.nextFloat()) + .vel(0, 0.03, 0).clr(1, 1, 0.65f).fade(0.7f, 0, 1).shaded(false).spawn(world); + } + } + + @Override + public boolean isOpaqueCube(IBlockState state){ + return false; + } + + @Override + public boolean isFullCube(IBlockState state){ + return false; + } + + @Override + public boolean isFullBlock(IBlockState state){ + return false; + } + + @Override + public boolean isNormalCube(IBlockState state){ + return false; + } + + @Override + public boolean canPlaceTorchOnTop(IBlockState state, IBlockAccess world, BlockPos pos){ + return false; + } + + @Override + public BlockFaceShape getBlockFaceShape(IBlockAccess world, IBlockState state, BlockPos pos, EnumFacing face){ + return face == EnumFacing.DOWN ? BlockFaceShape.SOLID : BlockFaceShape.UNDEFINED; + } + + @Override + public IBlockState getStateForPlacement(World world, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer){ + return this.getDefaultState().withProperty(FACING, placer.getHorizontalFacing().getOpposite()); + } + + @Nullable + @Override + public TileEntity createNewTileEntity(World world, int meta){ + return new TileEntityLectern(); + } + + @Override + public boolean onBlockActivated(World world, BlockPos pos, IBlockState block, EntityPlayer player, EnumHand hand, + EnumFacing side, float hitX, float hitY, float hitZ){ + + TileEntity tileEntity = world.getTileEntity(pos); + + if(tileEntity == null || player.isSneaking()){ + return false; + } + + player.openGui(Wizardry.instance, WizardryGuiHandler.LECTERN, world, pos.getX(), pos.getY(), pos.getZ()); + return true; + } + +} diff --git a/src/main/java/electroblob/wizardry/client/ClientProxy.java b/src/main/java/electroblob/wizardry/client/ClientProxy.java index b81987be..64e746d7 100644 --- a/src/main/java/electroblob/wizardry/client/ClientProxy.java +++ b/src/main/java/electroblob/wizardry/client/ClientProxy.java @@ -32,10 +32,7 @@ import electroblob.wizardry.packet.*; import electroblob.wizardry.registry.Spells; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.spell.*; -import electroblob.wizardry.tileentity.TileEntityArcaneWorkbench; -import electroblob.wizardry.tileentity.TileEntityMagicLight; -import electroblob.wizardry.tileentity.TileEntityShrineCore; -import electroblob.wizardry.tileentity.TileEntityStatue; +import electroblob.wizardry.tileentity.*; import electroblob.wizardry.util.ParticleBuilder; import electroblob.wizardry.util.ParticleBuilder.Type; import electroblob.wizardry.util.WandHelper; @@ -310,6 +307,7 @@ public class ClientProxy extends CommonProxy { public void registerParticles(){ // I'll be a good programmer and use the API method rather than the one above. Lead by example, as they say... ParticleWizardry.registerParticle(Type.BEAM, ParticleBeam::new); + ParticleWizardry.registerParticle(Type.BLOCK_HIGHLIGHT, ParticleBlockHighlight::new); ParticleWizardry.registerParticle(Type.BUFF, ParticleBuff::new); ParticleWizardry.registerParticle(Type.DARK_MAGIC, ParticleDarkMagic::new); ParticleWizardry.registerParticle(Type.DUST, ParticleDust::new); @@ -762,6 +760,7 @@ public class ClientProxy extends CommonProxy { ClientRegistry.bindTileEntitySpecialRenderer(TileEntityArcaneWorkbench.class, new RenderArcaneWorkbench()); ClientRegistry.bindTileEntitySpecialRenderer(TileEntityStatue.class, renderStatue = new RenderStatue()); ClientRegistry.bindTileEntitySpecialRenderer(TileEntityMagicLight.class, new RenderMagicLight()); + ClientRegistry.bindTileEntitySpecialRenderer(TileEntityLectern.class, new RenderLectern()); } } \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/client/gui/GuiArcaneWorkbench.java b/src/main/java/electroblob/wizardry/client/gui/GuiArcaneWorkbench.java index 28901598..245390eb 100644 --- a/src/main/java/electroblob/wizardry/client/gui/GuiArcaneWorkbench.java +++ b/src/main/java/electroblob/wizardry/client/gui/GuiArcaneWorkbench.java @@ -17,6 +17,7 @@ import electroblob.wizardry.packet.WizardryPacketHandler; import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.spell.Spell; import electroblob.wizardry.tileentity.TileEntityArcaneWorkbench; +import electroblob.wizardry.util.ISpellSortable; import electroblob.wizardry.util.WandHelper; import net.minecraft.client.Minecraft; import net.minecraft.client.audio.PositionedSoundRecord; @@ -115,9 +116,9 @@ public class GuiArcaneWorkbench extends GuiContainer { this.buttonList.clear(); this.buttonList.add(this.applyBtn = new GuiButtonApply(0, this.width / 2 + 64, this.height / 2 + 3)); - this.buttonList.add(new GuiButtonSort(1, this.guiLeft - 44, this.guiTop + 8, ContainerArcaneWorkbench.SortType.TIER)); - this.buttonList.add(new GuiButtonSort(2, this.guiLeft - 31, this.guiTop + 8, ContainerArcaneWorkbench.SortType.ELEMENT)); - this.buttonList.add(new GuiButtonSort(3, this.guiLeft - 18, this.guiTop + 8, ContainerArcaneWorkbench.SortType.ALPHABETICAL)); + this.buttonList.add(new GuiButtonSpellSort(1, this.guiLeft - 44, this.guiTop + 8, ISpellSortable.SortType.TIER, arcaneWorkbenchContainer, this)); + this.buttonList.add(new GuiButtonSpellSort(2, this.guiLeft - 31, this.guiTop + 8, ISpellSortable.SortType.ELEMENT, arcaneWorkbenchContainer, this)); + this.buttonList.add(new GuiButtonSpellSort(3, this.guiLeft - 18, this.guiTop + 8, ISpellSortable.SortType.ALPHABETICAL, arcaneWorkbenchContainer, this)); this.searchField = new GuiTextField(0, this.fontRenderer, this.guiLeft - 113, this.guiTop + 22, 104, this.fontRenderer.FONT_HEIGHT); this.searchField.setMaxStringLength(50); @@ -294,7 +295,7 @@ public class GuiArcaneWorkbench extends GuiContainer { // Scroll bar DrawingUtils.drawTexturedRect(guiLeft - BOOKSHELF_UI_WIDTH + SCROLL_BAR_LEFT, guiTop + SCROLL_BAR_TOP + (int)(scroll * (SCROLL_BAR_HEIGHT - SCROLL_HANDLE_HEIGHT) + 0.5f), - getMaxScrollRows() > 0 ? 30 : 30 + SCROLL_BAR_WIDTH, 476, + getMaxScrollRows() > 0 ? 0 : SCROLL_BAR_WIDTH, 476, SCROLL_BAR_WIDTH, SCROLL_HANDLE_HEIGHT, TEXTURE_WIDTH, TEXTURE_HEIGHT); // Tooltip only drawn if there is a wand @@ -507,7 +508,7 @@ public class GuiArcaneWorkbench extends GuiContainer { } } - this.buttonList.forEach(b -> b.drawButtonForegroundLayer(mouseX, mouseY)); + this.buttonList.forEach(b -> b.drawButtonForegroundLayer(mouseX - guiLeft, mouseY - guiTop)); } // Controls @@ -528,7 +529,7 @@ public class GuiArcaneWorkbench extends GuiContainer { animationTimer = 20; } - if(button instanceof GuiButtonSort) this.arcaneWorkbenchContainer.setSortType(((GuiButtonSort)button).sortType); + if(button instanceof GuiButtonSpellSort) this.arcaneWorkbenchContainer.setSortType(((GuiButtonSpellSort)button).sortType); } } @@ -587,45 +588,6 @@ public class GuiArcaneWorkbench extends GuiContainer { } } - // Nested classes - - private class GuiButtonSort extends GuiButton { - - private final ContainerArcaneWorkbench.SortType sortType; - - public GuiButtonSort(int id, int x, int y, ContainerArcaneWorkbench.SortType sortType){ - super(id, x, y, 10, 10, I18n.format("container." + Wizardry.MODID + ":arcane_workbench.sort_" + sortType.name)); - this.sortType = sortType; - } - - @Override - public void drawButton(Minecraft minecraft, int mouseX, int mouseY, float partialTicks){ - - if(this.visible){ - - // Whether the button is highlighted - this.hovered = mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.width && mouseY < this.y + this.height; - - int k = 0; - int l = 476 + this.sortType.ordinal() * this.height; - - if(sortType == GuiArcaneWorkbench.this.arcaneWorkbenchContainer.getSortType()){ - k += this.width; - if(GuiArcaneWorkbench.this.arcaneWorkbenchContainer.isSortDescending()) k += this.width; - } - - DrawingUtils.drawTexturedRect(this.x, this.y, k, l, this.width, this.height, TEXTURE_WIDTH, TEXTURE_HEIGHT); - - } - } - - @Override - public void drawButtonForegroundLayer(int mouseX, int mouseY){ - if(hovered) drawHoveringText(this.displayString, mouseX - guiLeft, mouseY - guiTop); - } - - } - private static class GuiButtonApply extends GuiButton { public GuiButtonApply(int id, int x, int y){ diff --git a/src/main/java/electroblob/wizardry/client/gui/GuiButtonSpellSort.java b/src/main/java/electroblob/wizardry/client/gui/GuiButtonSpellSort.java new file mode 100644 index 00000000..8e5c8439 --- /dev/null +++ b/src/main/java/electroblob/wizardry/client/gui/GuiButtonSpellSort.java @@ -0,0 +1,57 @@ +package electroblob.wizardry.client.gui; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.client.DrawingUtils; +import electroblob.wizardry.util.ISpellSortable; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.resources.I18n; +import net.minecraft.util.ResourceLocation; + +public class GuiButtonSpellSort extends GuiButton { + + private static final ResourceLocation TEXTURE = new ResourceLocation(Wizardry.MODID, "textures/gui/spell_sort_buttons.png"); + private static final int TEXTURE_WIDTH = 32; + private static final int TEXTURE_HEIGHT = 32; + + public final ISpellSortable.SortType sortType; + + private final ISpellSortable sortable; + private final GuiScreen parent; + + public GuiButtonSpellSort(int id, int x, int y, ISpellSortable.SortType sortType, ISpellSortable sortable, GuiScreen parent){ + super(id, x, y, 10, 10, I18n.format("container." + Wizardry.MODID + ":arcane_workbench.sort_" + sortType.name)); + this.sortType = sortType; + this.sortable = sortable; + this.parent = parent; + } + + @Override + public void drawButton(Minecraft minecraft, int mouseX, int mouseY, float partialTicks){ + + if(this.visible){ + + // Whether the button is highlighted + this.hovered = mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.width && mouseY < this.y + this.height; + + int k = 0; + int l = this.sortType.ordinal() * this.height; + + if(sortType == sortable.getSortType()){ + k += this.width; + if(sortable.isSortDescending()) k += this.width; + } + + parent.mc.getTextureManager().bindTexture(TEXTURE); + DrawingUtils.drawTexturedRect(this.x, this.y, k, l, this.width, this.height, TEXTURE_WIDTH, TEXTURE_HEIGHT); + + } + } + + @Override + public void drawButtonForegroundLayer(int mouseX, int mouseY){ + if(hovered) parent.drawHoveringText(this.displayString, mouseX, mouseY); + } + +} diff --git a/src/main/java/electroblob/wizardry/client/gui/handbook/GuiButtonTurnPage.java b/src/main/java/electroblob/wizardry/client/gui/GuiButtonTurnPage.java similarity index 69% rename from src/main/java/electroblob/wizardry/client/gui/handbook/GuiButtonTurnPage.java rename to src/main/java/electroblob/wizardry/client/gui/GuiButtonTurnPage.java index 662e71a1..ef45cae1 100644 --- a/src/main/java/electroblob/wizardry/client/gui/handbook/GuiButtonTurnPage.java +++ b/src/main/java/electroblob/wizardry/client/gui/GuiButtonTurnPage.java @@ -1,6 +1,5 @@ -package electroblob.wizardry.client.gui.handbook; +package electroblob.wizardry.client.gui; -import electroblob.wizardry.Wizardry; import electroblob.wizardry.client.DrawingUtils; import electroblob.wizardry.registry.WizardrySounds; import net.minecraft.client.Minecraft; @@ -11,12 +10,12 @@ import net.minecraft.client.renderer.GlStateManager; import net.minecraft.util.ResourceLocation; //@SideOnly(Side.CLIENT) -class GuiButtonTurnPage extends GuiButton { +public class GuiButtonTurnPage extends GuiButton { - static final int WIDTH = 20; - static final int HEIGHT = 12; + public static final int WIDTH = 20; + public static final int HEIGHT = 12; - enum Type { + public enum Type { NEXT_PAGE(0, 196), PREVIOUS_PAGE(0, 208), @@ -34,11 +33,15 @@ class GuiButtonTurnPage extends GuiButton { public final Type type; - private static final ResourceLocation texture = new ResourceLocation(Wizardry.MODID, "textures/gui/handbook.png"); + private final ResourceLocation texture; + private final int textureWidth, textureHeight; - public GuiButtonTurnPage(int id, int x, int y, Type type){ + public GuiButtonTurnPage(int id, int x, int y, Type type, ResourceLocation texture, int textureWidth, int textureHeight){ super(id, x, y, WIDTH, HEIGHT, ""); this.type = type; + this.texture = texture; + this.textureWidth = textureWidth; + this.textureHeight = textureHeight; } @Override @@ -50,12 +53,13 @@ class GuiButtonTurnPage extends GuiButton { public void drawButton(Minecraft minecraft, int mouseX, int mouseY, float partialTicks){ if(this.visible){ - + boolean flag = mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.width && mouseY < this.y + this.height; GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); minecraft.getTextureManager().bindTexture(texture); - DrawingUtils.drawTexturedRect(this.x, this.y, flag ? type.u + width : type.u, type.v, width, height, 512, 256); + DrawingUtils.drawTexturedRect(this.x, this.y, flag ? type.u + width : type.u, type.v, width, height, textureWidth, textureHeight); } } + } diff --git a/src/main/java/electroblob/wizardry/client/gui/GuiLectern.java b/src/main/java/electroblob/wizardry/client/gui/GuiLectern.java new file mode 100644 index 00000000..6c69b6f2 --- /dev/null +++ b/src/main/java/electroblob/wizardry/client/gui/GuiLectern.java @@ -0,0 +1,467 @@ +package electroblob.wizardry.client.gui; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.block.BlockBookshelf; +import electroblob.wizardry.client.DrawingUtils; +import electroblob.wizardry.client.gui.GuiButtonTurnPage.Type; +import electroblob.wizardry.data.SpellGlyphData; +import electroblob.wizardry.item.ItemSpellBook; +import electroblob.wizardry.packet.PacketLectern; +import electroblob.wizardry.packet.WizardryPacketHandler; +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.Spell; +import electroblob.wizardry.tileentity.TileEntityLectern; +import electroblob.wizardry.util.ISpellSortable; +import electroblob.wizardry.util.ParticleBuilder; +import electroblob.wizardry.util.WizardryUtilities; +import net.minecraft.client.Minecraft; +import net.minecraft.client.audio.PositionedSoundRecord; +import net.minecraft.client.audio.SoundHandler; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiTextField; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.resources.I18n; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.network.play.client.CPacketCloseWindow; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.stream.Collectors; + +public class GuiLectern extends GuiSpellInfo implements ISpellSortable { + + private static final ResourceLocation TEXTURE = new ResourceLocation(Wizardry.MODID, "textures/gui/lectern.png"); + /** The distance of the page buttons from the bottom outside corners of the GUI. */ + private static final int PAGE_BUTTON_INSET_X = 22, PAGE_BUTTON_INSET_Y = 13; + /** The distance between adjacent page turn buttons. */ + private static final int PAGE_BUTTON_SPACING = 20; + /** The distance of the sort buttons from the top left corner of the GUI. */ + private static final int SORT_BUTTON_INSET_X = 96, SORT_BUTTON_INSET_Y = 20; + /** The distance between adjacent sort buttons. */ + private static final int SORT_BUTTON_SPACING = 13; + /** The distance of the spell buttons from the top outside corners of the GUI. */ + private static final int SPELL_BUTTON_INSET_X = 23, SPELL_BUTTON_INSET_Y = 44; + /** The distance between adjacent spell buttons (in both x and y). */ + private static final int SPELL_BUTTON_SPACING = 38; + + private static final int SPELL_ROWS = 3, SPELL_COLUMNS = 3; + public static final int SPELL_BUTTON_COUNT = SPELL_ROWS * SPELL_COLUMNS * 2; // x2 because there are 2 pages + + private final TileEntityLectern lectern; + + private GuiButton nextPageButton; + private GuiButton prevPageButton; + private GuiButton lastPageButton; + private GuiButton firstPageButton; + private GuiButton indexButton; + private GuiButton locateButton; + + private GuiButton[] sortButtons = new GuiButton[3]; + private GuiButtonSpell[] spellButtons = new GuiButtonSpell[SPELL_BUTTON_COUNT]; + + /** The spell currently being viewed, or null if the index is being viewed. */ + private Spell currentSpell; + /** The available spells in nearby bookshelves; should not contain duplicates. */ + private List availableSpells = new ArrayList<>(); + /** The spells matching the current search criteria, sorted according to the current sort settings. Will be a subset + * of {@link GuiLectern#availableSpells}. */ + private List matchingSpells; + + private ISpellSortable.SortType sortType = ISpellSortable.SortType.TIER; + private boolean sortDescending = false; + + private GuiTextField searchField; + private boolean searchNeedsClearing; + + private int currentPage = 0; + + public GuiLectern(TileEntityLectern lectern){ + super(288, 180); + this.lectern = lectern; + this.currentSpell = lectern.currentSpell; + this.setTextureSize(512, 512); + } + + @Override + public Spell getSpell(){ + return currentSpell; + } + + @Override + public ResourceLocation getTexture(){ + return TEXTURE; + } + + @Override + public SortType getSortType(){ + return sortType; + } + + @Override + public boolean isSortDescending(){ + return sortDescending; + } + + private int getPageCount(){ + return MathHelper.ceil((float)matchingSpells.size() / SPELL_BUTTON_COUNT); + } + + private Spell getSpellForButton(GuiButtonSpell button){ + return matchingSpells.get(currentPage * SPELL_BUTTON_COUNT + button.index); + } + + @Override + public void initGui(){ + + super.initGui(); + + updateAvailableSpells(); + + final int left = this.width / 2 - this.xSize / 2; + final int top = this.height / 2 - this.ySize / 2; + + int buttonID = 0; + + // Page buttons + this.buttonList.add(nextPageButton = new GuiButtonTurnPage(buttonID++, left + xSize - PAGE_BUTTON_INSET_X - GuiButtonTurnPage.WIDTH, + top + ySize - PAGE_BUTTON_INSET_Y - GuiButtonTurnPage.HEIGHT, Type.NEXT_PAGE, TEXTURE, textureWidth, textureHeight)); + + this.buttonList.add(prevPageButton = new GuiButtonTurnPage(buttonID++, left + PAGE_BUTTON_INSET_X, + top + ySize - PAGE_BUTTON_INSET_Y - GuiButtonTurnPage.HEIGHT, Type.PREVIOUS_PAGE, TEXTURE, textureWidth, textureHeight)); + + this.buttonList.add(lastPageButton = new GuiButtonTurnPage(buttonID++, left + xSize - PAGE_BUTTON_INSET_X - GuiButtonTurnPage.WIDTH - PAGE_BUTTON_SPACING, + top + ySize - PAGE_BUTTON_INSET_Y - GuiButtonTurnPage.HEIGHT, Type.NEXT_SECTION, TEXTURE, textureWidth, textureHeight)); + + this.buttonList.add(firstPageButton = new GuiButtonTurnPage(buttonID++, left + PAGE_BUTTON_INSET_X + PAGE_BUTTON_SPACING, + top + ySize - PAGE_BUTTON_INSET_Y - GuiButtonTurnPage.HEIGHT, Type.PREVIOUS_SECTION, TEXTURE, textureWidth, textureHeight)); + + this.buttonList.add(indexButton = new GuiButtonTurnPage(buttonID++, left + xSize/2 - 23, + top + ySize - PAGE_BUTTON_INSET_Y - GuiButtonTurnPage.HEIGHT, Type.CONTENTS, TEXTURE, textureWidth, textureHeight)); + + this.buttonList.add(locateButton = new GuiButtonLocateBook(buttonID++, left + xSize/2 - 34, + top + ySize - PAGE_BUTTON_INSET_Y - GuiButtonTurnPage.HEIGHT)); + + // Sort buttons + for(SortType sortType : SortType.values()){ + this.buttonList.add(sortButtons[sortType.ordinal()] = new GuiButtonSpellSort(buttonID++, + left + SORT_BUTTON_INSET_X + SORT_BUTTON_SPACING * sortType.ordinal(), + top + SORT_BUTTON_INSET_Y, sortType, this, this)); + } + + // Spell buttons + for(int i = 0; i < SPELL_BUTTON_COUNT; i++){ + + int row = i % SPELL_COLUMNS; + int column = (i / SPELL_COLUMNS) % SPELL_ROWS; + + int x = i < SPELL_BUTTON_COUNT/2 ? SPELL_BUTTON_INSET_X + row * SPELL_BUTTON_SPACING + : xSize - SPELL_BUTTON_INSET_X - GuiButtonSpell.WIDTH - (2-row) * SPELL_BUTTON_SPACING; + int y = SPELL_BUTTON_INSET_Y + column * SPELL_BUTTON_SPACING; + + this.buttonList.add(spellButtons[i] = new GuiButtonSpell(buttonID++, left + x, top + y, i)); + } + + this.searchField = new GuiTextField(0, this.fontRenderer, left + 157, top + 21, 106, this.fontRenderer.FONT_HEIGHT); + this.searchField.setMaxStringLength(50); + this.searchField.setEnableBackgroundDrawing(false); + this.searchField.setVisible(true); + this.searchField.setTextColor(16777215); + this.searchField.setCanLoseFocus(false); + this.searchField.setFocused(true); + + updateMatchingSpells(); + updateButtonVisiblity(); + + } + + @Override + public void onGuiClosed(){ + WizardryPacketHandler.net.sendToServer(new PacketLectern.Message(lectern.getPos(), currentSpell)); + super.onGuiClosed(); + } + + @Override + protected void drawBackgroundLayer(int left, int top, int mouseX, int mouseY){ + if(currentSpell == Spells.none){ + drawIndexPage(left, top); + }else{ + super.drawBackgroundLayer(left, top, mouseX, mouseY); + } + } + + @Override + protected void drawForegroundLayer(int left, int top, int mouseX, int mouseY){ + + if(currentSpell == Spells.none){ + this.fontRenderer.drawString(I18n.format("gui." + Wizardry.MODID + ":lectern.title"), + left + 20, top + SORT_BUTTON_INSET_Y, 0); + }else{ + super.drawForegroundLayer(left, top, mouseX, mouseY); + } + + this.buttonList.forEach(b -> b.drawButtonForegroundLayer(mouseX, mouseY)); + } + + private void drawIndexPage(int left, int top){ + + for(int i = 0; i < SPELL_BUTTON_COUNT; i++){ + + int index = currentPage * SPELL_BUTTON_COUNT + i; + Spell spell = index < matchingSpells.size() ? matchingSpells.get(index) : Spells.none; + boolean discovered = Wizardry.proxy.shouldDisplayDiscovered(spell, null); + + Minecraft.getMinecraft().renderEngine.bindTexture(discovered ? spell.getIcon() : Spells.none.getIcon()); + + int row = i % SPELL_COLUMNS; + int column = (i / SPELL_COLUMNS) % SPELL_ROWS; + + int x = i < SPELL_BUTTON_COUNT/2 ? SPELL_BUTTON_INSET_X + row * SPELL_BUTTON_SPACING + : xSize - SPELL_BUTTON_INSET_X - GuiButtonSpell.WIDTH - (2-row) * SPELL_BUTTON_SPACING; + int y = SPELL_BUTTON_INSET_Y + column * SPELL_BUTTON_SPACING; + + DrawingUtils.drawTexturedRect(left + x + 1, top + y + 1, 0, 0, 32, 32, 32, 32); + } + + mc.renderEngine.bindTexture(getTexture()); + DrawingUtils.drawTexturedRect(left, top, 0, 256, xSize, ySize, textureWidth, textureHeight); + + this.searchField.drawTextBox(); + + GlStateManager.color(1, 1, 1, 1); + mc.renderEngine.bindTexture(getTexture()); + + } + + @Override + protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { + super.mouseClicked(mouseX, mouseY, mouseButton); + searchNeedsClearing = true; + } + + @Override + protected void actionPerformed(GuiButton button){ + + int lastPage = getPageCount() - 1; + + if(button == indexButton){ + currentSpell = Spells.none; + currentPage = 0; + + }else if(button == locateButton){ + // Close the GUI + this.mc.player.connection.sendPacket(new CPacketCloseWindow(this.mc.player.openContainer.windowId)); + this.mc.displayGuiScreen(null); + + // Find the location(s) of the current spell's book(s) and highlight them + for(IInventory bookshelf : BlockBookshelf.findNearbyBookshelves(lectern.getWorld(), lectern.getPos())){ + + for(int i = 0; i < bookshelf.getSizeInventory(); i++){ + + ItemStack stack = bookshelf.getStackInSlot(i); + + if(stack.getItem() instanceof ItemSpellBook){ + + Spell spell = Spell.byMetadata(stack.getMetadata()); + + if(spell == this.currentSpell){ + BlockPos pos = (((TileEntity)bookshelf).getPos()); + for(EnumFacing side : EnumFacing.VALUES){ + ParticleBuilder.create(ParticleBuilder.Type.BLOCK_HIGHLIGHT).pos( + WizardryUtilities.getFaceCentre(pos, side) + .add(new Vec3d(side.getDirectionVec()) + .scale(WizardryUtilities.ANTI_Z_FIGHTING_OFFSET))) + .face(side).clr(0.9f, 0.5f, 0.8f).fade(0.7f, 0, 1).spawn(mc.world); + } + break; // This bookshelf has the spell, skip to the next bookshelf + } + } + } + } + + }else if(button == nextPageButton){ + if(currentPage < lastPage) currentPage++; + + }else if(button == prevPageButton){ + if(currentPage > 0) currentPage--; + + }else if(button == lastPageButton){ + currentPage = lastPage; + + }else if(button == firstPageButton){ + currentPage = 0; + + }else if(button instanceof GuiButtonSpell){ + currentSpell = getSpellForButton((GuiButtonSpell)button); + + }else if(button instanceof GuiButtonSpellSort){ + + SortType sortType = (((GuiButtonSpellSort)button).sortType); + + if(this.sortType == sortType){ + this.sortDescending = !this.sortDescending; + }else{ + this.sortType = sortType; + this.sortDescending = false; + } + + updateMatchingSpells(); + } + + updateButtonVisiblity(); + + } + + @Override + protected void keyTyped(char typedChar, int keyCode) throws IOException { + + if(this.searchNeedsClearing){ + this.searchNeedsClearing = false; + this.searchField.setText(""); + this.currentPage = 0; + } + + if(this.searchField.textboxKeyTyped(typedChar, keyCode)){ + this.currentPage = 0; + updateMatchingSpells(); + updateButtonVisiblity(); + }else{ + super.keyTyped(typedChar, keyCode); + } + } + + private void updateButtonVisiblity(){ + + if(currentSpell == Spells.none){ + + this.searchField.setVisible(true); + + int lastPage = getPageCount() - 1; + + prevPageButton.visible = currentPage > 0; + firstPageButton.visible = currentPage > 0; + nextPageButton.visible = currentPage < lastPage; + lastPageButton.visible = currentPage < lastPage; + + indexButton.visible = false; + locateButton.visible = false; + + for(GuiButton button : sortButtons) button.visible = true; + + for(GuiButtonSpell button : spellButtons){ + button.visible = currentPage * SPELL_BUTTON_COUNT + button.index < matchingSpells.size(); + } + + }else{ + this.searchField.setVisible(false); + this.buttonList.forEach(b -> b.visible = false); // Hide all buttons... + indexButton.visible = true; // ... except the index button and locate button + locateButton.visible = true; + } + } + + private void updateMatchingSpells(){ + matchingSpells = availableSpells.stream() + .filter(s -> s.matches(searchField.getText().toLowerCase(Locale.ROOT))) + .sorted(sortDescending ? sortType.comparator.reversed() : sortType.comparator) + .collect(Collectors.toList()); + } + + // TODO: Call this when a bookshelf is added or removed + // TODO: Config option to always display all spells when in creative + private void updateAvailableSpells(){ + + availableSpells.clear(); + + // No need to exclude the lectern TE because it's not an IInventory! + for(IInventory bookshelf : BlockBookshelf.findNearbyBookshelves(lectern.getWorld(), lectern.getPos())){ + + for(int i=0; i= this.x && mouseY >= this.y && mouseX < this.x + this.width && mouseY < this.y + this.height; + GlStateManager.color(1, 1, 1, 1); + minecraft.getTextureManager().bindTexture(TEXTURE); + + DrawingUtils.drawTexturedRect(this.x, this.y, flag ? width : 0, 184, width, height, textureWidth, textureHeight); + } + } + + } + + private class GuiButtonSpell extends GuiButtonInvisible { + + private static final int WIDTH = 34, HEIGHT = 34; + + private final int index; + + public GuiButtonSpell(int id, int x, int y, int index){ + super(id, x, y, WIDTH, HEIGHT); + this.index = index; + } + + @Override + public void playPressSound(SoundHandler soundHandler){ + soundHandler.playSound(PositionedSoundRecord.getMasterRecord(WizardrySounds.MISC_PAGE_TURN, 1)); + } + + @Override + public void drawButton(Minecraft minecraft, int mouseX, int mouseY, float partialTicks){ + if(visible){ + super.drawButton(minecraft, mouseX, mouseY, partialTicks); + if(hovered){ + mc.renderEngine.bindTexture(getTexture()); + DrawingUtils.drawTexturedRect(x, y, 40, 180, width, height, textureWidth, textureHeight); + } + } + } + + @Override + public void drawButtonForegroundLayer(int mouseX, int mouseY){ + if(visible && hovered){ + Spell spell = getSpellForButton(this); + if(Wizardry.proxy.shouldDisplayDiscovered(spell, null)){ + drawHoveringText(Collections.singletonList(spell.getDisplayName()), mouseX, mouseY, fontRenderer); + }else{ + drawHoveringText(Collections.singletonList(SpellGlyphData.getGlyphName(spell, mc.world)), + mouseX, mouseY, mc.standardGalacticFontRenderer); + } + } + } + + } + +} diff --git a/src/main/java/electroblob/wizardry/client/gui/GuiSpellBook.java b/src/main/java/electroblob/wizardry/client/gui/GuiSpellBook.java index 3e26c194..d46a9886 100644 --- a/src/main/java/electroblob/wizardry/client/gui/GuiSpellBook.java +++ b/src/main/java/electroblob/wizardry/client/gui/GuiSpellBook.java @@ -1,113 +1,35 @@ package electroblob.wizardry.client.gui; -import electroblob.wizardry.Wizardry; -import electroblob.wizardry.client.DrawingUtils; -import electroblob.wizardry.constants.Tier; -import electroblob.wizardry.data.SpellGlyphData; -import electroblob.wizardry.data.WizardData; import electroblob.wizardry.item.ItemSpellBook; -import electroblob.wizardry.registry.Spells; -import electroblob.wizardry.registry.WizardrySounds; import electroblob.wizardry.spell.Spell; -import net.minecraft.client.Minecraft; -import net.minecraft.client.audio.PositionedSoundRecord; -import net.minecraft.client.gui.GuiScreen; -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.client.resources.I18n; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; -import org.lwjgl.input.Keyboard; +import net.minecraft.util.ResourceLocation; -public class GuiSpellBook extends GuiScreen { +public class GuiSpellBook extends GuiSpellInfo { - private int xSize, ySize; - private ItemSpellBook book; - private Spell spell; + private final ItemSpellBook book; + private final Spell spell; public GuiSpellBook(ItemStack stack){ - super(); - xSize = 288; - ySize = 180; - if(!(stack.getItem() instanceof ItemSpellBook)) throw new ClassCastException("Cannot create spell book GUI for item that does not extend ItemSpellBook!"); + + super(288, 180); + + if(!(stack.getItem() instanceof ItemSpellBook)){ + throw new ClassCastException("Cannot create spell book GUI for item that does not extend ItemSpellBook!"); + } + this.book = (ItemSpellBook)stack.getItem(); - this.spell = Spell.byMetadata(stack.getItemDamage()); + this.spell = (Spell.byMetadata(stack.getItemDamage())); } @Override - public void drawScreen(int par1, int par2, float par3){ - - int xPos = this.width / 2 - xSize / 2; - int yPos = this.height / 2 - this.ySize / 2; - - EntityPlayer player = Minecraft.getMinecraft().player; - - boolean discovered = true; - if(Wizardry.settings.discoveryMode && !player.isCreative() && WizardData.get(player) != null - && !WizardData.get(player).hasSpellBeenDiscovered(spell)){ - discovered = false; - } - - GlStateManager.color(1, 1, 1, 1); // Just in case - - // Draws spell illustration on opposite page, underneath the book so it shows through the hole. - Minecraft.getMinecraft().renderEngine.bindTexture(discovered ? spell.getIcon() : Spells.none.getIcon()); - DrawingUtils.drawTexturedRect(xPos + 146, yPos + 20, 0, 0, 128, 128, 128, 128); - - Minecraft.getMinecraft().renderEngine.bindTexture(book.getGuiTexture(spell)); - DrawingUtils.drawTexturedRect(xPos, yPos, 0, 0, xSize, ySize, xSize, 256); - - super.drawScreen(par1, par2, par3); - - if(discovered){ - this.fontRenderer.drawString(spell.getDisplayName(), xPos + 17, yPos + 15, 0); - this.fontRenderer.drawString(spell.getType().getDisplayName(), xPos + 17, yPos + 26, 0x777777); - }else{ - this.mc.standardGalacticFontRenderer.drawString(SpellGlyphData.getGlyphName(spell, player.world), xPos + 17, - yPos + 15, 0); - this.mc.standardGalacticFontRenderer.drawString(spell.getType().getDisplayName(), xPos + 17, yPos + 26, - 0x777777); - } - - // Novice is usually white but this doesn't show up - String tier = I18n.format("gui.ebwizardry:spell_book.tier", spell.getTier() == Tier.NOVICE ? - "\u00A77" + spell.getTier().getDisplayName() : spell.getTier().getDisplayNameWithFormatting()); - this.fontRenderer.drawString(tier, xPos + 17, yPos + 45, 0); - - String element = I18n.format("gui.ebwizardry:spell_book.element", spell.getElement().getFormattingCode() + spell.getElement().getDisplayName()); - if(!discovered) element = I18n.format("gui.ebwizardry:spell_book.element_undiscovered"); - this.fontRenderer.drawString(element, xPos + 17, yPos + 57, 0); - - String manaCost = I18n.format("gui.ebwizardry:spell_book.mana_cost", spell.getCost()); - if(spell.isContinuous) manaCost = I18n.format("gui.ebwizardry:spell_book.mana_cost_continuous", spell.getCost()); - if(!discovered) manaCost = I18n.format("gui.ebwizardry:spell_book.mana_cost_undiscovered"); - this.fontRenderer.drawString(manaCost, xPos + 17, yPos + 69, 0); - - if(discovered){ - this.fontRenderer.drawSplitString(spell.getDescription(), xPos + 17, yPos + 83, 118, 0); - }else{ - this.mc.standardGalacticFontRenderer.drawSplitString( - SpellGlyphData.getGlyphDescription(spell, player.world), xPos + 17, yPos + 83, 118, 0); - } + public Spell getSpell(){ + return spell; } @Override - public void initGui(){ - super.initGui(); - Keyboard.enableRepeatEvents(true); - this.buttonList.clear(); - - this.mc.getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(WizardrySounds.MISC_BOOK_OPEN, 1)); - } - - @Override - public void onGuiClosed(){ - super.onGuiClosed(); - Keyboard.enableRepeatEvents(false); - } - - @Override - public boolean doesGuiPauseGame(){ - return Wizardry.settings.booksPauseGame; + public ResourceLocation getTexture(){ + return book.getGuiTexture(spell); } } diff --git a/src/main/java/electroblob/wizardry/client/gui/GuiSpellInfo.java b/src/main/java/electroblob/wizardry/client/gui/GuiSpellInfo.java new file mode 100644 index 00000000..0bb77c4f --- /dev/null +++ b/src/main/java/electroblob/wizardry/client/gui/GuiSpellInfo.java @@ -0,0 +1,137 @@ +package electroblob.wizardry.client.gui; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.client.DrawingUtils; +import electroblob.wizardry.constants.Tier; +import electroblob.wizardry.data.SpellGlyphData; +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.registry.WizardrySounds; +import electroblob.wizardry.spell.Spell; +import net.minecraft.client.Minecraft; +import net.minecraft.client.audio.PositionedSoundRecord; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.resources.I18n; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.input.Keyboard; + +/** Abstract base class for both {@link GuiSpellBook} and {@link GuiLectern}. Centralises code common to both + * those classes. */ +public abstract class GuiSpellInfo extends GuiScreen { + + protected static final String TRANSLATION_KEY_PREFIX = "gui." + Wizardry.MODID + ":spell_book"; + + protected final int xSize, ySize; + protected int textureWidth = 512; + protected int textureHeight = 256; + + public GuiSpellInfo(int xSize, int ySize){ + super(); + this.xSize = xSize; + this.ySize = ySize; + } + + protected void setTextureSize(int width, int height){ + this.textureWidth = width; + this.textureHeight = height; + } + + /** Returns the spell to be displayed by this GUI. */ + public abstract Spell getSpell(); + + /** Returns the main texture for the background of this GUI. */ + public abstract ResourceLocation getTexture(); + + @Override + public void drawScreen(int mouseX, int mouseY, float partialTicks){ + int left = this.width/2 - xSize/2; + int top = this.height/2 - this.ySize/2; + this.drawBackgroundLayer(left, top, mouseX, mouseY); + super.drawScreen(mouseX, mouseY, partialTicks); // Just draws the buttons + this.drawForegroundLayer(left, top, mouseX, mouseY); + } + + /** + * Draws the background of the spell info GUI. This is called before buttons are drawn. + * @param left The x-coordinate of the left-hand edge of the GUI + * @param top The y-coordinate of the top edge of the GUI + * @param mouseX The current x position of the mouse pointer + * @param mouseY The current y position of the mouse pointer + */ + protected void drawBackgroundLayer(int left, int top, int mouseX, int mouseY){ + + boolean discovered = Wizardry.proxy.shouldDisplayDiscovered(getSpell(), null); + + GlStateManager.color(1, 1, 1, 1); // Just in case + + // Draws spell illustration on opposite page, underneath the book so it shows through the hole. + Minecraft.getMinecraft().renderEngine.bindTexture(discovered ? getSpell().getIcon() : Spells.none.getIcon()); + DrawingUtils.drawTexturedRect(left + 146, top + 20, 0, 0, 128, 128, 128, 128); + + Minecraft.getMinecraft().renderEngine.bindTexture(getTexture()); + DrawingUtils.drawTexturedRect(left, top, 0, 0, xSize, ySize, textureWidth, textureHeight); + } + + /** + * Draws the foreground of the spell info GUI. This is called after buttons are drawn. + * @param left The x-coordinate of the left-hand edge of the GUI + * @param top The y-coordinate of the top edge of the GUI + * @param mouseX The current x position of the mouse pointer + * @param mouseY The current y position of the mouse pointer + */ + protected void drawForegroundLayer(int left, int top, int mouseX, int mouseY){ + + boolean discovered = Wizardry.proxy.shouldDisplayDiscovered(getSpell(), null); + + if(discovered){ + this.fontRenderer.drawString(getSpell().getDisplayName(), left + 17, top + 15, 0); + this.fontRenderer.drawString(getSpell().getType().getDisplayName(), left + 17, top + 26, 0x777777); + }else{ + this.mc.standardGalacticFontRenderer.drawString(SpellGlyphData.getGlyphName(getSpell(), mc.world), left + 17, + top + 15, 0); + this.mc.standardGalacticFontRenderer.drawString(getSpell().getType().getDisplayName(), left + 17, top + 26, + 0x777777); + } + + // Novice is usually white but this doesn't show up + String tier = I18n.format(TRANSLATION_KEY_PREFIX + ".tier", getSpell().getTier() == Tier.NOVICE ? + "\u00A77" + getSpell().getTier().getDisplayName() : getSpell().getTier().getDisplayNameWithFormatting()); + this.fontRenderer.drawString(tier, left + 17, top + 45, 0); + + String element = I18n.format(TRANSLATION_KEY_PREFIX + ".element", getSpell().getElement().getFormattingCode() + getSpell().getElement().getDisplayName()); + if(!discovered) element = I18n.format(TRANSLATION_KEY_PREFIX + ".element_undiscovered"); + this.fontRenderer.drawString(element, left + 17, top + 57, 0); + + String manaCost = I18n.format(TRANSLATION_KEY_PREFIX + ".mana_cost", getSpell().getCost()); + if(getSpell().isContinuous) manaCost = I18n.format(TRANSLATION_KEY_PREFIX + ".mana_cost_continuous", getSpell().getCost()); + if(!discovered) manaCost = I18n.format(TRANSLATION_KEY_PREFIX + ".mana_cost_undiscovered"); + this.fontRenderer.drawString(manaCost, left + 17, top + 69, 0); + + if(discovered){ + this.fontRenderer.drawSplitString(getSpell().getDescription(), left + 17, top + 83, 118, 0); + }else{ + this.mc.standardGalacticFontRenderer.drawSplitString( + SpellGlyphData.getGlyphDescription(getSpell(), mc.world), left + 17, top + 83, 118, 0); + } + } + + @Override + public void initGui(){ + super.initGui(); + Keyboard.enableRepeatEvents(true); + this.buttonList.clear(); + this.mc.getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(WizardrySounds.MISC_BOOK_OPEN, 1)); + } + + @Override + public void onGuiClosed(){ + super.onGuiClosed(); + Keyboard.enableRepeatEvents(false); + } + + @Override + public boolean doesGuiPauseGame(){ + return Wizardry.settings.booksPauseGame; + } + +} diff --git a/src/main/java/electroblob/wizardry/client/gui/handbook/GuiWizardHandbook.java b/src/main/java/electroblob/wizardry/client/gui/handbook/GuiWizardHandbook.java index 13fa335f..bf947a03 100644 --- a/src/main/java/electroblob/wizardry/client/gui/handbook/GuiWizardHandbook.java +++ b/src/main/java/electroblob/wizardry/client/gui/handbook/GuiWizardHandbook.java @@ -8,7 +8,8 @@ import electroblob.wizardry.Wizardry; import electroblob.wizardry.client.ClientProxy; import electroblob.wizardry.client.DrawingUtils; import electroblob.wizardry.client.gui.GuiButtonInvisible; -import electroblob.wizardry.client.gui.handbook.GuiButtonTurnPage.Type; +import electroblob.wizardry.client.gui.GuiButtonTurnPage; +import electroblob.wizardry.client.gui.GuiButtonTurnPage.Type; import electroblob.wizardry.constants.Constants; import electroblob.wizardry.constants.Element; import electroblob.wizardry.constants.Tier; @@ -348,19 +349,19 @@ public class GuiWizardHandbook extends GuiScreen { this.buttonList.clear(); this.buttonList.add(next = new GuiButtonTurnPage(nextButtonId++, left + GUI_WIDTH - BUTTON_INSET_X - GuiButtonTurnPage.WIDTH, - top + GUI_HEIGHT - BUTTON_INSET_Y - GuiButtonTurnPage.HEIGHT, Type.NEXT_PAGE)); + top + GUI_HEIGHT - BUTTON_INSET_Y - GuiButtonTurnPage.HEIGHT, Type.NEXT_PAGE, texture, TEXTURE_WIDTH, TEXTURE_HEIGHT)); this.buttonList.add(previous = new GuiButtonTurnPage(nextButtonId++, left + BUTTON_INSET_X, - top + GUI_HEIGHT - BUTTON_INSET_Y - GuiButtonTurnPage.HEIGHT, Type.PREVIOUS_PAGE)); + top + GUI_HEIGHT - BUTTON_INSET_Y - GuiButtonTurnPage.HEIGHT, Type.PREVIOUS_PAGE, texture, TEXTURE_WIDTH, TEXTURE_HEIGHT)); this.buttonList.add(nextSection = new GuiButtonTurnPage(nextButtonId++, left + GUI_WIDTH - BUTTON_INSET_X - GuiButtonTurnPage.WIDTH - BUTTON_SPACING, - top + GUI_HEIGHT - BUTTON_INSET_Y - GuiButtonTurnPage.HEIGHT, Type.NEXT_SECTION)); + top + GUI_HEIGHT - BUTTON_INSET_Y - GuiButtonTurnPage.HEIGHT, Type.NEXT_SECTION, texture, TEXTURE_WIDTH, TEXTURE_HEIGHT)); this.buttonList.add(previousSection = new GuiButtonTurnPage(nextButtonId++, left + BUTTON_INSET_X + BUTTON_SPACING, - top + GUI_HEIGHT - BUTTON_INSET_Y - GuiButtonTurnPage.HEIGHT, Type.PREVIOUS_SECTION)); + top + GUI_HEIGHT - BUTTON_INSET_Y - GuiButtonTurnPage.HEIGHT, Type.PREVIOUS_SECTION, texture, TEXTURE_WIDTH, TEXTURE_HEIGHT)); this.buttonList.add(menu = new GuiButtonTurnPage(nextButtonId++, left + GUI_WIDTH/2 - 28, - top + GUI_HEIGHT - BUTTON_INSET_Y - GuiButtonTurnPage.HEIGHT, Type.CONTENTS)); + top + GUI_HEIGHT - BUTTON_INSET_Y - GuiButtonTurnPage.HEIGHT, Type.CONTENTS, texture, TEXTURE_WIDTH, TEXTURE_HEIGHT)); this.buttonList.add(bookmark = new GuiButtonInvisible(nextButtonId++, left + 130, top + 172, 11, 19) { @Override diff --git a/src/main/java/electroblob/wizardry/client/model/WizardryModels.java b/src/main/java/electroblob/wizardry/client/model/WizardryModels.java index 11ad3990..e03e22d5 100644 --- a/src/main/java/electroblob/wizardry/client/model/WizardryModels.java +++ b/src/main/java/electroblob/wizardry/client/model/WizardryModels.java @@ -84,6 +84,13 @@ public final class WizardryModels { registerItemModel(Item.getItemFromBlock(WizardryBlocks.acacia_bookshelf)); registerItemModel(Item.getItemFromBlock(WizardryBlocks.dark_oak_bookshelf)); + registerItemModel(Item.getItemFromBlock(WizardryBlocks.oak_lectern)); + registerItemModel(Item.getItemFromBlock(WizardryBlocks.spruce_lectern)); + registerItemModel(Item.getItemFromBlock(WizardryBlocks.birch_lectern)); + registerItemModel(Item.getItemFromBlock(WizardryBlocks.jungle_lectern)); + registerItemModel(Item.getItemFromBlock(WizardryBlocks.acacia_lectern)); + registerItemModel(Item.getItemFromBlock(WizardryBlocks.dark_oak_lectern)); + // Items registerMultiTexturedModel((ItemCrystal)WizardryItems.magic_crystal); diff --git a/src/main/java/electroblob/wizardry/client/particle/ParticleBlockHighlight.java b/src/main/java/electroblob/wizardry/client/particle/ParticleBlockHighlight.java new file mode 100644 index 00000000..8188fd45 --- /dev/null +++ b/src/main/java/electroblob/wizardry/client/particle/ParticleBlockHighlight.java @@ -0,0 +1,58 @@ +package electroblob.wizardry.client.particle; + +import electroblob.wizardry.Wizardry; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraftforge.client.event.TextureStitchEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.relauncher.Side; + +//@SideOnly(Side.CLIENT) +@Mod.EventBusSubscriber(Side.CLIENT) +public class ParticleBlockHighlight extends ParticleWizardry { + + private static final ResourceLocation TEXTURE = new ResourceLocation(Wizardry.MODID, "particle/block_highlight"); + + public ParticleBlockHighlight(World world, double x, double y, double z){ + + super(world, x, y, z, TEXTURE); + + this.particleGravity = 0; + this.setMaxAge(160); + this.particleScale = 5; + this.shaded = false; + } + + @Override + public boolean shouldDisableDepth(){ + return true; + } + + @Override + public void onUpdate(){ + + super.onUpdate(); + + // Fading + if(this.particleAge > this.particleMaxAge/2){ + this.setAlphaF(1 - ((float)this.particleAge - this.particleMaxAge/2f) / (this.particleMaxAge/2f)); + } + + EnumFacing facing = EnumFacing.fromAngle(yaw); + if(pitch == 90) facing = EnumFacing.UP; + if(pitch == -90) facing = EnumFacing.DOWN; + + // Disappears if there is no block behind it (this is the same check used to spawn it) + if(!world.getBlockState(new BlockPos(posX, posY, posZ).offset(facing.getOpposite())).getMaterial().isSolid()){ + this.setExpired(); + } + } + + @SubscribeEvent + public static void onTextureStitchEvent(TextureStitchEvent.Pre event){ + event.getMap().registerSprite(TEXTURE); + } +} diff --git a/src/main/java/electroblob/wizardry/client/renderer/RenderLectern.java b/src/main/java/electroblob/wizardry/client/renderer/RenderLectern.java new file mode 100644 index 00000000..4872b09b --- /dev/null +++ b/src/main/java/electroblob/wizardry/client/renderer/RenderLectern.java @@ -0,0 +1,53 @@ +package electroblob.wizardry.client.renderer; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.tileentity.TileEntityLectern; +import net.minecraft.block.BlockHorizontal; +import net.minecraft.client.model.ModelBook; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.MathHelper; + +public class RenderLectern extends TileEntitySpecialRenderer { + + private static final ResourceLocation BOOK_TEXTURE = new ResourceLocation(Wizardry.MODID, "textures/entity/lectern_book.png"); + private final ModelBook modelBook = new ModelBook(); + + @Override + public void render(TileEntityLectern te, double x, double y, double z, float partialTicks, int destroyStage, float alpha){ + + GlStateManager.pushMatrix(); + GlStateManager.translate((float)x + 0.5F, (float)y + 1, (float)z + 0.5F); + GlStateManager.rotate(90 - te.getWorld().getBlockState(te.getPos()).getValue(BlockHorizontal.FACING).getHorizontalAngle(), 0, 1, 0); + + float time = (float)te.ticksExisted + partialTicks; + + float spread = te.bookSpreadPrev + (te.bookSpread - te.bookSpreadPrev) * partialTicks; + + GlStateManager.translate(0, 0.12, 0); + if(spread > 0.3) GlStateManager.translate(0, MathHelper.sin(time * 0.1F) * 0.01F, 0); + + GlStateManager.rotate(112.5F, 0, 0, 1); + + GlStateManager.translate(0, 0.04 + (1 - spread) * 0.09, (1 - spread) * -0.1875); + + GlStateManager.rotate((1 - spread) * -90, 0, 1, 0); + + this.bindTexture(BOOK_TEXTURE); + + float f3 = te.pageFlipPrev + (te.pageFlip - te.pageFlipPrev) * partialTicks + 0.25F; + float f4 = te.pageFlipPrev + (te.pageFlip - te.pageFlipPrev) * partialTicks + 0.75F; + f3 = (f3 - (float)MathHelper.fastFloor(f3)) * 1.6F - 0.3F; + f4 = (f4 - (float)MathHelper.fastFloor(f4)) * 1.6F - 0.3F; + + f3 = MathHelper.clamp(f3, 0, 1); + f4 = MathHelper.clamp(f4, 0, 1); + + GlStateManager.enableCull(); + this.modelBook.render(null, time, f3, f4, spread, 0.0F, 0.0625F); + GlStateManager.popMatrix(); + + } + +} diff --git a/src/main/java/electroblob/wizardry/inventory/ContainerArcaneWorkbench.java b/src/main/java/electroblob/wizardry/inventory/ContainerArcaneWorkbench.java index a3dc3704..123fa1c0 100644 --- a/src/main/java/electroblob/wizardry/inventory/ContainerArcaneWorkbench.java +++ b/src/main/java/electroblob/wizardry/inventory/ContainerArcaneWorkbench.java @@ -9,6 +9,7 @@ import electroblob.wizardry.registry.WizardryAdvancementTriggers; import electroblob.wizardry.registry.WizardryItems; import electroblob.wizardry.spell.Spell; import electroblob.wizardry.tileentity.TileEntityArcaneWorkbench; +import electroblob.wizardry.util.ISpellSortable; import electroblob.wizardry.util.WandHelper; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; @@ -18,9 +19,7 @@ import net.minecraft.inventory.IInventory; import net.minecraft.inventory.Slot; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraftforge.common.MinecraftForge; @@ -47,7 +46,7 @@ import java.util.stream.Collectors; * for consistency, just in case). The bookshelf slot delegates to a virtual slot on the client side (which is where * the search and sorting is done), and then the click is sent to the server. */ -public class ContainerArcaneWorkbench extends Container { +public class ContainerArcaneWorkbench extends Container implements ISpellSortable { /** The arcane workbench tile entity associated with this container. */ public TileEntityArcaneWorkbench tileentity; @@ -70,7 +69,7 @@ public class ContainerArcaneWorkbench extends Container { private List activeBookshelfSlots = new ArrayList<>(); private int scroll = 0; - private SortType sortType = SortType.TIER; + private ISpellSortable.SortType sortType = ISpellSortable.SortType.TIER; private boolean sortDescending = false; private String searchText = ""; @@ -369,7 +368,7 @@ public class ContainerArcaneWorkbench extends Container { } /** Sets the sorting type to the given type, or toggles the sort direction if it is already that type. */ - public void setSortType(SortType sortType){ + public void setSortType(ISpellSortable.SortType sortType){ if(this.sortType == sortType){ this.sortDescending = !this.sortDescending; @@ -381,12 +380,12 @@ public class ContainerArcaneWorkbench extends Container { updateActiveBookshelfSlots(); } - /** Returns the current sorting type. */ - public SortType getSortType(){ + @Override + public ISpellSortable.SortType getSortType(){ return sortType; } - /** Returns true if the current sorting is in descending order, false otherwise. */ + @Override public boolean isSortDescending(){ return sortDescending; } @@ -435,6 +434,7 @@ public class ContainerArcaneWorkbench extends Container { // N.B. If we drop the requirement of it working with any container it could potentially be a lot easier since // we then always have control over the bookshelf classes + // TODO: Call this when a bookshelf is added or removed /** Called on initialisation, and whenever a bookshelf is added or removed. */ private void refreshBookshelfSlots(){ @@ -442,7 +442,7 @@ public class ContainerArcaneWorkbench extends Container { // TESTME: May need to do this for inventoryItemStacks (probably not though, seems like MC handles it) bookshelfSlots.clear(); - for(IInventory bookshelf : findNearbyBookshelves()){ + for(IInventory bookshelf : BlockBookshelf.findNearbyBookshelves(tileentity.getWorld(), tileentity.getPos(), tileentity)){ for(int i=0; i findNearbyBookshelves(){ - - List bookshelves = new ArrayList<>(); - - int searchRadius = 4; // TODO: Config option for this - - for(int x = -searchRadius; x <= searchRadius; x++){ - for(int y = -searchRadius; y <= searchRadius; y++){ - for(int z = -searchRadius; z <= searchRadius; z++){ - - BlockPos pos = this.tileentity.getPos().add(x, y, z); - // TODO: Config option for allowed containers - if(this.tileentity.getWorld().getBlockState(pos).getBlock() instanceof BlockBookshelf){ - TileEntity te = this.tileentity.getWorld().getTileEntity(pos); - if(te instanceof IInventory && te != this.tileentity) bookshelves.add((IInventory)te); - } - - } - } - } - - return bookshelves; - - } - - public enum SortType { - - TIER("tier", Comparator.naturalOrder()), - ELEMENT("element", Comparator.comparing(Spell::getElement).thenComparing(Spell::getTier)), - ALPHABETICAL("alphabetical", Comparator.comparing(Spell::getUnlocalisedName)); - - public String name; - public Comparator comparator; - - SortType(String name, Comparator comparator){ - this.name = name; - this.comparator = comparator; - } - - } } diff --git a/src/main/java/electroblob/wizardry/packet/PacketLectern.java b/src/main/java/electroblob/wizardry/packet/PacketLectern.java new file mode 100644 index 00000000..c499aa6e --- /dev/null +++ b/src/main/java/electroblob/wizardry/packet/PacketLectern.java @@ -0,0 +1,73 @@ +package electroblob.wizardry.packet; + +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.spell.Spell; +import electroblob.wizardry.tileentity.TileEntityLectern; +import io.netty.buffer.ByteBuf; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +/** [Client -> Server] This packet is sent when a player closes the lectern GUI to send the last-viewed spell to + * the server. */ +public class PacketLectern implements IMessageHandler { + + @Override + public IMessage onMessage(Message message, MessageContext ctx){ + + // Just to make sure that the side is correct + if(ctx.side.isServer()){ + + final EntityPlayerMP player = ctx.getServerHandler().player; + + player.getServerWorld().addScheduledTask(() -> { + + TileEntity tileentity = player.world.getTileEntity(message.pos); + + if(tileentity instanceof TileEntityLectern){ + + ((TileEntityLectern)tileentity).currentSpell = message.spell; + ((TileEntityLectern)tileentity).sync(); // Update other clients with the new state + + }else{ + Wizardry.logger.warn("Received a PacketLectern, but no lectern existed at the position specified!"); + } + + }); + } + + return null; + } + + public static class Message implements IMessage { + + private BlockPos pos; + private Spell spell; + + // This constructor is required otherwise you'll get errors (used somewhere in fml through reflection) + public Message(){} + + public Message(BlockPos pos, Spell spell){ + this.pos = pos; + this.spell = spell; + } + + @Override + public void fromBytes(ByteBuf buf){ + // The order is important + pos = new BlockPos(buf.readInt(), buf.readInt(), buf.readInt()); + spell = Spell.byNetworkID(buf.readInt()); + } + + @Override + public void toBytes(ByteBuf buf){ + buf.writeInt(pos.getX()); + buf.writeInt(pos.getY()); + buf.writeInt(pos.getZ()); + buf.writeInt(spell.networkID()); + } + } +} diff --git a/src/main/java/electroblob/wizardry/packet/WizardryPacketHandler.java b/src/main/java/electroblob/wizardry/packet/WizardryPacketHandler.java index 045205bf..8feabd56 100644 --- a/src/main/java/electroblob/wizardry/packet/WizardryPacketHandler.java +++ b/src/main/java/electroblob/wizardry/packet/WizardryPacketHandler.java @@ -31,6 +31,7 @@ public class WizardryPacketHandler { registerMessage(PacketEmitterData.class, PacketEmitterData.Message.class); registerMessage(PacketPossession.class, PacketPossession.Message.class); registerMessage(PacketConquerShrine.class, PacketConquerShrine.Message.class); + registerMessage(PacketLectern.class, PacketLectern.Message.class); } private static int nextPacketId = 0; diff --git a/src/main/java/electroblob/wizardry/registry/WizardryBlocks.java b/src/main/java/electroblob/wizardry/registry/WizardryBlocks.java index ed25dfd4..244e5291 100644 --- a/src/main/java/electroblob/wizardry/registry/WizardryBlocks.java +++ b/src/main/java/electroblob/wizardry/registry/WizardryBlocks.java @@ -64,6 +64,12 @@ public final class WizardryBlocks { public static final Block jungle_bookshelf = placeholder(); public static final Block acacia_bookshelf = placeholder(); public static final Block dark_oak_bookshelf = placeholder(); + public static final Block oak_lectern = placeholder(); + public static final Block spruce_lectern = placeholder(); + public static final Block birch_lectern = placeholder(); + public static final Block jungle_lectern = placeholder(); + public static final Block acacia_lectern = placeholder(); + public static final Block dark_oak_lectern = placeholder(); /** * Sets both the registry and unlocalised names of the given block, then registers it with the given registry. Use @@ -110,6 +116,12 @@ public final class WizardryBlocks { registerBlock(registry, "jungle_bookshelf", new BlockBookshelf()); registerBlock(registry, "acacia_bookshelf", new BlockBookshelf()); registerBlock(registry, "dark_oak_bookshelf", new BlockBookshelf()); + registerBlock(registry, "oak_lectern", new BlockLectern()); + registerBlock(registry, "birch_lectern", new BlockLectern()); + registerBlock(registry, "spruce_lectern", new BlockLectern()); + registerBlock(registry, "jungle_lectern", new BlockLectern()); + registerBlock(registry, "acacia_lectern", new BlockLectern()); + registerBlock(registry, "dark_oak_lectern", new BlockLectern()); } @@ -124,5 +136,6 @@ public final class WizardryBlocks { GameRegistry.registerTileEntity(TileEntityPlayerSaveTimed.class, new ResourceLocation(Wizardry.MODID, "player_save_timed")); GameRegistry.registerTileEntity(TileEntityShrineCore.class, new ResourceLocation(Wizardry.MODID, "shrine_core")); GameRegistry.registerTileEntity(TileEntityBookshelf.class, new ResourceLocation(Wizardry.MODID, "bookshelf")); + GameRegistry.registerTileEntity(TileEntityLectern.class, new ResourceLocation(Wizardry.MODID, "lectern")); } } \ No newline at end of file diff --git a/src/main/java/electroblob/wizardry/registry/WizardryItems.java b/src/main/java/electroblob/wizardry/registry/WizardryItems.java index b5c52052..e717d7f8 100644 --- a/src/main/java/electroblob/wizardry/registry/WizardryItems.java +++ b/src/main/java/electroblob/wizardry/registry/WizardryItems.java @@ -407,6 +407,13 @@ public final class WizardryItems { registerItemBlock(registry, WizardryBlocks.acacia_bookshelf); registerItemBlock(registry, WizardryBlocks.dark_oak_bookshelf); + registerItemBlock(registry, WizardryBlocks.oak_lectern); + registerItemBlock(registry, WizardryBlocks.spruce_lectern); + registerItemBlock(registry, WizardryBlocks.birch_lectern); + registerItemBlock(registry, WizardryBlocks.jungle_lectern); + registerItemBlock(registry, WizardryBlocks.acacia_lectern); + registerItemBlock(registry, WizardryBlocks.dark_oak_lectern); + // Items registerItem(registry, "magic_crystal", new ItemCrystal()); diff --git a/src/main/java/electroblob/wizardry/spell/Spell.java b/src/main/java/electroblob/wizardry/spell/Spell.java index 8db0c753..b93b35ff 100644 --- a/src/main/java/electroblob/wizardry/spell/Spell.java +++ b/src/main/java/electroblob/wizardry/spell/Spell.java @@ -552,6 +552,9 @@ public abstract class Spell extends IForgeRegistryEntry.Impl implements C return ((ForgeRegistry)registry).getID(this); } + // N.B. You don't *have* to use the network ID for networking, metadata is consistent within a world and will work + // fine, *however* when syncing a list/array of spells it is much more convenient to use network IDs. + /** Returns this spell's network ID number, similar to mod-specific entity IDs.
*
* Unlike {@link Spell#metadata()}, this is guaranteed to be sequential so is suitable for indexed lookup. @@ -947,7 +950,7 @@ public abstract class Spell extends IForgeRegistryEntry.Impl implements C return spell == null ? Spells.none : spell; } - /** Gets a spell instance from its network ID. Or the {@link None} spell if no such spell exists. */ + /** Gets a spell instance from its network ID, or the {@link None} spell if no such spell exists. */ public static Spell byNetworkID(int id){ if(id < 0 || id >= registry.getValuesCollection().size()){ return Spells.none; diff --git a/src/main/java/electroblob/wizardry/tileentity/TileEntityLectern.java b/src/main/java/electroblob/wizardry/tileentity/TileEntityLectern.java new file mode 100644 index 00000000..2cbdd8e6 --- /dev/null +++ b/src/main/java/electroblob/wizardry/tileentity/TileEntityLectern.java @@ -0,0 +1,98 @@ +package electroblob.wizardry.tileentity; + +import electroblob.wizardry.registry.Spells; +import electroblob.wizardry.spell.Spell; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.NetworkManager; +import net.minecraft.network.play.server.SPacketUpdateTileEntity; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.ITickable; +import net.minecraft.util.math.MathHelper; + +import java.util.Random; + +/** Controls the book animations and remembers the GUI state when not in use. */ +public class TileEntityLectern extends TileEntity implements ITickable { + + public static final double BOOK_OPEN_DISTANCE = 5; + + private static final Random rand = new Random(); + + public int ticksExisted; + public float pageFlip; + public float pageFlipPrev; + public float flipT; + public float flipA; + public float bookSpread; + public float bookSpreadPrev; + + public Spell currentSpell = Spells.none; + + @Override + public void update(){ + + this.bookSpreadPrev = this.bookSpread; + + EntityPlayer entityplayer = this.world.getClosestPlayer(this.pos.getX() + 0.5, this.pos.getY() + 0.5, + this.pos.getZ() + 0.5, BOOK_OPEN_DISTANCE, false); + + if(entityplayer != null){ + + this.bookSpread += 0.1f; + + if(this.bookSpread < 0.5f || rand.nextInt(40) == 0){ + float f1 = this.flipT; + while(f1 == flipT) this.flipT += (float)(rand.nextInt(4) - rand.nextInt(4)); + } + + }else{ + this.bookSpread -= 0.1f; + } + + this.bookSpread = MathHelper.clamp(this.bookSpread, 0.0f, 1.0f); + + this.ticksExisted++; + + this.pageFlipPrev = this.pageFlip; + float f = (this.flipT - this.pageFlip) * 0.4f; + f = MathHelper.clamp(f, -0.2f, 0.2f); + this.flipA += (f - this.flipA) * 0.9f; + this.pageFlip += this.flipA; + + } + + /** Called to manually sync the tile entity with clients. */ + public void sync(){ + this.world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 3); + } + + @Override + public NBTTagCompound writeToNBT(NBTTagCompound compound){ + super.writeToNBT(compound); // Confusingly, this method both writes to the supplied compound and returns it + compound.setInteger("spell", currentSpell.metadata()); + return compound; + } + + @Override + public void readFromNBT(NBTTagCompound compound){ + super.readFromNBT(compound); + currentSpell = Spell.byMetadata(compound.getInteger("spell")); + } + + @Override + public final NBTTagCompound getUpdateTag(){ + return this.writeToNBT(new NBTTagCompound()); + } + + @Override + public SPacketUpdateTileEntity getUpdatePacket(){ + return new SPacketUpdateTileEntity(pos, getBlockMetadata(), this.getUpdateTag()); + } + + @Override + public void onDataPacket(NetworkManager net, SPacketUpdateTileEntity pkt){ + readFromNBT(pkt.getNbtCompound()); + } + +} diff --git a/src/main/java/electroblob/wizardry/util/ISpellSortable.java b/src/main/java/electroblob/wizardry/util/ISpellSortable.java new file mode 100644 index 00000000..e6dd1ce7 --- /dev/null +++ b/src/main/java/electroblob/wizardry/util/ISpellSortable.java @@ -0,0 +1,35 @@ +package electroblob.wizardry.util; + +import electroblob.wizardry.spell.Spell; + +import java.util.Comparator; + +/** Interface for things that have a list of spells that can be sorted using {@link SortType}. This allows + * {@link electroblob.wizardry.client.gui.GuiButtonSpellSort GuiButtonSpellSort} to change its appearance based on the + * current sort setting. */ +public interface ISpellSortable { + + /** Returns the current sort type this {@code ISpellSortable} is set to sort by. */ + SortType getSortType(); + + /** Returns true if this {@code ISpellSortable} is currently set to sort in descending order, false if it is + * set to sort in ascending order. */ + boolean isSortDescending(); + + enum SortType { + + TIER("tier", Comparator.naturalOrder()), + ELEMENT("element", Comparator.comparing(Spell::getElement).thenComparing(Spell::getTier)), + ALPHABETICAL("alphabetical", Comparator.comparing(Spell::getUnlocalisedName)); + + public String name; + public Comparator comparator; + + SortType(String name, Comparator comparator){ + this.name = name; + this.comparator = comparator; + } + + } + +} diff --git a/src/main/java/electroblob/wizardry/util/ParticleBuilder.java b/src/main/java/electroblob/wizardry/util/ParticleBuilder.java index 273875b2..e0a1e8e2 100644 --- a/src/main/java/electroblob/wizardry/util/ParticleBuilder.java +++ b/src/main/java/electroblob/wizardry/util/ParticleBuilder.java @@ -93,6 +93,8 @@ public final class ParticleBuilder { public static class Type { /** 3D-rendered light-beam particle.

Defaults:
Lifetime: 1 tick
Colour: white */ public static final ResourceLocation BEAM = new ResourceLocation(Wizardry.MODID,"beam"); + /** Square block face highlight particle.

Defaults:
Lifetime: 160 ticks
Colour: white */ + public static final ResourceLocation BLOCK_HIGHLIGHT = new ResourceLocation(Wizardry.MODID,"block_highlight"); /** Helical animated 'buffing' particle.

Defaults:
Lifetime: 15 ticks *
Velocity: (0, 0.27, 0)
Colour: white */ public static final ResourceLocation BUFF = new ResourceLocation(Wizardry.MODID,"buff"); diff --git a/src/main/resources/assets/ebwizardry/blockstates/acacia_lectern.json b/src/main/resources/assets/ebwizardry/blockstates/acacia_lectern.json new file mode 100644 index 00000000..20fb6530 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/blockstates/acacia_lectern.json @@ -0,0 +1,14 @@ +{ + "forge_marker": 1, + "defaults": { + "model": "ebwizardry:acacia_lectern" + }, + "variants": { + "facing": { + "north": {}, + "east": { "y": 90 }, + "south": { "y": 180 }, + "west": { "y": 270 } + } + } +} diff --git a/src/main/resources/assets/ebwizardry/blockstates/birch_lectern.json b/src/main/resources/assets/ebwizardry/blockstates/birch_lectern.json new file mode 100644 index 00000000..1acb6ae4 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/blockstates/birch_lectern.json @@ -0,0 +1,14 @@ +{ + "forge_marker": 1, + "defaults": { + "model": "ebwizardry:birch_lectern" + }, + "variants": { + "facing": { + "north": {}, + "east": { "y": 90 }, + "south": { "y": 180 }, + "west": { "y": 270 } + } + } +} diff --git a/src/main/resources/assets/ebwizardry/blockstates/dark_oak_lectern.json b/src/main/resources/assets/ebwizardry/blockstates/dark_oak_lectern.json new file mode 100644 index 00000000..d193e745 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/blockstates/dark_oak_lectern.json @@ -0,0 +1,14 @@ +{ + "forge_marker": 1, + "defaults": { + "model": "ebwizardry:dark_oak_lectern" + }, + "variants": { + "facing": { + "north": {}, + "east": { "y": 90 }, + "south": { "y": 180 }, + "west": { "y": 270 } + } + } +} diff --git a/src/main/resources/assets/ebwizardry/blockstates/jungle_lectern.json b/src/main/resources/assets/ebwizardry/blockstates/jungle_lectern.json new file mode 100644 index 00000000..e12d2b53 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/blockstates/jungle_lectern.json @@ -0,0 +1,14 @@ +{ + "forge_marker": 1, + "defaults": { + "model": "ebwizardry:jungle_lectern" + }, + "variants": { + "facing": { + "north": {}, + "east": { "y": 90 }, + "south": { "y": 180 }, + "west": { "y": 270 } + } + } +} diff --git a/src/main/resources/assets/ebwizardry/blockstates/oak_lectern.json b/src/main/resources/assets/ebwizardry/blockstates/oak_lectern.json new file mode 100644 index 00000000..eb8141e5 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/blockstates/oak_lectern.json @@ -0,0 +1,14 @@ +{ + "forge_marker": 1, + "defaults": { + "model": "ebwizardry:oak_lectern" + }, + "variants": { + "facing": { + "north": {}, + "east": { "y": 90 }, + "south": { "y": 180 }, + "west": { "y": 270 } + } + } +} diff --git a/src/main/resources/assets/ebwizardry/blockstates/spruce_lectern.json b/src/main/resources/assets/ebwizardry/blockstates/spruce_lectern.json new file mode 100644 index 00000000..dffef19a --- /dev/null +++ b/src/main/resources/assets/ebwizardry/blockstates/spruce_lectern.json @@ -0,0 +1,14 @@ +{ + "forge_marker": 1, + "defaults": { + "model": "ebwizardry:spruce_lectern" + }, + "variants": { + "facing": { + "north": {}, + "east": { "y": 90 }, + "south": { "y": 180 }, + "west": { "y": 270 } + } + } +} diff --git a/src/main/resources/assets/ebwizardry/lang/en_gb.lang b/src/main/resources/assets/ebwizardry/lang/en_gb.lang index c51e35cf..c2b51ac9 100644 --- a/src/main/resources/assets/ebwizardry/lang/en_gb.lang +++ b/src/main/resources/assets/ebwizardry/lang/en_gb.lang @@ -40,6 +40,13 @@ tile.ebwizardry\:jungle_bookshelf.name=Jungle Bookshelf tile.ebwizardry\:acacia_bookshelf.name=Acacia Bookshelf tile.ebwizardry\:dark_oak_bookshelf.name=Dark Oak Bookshelf +tile.ebwizardry\:oak_lectern.name=Oak Lectern +tile.ebwizardry\:spruce_lectern.name=Spruce Lectern +tile.ebwizardry\:birch_lectern.name=Birch Lectern +tile.ebwizardry\:jungle_lectern.name=Jungle Lectern +tile.ebwizardry\:acacia_lectern.name=Acacia Lectern +tile.ebwizardry\:dark_oak_lectern.name=Dark Oak Lectern + item.ebwizardry\:crystal_magic.name=Magic Crystal item.ebwizardry\:crystal_fire.name=Fiery Crystal item.ebwizardry\:crystal_ice.name=Icy Crystal @@ -519,6 +526,8 @@ gui.ebwizardry\:spell_book.mana_cost=Mana Cost: %s gui.ebwizardry\:spell_book.mana_cost_continuous=Mana Cost: %s/second gui.ebwizardry\:spell_book.mana_cost_undiscovered=Mana Cost: ? +gui.ebwizardry\:lectern.title=Spell Lookup + container.ebwizardry\:arcane_workbench=Arcane Workbench container.ebwizardry\:arcane_workbench.apply=Apply container.ebwizardry\:arcane_workbench.mana=Mana\: diff --git a/src/main/resources/assets/ebwizardry/lang/en_us.lang b/src/main/resources/assets/ebwizardry/lang/en_us.lang index 6dee3005..ab54b962 100644 --- a/src/main/resources/assets/ebwizardry/lang/en_us.lang +++ b/src/main/resources/assets/ebwizardry/lang/en_us.lang @@ -40,6 +40,13 @@ tile.ebwizardry\:jungle_bookshelf.name=Jungle Bookshelf tile.ebwizardry\:acacia_bookshelf.name=Acacia Bookshelf tile.ebwizardry\:dark_oak_bookshelf.name=Dark Oak Bookshelf +tile.ebwizardry\:oak_lectern.name=Oak Lectern +tile.ebwizardry\:spruce_lectern.name=Spruce Lectern +tile.ebwizardry\:birch_lectern.name=Birch Lectern +tile.ebwizardry\:jungle_lectern.name=Jungle Lectern +tile.ebwizardry\:acacia_lectern.name=Acacia Lectern +tile.ebwizardry\:dark_oak_lectern.name=Dark Oak Lectern + item.ebwizardry\:crystal_magic.name=Magic Crystal item.ebwizardry\:crystal_fire.name=Fiery Crystal item.ebwizardry\:crystal_ice.name=Icy Crystal @@ -519,6 +526,8 @@ gui.ebwizardry\:spell_book.mana_cost=Mana Cost: %s gui.ebwizardry\:spell_book.mana_cost_continuous=Mana Cost: %s/second gui.ebwizardry\:spell_book.mana_cost_undiscovered=Mana Cost: ? +gui.ebwizardry\:lectern.title=Spell Lookup + container.ebwizardry\:arcane_workbench=Arcane Workbench container.ebwizardry\:arcane_workbench.apply=Apply container.ebwizardry\:arcane_workbench.mana=Mana\: diff --git a/src/main/resources/assets/ebwizardry/models/block/acacia_lectern.json b/src/main/resources/assets/ebwizardry/models/block/acacia_lectern.json new file mode 100644 index 00000000..1f7315c4 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/acacia_lectern.json @@ -0,0 +1,10 @@ +{ + "parent": "ebwizardry:block/lectern", + "textures": { + "particle": "ebwizardry:blocks/acacia_lectern_top", + "base": "ebwizardry:blocks/acacia_lectern_base", + "side": "ebwizardry:blocks/acacia_lectern_side", + "top": "ebwizardry:blocks/acacia_lectern_top", + "underside": "ebwizardry:blocks/acacia_lectern_underside" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/birch_lectern.json b/src/main/resources/assets/ebwizardry/models/block/birch_lectern.json new file mode 100644 index 00000000..5706382b --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/birch_lectern.json @@ -0,0 +1,10 @@ +{ + "parent": "ebwizardry:block/lectern", + "textures": { + "particle": "ebwizardry:blocks/birch_lectern_top", + "base": "ebwizardry:blocks/birch_lectern_base", + "side": "ebwizardry:blocks/birch_lectern_side", + "top": "ebwizardry:blocks/birch_lectern_top", + "underside": "ebwizardry:blocks/birch_lectern_underside" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/dark_oak_lectern.json b/src/main/resources/assets/ebwizardry/models/block/dark_oak_lectern.json new file mode 100644 index 00000000..fa7eb635 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/dark_oak_lectern.json @@ -0,0 +1,10 @@ +{ + "parent": "ebwizardry:block/lectern", + "textures": { + "particle": "ebwizardry:blocks/dark_oak_lectern_top", + "base": "ebwizardry:blocks/dark_oak_lectern_base", + "side": "ebwizardry:blocks/dark_oak_lectern_side", + "top": "ebwizardry:blocks/dark_oak_lectern_top", + "underside": "ebwizardry:blocks/dark_oak_lectern_underside" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/jungle_lectern.json b/src/main/resources/assets/ebwizardry/models/block/jungle_lectern.json new file mode 100644 index 00000000..0b560139 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/jungle_lectern.json @@ -0,0 +1,10 @@ +{ + "parent": "ebwizardry:block/lectern", + "textures": { + "particle": "ebwizardry:blocks/jungle_lectern_top", + "base": "ebwizardry:blocks/jungle_lectern_base", + "side": "ebwizardry:blocks/jungle_lectern_side", + "top": "ebwizardry:blocks/jungle_lectern_top", + "underside": "ebwizardry:blocks/jungle_lectern_underside" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/lectern.json b/src/main/resources/assets/ebwizardry/models/block/lectern.json new file mode 100644 index 00000000..03d694b3 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/lectern.json @@ -0,0 +1,116 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "elements": [ + { + "from": [2, 0, 2], + "to": [14, 1, 14], + "faces": { + "north": {"uv": [2, 15, 14, 16], "texture": "#side"}, + "east": {"uv": [2, 15, 14, 16], "texture": "#side"}, + "south": {"uv": [2, 15, 14, 16], "texture": "#side"}, + "west": {"uv": [2, 15, 14, 16], "texture": "#side"}, + "up": {"uv": [2, 2, 14, 14], "texture": "#base"}, + "down": {"uv": [2, 1, 14, 13], "texture": "#underside", "cullface": "down"} + } + }, + { + "from": [3, 1, 3], + "to": [13, 2, 13], + "faces": { + "north": {"uv": [3, 14, 13, 15], "texture": "#side"}, + "east": {"uv": [3, 14, 13, 15], "texture": "#side"}, + "south": {"uv": [3, 14, 13, 15], "texture": "#side"}, + "west": {"uv": [3, 14, 13, 15], "texture": "#side"}, + "up": {"uv": [3, 3, 13, 13], "texture": "#base"} + } + }, + { + "from": [4, 13, 4], + "to": [12, 15, 12], + "faces": { + "north": {"uv": [4, 1, 12, 3], "texture": "#side"}, + "east": {"uv": [4, 1, 12, 3], "texture": "#side"}, + "south": {"uv": [4, 1, 12, 3], "texture": "#side"}, + "west": {"uv": [4, 1, 12, 3], "texture": "#side"}, + "down": {"uv": [4, 3, 12, 11], "texture": "#underside"} + } + }, + { + "from": [5, 2, 5], + "to": [11, 13, 11], + "faces": { + "north": {"uv": [5, 3, 11, 14], "texture": "#side"}, + "east": {"uv": [5, 3, 11, 14], "texture": "#side"}, + "south": {"uv": [5, 3, 11, 14], "texture": "#side"}, + "west": {"uv": [5, 3, 11, 14], "texture": "#side"} + } + }, + { + "from": [0, 14.07612, 3.61732], + "to": [16, 16.07612, 17.61732], + "rotation": {"angle": -22.5, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [0, 14, 16, 16], "texture": "#top"}, + "east": {"uv": [1, 14, 15, 16], "texture": "#underside"}, + "south": {"uv": [0, 14, 16, 16], "texture": "#top"}, + "west": {"uv": [1, 14, 15, 16], "texture": "#underside"}, + "up": {"uv": [0, 0, 16, 14], "rotation": 180, "texture": "#top"}, + "down": {"uv": [0, 0, 16, 14], "texture": "#underside"} + } + }, + { + "from": [1, 16.07612, 3.61732], + "to": [15, 17.07612, 4.61732], + "rotation": {"angle": -22.5, "axis": "x", "origin": [8, 8, 8]}, + "faces": { + "north": {"uv": [1, 13, 15, 14], "texture": "#top"}, + "east": {"uv": [1, 13, 2, 14], "texture": "#top"}, + "south": {"uv": [1, 13, 15, 14], "rotation": 180, "texture": "#top"}, + "west": {"uv": [14, 13, 15, 14], "texture": "#top"}, + "up": {"uv": [1, 13, 15, 14], "rotation": 180, "texture": "#top"} + } + }, + { + "from": [4, 15, 9], + "to": [12, 17, 12], + "faces": { + "east": {"uv": [9, 0, 12, 2], "rotation": 180, "texture": "#side"}, + "south": {"uv": [4, 0, 12, 2], "rotation": 180, "texture": "#side"}, + "west": {"uv": [4, 0, 7, 2], "rotation": 180, "texture": "#side"} + } + } + ], + "display": { + "thirdperson_righthand": { + "rotation": [75, 45, 0], + "translation": [0, 2.5, 0], + "scale": [0.375, 0.375, 0.375] + }, + "thirdperson_lefthand": { + "rotation": [75, 45, 0], + "translation": [0, 2.5, 0], + "scale": [0.375, 0.375, 0.375] + }, + "firstperson_righthand": { + "rotation": [0, 45, 0], + "scale": [0.4, 0.4, 0.4] + }, + "firstperson_lefthand": { + "rotation": [0, 225, 0], + "scale": [0.4, 0.4, 0.4] + }, + "ground": { + "translation": [0, 3, 0], + "scale": [0.25, 0.25, 0.25] + }, + "gui": { + "rotation": [30, 225, 0], + "translation": [0, -1, 0], + "scale": [0.625, 0.625, 0.625] + }, + "fixed": { + "scale": [0.5, 0.5, 0.5] + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ebwizardry/models/block/oak_lectern.json b/src/main/resources/assets/ebwizardry/models/block/oak_lectern.json new file mode 100644 index 00000000..bbd75a37 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/oak_lectern.json @@ -0,0 +1,10 @@ +{ + "parent": "ebwizardry:block/lectern", + "textures": { + "particle": "ebwizardry:blocks/oak_lectern_top", + "base": "ebwizardry:blocks/oak_lectern_base", + "side": "ebwizardry:blocks/oak_lectern_side", + "top": "ebwizardry:blocks/oak_lectern_top", + "underside": "ebwizardry:blocks/oak_lectern_underside" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/block/spruce_lectern.json b/src/main/resources/assets/ebwizardry/models/block/spruce_lectern.json new file mode 100644 index 00000000..396cdfed --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/block/spruce_lectern.json @@ -0,0 +1,10 @@ +{ + "parent": "ebwizardry:block/lectern", + "textures": { + "particle": "ebwizardry:blocks/spruce_lectern_top", + "base": "ebwizardry:blocks/spruce_lectern_base", + "side": "ebwizardry:blocks/spruce_lectern_side", + "top": "ebwizardry:blocks/spruce_lectern_top", + "underside": "ebwizardry:blocks/spruce_lectern_underside" + } +} diff --git a/src/main/resources/assets/ebwizardry/models/item/acacia_lectern.json b/src/main/resources/assets/ebwizardry/models/item/acacia_lectern.json new file mode 100644 index 00000000..59f077e4 --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/acacia_lectern.json @@ -0,0 +1,3 @@ +{ + "parent": "ebwizardry:block/acacia_lectern" +} diff --git a/src/main/resources/assets/ebwizardry/models/item/birch_lectern.json b/src/main/resources/assets/ebwizardry/models/item/birch_lectern.json new file mode 100644 index 00000000..aaa107eb --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/birch_lectern.json @@ -0,0 +1,3 @@ +{ + "parent": "ebwizardry:block/birch_lectern" +} diff --git a/src/main/resources/assets/ebwizardry/models/item/dark_oak_lectern.json b/src/main/resources/assets/ebwizardry/models/item/dark_oak_lectern.json new file mode 100644 index 00000000..324650ba --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/dark_oak_lectern.json @@ -0,0 +1,3 @@ +{ + "parent": "ebwizardry:block/dark_oak_lectern" +} diff --git a/src/main/resources/assets/ebwizardry/models/item/jungle_lectern.json b/src/main/resources/assets/ebwizardry/models/item/jungle_lectern.json new file mode 100644 index 00000000..59a3dffd --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/jungle_lectern.json @@ -0,0 +1,3 @@ +{ + "parent": "ebwizardry:block/jungle_lectern" +} diff --git a/src/main/resources/assets/ebwizardry/models/item/oak_lectern.json b/src/main/resources/assets/ebwizardry/models/item/oak_lectern.json new file mode 100644 index 00000000..2ec35f3e --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/oak_lectern.json @@ -0,0 +1,3 @@ +{ + "parent": "ebwizardry:block/oak_lectern" +} diff --git a/src/main/resources/assets/ebwizardry/models/item/spruce_lectern.json b/src/main/resources/assets/ebwizardry/models/item/spruce_lectern.json new file mode 100644 index 00000000..4aeb91ca --- /dev/null +++ b/src/main/resources/assets/ebwizardry/models/item/spruce_lectern.json @@ -0,0 +1,3 @@ +{ + "parent": "ebwizardry:block/spruce_lectern" +} diff --git a/src/main/resources/assets/ebwizardry/spells/arcane_jammer.json b/src/main/resources/assets/ebwizardry/spells/arcane_jammer.json index bdd61d41..d6b4634d 100644 --- a/src/main/resources/assets/ebwizardry/spells/arcane_jammer.json +++ b/src/main/resources/assets/ebwizardry/spells/arcane_jammer.json @@ -12,7 +12,7 @@ }, "tier": "advanced", "element": "healing", - "type": "attack", + "type": "alteration", "cost": 30, "chargeup": 0, "cooldown": 50, diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/acacia_lectern_base.png b/src/main/resources/assets/ebwizardry/textures/blocks/acacia_lectern_base.png new file mode 100644 index 00000000..77697875 Binary files /dev/null and b/src/main/resources/assets/ebwizardry/textures/blocks/acacia_lectern_base.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/acacia_lectern_side.png b/src/main/resources/assets/ebwizardry/textures/blocks/acacia_lectern_side.png new file mode 100644 index 00000000..5dfc524b Binary files /dev/null and b/src/main/resources/assets/ebwizardry/textures/blocks/acacia_lectern_side.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/acacia_lectern_top.png b/src/main/resources/assets/ebwizardry/textures/blocks/acacia_lectern_top.png new file mode 100644 index 00000000..4f588ada Binary files /dev/null and b/src/main/resources/assets/ebwizardry/textures/blocks/acacia_lectern_top.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/acacia_lectern_underside.png b/src/main/resources/assets/ebwizardry/textures/blocks/acacia_lectern_underside.png new file mode 100644 index 00000000..8305f170 Binary files /dev/null and b/src/main/resources/assets/ebwizardry/textures/blocks/acacia_lectern_underside.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/birch_lectern_base.png b/src/main/resources/assets/ebwizardry/textures/blocks/birch_lectern_base.png new file mode 100644 index 00000000..19b1e482 Binary files /dev/null and b/src/main/resources/assets/ebwizardry/textures/blocks/birch_lectern_base.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/birch_lectern_side.png b/src/main/resources/assets/ebwizardry/textures/blocks/birch_lectern_side.png new file mode 100644 index 00000000..e71307dd Binary files /dev/null and b/src/main/resources/assets/ebwizardry/textures/blocks/birch_lectern_side.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/birch_lectern_top.png b/src/main/resources/assets/ebwizardry/textures/blocks/birch_lectern_top.png new file mode 100644 index 00000000..41146dff Binary files /dev/null and b/src/main/resources/assets/ebwizardry/textures/blocks/birch_lectern_top.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/birch_lectern_underside.png b/src/main/resources/assets/ebwizardry/textures/blocks/birch_lectern_underside.png new file mode 100644 index 00000000..e8ae2c11 Binary files /dev/null and b/src/main/resources/assets/ebwizardry/textures/blocks/birch_lectern_underside.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/dark_oak_lectern_base.png b/src/main/resources/assets/ebwizardry/textures/blocks/dark_oak_lectern_base.png new file mode 100644 index 00000000..f0e125ed Binary files /dev/null and b/src/main/resources/assets/ebwizardry/textures/blocks/dark_oak_lectern_base.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/dark_oak_lectern_side.png b/src/main/resources/assets/ebwizardry/textures/blocks/dark_oak_lectern_side.png new file mode 100644 index 00000000..4c040558 Binary files /dev/null and b/src/main/resources/assets/ebwizardry/textures/blocks/dark_oak_lectern_side.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/dark_oak_lectern_top.png b/src/main/resources/assets/ebwizardry/textures/blocks/dark_oak_lectern_top.png new file mode 100644 index 00000000..7b5c5548 Binary files /dev/null and b/src/main/resources/assets/ebwizardry/textures/blocks/dark_oak_lectern_top.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/dark_oak_lectern_underside.png b/src/main/resources/assets/ebwizardry/textures/blocks/dark_oak_lectern_underside.png new file mode 100644 index 00000000..63d023d3 Binary files /dev/null and b/src/main/resources/assets/ebwizardry/textures/blocks/dark_oak_lectern_underside.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/gilded_dark_oak_wood.png b/src/main/resources/assets/ebwizardry/textures/blocks/gilded_dark_oak_wood.png index 786dcc9b..6c016fc7 100644 Binary files a/src/main/resources/assets/ebwizardry/textures/blocks/gilded_dark_oak_wood.png and b/src/main/resources/assets/ebwizardry/textures/blocks/gilded_dark_oak_wood.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/jungle_lectern_base.png b/src/main/resources/assets/ebwizardry/textures/blocks/jungle_lectern_base.png new file mode 100644 index 00000000..a4f7fde5 Binary files /dev/null and b/src/main/resources/assets/ebwizardry/textures/blocks/jungle_lectern_base.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/jungle_lectern_side.png b/src/main/resources/assets/ebwizardry/textures/blocks/jungle_lectern_side.png new file mode 100644 index 00000000..44fb9521 Binary files /dev/null and b/src/main/resources/assets/ebwizardry/textures/blocks/jungle_lectern_side.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/jungle_lectern_top.png b/src/main/resources/assets/ebwizardry/textures/blocks/jungle_lectern_top.png new file mode 100644 index 00000000..0683e9c7 Binary files /dev/null and b/src/main/resources/assets/ebwizardry/textures/blocks/jungle_lectern_top.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/jungle_lectern_underside.png b/src/main/resources/assets/ebwizardry/textures/blocks/jungle_lectern_underside.png new file mode 100644 index 00000000..1e98ffa2 Binary files /dev/null and b/src/main/resources/assets/ebwizardry/textures/blocks/jungle_lectern_underside.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/oak_lectern_base.png b/src/main/resources/assets/ebwizardry/textures/blocks/oak_lectern_base.png new file mode 100644 index 00000000..a7b2109e Binary files /dev/null and b/src/main/resources/assets/ebwizardry/textures/blocks/oak_lectern_base.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/oak_lectern_side.png b/src/main/resources/assets/ebwizardry/textures/blocks/oak_lectern_side.png new file mode 100644 index 00000000..414690ab Binary files /dev/null and b/src/main/resources/assets/ebwizardry/textures/blocks/oak_lectern_side.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/oak_lectern_top.png b/src/main/resources/assets/ebwizardry/textures/blocks/oak_lectern_top.png new file mode 100644 index 00000000..ad128f79 Binary files /dev/null and b/src/main/resources/assets/ebwizardry/textures/blocks/oak_lectern_top.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/oak_lectern_underside.png b/src/main/resources/assets/ebwizardry/textures/blocks/oak_lectern_underside.png new file mode 100644 index 00000000..10fae59c Binary files /dev/null and b/src/main/resources/assets/ebwizardry/textures/blocks/oak_lectern_underside.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/spruce_lectern_base.png b/src/main/resources/assets/ebwizardry/textures/blocks/spruce_lectern_base.png new file mode 100644 index 00000000..2ab6af8e Binary files /dev/null and b/src/main/resources/assets/ebwizardry/textures/blocks/spruce_lectern_base.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/spruce_lectern_side.png b/src/main/resources/assets/ebwizardry/textures/blocks/spruce_lectern_side.png new file mode 100644 index 00000000..bff762de Binary files /dev/null and b/src/main/resources/assets/ebwizardry/textures/blocks/spruce_lectern_side.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/spruce_lectern_top.png b/src/main/resources/assets/ebwizardry/textures/blocks/spruce_lectern_top.png new file mode 100644 index 00000000..6e3c7f1c Binary files /dev/null and b/src/main/resources/assets/ebwizardry/textures/blocks/spruce_lectern_top.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/blocks/spruce_lectern_underside.png b/src/main/resources/assets/ebwizardry/textures/blocks/spruce_lectern_underside.png new file mode 100644 index 00000000..cc7e92bc Binary files /dev/null and b/src/main/resources/assets/ebwizardry/textures/blocks/spruce_lectern_underside.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/entity/lectern_book.png b/src/main/resources/assets/ebwizardry/textures/entity/lectern_book.png new file mode 100644 index 00000000..4b9b746d Binary files /dev/null and b/src/main/resources/assets/ebwizardry/textures/entity/lectern_book.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/gui/arcane_workbench.png b/src/main/resources/assets/ebwizardry/textures/gui/arcane_workbench.png index 786a491b..252ba0a6 100644 Binary files a/src/main/resources/assets/ebwizardry/textures/gui/arcane_workbench.png and b/src/main/resources/assets/ebwizardry/textures/gui/arcane_workbench.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/gui/lectern.png b/src/main/resources/assets/ebwizardry/textures/gui/lectern.png new file mode 100644 index 00000000..a6b253c2 Binary files /dev/null and b/src/main/resources/assets/ebwizardry/textures/gui/lectern.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/gui/spell_book_advanced.png b/src/main/resources/assets/ebwizardry/textures/gui/spell_book_advanced.png index 72b51efd..1bc9af05 100644 Binary files a/src/main/resources/assets/ebwizardry/textures/gui/spell_book_advanced.png and b/src/main/resources/assets/ebwizardry/textures/gui/spell_book_advanced.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/gui/spell_book_apprentice.png b/src/main/resources/assets/ebwizardry/textures/gui/spell_book_apprentice.png index 7c1cab34..e816021a 100644 Binary files a/src/main/resources/assets/ebwizardry/textures/gui/spell_book_apprentice.png and b/src/main/resources/assets/ebwizardry/textures/gui/spell_book_apprentice.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/gui/spell_book_master.png b/src/main/resources/assets/ebwizardry/textures/gui/spell_book_master.png index 6a6396e1..7266a64e 100644 Binary files a/src/main/resources/assets/ebwizardry/textures/gui/spell_book_master.png and b/src/main/resources/assets/ebwizardry/textures/gui/spell_book_master.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/gui/spell_book_novice.png b/src/main/resources/assets/ebwizardry/textures/gui/spell_book_novice.png index 19a78f8f..20699914 100644 Binary files a/src/main/resources/assets/ebwizardry/textures/gui/spell_book_novice.png and b/src/main/resources/assets/ebwizardry/textures/gui/spell_book_novice.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/gui/spell_sort_buttons.png b/src/main/resources/assets/ebwizardry/textures/gui/spell_sort_buttons.png new file mode 100644 index 00000000..9ed4d337 Binary files /dev/null and b/src/main/resources/assets/ebwizardry/textures/gui/spell_sort_buttons.png differ diff --git a/src/main/resources/assets/ebwizardry/textures/particle/block_highlight.png b/src/main/resources/assets/ebwizardry/textures/particle/block_highlight.png new file mode 100644 index 00000000..8e6c4e01 Binary files /dev/null and b/src/main/resources/assets/ebwizardry/textures/particle/block_highlight.png differ