From f4650eeb4567567ebd1d2d02f734cfcd93cdb0a4 Mon Sep 17 00:00:00 2001 From: Vaern Date: Thu, 30 Dec 2021 22:37:30 -0800 Subject: [PATCH] more small reactor funnies --- .../ContainerMachineReactorSmall.java | 29 +- .../container/ContainerReactorZirnox.java | 14 +- .../inventory/gui/GUIMachineReactorSmall.java | 105 +++-- .../hbm/inventory/gui/GuiInfoContainer.java | 377 +++++++++++++++++- .../inventory/recipes/FuelPoolRecipes.java | 21 +- src/main/java/com/hbm/items/ModItems.java | 2 +- src/main/java/com/hbm/lib/Library.java | 24 ++ .../java/com/hbm/packet/AuxButtonPacket.java | 7 - .../render/tileentity/RenderSmallReactor.java | 12 +- .../TileEntityMachineReactorSmall.java | 154 ++++--- .../hbm/textures/gui/gauges/seven_segment.png | Bin 0 -> 656 bytes .../textures/gui/gui_reactor_experimental.png | Bin 3273 -> 1939 bytes 12 files changed, 612 insertions(+), 133 deletions(-) create mode 100644 src/main/resources/assets/hbm/textures/gui/gauges/seven_segment.png diff --git a/src/main/java/com/hbm/inventory/container/ContainerMachineReactorSmall.java b/src/main/java/com/hbm/inventory/container/ContainerMachineReactorSmall.java index f488949a7..228493ccb 100644 --- a/src/main/java/com/hbm/inventory/container/ContainerMachineReactorSmall.java +++ b/src/main/java/com/hbm/inventory/container/ContainerMachineReactorSmall.java @@ -45,33 +45,28 @@ private TileEntityMachineReactorSmall seleniumEngine; } @Override - public ItemStack transferStackInSlot(EntityPlayer p_82846_1_, int par2) + public ItemStack transferStackInSlot(EntityPlayer player, int index) { ItemStack var3 = null; - Slot var4 = (Slot) this.inventorySlots.get(par2); + Slot slot = (Slot) this.inventorySlots.get(index); - if (var4 != null && var4.getHasStack()) - { - ItemStack var5 = var4.getStack(); - var3 = var5.copy(); + if (slot != null && slot.getHasStack()) { + ItemStack stack = slot.getStack(); + var3 = stack.copy(); - if (par2 <= 12) { - if (!this.mergeItemStack(var5, 13, this.inventorySlots.size(), true)) + if (index <= 12) { + if (!this.mergeItemStack(stack, 13, this.inventorySlots.size(), true)) { return null; } } else { - if (!this.mergeItemStack(var5, 0, 13, true)) + if (!this.mergeItemStack(stack, 0, 13, true)) return null; } - - if (var5.stackSize == 0) - { - var4.putStack((ItemStack) null); - } - else - { - var4.onSlotChanged(); + if (stack.stackSize == 0) { + slot.putStack((ItemStack) null); + } else { + slot.onSlotChanged(); } } diff --git a/src/main/java/com/hbm/inventory/container/ContainerReactorZirnox.java b/src/main/java/com/hbm/inventory/container/ContainerReactorZirnox.java index 73b2dba28..3790369af 100644 --- a/src/main/java/com/hbm/inventory/container/ContainerReactorZirnox.java +++ b/src/main/java/com/hbm/inventory/container/ContainerReactorZirnox.java @@ -89,23 +89,15 @@ public class ContainerReactorZirnox extends Container { if(!this.mergeItemStack(stack, 25, 26, true)) return null; - } else { - - if(stack.getItem() instanceof ItemZirnoxRod) { - - if(!this.mergeItemStack(stack, 0, 24, true)) - return null; - } - } + } else if(!this.mergeItemStack(stack, 0, 24, true)) + return null; } - - if (stack.stackSize == 0) { + if (stack.stackSize == 0) { slot.putStack((ItemStack) null); } else { slot.onSlotChanged(); } } - return var3; } diff --git a/src/main/java/com/hbm/inventory/gui/GUIMachineReactorSmall.java b/src/main/java/com/hbm/inventory/gui/GUIMachineReactorSmall.java index 936a33c11..d2c42aad9 100644 --- a/src/main/java/com/hbm/inventory/gui/GUIMachineReactorSmall.java +++ b/src/main/java/com/hbm/inventory/gui/GUIMachineReactorSmall.java @@ -1,37 +1,63 @@ package com.hbm.inventory.gui; +import org.apache.commons.lang3.math.NumberUtils; +import org.lwjgl.input.Keyboard; import org.lwjgl.opengl.GL11; import com.hbm.inventory.FluidTank; import com.hbm.inventory.container.ContainerMachineReactorSmall; import com.hbm.lib.RefStrings; -import com.hbm.packet.AuxButtonPacket; +import com.hbm.packet.NBTControlPacket; import com.hbm.packet.PacketDispatcher; import com.hbm.tileentity.machine.TileEntityMachineReactorSmall; import net.minecraft.client.Minecraft; import net.minecraft.client.audio.PositionedSoundRecord; +import net.minecraft.client.gui.GuiTextField; import net.minecraft.client.resources.I18n; import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.MathHelper; import net.minecraft.util.ResourceLocation; public class GUIMachineReactorSmall extends GuiInfoContainer { private static ResourceLocation texture = new ResourceLocation(RefStrings.MODID + ":textures/gui/gui_reactor_experimental.png"); private TileEntityMachineReactorSmall reactor; + private final NumberDisplay[] displays = new NumberDisplay[2]; + + private GuiTextField field; - public GUIMachineReactorSmall(InventoryPlayer invPlayer, TileEntityMachineReactorSmall tedf) { - super(new ContainerMachineReactorSmall(invPlayer, tedf)); - reactor = tedf; - + public GUIMachineReactorSmall(InventoryPlayer invPlayer, TileEntityMachineReactorSmall te) { + super(new ContainerMachineReactorSmall(invPlayer, te)); + reactor = te; this.xSize = 176; this.ySize = 222; + displays[0] = new NumberDisplay(12, 19).setDigitLength(4); + displays[1] = new NumberDisplay(12, 55).setDigitLength(3); + } + + @Override + public void initGui() { + super.initGui(); + + this.guiLeft = (this.width - this.xSize) / 2; + this.guiTop = (this.height - this.ySize) / 2; + + Keyboard.enableRepeatEvents(true); + + this.field = new GuiTextField(this.fontRendererObj, guiLeft + 11, guiTop + 86, 35, 9); + this.field.setTextColor(0x00ff00); + this.field.setDisabledTextColour(0x008000); + this.field.setEnableBackgroundDrawing(false); + this.field.setMaxStringLength(3); } @Override public void drawScreen(int mouseX, int mouseY, float f) { super.drawScreen(mouseX, mouseY, f); - this.drawCustomInfo(this, mouseX, mouseY, guiLeft + 80, guiTop + 120, 88, 4, new String[] { "Core Temperature:", " " + Math.round((reactor.heat) * 0.00002 * 480 + 20) + "°C" }); + this.drawCustomInfo(this, mouseX, mouseY, guiLeft + 80, guiTop + 120, 88, 4, new String[] { "Core Temperature:", " " + Math.round((reactor.heat) * 0.00002 * 980 + 20) + "°C" }); String[] text = new String[] { "Coolant will move heat from the core to", "the hull. Water will use that heat and", @@ -50,27 +76,42 @@ public class GUIMachineReactorSmall extends GuiInfoContainer { "using the button next to the", "fluid gauges." }; this.drawCustomInfoStat(mouseX, mouseY, guiLeft - 16, guiTop + 36 + 16, 16, 16, guiLeft - 8, guiTop + 36 + 16, text1); - - String[] text5 = new String[] { reactor.retracting ? "Raise control rods" : "Lower control rods"}; - this.drawCustomInfoStat(mouseX, mouseY, guiLeft + 52, guiTop + 53, 18, 18, mouseX, mouseY, text5); } @Override protected void drawGuiContainerForegroundLayer(int i, int j) { String name = this.reactor.hasCustomInventoryName() ? this.reactor.getInventoryName() : I18n.format(this.reactor.getInventoryName()); + final String[] labels = { "Flux", "Heat", "Control Rods" }; - this.fontRendererObj.drawString(name, this.xSize / 2 - this.fontRendererObj.getStringWidth(name) / 2, 6, 4210752); + this.fontRendererObj.drawString(name, 124 - this.fontRendererObj.getStringWidth(name) / 2, 6, 4210752); this.fontRendererObj.drawString(I18n.format("container.inventory"), 8, this.ySize - 96 + 2, 4210752); + this.fontRendererObj.drawString(labels[0], 11, 9, 15066597); + this.fontRendererObj.drawString(labels[1], 11, 45, 15066597); + this.fontRendererObj.drawString(labels[2], 9, 74, 4210752); } - protected void mouseClicked(int x, int y, int i) { - super.mouseClicked(x, y, i); - - if(guiLeft + 52 <= x && guiLeft + 52 + 16 > x && guiTop + 53 < y && guiTop + 53 + 16 >= y) { + protected void mouseClicked(int mouseX, int mouseY, int i) { + super.mouseClicked(mouseX, mouseY, i); + this.field.mouseClicked(mouseX, mouseY, i); + + if(guiLeft + 51 <= mouseX && guiLeft + 51 + 12 > mouseX && guiTop + 84 < mouseY && guiTop + 84 + 12 >= mouseY) { + + double level; - mc.getSoundHandler().playSound(PositionedSoundRecord.func_147674_a(new ResourceLocation("gui.button.press"), 1.0F)); - PacketDispatcher.wrapper.sendToServer(new AuxButtonPacket(reactor.xCoord, reactor.yCoord, reactor.zCoord, reactor.retracting ? 0 : 1, 0)); - } + if(NumberUtils.isNumber(field.getText())) { + int j = (int)MathHelper.clamp_double(Double.parseDouble(field.getText()), 0, 100); + field.setText(j + ""); + level = j * 0.01D; + } else { + return; + } + + NBTTagCompound control = new NBTTagCompound(); + control.setDouble("level", level); + + PacketDispatcher.wrapper.sendToServer(new NBTControlPacket(control, reactor.xCoord, reactor.yCoord, reactor.zCoord)); + mc.getSoundHandler().playSound(PositionedSoundRecord.func_147674_a(new ResourceLocation("hbm:block.rbmk_az5_cover"), 0.5F)); + } } @Override @@ -80,7 +121,7 @@ public class GUIMachineReactorSmall extends GuiInfoContainer { drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize); - if(reactor.hasHeat()) { + if(reactor.heat > 0) { int i = reactor.getHeatScaled(88); i = (int) Math.min(i, 160); @@ -88,22 +129,38 @@ public class GUIMachineReactorSmall extends GuiInfoContainer { drawTexturedModalRect(guiLeft + 80, guiTop + 120, 0, 230, i, 4); } - if(!reactor.retracting) - drawTexturedModalRect(guiLeft + 52, guiTop + 53, 212, 0, 18, 18); - - if(reactor.rods >= reactor.rodsMax) { + if(reactor.level >= 100) { for(int x = 0; x < 3; x++) for(int y = 0; y < 3; y++) drawTexturedModalRect(guiLeft + 79 + 36 * x, guiTop + 17 + 36 * y, 176, 0, 18, 18); - } else if(reactor.rods > 0) { + } else if(reactor.level > 0) { for(int x = 0; x < 3; x++) for(int y = 0; y < 3; y++) drawTexturedModalRect(guiLeft + 79 + 36 * x, guiTop + 17 + 36 * y, 194, 0, 18, 18); - } + } + + for(byte i = 0; i < 2; i++) + displays[i].drawNumber(reactor.getDisplayData()[i]); this.drawInfoPanel(guiLeft - 16, guiTop + 36, 16, 16, 2); this.drawInfoPanel(guiLeft - 16, guiTop + 36 + 16, 16, 16, 3); + + this.field.drawTextBox(); + } + + @Override + protected void keyTyped(char c, int i) { + + if(this.field.textboxKeyTyped(c, i)) + return; + + if(i == 1 || i == this.mc.gameSettings.keyBindInventory.getKeyCode()) { + this.mc.thePlayer.closeScreen(); + return; + } + + super.keyTyped(c, i); } } diff --git a/src/main/java/com/hbm/inventory/gui/GuiInfoContainer.java b/src/main/java/com/hbm/inventory/gui/GuiInfoContainer.java index c408ef126..5c62c97e3 100644 --- a/src/main/java/com/hbm/inventory/gui/GuiInfoContainer.java +++ b/src/main/java/com/hbm/inventory/gui/GuiInfoContainer.java @@ -1,18 +1,34 @@ package com.hbm.inventory.gui; +import java.math.BigDecimal; +import java.math.RoundingMode; import java.util.Arrays; +import javax.annotation.Nonnegative; + +import com.google.common.annotations.Beta; import com.hbm.lib.Library; import com.hbm.lib.RefStrings; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.client.renderer.Tessellator; import net.minecraft.inventory.Container; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.MathHelper; import net.minecraft.util.ResourceLocation; public abstract class GuiInfoContainer extends GuiContainer { - ResourceLocation guiUtil = new ResourceLocation(RefStrings.MODID + ":textures/gui/gui_utility.png"); + static final ResourceLocation guiUtil = new ResourceLocation(RefStrings.MODID + ":textures/gui/gui_utility.png"); + protected static final ResourceLocation numDisplays = new ResourceLocation(RefStrings.MODID, "textures/gui/gauges/seven_segment.pn"); + /** Default text color **/ + public static final int color0 = 4210752; + /** Green computer color **/ + public static final int color1 = 0x00ff00; + public static final char slimCursor = '\u2502'; + public static final char blockCursor = '\u2588'; + public static final ResourceLocation keyboard = new ResourceLocation(RefStrings.MODID, "misc.keyPress"); public GuiInfoContainer(Container p_i1072_1_) { super(p_i1072_1_); @@ -81,5 +97,364 @@ public abstract class GuiInfoContainer extends GuiContainer { drawTexturedModalRect(x, y, 24, 32, 16, 16); break; } } + + /** + * Seven segment style displays for GUIs, tried to be as adaptable as possible. Still has some bugs that need to be ironed out but it works for the most part. + * @author UFFR + * + */ + @Beta + public class NumberDisplay + { + /** The display's X coordinate **/ + private int displayX; + /** The display's Y coordinate **/ + private int displayY; + /** The X coordinate of the reference **/ + private int referenceX = 10; + /** The Y coordinate of the reference **/ + private int referenceY = 18; + /** The amount of padding between digits, default 3 **/ + @Nonnegative + private byte padding = 3; + /** Does it blink or not, default false, not yet used **/ + private boolean blink = false; + /** Max number the display can handle **/ + private float maxNum; + /** Min number the display can handle **/ + private float minNum; + private boolean customBounds = false; + // Should it be a decimal number? + private boolean isFloat = false; + // How many trailing zeros? + private byte floatPad = 1; + /** Does it pad out with zeros **/ + private boolean pads = false; + /** Max number of digits the display has, default 3 **/ + @Nonnegative + private byte digitLength = 3; + private Number numIn = 0; + private char[] toDisp = {'0', '0', '0'}; + @Nonnegative + private short dispOffset = 0; + /** + * Construct a new number display + * @param dX X coordinate of the display + * @param dY Y coordinate of the display + * @param c Color to use, invalid enums will default to yellow + */ + public NumberDisplay(int x, int y, EnumChatFormatting c) + { + this(x, y); + setupColor(c); + } + /** + * Construct a new number display, color is yellow + * @param x X coordinate of the display + * @param y Y coordinate of the display + */ + public NumberDisplay(int x, int y) + { + displayX = x; + displayY = y; + } + public void setupColor(EnumChatFormatting c) + { + byte row = 4, column = 3; + switch (c) + { + case OBFUSCATED: + case RESET: + case STRIKETHROUGH: + case UNDERLINE: + break; + default: + column = (byte) (c.ordinal() % 4); + row = (byte) Math.floorDiv(c.ordinal(), 4); + break; + } +// System.out.println(column); +// System.out.println(row); + referenceY = 6 * row; + referenceX = 5 * column; + } + /** + * Draw custom number + * @param num - The char array that has the number + */ + public void drawNumber(char[] num) + { + if (blink && !Library.getBlink()) + return; + + short gap = (short) (digitLength - num.length); + for (int i = 0; i < num.length; i++) + { + if (num[i] == '.') + gap--; + dispOffset = (short) ((padding + 6) * (i + gap)); + drawChar(num[i]); + } + if (pads) + padOut(gap); + } + /** Draw the previously provided number **/ + public void drawNumber() + { +// System.out.println(referenceX); +// System.out.println(referenceY); + mc.getTextureManager().bindTexture(numDisplays); + if (isFloat) + formatForFloat(); + drawNumber(toDisp); + } + public void drawNumber(Number num) + { + setNumber(num); + drawNumber(); + } + private void padOut(short gap) + { + if (gap == 0) + return; + for (int i = 0; i < gap; i++) + { + dispOffset = (short) ((padding + 6) * i); + drawChar('0'); + } + } + + /** Draw a single character (requires dispOffset to be set) **/ + public void drawChar(char num) + { +// System.out.println(num); + switch (num) + { + case '1': + drawVertical(1, 0); + drawVertical(1, 1); + break; + case '2': + drawHorizontal(0); + drawVertical(1, 0); + drawHorizontal(1); + drawVertical(0, 1); + drawHorizontal(2); + break; + case '3': + drawHorizontal(0); + drawHorizontal(1); + drawHorizontal(2); + drawVertical(1, 0); + drawVertical(1, 1); + break; + case '4': + drawVertical(0, 0); + drawVertical(1, 0); + drawVertical(1, 1); + drawHorizontal(1); + break; + case '5': + drawHorizontal(0); + drawHorizontal(1); + drawHorizontal(2); + drawVertical(0, 0); + drawVertical(1, 1); + break; + case '6': + drawHorizontal(0); + drawHorizontal(1); + drawHorizontal(2); + drawVertical(0, 0); + drawVertical(0, 1); + drawVertical(1, 1); + break; + case '7': + drawHorizontal(0); + drawVertical(1, 0); + drawVertical(1, 1); + break; + case '8': + drawHorizontal(0); + drawHorizontal(1); + drawHorizontal(2); + drawVertical(0, 0); + drawVertical(1, 0); + drawVertical(0, 1); + drawVertical(1, 1); + break; + case '9': + drawHorizontal(0); + drawHorizontal(1); + drawHorizontal(2); + drawVertical(0, 0); + drawVertical(1, 0); + drawVertical(1, 1); + break; + case '0': + drawHorizontal(0); + drawHorizontal(2); + drawVertical(0, 0); + drawVertical(0, 1); + drawVertical(1, 0); + drawVertical(1, 1); + break; + case '-': + drawHorizontal(1); + break; + case '.': + drawPeriod(); + break; + case 'E': + default: + drawHorizontal(0); + drawHorizontal(1); + drawHorizontal(2); + drawVertical(0, 0); + drawVertical(0, 1); + break; + } + } + + private void drawHorizontal(int pos) + { + byte offset = (byte) (pos * 6); + renderSegment(guiLeft + displayX + dispOffset + 1, guiTop + displayY + offset, referenceX + 1, referenceY, 4, 1); + //System.out.println(referenceX + 1 + ", " + referenceY + ", " + pos); + } + + private void drawPeriod() + { + renderSegment(guiLeft + displayX + dispOffset + padding - (int) Math.ceil(padding / 2) + 5, guiTop + displayY + 12, referenceX + 1, referenceY, 1, 1); + } + + private void drawVertical(int posX, int posY) + { + byte offsetX = (byte) (posX * 5); + byte offsetY = (byte) (posY * 6); + renderSegment(guiLeft + displayX + offsetX + dispOffset, guiTop + displayY + offsetY + 1, referenceX, referenceY + 1, 1, 5); + } + /** + * drawTexturedModalRect() for cool kids + * @param renX X coordinate to render the part + * @param renY Y coordinate to render the part + * @param refX X coordinate of the reference + * @param refY Y coordinate of the reference + * @param width Relevant for horizontals + * @param height Relevant for verticals + */ + private void renderSegment(int renX, int renY, int refX, int refY, int width, int height) + { + final Tessellator tess = Tessellator.instance; + final float z = GuiInfoContainer.this.zLevel; + tess.startDrawingQuads(); + tess.addVertexWithUV(renX, renY + height, z, refX, (refY + height)); + tess.addVertexWithUV(renX + width, renY + height, z, (refX + width), (refY + height)); + tess.addVertexWithUV(renX + width, renY + 0, z, (refX + width), refY); + tess.addVertexWithUV(renX, renY, z, refX, refY); + tess.draw(); + } + + public void setNumber(Number num) + { + numIn = num; + if (customBounds) + numIn = MathHelper.clamp_double(num.doubleValue(), minNum, maxNum); + if (isFloat) + formatForFloat(); + else + { + toDisp = new Long(Math.round(numIn.doubleValue())).toString().toCharArray(); + toDisp = truncOrExpand(); + } + } + /** Get the set number **/ + public Number getNumber() + { + return numIn; + } + /** Get the char array for display **/ + public char[] getDispNumber() + { + return toDisp.clone(); + } + /** Make the display blink **/ + public NumberDisplay setBlinks() + { + blink = true; + return this; + } + /** Padding between digits, default 3 **/ + public NumberDisplay setPadding(@Nonnegative int p) + { + padding = (byte) p; + return this; + } + /** Max number of digits **/ + public NumberDisplay setDigitLength(@Nonnegative int l) + { + digitLength = (byte) l; + toDisp = truncOrExpand(); + return this; + } + /** Set custom number bounds **/ + public NumberDisplay setMaxMin(float max, float min) + { + if (min > max) + throw new IllegalArgumentException("Minimum value is larger than maximum value!"); + maxNum = max; + minNum = min; + customBounds = true; + return this; + } + /** Pad out the left side of the number with zeros **/ + public NumberDisplay setPadNumber() + { + pads = true; + return this; + } + /** Set the number to be a decimal, default zero trailing is 1 **/ + public NumberDisplay setFloat() + { + return setFloat(1); + } + /** Set the number to be a decimal with specified zero trailing **/ + public NumberDisplay setFloat(@Nonnegative int pad) + { + floatPad = (byte) pad; + isFloat = true; + + formatForFloat(); + + return this; + } + private void formatForFloat() + { + BigDecimal bd = new BigDecimal(numIn.toString()); + bd = bd.setScale(floatPad, RoundingMode.HALF_UP); + +// char[] proc = new Double(bd.doubleValue()).toString().toCharArray(); + char[] proc = bd.toString().toCharArray(); + proc = Double.valueOf(Library.roundDecimal(numIn.doubleValue(), floatPad)).toString().toCharArray(); + + if (proc.length == digitLength) + toDisp = proc; + else + toDisp = truncOrExpand(); + } + @Beta + private char[] truncOrExpand() + { + if (isFloat) + { + char[] out = Arrays.copyOf(toDisp, digitLength); + for (int i = 0; i < digitLength; i++) + if (out[i] == '\u0000') + out[i] = '0'; + return out.clone(); + } + return toDisp; + } + } } diff --git a/src/main/java/com/hbm/inventory/recipes/FuelPoolRecipes.java b/src/main/java/com/hbm/inventory/recipes/FuelPoolRecipes.java index c8b96be7e..10aa0e13d 100644 --- a/src/main/java/com/hbm/inventory/recipes/FuelPoolRecipes.java +++ b/src/main/java/com/hbm/inventory/recipes/FuelPoolRecipes.java @@ -12,13 +12,18 @@ public class FuelPoolRecipes { public static final HashMap recipes = new HashMap(); public static void register() { - recipes.put(new ComparableStack(ModItems.waste_natural_uranium_hot), new ItemStack(ModItems.waste_natural_uranium)); - recipes.put(new ComparableStack(ModItems.waste_uranium_hot), new ItemStack(ModItems.waste_uranium)); - recipes.put(new ComparableStack(ModItems.waste_thorium_hot), new ItemStack(ModItems.waste_thorium)); - recipes.put(new ComparableStack(ModItems.waste_mox_hot), new ItemStack(ModItems.waste_mox)); - recipes.put(new ComparableStack(ModItems.waste_plutonium_hot), new ItemStack(ModItems.waste_plutonium)); - recipes.put(new ComparableStack(ModItems.waste_u233_hot), new ItemStack(ModItems.waste_u233)); - recipes.put(new ComparableStack(ModItems.waste_u235_hot), new ItemStack(ModItems.waste_u235)); - recipes.put(new ComparableStack(ModItems.waste_schrabidium_hot), new ItemStack(ModItems.waste_schrabidium)); + recipes.put(new ComparableStack(new ItemStack(ModItems.waste_natural_uranium, 1, 1)), new ItemStack(ModItems.waste_natural_uranium)); + recipes.put(new ComparableStack(new ItemStack(ModItems.waste_uranium, 1, 1)), new ItemStack(ModItems.waste_uranium)); + recipes.put(new ComparableStack(new ItemStack(ModItems.waste_thorium, 1, 1)), new ItemStack(ModItems.waste_thorium)); + recipes.put(new ComparableStack(new ItemStack(ModItems.waste_mox, 1, 1)), new ItemStack(ModItems.waste_mox)); + recipes.put(new ComparableStack(new ItemStack(ModItems.waste_plutonium, 1, 1)), new ItemStack(ModItems.waste_plutonium)); + recipes.put(new ComparableStack(new ItemStack(ModItems.waste_u233, 1, 1)), new ItemStack(ModItems.waste_u233)); + recipes.put(new ComparableStack(new ItemStack(ModItems.waste_u235, 1, 1)), new ItemStack(ModItems.waste_u235)); + recipes.put(new ComparableStack(new ItemStack(ModItems.waste_schrabidium, 1, 1)), new ItemStack(ModItems.waste_schrabidium)); + recipes.put(new ComparableStack(new ItemStack(ModItems.waste_plate_u233, 1, 1)), new ItemStack(ModItems.waste_plate_u233)); + recipes.put(new ComparableStack(new ItemStack(ModItems.waste_plate_u235, 1, 1)), new ItemStack(ModItems.waste_plate_u235)); + recipes.put(new ComparableStack(new ItemStack(ModItems.waste_plate_mox, 1, 1)), new ItemStack(ModItems.waste_plate_mox)); + recipes.put(new ComparableStack(new ItemStack(ModItems.waste_plate_pu239, 1, 1)), new ItemStack(ModItems.waste_plate_pu239)); + recipes.put(new ComparableStack(new ItemStack(ModItems.waste_plate_sa326, 1, 1)), new ItemStack(ModItems.waste_plate_sa326)); } } diff --git a/src/main/java/com/hbm/items/ModItems.java b/src/main/java/com/hbm/items/ModItems.java index 39e076147..9855ed480 100644 --- a/src/main/java/com/hbm/items/ModItems.java +++ b/src/main/java/com/hbm/items/ModItems.java @@ -3590,7 +3590,7 @@ public class ModItems { plate_fuel_u235 = new ItemPlateFuel(1100000).setFunction(FunctionEnum.SQUARE_ROOT, 40).setUnlocalizedName("plate_fuel_u235").setMaxStackSize(1).setCreativeTab(MainRegistry.controlTab).setTextureName(RefStrings.MODID + ":plate_fuel_u235"); plate_fuel_mox = new ItemPlateFuel(1400000).setFunction(FunctionEnum.LOGARITHM, 50).setUnlocalizedName("plate_fuel_mox").setMaxStackSize(1).setCreativeTab(MainRegistry.controlTab).setTextureName(RefStrings.MODID + ":plate_fuel_mox"); plate_fuel_pu239 = new ItemPlateFuel(1000000).setFunction(FunctionEnum.NEGATIVE_QUADRATIC, 25).setUnlocalizedName("plate_fuel_pu239").setMaxStackSize(1).setCreativeTab(MainRegistry.controlTab).setTextureName(RefStrings.MODID + ":plate_fuel_pu239"); - plate_fuel_sa326 = new ItemPlateFuel(1000000).setFunction(FunctionEnum.LINEAR, 40).setUnlocalizedName("plate_fuel_sa326").setMaxStackSize(1).setCreativeTab(MainRegistry.controlTab).setTextureName(RefStrings.MODID + ":plate_fuel_sa326"); + plate_fuel_sa326 = new ItemPlateFuel(1000000).setFunction(FunctionEnum.LINEAR, 60).setUnlocalizedName("plate_fuel_sa326").setMaxStackSize(1).setCreativeTab(MainRegistry.controlTab).setTextureName(RefStrings.MODID + ":plate_fuel_sa326"); rbmk_lid = new ItemRBMKLid().setUnlocalizedName("rbmk_lid").setCreativeTab(MainRegistry.controlTab).setTextureName(RefStrings.MODID + ":rbmk_lid"); rbmk_lid_glass = new ItemRBMKLid().setUnlocalizedName("rbmk_lid_glass").setCreativeTab(MainRegistry.controlTab).setTextureName(RefStrings.MODID + ":rbmk_lid_glass"); diff --git a/src/main/java/com/hbm/lib/Library.java b/src/main/java/com/hbm/lib/Library.java index db0f3e45b..e33e847fc 100644 --- a/src/main/java/com/hbm/lib/Library.java +++ b/src/main/java/com/hbm/lib/Library.java @@ -1,10 +1,14 @@ package com.hbm.lib; +import java.math.BigDecimal; +import java.math.RoundingMode; import java.util.ArrayList; import java.util.List; import java.util.Random; import java.util.Set; +import javax.annotation.Nonnegative; + import com.google.common.collect.Sets; import com.hbm.blocks.ModBlocks; import com.hbm.calc.UnionOfTileEntitiesAndBooleansForFluids; @@ -82,6 +86,26 @@ public class Library { "5bf069bc-5b46-4179-aafe-35c0a07dee8b", //JMF781 }); + /** + * Rounds a number to so many significant digits + * @param num The number to round + * @param digits Amount of digits + * @return The rounded double + */ + public static double roundDecimal(double num, @Nonnegative int digits) + { + if (digits < 0) + throw new IllegalArgumentException("Attempted negative number in non-negative field! Attempted value: " + digits); + + return new BigDecimal(num).setScale(digits, RoundingMode.HALF_UP).doubleValue(); + } + + + public static boolean getBlink() + { + return System.currentTimeMillis() % 1000 < 500; + } + //the old list that allowed superuser mode for the ZOMG //currently unused public static List superuser = new ArrayList(); diff --git a/src/main/java/com/hbm/packet/AuxButtonPacket.java b/src/main/java/com/hbm/packet/AuxButtonPacket.java index 865f59afc..138fe1bca 100644 --- a/src/main/java/com/hbm/packet/AuxButtonPacket.java +++ b/src/main/java/com/hbm/packet/AuxButtonPacket.java @@ -81,13 +81,6 @@ public class AuxButtonPacket implements IMessage { //try { TileEntity te = p.worldObj.getTileEntity(m.x, m.y, m.z); - if (te instanceof TileEntityMachineReactorSmall) { - TileEntityMachineReactorSmall reactor = (TileEntityMachineReactorSmall)te; - - if(m.id == 0) - reactor.retracting = m.value == 1; - } - if (te instanceof TileEntityRadioRec) { TileEntityRadioRec radio = (TileEntityRadioRec)te; diff --git a/src/main/java/com/hbm/render/tileentity/RenderSmallReactor.java b/src/main/java/com/hbm/render/tileentity/RenderSmallReactor.java index 55e9e6709..def7347f2 100644 --- a/src/main/java/com/hbm/render/tileentity/RenderSmallReactor.java +++ b/src/main/java/com/hbm/render/tileentity/RenderSmallReactor.java @@ -1,5 +1,7 @@ package com.hbm.render.tileentity; +import java.util.Random; + import org.lwjgl.opengl.GL11; import com.hbm.main.ResourceManager; @@ -23,16 +25,18 @@ public class RenderSmallReactor extends TileEntitySpecialRenderer { bindTexture(ResourceManager.reactor_small_base_tex); ResourceManager.reactor_small_base.renderAll(); - + + double level = (reactor.lastLevel + (reactor.level - reactor.lastLevel) * f); + GL11.glPushMatrix(); - GL11.glTranslated(0.0D, (double) reactor.rods / reactor.rodsMax, 0.0D); + GL11.glTranslated(0.0D, level, 0.0D); bindTexture(ResourceManager.reactor_small_rods_tex); ResourceManager.reactor_small_rods.renderAll(); GL11.glPopMatrix(); - if(reactor.hasHeat() && reactor.isSubmerged()) { + if(reactor.totalFlux > 10 && reactor.isSubmerged()) { GL11.glDisable(GL11.GL_TEXTURE_2D); GL11.glEnable(GL11.GL_BLEND); @@ -45,7 +49,7 @@ public class RenderSmallReactor extends TileEntitySpecialRenderer { for(double d = 0.285; d < 0.7; d += 0.025) { tess.startDrawingQuads(); - tess.setColorRGBA_F(0.4F, 0.9F, 1.0F, 0.15F); + tess.setColorRGBA_F(0.4F, 0.9F, 1.0F, 0.025F + (float) (Math.random() * 0.02F) + 0.125F * (reactor.totalFlux / 1000F)); double top = 1.375; double bottom = 1.375; diff --git a/src/main/java/com/hbm/tileentity/machine/TileEntityMachineReactorSmall.java b/src/main/java/com/hbm/tileentity/machine/TileEntityMachineReactorSmall.java index 384304a64..5057def76 100644 --- a/src/main/java/com/hbm/tileentity/machine/TileEntityMachineReactorSmall.java +++ b/src/main/java/com/hbm/tileentity/machine/TileEntityMachineReactorSmall.java @@ -10,6 +10,7 @@ import com.hbm.blocks.machine.MachineReactorSmall; import com.hbm.config.MobConfig; import com.hbm.explosion.ExplosionNukeGeneric; import com.hbm.handler.radiation.ChunkRadiationManager; +import com.hbm.interfaces.IControlReceiver; import com.hbm.inventory.FluidTank; import com.hbm.inventory.RecipesCommon.ComparableStack; import com.hbm.items.ModItems; @@ -17,6 +18,7 @@ import com.hbm.items.machine.ItemPlateFuel; import com.hbm.lib.Library; import com.hbm.packet.PacketDispatcher; import com.hbm.tileentity.TileEntityMachineBase; +import com.hbm.tileentity.machine.rbmk.RBMKDials; import cpw.mods.fml.common.network.NetworkRegistry.TargetPoint; import cpw.mods.fml.relauncher.Side; @@ -33,22 +35,24 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.Vec3; import net.minecraftforge.common.util.ForgeDirection; -//TODO: Fix all unneeded methods; fix reactor control; Add seven digit displays for total flux + heat; revamp gui; revamp breeder to rely on reactor and use total flux calcs; -public class TileEntityMachineReactorSmall extends TileEntityMachineBase { - +//TODO: fix reactor control; revamp gui; revamp breeder to rely on reactor and use total flux calcs; +public class TileEntityMachineReactorSmall extends TileEntityMachineBase implements IControlReceiver { + + @SideOnly(Side.CLIENT) + public double lastLevel; + public double level; + public double speed = 0.04; + public double targetLevel; + public int heat; public final int maxHeat = 50000; - public int rods; - public static final int rodsMax = 50; - public boolean retracting = true; public int[] slotFlux = new int[12]; - int totalFlux = 0; - - private static final int[] slots_top = new int[] { 0 }; - private static final int[] slots_bottom = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15 }; - private static final int[] slots_side = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14 }; + public int totalFlux = 0; + + private static final int[] slot_io = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; public TileEntityMachineReactorSmall() { super(12); @@ -79,21 +83,21 @@ public class TileEntityMachineReactorSmall extends TileEntityMachineBase { public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); heat = nbt.getInteger("heat"); - rods = nbt.getInteger("rods"); - retracting = nbt.getBoolean("ret"); + level = nbt.getDouble("level"); + targetLevel = nbt.getDouble("targetLevel"); } @Override public void writeToNBT(NBTTagCompound nbt) { super.writeToNBT(nbt); nbt.setInteger("heat", heat); - nbt.setInteger("rods", rods); - nbt.setBoolean("ret", retracting); + nbt.setDouble("level", level); + nbt.setDouble("targetLevel", targetLevel); } @Override public int[] getAccessibleSlotsFromSide(int side) { - return side == 0 ? slots_bottom : (side == 1 ? slots_top : slots_side); + return slot_io; } @Override @@ -110,45 +114,17 @@ public class TileEntityMachineReactorSmall extends TileEntityMachineBase { return (heat * i) / maxHeat; } - public boolean hasHeat() { - return heat > 0; - } - @Override public void updateEntity() { + + rodControl(); if(!worldObj.isRemote) { + totalFlux = 0; - if(retracting && rods > 0) { - - if(rods == rodsMax) - this.worldObj.playSoundEffect(this.xCoord, this.yCoord, this.zCoord, "hbm:block.reactorStart", 1.0F, 0.75F); - - rods --; - if(rods == 0) - this.worldObj.playSoundEffect(this.xCoord, this.yCoord, this.zCoord, "hbm:block.reactorStop", 1.0F, 1.0F); - } - if(!retracting && rods < rodsMax) { - - if(rods == 0) - this.worldObj.playSoundEffect(this.xCoord, this.yCoord, this.zCoord, "hbm:block.reactorStart", 1.0F, 0.75F); - - rods ++; - - if(rods == rodsMax) - this.worldObj.playSoundEffect(this.xCoord, this.yCoord, this.zCoord, "hbm:block.reactorStop", 1.0F, 1.0F); - } - - if(rods > rodsMax) - rods = rodsMax; - if(rods < 0) - rods = 0; - - if(rods > 0) + if(level > 0) { reaction(); - for(byte i = 0; i < slotFlux.length; i++) { - totalFlux += slotFlux[i]; - } + } getInteractions(); @@ -169,25 +145,28 @@ public class TileEntityMachineReactorSmall extends TileEntityMachineBase { this.explode(); } - if(rods > 0 && heat > 0 && !(blocksRad(xCoord + 1, yCoord + 1, zCoord) && blocksRad(xCoord - 1, yCoord + 1, zCoord) && blocksRad(xCoord, yCoord + 1, zCoord + 1) && blocksRad(xCoord, yCoord + 1, zCoord - 1))) { + //change to 3D rad like demon-core + if(level > 0 && heat > 0 && !(blocksRad(xCoord + 1, yCoord + 1, zCoord) && blocksRad(xCoord - 1, yCoord + 1, zCoord) && blocksRad(xCoord, yCoord + 1, zCoord + 1) && blocksRad(xCoord, yCoord + 1, zCoord - 1))) { float rad = (float) heat / (float) maxHeat * 50F; ChunkRadiationManager.proxy.incrementRad(worldObj, xCoord, yCoord, zCoord, rad); } NBTTagCompound data = new NBTTagCompound(); data.setInteger("heat", heat); - data.setInteger("rods", rods); - data.setBoolean("ret", retracting); + data.setDouble("level", level); + data.setDouble("targetLevel", targetLevel); data.setIntArray("slotFlux", slotFlux); + data.setInteger("totalFlux", totalFlux); this.networkPack(data, 150); } } public void networkUnpack(NBTTagCompound data) { this.heat = data.getInteger("heat"); - this.rods = data.getInteger("rods"); - this.retracting = data.getBoolean("ret"); + this.level = data.getDouble("level"); + this.targetLevel = data.getDouble("targetLevel"); this.slotFlux = data.getIntArray("slotFlux"); + this.totalFlux = data.getInteger("totalFlux"); } private byte getWater() { @@ -241,7 +220,7 @@ public class TileEntityMachineReactorSmall extends TileEntityMachineBase { TileEntityMachineReactor reactor = (TileEntityMachineReactor) tile; - if(reactor.charge <= 1 && this.heat > 0) { + if(reactor.charge <= 1 && this.totalFlux > 0) { reactor.charge = 1; reactor.heat = (int) Math.floor(heat * 4 / maxHeat) + 1; } @@ -297,16 +276,18 @@ public class TileEntityMachineReactorSmall extends TileEntityMachineBase { private void reaction() { for(byte i = 0; i < 12; i++) { - if(slots[i] == null) + if(slots[i] == null) { + slotFlux[i] = 0; continue; + } if(slots[i].getItem() instanceof ItemPlateFuel) { ItemPlateFuel rod = (ItemPlateFuel) slots[i].getItem(); - int outFlux = rod.react(worldObj, slots[i], slotFlux[i] + 10); - rod.setLifeTime(slots[i], rod.getLifeTime(slots[i]) + outFlux); + int outFlux = rod.react(worldObj, slots[i], slotFlux[i] + 1); this.heat += outFlux * 2; slotFlux[i] = 0; + totalFlux += outFlux; int[] neighborSlots = getNeighboringSlots(i); @@ -315,13 +296,15 @@ public class TileEntityMachineReactorSmall extends TileEntityMachineBase { } for(byte j = 0; j < neighborSlots.length; j++) { - slotFlux[neighborSlots[j]] += outFlux * (rods / rodsMax); + slotFlux[neighborSlots[j]] += (int) (outFlux * level); } continue; } if(slots[i].getItem() == ModItems.meteorite_sword_bred) slots[i] = new ItemStack(ModItems.meteorite_sword_irradiated); + + slotFlux[i] = 0; } } @@ -361,7 +344,58 @@ public class TileEntityMachineReactorSmall extends TileEntityMachineBase { } } } - + + //Control Rods + @Override + public boolean hasPermission(EntityPlayer player) { + return Vec3.createVectorHelper(xCoord - player.posX, yCoord - player.posY, zCoord - player.posZ).lengthVector() < 20; + } + + @Override + public void receiveControl(NBTTagCompound data) { + if(data.hasKey("level")) { + this.setTarget(data.getDouble("level")); + } + this.worldObj.playSoundEffect(this.xCoord, this.yCoord, this.zCoord, "hbm:block.reactorStop", 1.0F, 1.0F); + + this.markDirty(); + } + + public void setTarget(double target) { + this.targetLevel = target; + } + + public void rodControl() { + if(worldObj.isRemote) { + + this.lastLevel = this.level; + + } else { + + if(level < targetLevel) { + + level += speed; + + if(level >= targetLevel) + level = targetLevel; + } + + if(level > targetLevel) { + + level -= speed; + + if(level <= targetLevel) + level = targetLevel; + } + } + } + + public int[] getDisplayData() { + int[] data = new int[2]; + data[0] = this.totalFlux; + data[1] = (int) Math.round((this.heat) * 0.00002 * 980 + 20); + return data; + } @Override public AxisAlignedBB getRenderBoundingBox() { diff --git a/src/main/resources/assets/hbm/textures/gui/gauges/seven_segment.png b/src/main/resources/assets/hbm/textures/gui/gauges/seven_segment.png new file mode 100644 index 0000000000000000000000000000000000000000..a43f80efbd16d47afa55d3e22bc06ea355f9c5da GIT binary patch literal 656 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 literal 3273 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