package com.amadornes.framez.part; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import net.minecraft.client.renderer.RenderBlocks; import net.minecraft.client.renderer.Tessellator; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.nbt.NBTTagString; import net.minecraft.util.IIcon; import net.minecraft.util.MovingObjectPosition; import net.minecraft.util.Vec3; import net.minecraft.world.World; import net.minecraftforge.client.IItemRenderer.ItemRenderType; import net.minecraftforge.common.util.ForgeDirection; import org.lwjgl.opengl.GL11; import uk.co.qmunity.lib.client.render.RenderHelper; import uk.co.qmunity.lib.vec.Vec3d; import uk.co.qmunity.lib.vec.Vec3dCube; import codechicken.lib.data.MCDataInput; import codechicken.lib.data.MCDataOutput; import codechicken.lib.raytracer.ExtendedMOP; import codechicken.lib.raytracer.IndexedCuboid6; import codechicken.lib.render.RenderUtils; import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Vector3; import codechicken.microblock.CommonMicroblock; import codechicken.microblock.FaceMicroblock; import codechicken.microblock.HollowMicroblock; import codechicken.multipart.TMultiPart; import codechicken.multipart.TNormalOcclusion; import com.amadornes.framez.Framez; import com.amadornes.framez.api.modifier.IFrameModifier; import com.amadornes.framez.api.modifier.IFrameSideModifier; import com.amadornes.framez.api.movement.IFrame; import com.amadornes.framez.api.movement.IMovement; import com.amadornes.framez.client.RenderFrame; import com.amadornes.framez.config.Config; import com.amadornes.framez.init.FramezItems; import com.amadornes.framez.modifier.FrameFactory; import com.amadornes.framez.modifier.FrameModifierRegistry; import com.amadornes.framez.ref.References; import com.amadornes.framez.util.FramezUtils; public class PartFrame extends TMultiPart implements TNormalOcclusion, IFrame { private List<IFrameModifier> modifiers; private List<IFrameSideModifier>[] sideModifiers; private boolean[] hidden = new boolean[6]; public PartFrame() { } @Override public String getType() { return FrameFactory.getIdentifier(References.FRAME_PART_ID, getModifiers()); } @Override public World getWorld() { if (tile() == null) return null; return world(); } @Override public int getX() { if (tile() == null) return 0; return x(); } @Override public int getY() { if (tile() == null) return 0; return y(); } @Override public int getZ() { if (tile() == null) return 0; return z(); } @Override public boolean doesTick() { return false; } public ItemStack getItem() { NBTTagList tagList = new NBTTagList(); for (IFrameModifier mod : getModifiers()) tagList.appendTag(new NBTTagString(mod.getType())); NBTTagCompound tag = new NBTTagCompound(); tag.setTag("modifiers", tagList); ItemStack is = new ItemStack(FramezItems.frame); is.setTagCompound(tag); return is; } @Override public ItemStack pickItem(MovingObjectPosition hit) { return getItem(); } @Override public Iterable<ItemStack> getDrops() { return Arrays.asList(getItem()); } @Override public Iterable<Cuboid6> getCollisionBoxes() { return Arrays.asList(new Cuboid6(0, 0, 0, 1, 1, 1)); } @Override public Iterable<IndexedCuboid6> getSubParts() { List<IndexedCuboid6> l = new ArrayList<IndexedCuboid6>(); Vec3dCube c1 = new Vec3dCube(0, 0, 0, 2 / 16D, 2 / 16D, 1); Vec3dCube c2 = new Vec3dCube(0, 2 / 16D, 0, 2 / 16D, 14 / 16D, 2 / 16D); Vec3dCube c3 = new Vec3dCube(0, 14 / 16D, 0, 2 / 16D, 1, 1); for (int i = 0; i < 4; i++) { l.add(new IndexedCuboid6(0, new Cuboid6(c1.clone().rotate(0, i * 90, 0, Vec3d.center).toAABB()))); l.add(new IndexedCuboid6(0, new Cuboid6(c2.clone().rotate(0, i * 90, 0, Vec3d.center).toAABB()))); l.add(new IndexedCuboid6(0, new Cuboid6(c3.clone().rotate(0, i * 90, 0, Vec3d.center).toAABB()))); } if (getWorld() != null && (!getWorld().isRemote || !Config.click_through_frames)) if (is2D()) l.add(new IndexedCuboid6(0, new Cuboid6(0, 0, 0, 1, 1, 1).expand(-0.001))); else l.add(new IndexedCuboid6(0, new Cuboid6(1 / 16D, 1 / 16D, 1 / 16D, 15 / 16D, 15 / 16D, 15 / 16D))); return l; } @Override public ExtendedMOP collisionRayTrace(Vec3 start, Vec3 end) { ExtendedMOP mop = super.collisionRayTrace(start, end); double d = 0.001; if (mop != null) { if (mop.hitVec.xCoord % 1 == 0) mop.hitVec.xCoord += ForgeDirection.getOrientation(mop.sideHit).offsetX * d; if (mop.hitVec.yCoord % 1 == 0) mop.hitVec.yCoord += ForgeDirection.getOrientation(mop.sideHit).offsetY * d; if (mop.hitVec.zCoord % 1 == 0) mop.hitVec.zCoord += ForgeDirection.getOrientation(mop.sideHit).offsetZ * d; // mop.blockX = (int) Math.floor(mop.hitVec.xCoord); // mop.blockY = (int) Math.floor(mop.hitVec.yCoord); // mop.blockZ = (int) Math.floor(mop.hitVec.zCoord); } return mop; } @Override public Iterable<Cuboid6> getOcclusionBoxes() { return new ArrayList<Cuboid6>(); } @Override public boolean occlusionTest(TMultiPart part) { if (part instanceof CommonMicroblock) { if (!(part instanceof FaceMicroblock) && !(part instanceof HollowMicroblock)) return false; if (((CommonMicroblock) part).getSize() > 2) return false; } return !(part instanceof PartFrame) && super.occlusionTest(part); } @Override public Collection<IFrameModifier> getModifiers() { if (modifiers == null) return modifiers = new ArrayList<IFrameModifier>(); return modifiers; } @SuppressWarnings("unchecked") @Override public Collection<IFrameSideModifier> getSideModifiers(ForgeDirection side) { if (sideModifiers == null) { sideModifiers = new ArrayList[6]; for (int i = 0; i < 6; i++) sideModifiers[i] = new ArrayList<IFrameSideModifier>(); } return sideModifiers[side.ordinal()]; } @Override public boolean addSideModifier(ForgeDirection side, String modifier) { IFrameModifier mod = FrameModifierRegistry.instance().findModifier(modifier); if (mod == null) return false; if (!(mod instanceof IFrameSideModifier)) return false; Collection<IFrameSideModifier> l = getSideModifiers(side); if (FramezUtils.hasModifier(l, mod)) return false; boolean result = l.add((IFrameSideModifier) mod); sendDescUpdate(); tile().markDirty(); return result; } @Override public boolean removeSideModifier(ForgeDirection side, String modifier) { IFrameModifier mod = FrameModifierRegistry.instance().findModifier(modifier); if (mod == null) return false; if (!(mod instanceof IFrameSideModifier)) return false; Collection<IFrameSideModifier> l = getSideModifiers(side); if (!FramezUtils.hasModifier(l, mod)) return false; boolean result = l.remove(mod); sendDescUpdate(); tile().markDirty(); return result; } @Override public int getMaxMovedBlocks() { return 6; } @Override public int getMaxMultiparts() { return 2; } @Override public int getMultiparts() { return tile().jPartList().size() - 1; } @Override public boolean canRenderInPass(int pass) { return is2D() ? pass == 0 || Config.click_through_frames : true; } @Override public boolean drawHighlight(MovingObjectPosition hit, EntityPlayer player, float frame) { GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); GL11.glDisable(GL11.GL_TEXTURE_2D); GL11.glColor4f(0, 0, 0, 0.4F); GL11.glLineWidth(2); GL11.glDepthMask(true); GL11.glPushMatrix(); RenderUtils.translateToWorldCoords(player, frame); GL11.glTranslated(x(), y(), z()); { double d = 0.002; if (!is2D()) { RenderUtils.drawCuboidOutline(new Cuboid6(2 / 16D + d, isSideHidden(ForgeDirection.DOWN) ? d * 2 : -d * 2, 2 / 16D + d, 14 / 16D - d, 1 + (isSideHidden(ForgeDirection.UP) ? -d * 2 : d * 2), 14 / 16D - d)); RenderUtils.drawCuboidOutline(new Cuboid6(isSideHidden(ForgeDirection.WEST) ? d * 2 : -d * 2, 2 / 16D + d, 2 / 16D + d, 1 + (isSideHidden(ForgeDirection.EAST) ? -d * 2 : d * 2), 14 / 16D - d, 14 / 16D - d)); RenderUtils.drawCuboidOutline(new Cuboid6(2 / 16D + d, 2 / 16D + d, isSideHidden(ForgeDirection.NORTH) ? d : -d, 14 / 16D - d, 14 / 16D - d, 1 + (isSideHidden(ForgeDirection.SOUTH) ? -d * 2 : d * 2))); } RenderUtils.drawCuboidOutline(new Cuboid6(0, 0, 0, 1, 1, 1).expand(d)); } GL11.glPopMatrix(); GL11.glDepthMask(false); GL11.glEnable(GL11.GL_TEXTURE_2D); GL11.glDisable(GL11.GL_BLEND); return true; } @Override public boolean renderStatic(RenderHelper renderer, int pass) { IIcon borderT = getBorderIcon(); IIcon borderPanelT = getBorderPanelIcon(); IIcon crossT = getCrossIcon(); IIcon simpleT = getSimpleIcon(); IIcon[] border = new IIcon[] { borderT, borderT, borderT, borderT, borderT, borderT }; IIcon[] cross = new IIcon[] { crossT, crossT, crossT, crossT, crossT, crossT }; IIcon[] simple = new IIcon[] { simpleT, simpleT, simpleT, simpleT, simpleT, simpleT }; for (ForgeDirection d : ForgeDirection.VALID_DIRECTIONS) { int mb = getMicroblock(d); if (mb != 0) { cross[d.ordinal()] = null; if (mb == 2) { border[d.ordinal()] = borderPanelT; simple[d.ordinal()] = borderPanelT; } else { simple[d.ordinal()] = borderT; } } } if (hidden == null) hidden = new boolean[6]; boolean renderedModifier = false; for (ForgeDirection d : ForgeDirection.VALID_DIRECTIONS) for (IFrameSideModifier m : getSideModifiers(d)) renderedModifier |= m.renderStatic(this, d, renderer, pass); if (!is2D()) return RenderFrame.renderFrame3D(renderer, border, borderT, cross, simple, hidden, pass) || renderedModifier; else return RenderFrame.renderFrame2D(renderer, simple, hidden) || renderedModifier; } @Override public boolean renderStatic(Vector3 pos, int pass) { if (!canRenderInPass(pass)) return false; RenderHelper renderer = RenderHelper.instance; renderer.reset(); renderer.setRenderCoords(getWorld(), (int) pos.x, (int) pos.y, (int) pos.z); boolean result = renderStatic(renderer, pass); renderer.fullReset(); return result; } @Override public void renderDynamic(Vec3d pos, int pass, double frame) { for (ForgeDirection d : ForgeDirection.VALID_DIRECTIONS) for (IFrameSideModifier m : getSideModifiers(d)) m.renderDynamic(this, d, pos, pass, frame); } @Override public void renderDynamic(Vector3 pos, float frame, int pass) { renderDynamic(new Vec3d(pos.x, pos.y, pos.z), pass, frame); } @Override public void renderItem(ItemStack item, ItemRenderType type) { Tessellator t = Tessellator.instance; RenderHelper renderer = RenderHelper.instance; renderer.fullReset(); GL11.glPushMatrix(); { t.startDrawingQuads(); if (canRenderInPass(0)) renderStatic(renderer, 0); if (canRenderInPass(1)) renderStatic(renderer, 1); t.draw(); if (canRenderInPass(0)) renderDynamic(new Vec3d(0, 0, 0), 0, Framez.proxy.getFrame()); if (canRenderInPass(1)) renderDynamic(new Vec3d(0, 0, 0), 1, Framez.proxy.getFrame()); } GL11.glPopMatrix(); renderer.fullReset(); } @Override public void drawBreaking(RenderBlocks renderBlocks) { RenderHelper.instance.setOverrideTexture(renderBlocks.overrideBlockTexture); renderStatic(new Vector3(getX(), getY(), getZ()), 0); RenderHelper.instance.fullReset(); } @Override public boolean isSideSticky(World world, int x, int y, int z, ForgeDirection side, IMovement movement) { return true; } @Override public int getMicroblock(ForgeDirection face) { if (tile() != null) { for (TMultiPart p : tile().jPartList()) { if (p instanceof FaceMicroblock || p instanceof HollowMicroblock) { int pos = ((CommonMicroblock) p).getShape(); if (pos != face.ordinal()) continue; if (((CommonMicroblock) p).getSize() == 2) return 2; else return 1; } } } return 0; } @Override public IIcon getBorderIcon() { return null; } @Override public IIcon getBorderPanelIcon() { return null; } @Override public IIcon getCrossIcon() { return null; } @Override public IIcon getSimpleIcon() { return null; } @Override public boolean is2D() { return Config.simple_frames; } @Override public boolean isSideHidden(ForgeDirection side) { if (hidden == null) hidden = new boolean[6]; return hidden[side.ordinal()]; } @Override public void setSideHidden(ForgeDirection side, boolean hidden) { if (this.hidden == null) this.hidden = new boolean[6]; this.hidden[side.ordinal()] = hidden; sendDescUpdate(); } @Override public void save(NBTTagCompound tag) { if (hidden == null) hidden = new boolean[6]; super.save(tag); for (int i = 0; i < 6; i++) { tag.setBoolean("hidden_" + i, hidden[i]); NBTTagList l = new NBTTagList(); for (IFrameSideModifier m : getSideModifiers(ForgeDirection.getOrientation(i))) l.appendTag(new NBTTagString(m.getType())); tag.setTag("sidemods_" + i, l); } } @Override public void load(NBTTagCompound tag) { if (hidden == null) hidden = new boolean[6]; super.load(tag); for (int i = 0; i < 6; i++) { hidden[i] = tag.getBoolean("hidden_" + i); NBTTagList l = tag.getTagList("sidemods_" + i, new NBTTagString().getId()); Collection<IFrameSideModifier> c = getSideModifiers(ForgeDirection.getOrientation(i)); c.clear(); for (int j = 0; j < l.tagCount(); j++) c.add((IFrameSideModifier) FrameModifierRegistry.instance().findModifier(l.getStringTagAt(j))); } } @Override public void writeDesc(MCDataOutput packet) { if (hidden == null) hidden = new boolean[6]; super.writeDesc(packet); for (int i = 0; i < 6; i++) packet.writeBoolean(hidden[i]); for (ForgeDirection d : ForgeDirection.VALID_DIRECTIONS) { Collection<IFrameSideModifier> c = getSideModifiers(d); packet.writeInt(c.size()); for (IFrameModifier m : c) packet.writeString(m.getType()); } } @Override public void readDesc(MCDataInput packet) { if (hidden == null) hidden = new boolean[6]; super.readDesc(packet); for (int i = 0; i < 6; i++) hidden[i] = packet.readBoolean(); for (ForgeDirection d : ForgeDirection.VALID_DIRECTIONS) { Collection<IFrameSideModifier> c = getSideModifiers(d); c.clear(); int amt = packet.readInt(); for (int i = 0; i < amt; i++) c.add((IFrameSideModifier) FrameModifierRegistry.instance().findModifier(packet.readString())); } } }