package codechicken.wirelessredstone.logic; import java.util.Arrays; import codechicken.core.ClientUtils; import codechicken.core.asm.InterfaceDependancies; import codechicken.lib.data.MCDataInput; import codechicken.lib.data.MCDataOutput; import codechicken.lib.raytracer.IndexedCuboid6; import codechicken.lib.vec.BlockCoord; import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.RedundantTransformation; import codechicken.lib.vec.Rotation; import codechicken.lib.vec.Transformation; import codechicken.lib.vec.Vector3; import codechicken.microblock.FaceMicroClass; import codechicken.microblock.JMicroShrinkRender; import codechicken.microblock.MicroOcclusion; import codechicken.multipart.IFaceRedstonePart; import codechicken.multipart.IRedstonePart; import codechicken.multipart.IconHitEffects; import codechicken.multipart.JCuboidPart; import codechicken.multipart.JIconHitEffects; import codechicken.multipart.JNormalOcclusion; import codechicken.multipart.JPartialOcclusion; import codechicken.multipart.NormalOcclusionTest; import codechicken.multipart.RedstoneInteractions; import codechicken.multipart.TFacePart; import codechicken.multipart.TMultiPart; import codechicken.multipart.TileMultipart; import codechicken.wirelessredstone.core.RedstoneEther; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import net.minecraft.client.particle.EffectRenderer; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.IIcon; import net.minecraft.util.MovingObjectPosition; import net.minecraftforge.common.util.ForgeDirection; import static codechicken.lib.vec.Rotation.*; import static codechicken.lib.vec.Vector3.*; @InterfaceDependancies public abstract class WirelessPart extends JCuboidPart implements TFacePart, JIconHitEffects, IFaceRedstonePart, JNormalOcclusion, JPartialOcclusion, JMicroShrinkRender { private static Cuboid6[] nBoxes = new Cuboid6[6]; static { Cuboid6 base = new Cuboid6(1 / 8D, 0, 1 / 8D, 7 / 8D, 1 / 8D, 7 / 8D); for (int s = 0; s < 6; s++) nBoxes[s] = base.copy().apply(sideRotations[s].at(center)); } public byte state; public String owner; //rendering public Cuboid6 baseRenderBounds; public int baseRenderMask; protected int spinoffset; public int rotation() { return state & 3; } public void setRotation(int rot) { state = (byte) ((state & 0xFC) | rot); } public int side() { return state >> 2 & 7; } public void setSide(int side) { state = (byte) ((state & 0xE3) | side << 2); } public int shape() { return state & 0x1F; } /** * Whether the device is currently operational (powered for transmitters, receiving, or unpowered for jammers) */ public boolean active() { return (state & 0x20) > 0; } public void setActive(boolean active) { state &= 0xDF; if (active) state |= 0x20; } public boolean disabled() { return (state & 0x40) > 0; } public void setDisabled(boolean disabled) { state &= 0xBF; if (disabled) state |= 0x40; } public int getPoweringLevel() { int s = RedstoneInteractions.getPowerTo(this, Rotation.rotateSide(side(), rotation())); int i = getInternalPower(); if (i > s) s = i; return s; } public int getInternalPower() { TMultiPart part = tile().partMap(Rotation.rotateSide(side(), rotation())); if (part instanceof IRedstonePart) { IRedstonePart rp = (IRedstonePart) part; return Math.max(rp.strongPowerLevel(side()), rp.weakPowerLevel(side())) << 4; } return 0; } public Transformation rotationT() { return sideOrientation(side(), rotation()); } @Override public void load(NBTTagCompound tag) { state = tag.getByte("state"); if (tag.hasKey("owner")) owner = tag.getString("owner"); } @Override public void save(NBTTagCompound tag) { tag.setByte("state", state); if (owner != null) tag.setString("owner", owner); } @Override public void readDesc(MCDataInput packet) { state = packet.readByte(); } @Override public void read(MCDataInput packet) { super.read(packet); onPartChanged(this); } @Override public void writeDesc(MCDataOutput packet) { packet.writeByte(state); } @Override public void onWorldJoin() { if (!world().isRemote) addToEther(); } @Override public void onWorldSeparate() { if (!world().isRemote) removeFromEther(); } @Override public int getFace() { return side(); } @Override public boolean canConnectRedstone(int side) { return side == rotateSide(side(), rotation()); } @Override public void onNeighborChanged() { dropIfCantStay(); } @Override public ItemStack pickItem(MovingObjectPosition hit) { return getItem(); } @Override public Iterable<ItemStack> getDrops() { return Arrays.asList(getItem()); } @Override public int strongPowerLevel(int side) { return 0; } @Override public int weakPowerLevel(int side) { return strongPowerLevel(side); } public void updateChange() { tile().markDirty(); tile().notifyPartChange(this); sendDescUpdate(); } public boolean dropIfCantStay() { BlockCoord pos = new BlockCoord(tile()).offset(side()); if (!world().isSideSolid(pos.x, pos.y, pos.z, ForgeDirection.getOrientation(side() ^ 1))) { drop(); return true; } return false; } public void drop() { TileMultipart.dropItem(getItem(), world(), Vector3.fromTileEntityCenter(tile())); tile().remPart(this); } public void setupPlacement(EntityPlayer player, int side) { setSide(side ^ 1); setRotation(Rotation.getSidedRotation(player, side) ^ 2); owner = player.getCommandSenderName(); } public abstract ItemStack getItem(); public abstract void addToEther(); public abstract void removeFromEther(); public abstract Cuboid6 getExtensionBB(); public abstract int modelId(); public int textureSet() { return active() ? 1 : 0; } public abstract Vector3 getPearlPos(); public Transformation getPearlRotation() { return new RedundantTransformation(); } public double getPearlScale() { return 0.05; } public abstract double getPearlSpin(); public abstract float getPearlLight(); public double getFloating() { if (tile() != null) return RedstoneEther.getSineWave(ClientUtils.getRenderTime() + x() * 3 + y() * 5 + z() * 9, 7); return 0; } @Override public boolean allowCompleteOcclusion() { return false; } @Override public Cuboid6 getBounds() { return baseBounds(side()); } @Override public Iterable<Cuboid6> getPartialOcclusionBoxes() { return getCollisionBoxes(); } @Override public Iterable<Cuboid6> getOcclusionBoxes() { return Arrays.asList(nBoxes[side()], getExtensionBB()); } @Override public boolean occlusionTest(TMultiPart npart) { return NormalOcclusionTest.apply(this, npart); } @Override public Iterable<IndexedCuboid6> getSubParts() { return Arrays.asList(new IndexedCuboid6(0, getBounds())); } @Override public float getStrength(MovingObjectPosition hit, EntityPlayer player) { return 10F; } @Override public boolean renderStatic(Vector3 pos, int pass) { if (pass == 0) { RenderWireless.renderWorld(this); return true; } return false; } @Override public void renderDynamic(Vector3 pos, float frame, int pass) { if (pass == 0) RenderWireless.renderPearl(pos, this); } @Override public void onPartChanged(TMultiPart part) { if (world().isRemote) { recalcBounds(); } else { onNeighborChanged(); } } @Override public void onAdded() { super.onAdded(); if (world().isRemote) recalcBounds(); } public void recalcBounds() { baseRenderBounds = getBounds().copy(); baseRenderMask = MicroOcclusion.recalcBounds(this, baseRenderBounds); baseRenderBounds = baseRenderBounds.apply(rotationT().at(center).inverse()); } @Override public int getSlotMask() { return 1 << getSlot(); } @Override public boolean solid(int side) { return false; } @Override public int redstoneConductionMap() { return 0; } @Override public int getPriorityClass() { return -1; } @Override public int getSize() { return 1; } @Override public int getSlot() { return side(); } @Override public boolean isTransparent() { return false; } public static Cuboid6 baseBounds(int i) { return FaceMicroClass.aBounds()[0x10 | i]; } @Override public boolean activate(EntityPlayer player, MovingObjectPosition hit, ItemStack held) { if (hit.sideHit == (side() ^ 1) && player.isSneaking()) { int r = rotation(); setRotation((r + 1) % 4); if (!tile().canReplacePart(this, this)) { setRotation(r); return false; } if (!world().isRemote) { updateChange(); onPartChanged(this); } else { setRotation(r); } return true; } return false; } @Override public void addDestroyEffects(MovingObjectPosition hit, EffectRenderer effectRenderer) { IconHitEffects.addDestroyEffects(this, effectRenderer); } @Override @SideOnly(Side.CLIENT) public void addHitEffects(MovingObjectPosition hit, EffectRenderer effectRenderer) { IconHitEffects.addHitEffects(this, hit, effectRenderer); } @Override @SideOnly(Side.CLIENT) public IIcon getBreakingIcon(Object subPart, int side) { return getBrokenIcon(side); } @Override @SideOnly(Side.CLIENT) public IIcon getBrokenIcon(int side) { return RenderWireless.getBreakingIcon(textureSet()); } }