package mods.eln.item.electricalitem; import mods.eln.Eln; import mods.eln.generic.GenericItemUsingDamageDescriptor; import mods.eln.item.electricalinterface.IItemEnergyBattery; import mods.eln.misc.Obj3D; import mods.eln.misc.Obj3D.Obj3DPart; import mods.eln.misc.Utils; import mods.eln.misc.UtilsClient; import mods.eln.server.PlayerManager.PlayerMetadata; import mods.eln.wiki.Data; import net.minecraft.block.Block; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.init.Blocks; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.MathHelper; import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.storage.ExtendedBlockStorage; import net.minecraftforge.client.IItemRenderer.ItemRenderType; import net.minecraftforge.client.IItemRenderer.ItemRendererHelper; import org.lwjgl.opengl.GL11; import java.util.List; import static mods.eln.i18n.I18N.tr; public class PortableOreScannerItem extends GenericItemUsingDamageDescriptor implements IItemEnergyBattery { double energyStorage, dischargePower, chargePower; float viewRange, viewYAlpha; int resWidth, resHeight; private Obj3D obj; private final ResourceLocation iconResource; Obj3DPart base, led, ledHalo; Obj3DPart textBat[], textRun, textInit; Obj3DPart buttons, screenDamage[], screenLuma; private byte damagePerBreakLevel = 3; static final byte sIdle = 0, sBoot = 1, sRun = 2, sStop = 3, sError = 4; static final short bootTime = (short) (4 / 0.05); static final short stopTime = (short) (1 / 0.05); static final double minimalEnergyTimeToBoot = 1; public PortableOreScannerItem(String name, Obj3D obj, double energyStorage, double chargePower, double dischargePower, float viewRange, float viewYAlpha, int resWidth, int resHeight) { super(name); this.chargePower = chargePower; this.dischargePower = dischargePower; this.energyStorage = energyStorage; this.viewRange = viewRange; this.viewYAlpha = viewYAlpha; this.resWidth = resWidth; this.resHeight = resHeight; this.obj = obj; if (obj != null) { base = obj.getPart("Base"); led = obj.getPart("Led"); ledHalo = obj.getPart("LedHalo"); textBat = new Obj3DPart[4]; for (int idx = 0; idx < 4; idx++) textBat[idx] = obj.getPart("TextBat" + idx); textRun = obj.getPart("TextRun"); textInit = obj.getPart("TextInit"); screenDamage = new Obj3DPart[3]; for (int idx = 0; idx < 3; idx++) screenDamage[idx] = obj.getPart("ScreenDamageL" + (idx + 1)); buttons = obj.getPart("Buttons"); screenLuma = obj.getPart("ScreenLuma"); } iconResource = new ResourceLocation("eln", "textures/items/x-rayscanner.png"); } @Override public void onUpdate(ItemStack stack, World world, Entity entity, int par4, boolean par5) { if (world.isRemote) return; if (!(entity instanceof EntityPlayerMP)) return; PlayerMetadata playerData = Eln.playerManager.get((EntityPlayerMP) entity); double energy = getEnergy(stack); byte state = getState(stack); short counter = getCounter(stack); if (getDamage(stack) / damagePerBreakLevel >= 4) { if (state != sIdle) setState(stack, sIdle); return; } switch (state) { /*case sIdle: if(playerInteractRise && energy > dischargePower*minimalEnergyTimeToBoot){ setState(stack, sBoot); setCounter(stack, bootTime); } break;*/ case sBoot: if (--counter != 0) { setCounter(stack, counter); } else { setState(stack, sRun); } break; /*case sRun: if(playerInteractRise){ setState(stack, sStop); setCounter(stack, stopTime); } break;*/ case sStop: if (--counter != 0) { setCounter(stack, counter); } else { setState(stack, sIdle); } break; } } @Override public ItemStack onItemRightClick(ItemStack s, World w, EntityPlayer p) { if (w.isRemote) return s; boolean playerInteractRise = true; double energy = getEnergy(s); byte state = getState(s); short counter = getCounter(s); switch (state) { case sIdle: if (playerInteractRise && energy > dischargePower * minimalEnergyTimeToBoot) { setState(s, sBoot); setCounter(s, bootTime); } break; case sRun: if (playerInteractRise) { setState(s, sStop); setCounter(s, stopTime); } break; } return s; } @Override public void setParent(Item item, int damage) { super.setParent(item, damage); Data.addPortable(newItemStack()); } @Override public NBTTagCompound getDefaultNBT() { NBTTagCompound nbt = new NBTTagCompound(); nbt.setDouble("e", energyStorage * 0.2); nbt.setByte("s", (byte) sBoot); nbt.setShort("c", (short) (bootTime)); nbt.setByte("d", (byte) 0); return nbt; } @Override public void addInformation(ItemStack itemStack, EntityPlayer entityPlayer, List list, boolean par4) { super.addInformation(itemStack, entityPlayer, list, par4); list.add(tr("Discharge power: %1$W", (int) dischargePower)); if (itemStack != null) { list.add(tr("Stored energy: %1$J (%2$%)", getEnergy(itemStack), (int) (getEnergy(itemStack) / energyStorage * 100))); } } public double getEnergy(ItemStack stack) { return getNbt(stack).getDouble("e"); } public void setEnergy(ItemStack stack, double value) { getNbt(stack).setDouble("e", value); } public byte getState(ItemStack stack) { return getNbt(stack).getByte("s"); } public void setState(ItemStack stack, byte value) { getNbt(stack).setByte("s", value); } public short getCounter(ItemStack stack) { return getNbt(stack).getShort("c"); } public void setCounter(ItemStack stack, short value) { getNbt(stack).setShort("c", value); } public byte getDamage(ItemStack stack) { return getNbt(stack).getByte("d"); } public void setDamage(ItemStack stack, byte value) { getNbt(stack).setByte("d", value); } @Override public boolean onDroppedByPlayer(ItemStack stack, EntityPlayer player) { setState(stack, sIdle); return super.onDroppedByPlayer(stack, player); } @Override public double getEnergyMax(ItemStack stack) { return energyStorage; } @Override public double getChargePower(ItemStack stack) { return chargePower; } @Override public double getDischagePower(ItemStack stack) { return dischargePower; } @Override public int getPriority(ItemStack stack) { return 0; } @Override public boolean handleRenderType(ItemStack item, ItemRenderType type) { return true; } @Override public boolean shouldUseRenderHelper(ItemRenderType type, ItemStack item, ItemRendererHelper helper) { return type != ItemRenderType.INVENTORY; } /* @Override public boolean onEntitySwing(EntityLivingBase entityLiving, ItemStack stack) { if(entityLiving.worldObj.isRemote == false){ setDamage(stack, (byte) (getDamage(stack)+1)); Utils.println("Break"); } return super.onEntitySwing(entityLiving, stack); }*/ public boolean onBlockStartBreak(ItemStack itemstack, int x, int y, int z, EntityPlayer player) { if (!player.worldObj.isRemote) { setDamage(itemstack, (byte) (getDamage(itemstack) + 1)); //Utils.println("Break"); } return super.onBlockStartBreak(itemstack, x, y, z, player); } @Override public void renderItem(ItemRenderType type, ItemStack item, Object... data) { if (type == ItemRenderType.INVENTORY) { super.renderItem(type, item, data); UtilsClient.drawEnergyBare(type, (float) (getEnergy(item) / getEnergyMax(item))); return; } double energy = getEnergy(item); byte state = getState(item); GL11.glPushMatrix(); Entity e; switch (type) { case ENTITY: e = null; GL11.glTranslatef(0, -0.2f, 0); GL11.glRotatef(90, 0, 0, 1); break; case EQUIPPED: e = (Entity) data[1]; GL11.glRotatef(130, 0, 0, 1); GL11.glRotatef(140, 1, 0, 0); GL11.glRotatef(-20, 0, 1, 0); GL11.glScalef(1.6f, 1.6f, 1.6f); GL11.glTranslatef(-0.2f, 0.7f, -0.0f); break; case EQUIPPED_FIRST_PERSON: e = (Entity) data[1]; GL11.glTranslatef(0, 1, 0); GL11.glRotatef(90, 0, 0, 1); GL11.glRotatef(35, 1, 0, 0); GL11.glTranslatef(0.0f, 1, -0.2f); break; case INVENTORY: GL11.glPopMatrix(); return; case FIRST_PERSON_MAP: e = null; break; default: e = null; break; } boolean drawScreen = e != null && UtilsClient.clientDistanceTo(e) < 10; boolean drawRay = drawScreen && state == sRun; base.draw(); if (drawRay) { GL11.glPushMatrix(); Object oRender = Eln.clientLiveDataManager.getData(item, 1); if (oRender == null) oRender = Eln.clientLiveDataManager.newData(item, new RenderStorage(viewRange, viewYAlpha, resWidth, resHeight), 1); RenderStorage render = (RenderStorage) oRender; render.generate(e.worldObj, e.posX, Utils.getHeadPosY(e), e.posZ, e.rotationYaw * (float) Math.PI / 180.0F, e.rotationPitch * (float) Math.PI / 180.0F); float scale = 1f / resWidth * 0.50f; float p = 1 / 64f; GL11.glTranslatef(0.90668f, 0.163f, -0.25078f); GL11.glRotatef(270, 1, 0, 0); GL11.glRotatef(270, 0, 0, 1); GL11.glScalef(scale, -scale, 1); render.draw(); GL11.glPopMatrix(); float r = 0, g = 0, b = 0; int count = 0; for (int y = 0; y < resHeight; y += 6) { for (int x = 0; x < resHeight; x += 6) { r += render.screenRed[y][x]; g += render.screenGreen[y][x]; b += render.screenBlue[y][x]; count++; } } r /= count; g /= count; b /= count; UtilsClient.drawHalo(screenLuma, r, g, b, e, false); } if (drawScreen) { if (state == sIdle) { GL11.glColor4f(0.5f, 0.5f, 0.5f, 1f); led.draw(); GL11.glColor4f(1f, 1f, 1f, 1f); buttons.draw(); } UtilsClient.disableLight(); if (state != sIdle) { GL11.glColor4f(1f, 1f, 1f, 1f); buttons.draw(); float r = 0, g = 0, b = 0; switch (state) { case sBoot: r = 0.9f; g = 0.4f; b = 0f; break; case sRun: r = 0f; g = 1f; b = 0f; break; case sStop: r = 1f; g = 0f; b = 0f; break; default: break; } GL11.glColor4f(r * 0.6f, g * 0.6f, b * 0.6f, 1f); led.draw(); UtilsClient.enableBlend(); UtilsClient.drawHaloNoLightSetup(ledHalo, r, g, b, e, false); } GL11.glColor4f(1f, 1f, 1f, 0.4f); switch (state) { case sBoot: textInit.draw(); break; case sRun: textRun.draw(); int batLevel = Math.min(textBat.length - 1, (int) (energy / energyStorage * textBat.length + 0.5f)); textBat[batLevel].draw(); break; default: break; } UtilsClient.enableBlend(); GL11.glColor4f(1f, 1f, 1f, 1f); int breakLevel = getDamage(item) / damagePerBreakLevel; if (state == sIdle) breakLevel = Math.min(breakLevel, screenDamage.length - 1); for (int idx = 0; idx < breakLevel; idx++) { if (idx == screenDamage.length) break; screenDamage[Math.min(screenDamage.length - 1, breakLevel - 1) - idx].draw(); } UtilsClient.disableBlend(); UtilsClient.enableLight(); } GL11.glPopMatrix(); } public static class RenderStorage { float camDist; float viewRange, viewYAlpha, viewXAlpha; public int resWidth, resHeight; float[][] screenRed, screenBlue, screenGreen; short[][][] worldBlocks; int worldBlocksDim, worldBlocksDim2; public static float[] blockKeyFactor; public RenderStorage(float viewRange, float viewYAlpha, int resWidth, int resHeight) { this.viewRange = viewRange; this.viewYAlpha = viewYAlpha; this.camDist = (float) (resWidth / 2 / Math.tan(viewYAlpha / 2)); this.resWidth = resWidth; this.resHeight = resHeight; this.worldBlocksDim = (int) (viewRange * 2 + 3); this.worldBlocksDim2 = this.worldBlocksDim / 2; screenRed = new float[resHeight][resWidth]; screenBlue = new float[resHeight][resWidth]; screenGreen = new float[resHeight][resWidth]; worldBlocks = new short[worldBlocksDim][worldBlocksDim][worldBlocksDim]; } public static float[] getBlockKeyFactor() { if (blockKeyFactor == null) { blockKeyFactor = new float[1024 * 64]; for (int blockId = 0; blockId < 4096; blockId++) { //Block block = Block.blocksList[blockId]; for (int meta = 0; meta < 16; meta++) { //if(block == null) blockKeyFactor[blockId + (meta << 12)] = 0; //else //blockKeyFactor[blockId + (meta << 12)] = block.isOpaqueCube() ? 0.2f : 0; } } } for (OreScannerConfigElement c : Eln.instance.oreScannerConfig) { if (c.blockKey >= 0 && c.blockKey < blockKeyFactor.length) blockKeyFactor[c.blockKey] = c.factor; } return blockKeyFactor; } public static class OreScannerConfigElement { public int blockKey; public float factor; public OreScannerConfigElement(int blockKey, float factor) { this.blockKey = blockKey; this.factor = factor; } } public void generate(World w, double posX, double posY, double posZ, float alphaY, float alphaX) { float[] blockKeyFactor = getBlockKeyFactor(); long start = System.nanoTime(); //Utils.println(posX + " " + posY + " " + posZ + " " + alphaX + " " + alphaY + " "); int posXint = (int) Math.round(posX); int posYint = (int) Math.round(posY); int posZint = (int) Math.round(posZ); for (int z = 0; z < worldBlocksDim; z++) { for (int y = 0; y < worldBlocksDim; y++) { for (int x = 0; x < worldBlocksDim; x++) { worldBlocks[x][y][z] = -1; } } } for (int screenY = 0; screenY < resHeight; screenY++) { int i = 0; i++; for (int screenX = 0; screenX < resWidth; screenX++) { float x = (float) (posX - posXint), y = (float) (posY - posYint), z = (float) (posZ - posZint); float vx = -(screenX - resWidth / 2); float vy = -(screenY - resHeight / 2); float vz = camDist; { float sin = MathHelper.sin(alphaX); float cos = MathHelper.cos(alphaX); float temp = vy; vy = vy * cos - vz * sin; vz = vz * cos + temp * sin; } { float sin = MathHelper.sin(alphaY); float cos = MathHelper.cos(alphaY); float temp = vx; vx = vx * cos - vz * sin; vz = vz * cos + temp * sin; } float normInv = 1f / (float) Math.sqrt(vx * vx + vy * vy + vz * vz); vx *= normInv; vy *= normInv; vz *= normInv; if (vx == 0) vx += 0.0001f; if (vy == 0) vy += 0.0001f; if (vz == 0) vz += 0.0001f; float vxInv = 1f / vx, vyInv = 1f / vy, vzInv = 1f / vz; float stackRed = 0, stackBlue = 0, stackGreen = 0; float d = 0; while (d < viewRange) { float xFloor = MathHelper.floor_float(x); float yFloor = MathHelper.floor_float(y); float zFloor = MathHelper.floor_float(z); float dx = x - xFloor, dy = y - yFloor, dz = z - zFloor; dx = (vx > 0 ? (1 - dx) * vxInv : -dx * vxInv); dy = (vy > 0 ? (1 - dy) * vyInv : -dy * vyInv); dz = (vz > 0 ? (1 - dz) * vzInv : -dz * vzInv); float dBest = Math.min(Math.min(dx, dy), dz) + 0.01f; int xInt = (int) xFloor + worldBlocksDim2; int yInt = (int) yFloor + worldBlocksDim2; int zInt = (int) zFloor + worldBlocksDim2; int blockKey = worldBlocks[xInt][yInt][zInt]; if (blockKey < 0) blockKey += 65536; if (blockKey == 65535) { int xBlock = posXint + (int) xFloor; int yBlock = posYint + (int) yFloor; int zBlock = posZint + (int) zFloor; blockKey = 0; if (yBlock >= 0 && yBlock < 256) { Chunk chunk = w.getChunkFromBlockCoords(xBlock, zBlock); if (chunk != null) { ExtendedBlockStorage storage = chunk.getBlockStorageArray()[yBlock >> 4]; if (storage != null) { int xLocal = xBlock & 0xF; int yLocal = yBlock & 0xF; int zLocal = zBlock & 0xF; int blockId = storage.getBlockLSBArray()[yLocal << 8 | zLocal << 4 | xLocal] & 0xFF; if (storage.getBlockMSBArray() != null) { blockId |= storage.getBlockMSBArray().get(xLocal, yLocal, zLocal) << 8; } blockKey = (blockId + (storage.getExtBlockMetadata(xLocal, yLocal, zLocal) << 12)); } } } if (blockKey >= 1024 * 64) { blockKey = 0; } worldBlocks[xInt][yInt][zInt] = (short) blockKey; } float dToStack; if (d + dBest < viewRange) dToStack = dBest; else { dToStack = (viewRange - d); } stackGreen += blockKeyFactor[blockKey] * dToStack; Block b = Block.getBlockById(blockKey & 0xFFF); if (b != Blocks.air && b != Eln.lightBlock) { if (b.isOpaqueCube()) stackRed += 0.2f * dToStack; else stackRed += 0.1f * dToStack; } else stackBlue += 0.06f * dToStack; x += vx * dBest; y += vy * dBest; z += vz * dBest; d += dBest; } screenRed[screenY][screenX] = stackRed - stackGreen * 0f; screenGreen[screenY][screenX] = stackGreen; screenBlue[screenY][screenX] = stackBlue - stackGreen * 0f; } } long end = System.nanoTime(); //Utils.println("Generate : " + (end - start)/1000 + "us"); } float noiseRand() { return ((float) Math.random() - 0.5f) * 0.03f; } public void draw() { draw(1f, 1f, 1f); } public void draw(float redFactor, float greenFactor, float blueFactor) { long start = System.nanoTime(); UtilsClient.disableLight(); UtilsClient.disableTexture(); //GL11.glShadeModel(GL11.GL_SMOOTH); for (int screenY = 0; screenY < resHeight; screenY++) { GL11.glBegin(GL11.GL_QUAD_STRIP); for (int screenX = 0; screenX < resWidth + 1; screenX++) { //s = screen[screenY][screenX]; GL11.glColor3f(s >= 0 ? s : 0, 0, s < 0.1 ? -s + 0.1f : 0); //Color c = Color.getHSBColor(Math.max(0, Math.min(1, s)), 1, 1); // GL11.glColor3ub((byte)c.getRed(), (byte)c.getGreen(), (byte)c.getBlue()); if (screenX != resWidth) GL11.glColor3f(screenRed[screenY][screenX] * redFactor + noiseRand(), screenGreen[screenY][screenX] * greenFactor + noiseRand(), screenBlue[screenY][screenX] * blueFactor + noiseRand()); GL11.glVertex3f(screenX, screenY, 0); GL11.glVertex3f(screenX, screenY + 1, 0); /*-GL11.glColor3f(screen[screenY][screenX], 0, 0); GL11.glVertex3f(screenX, screenY, 0); GL11.glColor3f(screen[screenY + 1][screenX], 0, 0); GL11.glVertex3f(screenX, screenY + 1, 0); GL11.glColor3f(screen[screenY + 1][screenX + 1], 0, 0); GL11.glVertex3i(screenX + 1, screenY + 1, 0); GL11.glColor3f(screen[screenY][screenX], 0, 0); GL11.glVertex3f(screenX, screenY, 0); GL11.glColor3f(screen[screenY + 1][screenX + 1], 0, 0); GL11.glVertex3i(screenX + 1, screenY + 1, 0); GL11.glColor3f(screen[screenY][screenX + 1], 0, 0); GL11.glVertex3f(screenX + 1, screenY, 0);-* /*GL11.glColor3f(screen[screenY + 1][screenX + 1], 0, 0); GL11.glVertex3i(screenX + 1, screenY + 1, 0); GL11.glColor3f(screen[screenY][screenX + 1], 0, 0); GL11.glVertex3i(screenX + 1, screenY, 0);*/ } GL11.glEnd(); } UtilsClient.enableTexture(); UtilsClient.enableLight(); GL11.glColor3f(1f, 1f, 1f); //GL11.glShadeModel(GL11.GL_FLAT); long end = System.nanoTime(); //Utils.println("Draw : " + (end - start)/1000 + "us"); } } @Override public void electricalItemUpdate(ItemStack stack, double time) { double energy = getEnergy(stack); byte state = getState(stack); switch (state) { //energy consumption case sIdle: break; default: energy -= dischargePower * time; if (energy <= 0) { setState(stack, sIdle); setEnergy(stack, 0); return; } setEnergy(stack, energy); break; } } } /* for(int z = (posZint - worldBlocksDim2) &~15; z < posZint + worldBlocksDim2; z += 16){ for(int x = (posXint - worldBlocksDim2) &~15; x < posXint + worldBlocksDim2; x += 16){ for(int y = (posYint - worldBlocksDim2) &~15; y < posYint + worldBlocksDim2; y += 16){ for(int zSub = Math.max(z, posZint - worldBlocksDim2) & 15; zSub < (z + 16 posZint + worldBlocksDim2< ((posZint + worldBlocksDim2) & 15); z += 16){ for(int xSub = Math.max(z, posZint - worldBlocksDim2) & 15; x < posXint - worldBlocksDim2; x += 16){ for(int ySub = Math.max(z, posZint - worldBlocksDim2) & 15; y < posYint - worldBlocksDim2; y += 16){ } } } } } } */