From 865ad1377f64afdf7a737d995e4c44f9acc62762 Mon Sep 17 00:00:00 2001 From: Boblet Date: Fri, 27 Mar 2026 12:21:04 +0100 Subject: [PATCH] numitrons --- changelog | 7 + src/main/java/com/hbm/blocks/ModBlocks.java | 6 + .../hbm/blocks/machine/rbmk/RBMKGauge.java | 41 +++++ .../hbm/blocks/machine/rbmk/RBMKKeyPad.java | 30 ++++ .../machine/rbmk/RBMKMiniPanelBase.java | 8 +- .../hbm/blocks/machine/rbmk/RBMKNumitron.java | 50 ++++++ .../inventory/gui/GUIScreenRBMKDisplay.java | 149 ++++++++++++++++ .../hbm/inventory/gui/GUIScreenRBMKGauge.java | 3 - src/main/java/com/hbm/main/ClientProxy.java | 1 + .../java/com/hbm/main/CraftingManager.java | 9 +- .../java/com/hbm/main/ResourceManager.java | 3 + .../render/tileentity/RenderRBMKNumitron.java | 112 ++++++++++++ .../java/com/hbm/tileentity/TileMappings.java | 1 + .../machine/rbmk/TileEntityRBMKNumitron.java | 165 ++++++++++++++++++ src/main/resources/assets/hbm/lang/de_DE.lang | 4 + src/main/resources/assets/hbm/lang/en_US.lang | 4 + .../assets/hbm/models/rbmk/numitron.obj | 79 +++++++++ .../gui/machine/gui_rbmk_numitron.png | Bin 0 -> 2618 bytes .../hbm/textures/models/network/numitron.png | Bin 0 -> 153 bytes .../models/network/numitron_lights.png | Bin 0 -> 712 bytes 20 files changed, 665 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/hbm/blocks/machine/rbmk/RBMKNumitron.java create mode 100644 src/main/java/com/hbm/inventory/gui/GUIScreenRBMKDisplay.java create mode 100644 src/main/java/com/hbm/render/tileentity/RenderRBMKNumitron.java create mode 100644 src/main/java/com/hbm/tileentity/machine/rbmk/TileEntityRBMKNumitron.java create mode 100644 src/main/resources/assets/hbm/models/rbmk/numitron.obj create mode 100644 src/main/resources/assets/hbm/textures/gui/machine/gui_rbmk_numitron.png create mode 100644 src/main/resources/assets/hbm/textures/models/network/numitron.png create mode 100644 src/main/resources/assets/hbm/textures/models/network/numitron_lights.png diff --git a/changelog b/changelog index ac144268b..d6c23b018 100644 --- a/changelog +++ b/changelog @@ -9,6 +9,12 @@ * Base production rates for plasma forge exclusive recipes are very slow * Does not accept upgrades, however, can use up otherwise useless fission fragments and unstable isotopes to gain a temporary x4 speed bonus with no penalty * Can also assemble fusion reactor vessels, which are cheaper but need quantum circuits +* Blank Redstone-over-Radio Panel + * A cheap way of extending the size of RoR control consoles without needing unconfigured button or gauge panels + * Now used to craft the other RoR panel variants +* Redstone-over-Radio numeric display + * Shows integer RoR values as numbers + * Can have up to two display panels per block ## Changed * Doubled bismuth and tantalum yields from high-performance solvent bedrock ore processing @@ -21,6 +27,7 @@ * The restrictions for firing Folly (using the scope, waiting for the startup) no longer apply to NPCs (which can never fulfill them anyway), allowing them to actually use it * The plinking sound played when a drill cannot break a block now only plays once for the entire AoE instead of once for every single block that couldn't be broken * Fluid barrels now have a sideways connector when hooked up to pipes, bridging the two pixel gap +* Redstone over radio panels now render with their unique parts in the inventory, making the items easier to tell apart ## Fixed * Fixed size 15 dual kerosene thruster not rendering at all diff --git a/src/main/java/com/hbm/blocks/ModBlocks.java b/src/main/java/com/hbm/blocks/ModBlocks.java index 2c9a506ab..30f95d49e 100644 --- a/src/main/java/com/hbm/blocks/ModBlocks.java +++ b/src/main/java/com/hbm/blocks/ModBlocks.java @@ -1090,9 +1090,11 @@ public class ModBlocks { public static Block rbmk_heater; public static Block rbmk_console; public static Block rbmk_crane_console; + public static Block rbmk_display_blank; public static Block rbmk_display; public static Block rbmk_key_pad; public static Block rbmk_gauge; + public static Block rbmk_numitron; public static Block rbmk_autoloader; public static Block rbmk_loader; public static Block rbmk_steam_inlet; @@ -2113,9 +2115,11 @@ public class ModBlocks { rbmk_heater = new RBMKHeater().setBlockName("rbmk_heater").setCreativeTab(MainRegistry.machineTab).setBlockTextureName(RefStrings.MODID + ":rbmk/rbmk_heater"); rbmk_console = new RBMKConsole().setBlockName("rbmk_console").setCreativeTab(MainRegistry.machineTab).setBlockTextureName(RefStrings.MODID + ":rbmk/rbmk_console"); rbmk_crane_console = new RBMKCraneConsole().setBlockName("rbmk_crane_console").setCreativeTab(MainRegistry.machineTab).setBlockTextureName(RefStrings.MODID + ":rbmk/rbmk_crane_console"); + rbmk_display_blank = new RBMKMiniPanelBase().setBlockName("rbmk_display_blank").setCreativeTab(MainRegistry.machineTab).setBlockTextureName(RefStrings.MODID + ":rbmk/rbmk_display"); rbmk_display = new RBMKDisplay().setBlockName("rbmk_display").setCreativeTab(MainRegistry.machineTab).setBlockTextureName(RefStrings.MODID + ":rbmk/rbmk_display"); rbmk_key_pad = new RBMKKeyPad().setBlockName("rbmk_key_pad").setCreativeTab(MainRegistry.machineTab).setBlockTextureName(RefStrings.MODID + ":rbmk/rbmk_display"); rbmk_gauge = new RBMKGauge().setBlockName("rbmk_gauge").setCreativeTab(MainRegistry.machineTab).setBlockTextureName(RefStrings.MODID + ":rbmk/rbmk_display"); + rbmk_numitron = new RBMKNumitron().setBlockName("rbmk_numitron").setCreativeTab(MainRegistry.machineTab).setBlockTextureName(RefStrings.MODID + ":rbmk/rbmk_display"); rbmk_autoloader = new RBMKAutoloader().setBlockName("rbmk_autoloader").setCreativeTab(MainRegistry.machineTab).setHardness(50.0F).setResistance(60.0F).setBlockTextureName(RefStrings.MODID + ":rbmk_autoloader"); rbmk_loader = new RBMKLoader(Material.iron).setBlockName("rbmk_loader").setCreativeTab(MainRegistry.machineTab).setHardness(50.0F).setResistance(60.0F).setBlockTextureName(RefStrings.MODID + ":rbmk_loader"); rbmk_steam_inlet = new RBMKInlet(Material.iron).setBlockName("rbmk_steam_inlet").setCreativeTab(MainRegistry.machineTab).setHardness(50.0F).setResistance(60.0F).setBlockTextureName(RefStrings.MODID + ":rbmk_steam_inlet"); @@ -3107,9 +3111,11 @@ public class ModBlocks { GameRegistry.registerBlock(rbmk_heater, rbmk_heater.getUnlocalizedName()); GameRegistry.registerBlock(rbmk_console, rbmk_console.getUnlocalizedName()); GameRegistry.registerBlock(rbmk_crane_console, rbmk_crane_console.getUnlocalizedName()); + register(rbmk_display_blank); register(rbmk_display); register(rbmk_key_pad); register(rbmk_gauge); + register(rbmk_numitron); register(rbmk_autoloader); register(rbmk_loader); register(rbmk_steam_inlet); diff --git a/src/main/java/com/hbm/blocks/machine/rbmk/RBMKGauge.java b/src/main/java/com/hbm/blocks/machine/rbmk/RBMKGauge.java index dc4016e1d..96c3ac01c 100644 --- a/src/main/java/com/hbm/blocks/machine/rbmk/RBMKGauge.java +++ b/src/main/java/com/hbm/blocks/machine/rbmk/RBMKGauge.java @@ -1,10 +1,16 @@ package com.hbm.blocks.machine.rbmk; +import org.lwjgl.opengl.GL11; + import com.hbm.main.MainRegistry; +import com.hbm.main.ResourceManager; +import com.hbm.render.tileentity.RenderArcFurnace; import com.hbm.tileentity.machine.rbmk.TileEntityRBMKGauge; import api.hbm.block.IToolable; import cpw.mods.fml.common.network.internal.FMLNetworkHandler; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.World; @@ -22,4 +28,39 @@ public class RBMKGauge extends RBMKMiniPanelBase implements IToolable { if(world.isRemote) FMLNetworkHandler.openGui(player, MainRegistry.instance, 0, world, x, y, z); return true; } + + @Override + public void renderInventoryBlock(Block block, int meta, int modelId, Object renderBlocks) { + super.renderInventoryBlock(block, meta, modelId, renderBlocks); + + GL11.glPushMatrix(); + GL11.glTranslated(0, -0.5, 0); + GL11.glRotated(-90, 0, 1, 0); + + for(int i = 0; i < 4; i++) { + + GL11.glPushMatrix(); + GL11.glTranslated(0.25, (i / 2) * -0.5 + 0.25, (i % 2) * -0.5 + 0.25); + + GL11.glColor3f(1F, 1F, 1F); + Minecraft.getMinecraft().getTextureManager().bindTexture(ResourceManager.rbmk_gauge_tex); + ResourceManager.rbmk_gauge.renderPart("Gauge"); + + GL11.glColor3f(0.5F, 0F, 0F); + GL11.glTranslated(0, 0.4375, -0.125); + GL11.glRotated(85, 1, 0, 0); + GL11.glTranslated(0, -0.4375, 0.125); + + GL11.glDisable(GL11.GL_TEXTURE_2D); + RenderArcFurnace.fullbright(true); + GL11.glEnable(GL11.GL_LIGHTING); + ResourceManager.rbmk_gauge.renderPart("Needle"); + RenderArcFurnace.fullbright(false); + GL11.glEnable(GL11.GL_TEXTURE_2D); + + GL11.glPopMatrix(); + } + + GL11.glPopMatrix(); + } } diff --git a/src/main/java/com/hbm/blocks/machine/rbmk/RBMKKeyPad.java b/src/main/java/com/hbm/blocks/machine/rbmk/RBMKKeyPad.java index a9976667d..87af42894 100644 --- a/src/main/java/com/hbm/blocks/machine/rbmk/RBMKKeyPad.java +++ b/src/main/java/com/hbm/blocks/machine/rbmk/RBMKKeyPad.java @@ -1,10 +1,15 @@ package com.hbm.blocks.machine.rbmk; +import org.lwjgl.opengl.GL11; + import com.hbm.main.MainRegistry; +import com.hbm.main.ResourceManager; import com.hbm.tileentity.machine.rbmk.TileEntityRBMKKeyPad; import api.hbm.block.IToolable; import cpw.mods.fml.common.network.internal.FMLNetworkHandler; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.World; @@ -48,4 +53,29 @@ public class RBMKKeyPad extends RBMKMiniPanelBase implements IToolable { return true; } + + @Override + public void renderInventoryBlock(Block block, int meta, int modelId, Object renderBlocks) { + super.renderInventoryBlock(block, meta, modelId, renderBlocks); + + GL11.glPushMatrix(); + GL11.glTranslated(0, -0.5, 0); + GL11.glRotated(-90, 0, 1, 0); + + for(int i = 0; i < 4; i++) { + + GL11.glPushMatrix(); + GL11.glTranslated(0.25, (i / 2) * -0.5 + 0.25, (i % 2) * -0.5 + 0.25); + + GL11.glColor3f(1F, 1F, 1F); + Minecraft.getMinecraft().getTextureManager().bindTexture(ResourceManager.rbmk_keypad_tex); + ResourceManager.rbmk_button.renderPart("Socket"); + GL11.glColor3f(0.65F, 0F, 0F); + ResourceManager.rbmk_button.renderPart("Button"); + GL11.glPopMatrix(); + } + + GL11.glColor3f(1F, 1F, 1F); + GL11.glPopMatrix(); + } } diff --git a/src/main/java/com/hbm/blocks/machine/rbmk/RBMKMiniPanelBase.java b/src/main/java/com/hbm/blocks/machine/rbmk/RBMKMiniPanelBase.java index db0adf4c2..357753062 100644 --- a/src/main/java/com/hbm/blocks/machine/rbmk/RBMKMiniPanelBase.java +++ b/src/main/java/com/hbm/blocks/machine/rbmk/RBMKMiniPanelBase.java @@ -15,16 +15,22 @@ import net.minecraft.client.renderer.RenderBlocks; import net.minecraft.client.renderer.Tessellator; import net.minecraft.entity.EntityLivingBase; import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.MathHelper; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; -public abstract class RBMKMiniPanelBase extends BlockContainer implements ISBRHUniversal { +public class RBMKMiniPanelBase extends BlockContainer implements ISBRHUniversal { public RBMKMiniPanelBase() { super(Material.iron); } + @Override + public TileEntity createNewTileEntity(World world, int meta) { + return null; + } + @Override public int getRenderType() { return renderID; } @Override public boolean isOpaqueCube() { return false; } @Override public boolean renderAsNormalBlock() { return false; } diff --git a/src/main/java/com/hbm/blocks/machine/rbmk/RBMKNumitron.java b/src/main/java/com/hbm/blocks/machine/rbmk/RBMKNumitron.java new file mode 100644 index 000000000..3bce56cac --- /dev/null +++ b/src/main/java/com/hbm/blocks/machine/rbmk/RBMKNumitron.java @@ -0,0 +1,50 @@ +package com.hbm.blocks.machine.rbmk; + +import org.lwjgl.opengl.GL11; + +import com.hbm.main.MainRegistry; +import com.hbm.main.ResourceManager; +import com.hbm.tileentity.machine.rbmk.TileEntityRBMKNumitron; + +import api.hbm.block.IToolable; +import cpw.mods.fml.common.network.internal.FMLNetworkHandler; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; + +public class RBMKNumitron extends RBMKMiniPanelBase implements IToolable { + + @Override + public TileEntity createNewTileEntity(World world, int meta) { + return new TileEntityRBMKNumitron(); + } + + @Override + public boolean onScrew(World world, EntityPlayer player, int x, int y, int z, int side, float fX, float fY, float fZ, ToolType tool) { + if(tool != ToolType.SCREWDRIVER) return false; + if(world.isRemote) FMLNetworkHandler.openGui(player, MainRegistry.instance, 0, world, x, y, z); + return true; + } + + @Override + public void renderInventoryBlock(Block block, int meta, int modelId, Object renderBlocks) { + super.renderInventoryBlock(block, meta, modelId, renderBlocks); + + GL11.glPushMatrix(); + GL11.glTranslated(0, -0.5, 0); + GL11.glRotated(-90, 0, 1, 0); + + for(int i = 0; i < 2; i++) { + + GL11.glPushMatrix(); + GL11.glTranslated(0.25, i * -0.5 + 0.25, 0); + Minecraft.getMinecraft().getTextureManager().bindTexture(ResourceManager.rbmk_numitron_tex); + ResourceManager.rbmk_numitron.renderAll(); + GL11.glPopMatrix(); + } + + GL11.glPopMatrix(); + } +} diff --git a/src/main/java/com/hbm/inventory/gui/GUIScreenRBMKDisplay.java b/src/main/java/com/hbm/inventory/gui/GUIScreenRBMKDisplay.java new file mode 100644 index 000000000..3a69051be --- /dev/null +++ b/src/main/java/com/hbm/inventory/gui/GUIScreenRBMKDisplay.java @@ -0,0 +1,149 @@ +package com.hbm.inventory.gui; + +import org.lwjgl.input.Keyboard; +import org.lwjgl.opengl.GL11; + +import com.hbm.lib.RefStrings; +import com.hbm.packet.PacketDispatcher; +import com.hbm.packet.toserver.NBTControlPacket; +import com.hbm.tileentity.machine.rbmk.TileEntityRBMKNumitron; +import com.hbm.util.i18n.I18nUtil; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.audio.PositionedSoundRecord; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.gui.GuiTextField; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.ResourceLocation; + +public class GUIScreenRBMKDisplay extends GuiScreen { + + private static ResourceLocation texture = new ResourceLocation(RefStrings.MODID + ":textures/gui/machine/gui_rbmk_numitron.png"); + public TileEntityRBMKNumitron display; + protected int xSize = 256; + protected int ySize = 114; + protected int guiLeft; + protected int guiTop; + + protected GuiTextField[] label = new GuiTextField[2]; + protected GuiTextField[] rtty = new GuiTextField[2]; + protected boolean[] active = new boolean[2]; + protected boolean[] polling = new boolean[2]; + + public GUIScreenRBMKDisplay(TileEntityRBMKNumitron display) { + this.display = display; + } + + @Override + public void initGui() { + super.initGui(); + this.guiLeft = (this.width - this.xSize) / 2; + this.guiTop = (this.height - this.ySize) / 2; + + Keyboard.enableRepeatEvents(true); + + int oX = 4; + int oY = 4; + + for(int i = 0; i < 2; i++) { + label[i] = new GuiTextField(this.fontRendererObj, guiLeft + 175 + oX, guiTop + 55 + oY + i * 36, 72 - oX * 2, 14); + GUIScreenRBMKKeyPad.setupTextFieldStandard(label[i], 30, display.displays[i].label); + rtty[i] = new GuiTextField(this.fontRendererObj, guiLeft + 27 + oX, guiTop + 55 + oY + i * 36, 72 - oX * 2, 14); + GUIScreenRBMKKeyPad.setupTextFieldStandard(rtty[i], 10, display.displays[i].rtty); + + active[i] = display.displays[i].active; + polling[i] = display.displays[i].polling; + } + } + + @Override + public void drawScreen(int mouseX, int mouseY, float f) { + this.drawDefaultBackground(); + this.drawGuiContainerBackgroundLayer(f, mouseX, mouseY); + GL11.glDisable(GL11.GL_LIGHTING); + this.drawGuiContainerForegroundLayer(mouseX, mouseY); + GL11.glEnable(GL11.GL_LIGHTING); + } + + private void drawGuiContainerForegroundLayer(int x, int y) { + String name = I18nUtil.resolveKey("container.rbmkNumitron"); + this.fontRendererObj.drawString(name, this.guiLeft + this.xSize / 2 - this.fontRendererObj.getStringWidth(name) / 2, this.guiTop + 6, 4210752); + } + + private void drawGuiContainerBackgroundLayer(float f, int mouseX, int mouseY) { + GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + Minecraft.getMinecraft().getTextureManager().bindTexture(texture); + drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize); + + for(int i = 0; i < 2; i++) { + if(this.active[i]) drawTexturedModalRect(guiLeft + 111, guiTop + i * 36 + 54, 18, 114, 16, 16); + if(this.polling[i]) drawTexturedModalRect(guiLeft + 128, guiTop + i * 36 + 53, 0, 114, 18, 18); + } + + for(int i = 0; i < 2; i++) { + this.label[i].drawTextBox(); + this.rtty[i].drawTextBox(); + } + } + + @Override + protected void mouseClicked(int x, int y, int b) { + super.mouseClicked(x, y, b); + + for(int i = 0; i < 2; i++) { + if(guiLeft + 111 <= x && guiLeft + 111 + 16 > x && guiTop + i * 36 + 54 < y && guiTop + i * 36 + 54 + 16 >= y) { + this.active[i] = !this.active[i]; + mc.getSoundHandler().playSound(PositionedSoundRecord.func_147674_a(new ResourceLocation("gui.button.press"), 0.5F + (this.active[i] ? 0.25F : 0F))); + return; + } + + if(guiLeft + 128 <= x && guiLeft + 128 + 18 > x && guiTop + i * 36 + 53 < y && guiTop + i * 36 + 53 + 18 >= y) { + this.polling[i] = !this.polling[i]; + mc.getSoundHandler().playSound(PositionedSoundRecord.func_147674_a(new ResourceLocation("gui.button.press"), 0.5F + (this.polling[i] ? 0.25F : 0F))); + return; + } + } + + if(guiLeft + 209 <= x && guiLeft + 209 + 18 > x && guiTop + 17 < y && guiTop + 17 + 18 >= y) { + mc.getSoundHandler().playSound(PositionedSoundRecord.func_147674_a(new ResourceLocation("gui.button.press"), 1.0F)); + NBTTagCompound data = new NBTTagCompound(); + byte active = 0; + byte polling = 0; + for(int i = 0; i < 2; i++) { + if(this.active[i]) active |= 1 << i; + if(this.polling[i]) polling |= 1 << i; + } + data.setByte("active", active); + data.setByte("polling", polling); + + for(int i = 0; i < 2; i++) { + data.setString("label" + i, this.label[i].getText()); + data.setString("rtty" + i, this.rtty[i].getText()); + } + PacketDispatcher.wrapper.sendToServer(new NBTControlPacket(data, display.xCoord, display.yCoord, display.zCoord)); + return; + } + + for(int i = 0; i < 2; i++) { + this.label[i].mouseClicked(x, y, b); + this.rtty[i].mouseClicked(x, y, b); + } + } + + @Override + protected void keyTyped(char c, int b) { + + for(int i = 0; i < 2; i++) { + if(this.label[i].textboxKeyTyped(c, b)) return; + if(this.rtty[i].textboxKeyTyped(c, b)) return; + } + + if(b == 1 || b == this.mc.gameSettings.keyBindInventory.getKeyCode()) { + this.mc.thePlayer.closeScreen(); + this.mc.setIngameFocus(); + } + } + + @Override public void onGuiClosed() { Keyboard.enableRepeatEvents(false); } + @Override public boolean doesGuiPauseGame() { return false; } +} diff --git a/src/main/java/com/hbm/inventory/gui/GUIScreenRBMKGauge.java b/src/main/java/com/hbm/inventory/gui/GUIScreenRBMKGauge.java index d58cb92e8..ed6ea5adf 100644 --- a/src/main/java/com/hbm/inventory/gui/GUIScreenRBMKGauge.java +++ b/src/main/java/com/hbm/inventory/gui/GUIScreenRBMKGauge.java @@ -35,9 +35,6 @@ public class GUIScreenRBMKGauge extends GuiScreen { public GUIScreenRBMKGauge(TileEntityRBMKGauge keypad) { this.keypad = keypad; - - this.xSize = 256; - this.ySize = 204; } @Override diff --git a/src/main/java/com/hbm/main/ClientProxy.java b/src/main/java/com/hbm/main/ClientProxy.java index a2f00e00a..926670368 100644 --- a/src/main/java/com/hbm/main/ClientProxy.java +++ b/src/main/java/com/hbm/main/ClientProxy.java @@ -413,6 +413,7 @@ public class ClientProxy extends ServerProxy { ClientRegistry.bindTileEntitySpecialRenderer(TileEntityRBMKDisplay.class, new RenderRBMKDisplay()); ClientRegistry.bindTileEntitySpecialRenderer(TileEntityRBMKKeyPad.class, new RenderRBMKKeyPad()); ClientRegistry.bindTileEntitySpecialRenderer(TileEntityRBMKGauge.class, new RenderRBMKGauge()); + ClientRegistry.bindTileEntitySpecialRenderer(TileEntityRBMKNumitron.class, new RenderRBMKNumitron()); ClientRegistry.bindTileEntitySpecialRenderer(TileEntityRBMKRod.class, new RenderRBMKFuelChannel()); ClientRegistry.bindTileEntitySpecialRenderer(TileEntityRBMKRodReaSim.class, new RenderRBMKFuelChannel()); ClientRegistry.bindTileEntitySpecialRenderer(TileEntityRBMKAutoloader.class, new RenderRBMKAutoloader()); diff --git a/src/main/java/com/hbm/main/CraftingManager.java b/src/main/java/com/hbm/main/CraftingManager.java index 488100db5..42a3e74cc 100644 --- a/src/main/java/com/hbm/main/CraftingManager.java +++ b/src/main/java/com/hbm/main/CraftingManager.java @@ -790,9 +790,12 @@ public class CraftingManager { addRecipeAuto(new ItemStack(ModBlocks.rbmk_loader, 1), new Object[] { "SCS", "CBC", "SCS", 'S', STEEL.plate(), 'C', CU.ingot(), 'B', ModItems.tank_steel }); addRecipeAuto(new ItemStack(ModBlocks.rbmk_steam_inlet, 1), new Object[] { "SCS", "CBC", "SCS", 'S', STEEL.ingot(), 'C', IRON.plate(), 'B', ModItems.tank_steel }); addRecipeAuto(new ItemStack(ModBlocks.rbmk_steam_outlet, 1), new Object[] { "SCS", "CBC", "SCS", 'S', STEEL.ingot(), 'C', CU.plate(), 'B', ModItems.tank_steel }); - addRecipeAuto(new ItemStack(ModBlocks.rbmk_display, 1), new Object[] { "B", "C", "D", 'B', B.ingot(), 'D', ModBlocks.deco_rbmk, 'C', DictFrame.fromOne(ModItems.circuit, EnumCircuitType.VACUUM_TUBE) }); - addRecipeAuto(new ItemStack(ModBlocks.rbmk_key_pad, 1), new Object[] { "B", "C", "D", 'B', ModBlocks.radio_torch_sender, 'D', ModBlocks.deco_rbmk, 'C', DictFrame.fromOne(ModItems.circuit, EnumCircuitType.ANALOG) }); - addRecipeAuto(new ItemStack(ModBlocks.rbmk_gauge, 1), new Object[] { "B", "C", "D", 'B', ModBlocks.radio_torch_receiver, 'D', ModBlocks.deco_rbmk, 'C', DictFrame.fromOne(ModItems.circuit, EnumCircuitType.VACUUM_TUBE) }); + + addRecipeAuto(new ItemStack(ModBlocks.rbmk_display_blank, 8), new Object[] { "B", "D", 'B', B.ingot(), 'D', ModBlocks.concrete_asbestos }); + addRecipeAuto(new ItemStack(ModBlocks.rbmk_display, 1), new Object[] { "C", "B", 'C', ModItems.crt_display, 'B', ModBlocks.rbmk_display_blank }); + addRecipeAuto(new ItemStack(ModBlocks.rbmk_key_pad, 1), new Object[] { "R", "C", "B", 'R', ModBlocks.radio_torch_sender, 'B', ModBlocks.rbmk_display_blank, 'C', DictFrame.fromOne(ModItems.circuit, EnumCircuitType.ANALOG) }); + addRecipeAuto(new ItemStack(ModBlocks.rbmk_gauge, 1), new Object[] { "R", "C", "B", 'R', ModBlocks.radio_torch_receiver, 'B', ModBlocks.rbmk_display_blank, 'C', DictFrame.fromOne(ModItems.circuit, EnumCircuitType.VACUUM_TUBE) }); + addRecipeAuto(new ItemStack(ModBlocks.rbmk_numitron, 1), new Object[] { " R ", "CCC", " B ", 'R', ModBlocks.radio_torch_receiver, 'B', ModBlocks.rbmk_display_blank, 'C', DictFrame.fromOne(ModItems.circuit, EnumCircuitType.NUMITRON) }); addRecipeAuto(new ItemStack(ModBlocks.deco_rbmk, 8), new Object[] { "R", 'R', ModBlocks.rbmk_blank }); addRecipeAuto(new ItemStack(ModBlocks.deco_rbmk_smooth, 1), new Object[] { "R", 'R', ModBlocks.deco_rbmk }); diff --git a/src/main/java/com/hbm/main/ResourceManager.java b/src/main/java/com/hbm/main/ResourceManager.java index c8b8c7898..9c939b8b3 100644 --- a/src/main/java/com/hbm/main/ResourceManager.java +++ b/src/main/java/com/hbm/main/ResourceManager.java @@ -1628,6 +1628,7 @@ public class ResourceManager { public static final HFRWavefrontObjectVBO rbmk_console = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/rbmk/rbmk_console.obj")).asVBO(); public static final HFRWavefrontObjectVBO rbmk_button = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/rbmk/button.obj")).asVBO(); public static final HFRWavefrontObjectVBO rbmk_gauge = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/rbmk/gauge.obj")).asVBO(); + public static final HFRWavefrontObjectVBO rbmk_numitron = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/rbmk/numitron.obj")).asVBO(); public static final HFRWavefrontObject rbmk_debris = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/rbmk/debris.obj")).noSmooth(); public static final ResourceLocation rbmk_crane_console_tex = new ResourceLocation(RefStrings.MODID, "textures/models/machines/crane_console.png"); public static final ResourceLocation rbmk_crane_tex = new ResourceLocation(RefStrings.MODID, "textures/models/machines/rbmk_crane.png"); @@ -1635,6 +1636,8 @@ public class ResourceManager { public static final ResourceLocation rbmk_console_tex = new ResourceLocation(RefStrings.MODID, "textures/models/machines/rbmk_control.png"); public static final ResourceLocation rbmk_keypad_tex = new ResourceLocation(RefStrings.MODID, "textures/models/network/keypad.png"); public static final ResourceLocation rbmk_gauge_tex = new ResourceLocation(RefStrings.MODID, "textures/models/network/gauge.png"); + public static final ResourceLocation rbmk_numitron_tex = new ResourceLocation(RefStrings.MODID, "textures/models/network/numitron.png"); + public static final ResourceLocation rbmk_numitron_lights_tex = new ResourceLocation(RefStrings.MODID, "textures/models/network/numitron_lights.png"); public static final HFRWavefrontObject hev_battery = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/blocks/battery.obj")).noSmooth(); public static final HFRWavefrontObject anvil = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/blocks/anvil.obj")).noSmooth(); public static final HFRWavefrontObject crystal_power = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/blocks/crystals_power.obj")).noSmooth(); diff --git a/src/main/java/com/hbm/render/tileentity/RenderRBMKNumitron.java b/src/main/java/com/hbm/render/tileentity/RenderRBMKNumitron.java new file mode 100644 index 000000000..b8525d486 --- /dev/null +++ b/src/main/java/com/hbm/render/tileentity/RenderRBMKNumitron.java @@ -0,0 +1,112 @@ +package com.hbm.render.tileentity; + +import org.lwjgl.opengl.GL11; + +import com.hbm.main.ResourceManager; +import com.hbm.tileentity.machine.rbmk.TileEntityRBMKNumitron; +import com.hbm.tileentity.machine.rbmk.TileEntityRBMKNumitron.DisplayUnit; +import com.hbm.util.BobMathUtil; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; +import net.minecraft.tileentity.TileEntity; + +public class RenderRBMKNumitron extends TileEntitySpecialRenderer { + + @Override + public void renderTileEntityAt(TileEntity te, double x, double y, double z, float interp) { + + GL11.glPushMatrix(); + GL11.glTranslated(x + 0.5, y, z + 0.5); + GL11.glEnable(GL11.GL_CULL_FACE); + GL11.glEnable(GL11.GL_LIGHTING); + + switch(te.getBlockMetadata()) { + case 2: GL11.glRotatef(90, 0F, 1F, 0F); break; + case 4: GL11.glRotatef(180, 0F, 1F, 0F); break; + case 3: GL11.glRotatef(270, 0F, 1F, 0F); break; + case 5: GL11.glRotatef(0, 0F, 1F, 0F); break; + } + + TileEntityRBMKNumitron gauge = (TileEntityRBMKNumitron) te; + + for(int i = 0; i < 2; i++) { + DisplayUnit unit = gauge.displays[i]; + if(!unit.active) continue; + + GL11.glPushMatrix(); + GL11.glTranslated(0.25, i * -0.5 + 0.25, 0); + + GL11.glColor3f(1F, 1F, 1F); + this.bindTexture(ResourceManager.rbmk_numitron_tex); + ResourceManager.rbmk_numitron.renderAll(); + + GL11.glPushMatrix(); + + RenderArcFurnace.fullbright(true); + GL11.glEnable(GL11.GL_LIGHTING); + + this.bindTexture(ResourceManager.rbmk_numitron_lights_tex); + + double scale = 200D; + double w = 8D / scale; + double h = 13D / scale; + double yOffset = 0.5625D; + + String value = BobMathUtil.getShortNumber(unit.value); + while(value.length() < 7) value = "0" + value; + + Tessellator tess = Tessellator.instance; + tess.startDrawingQuads(); + for(int j = 0; j < 7; j++) { + double zOffset = (j - 3) * 0.1D; + char c = value.charAt(j); + double u = -1; + double v = 0; + if(c == '.') {u = 0.9; v = 0.5;} + if(c == '-') {u = 0.8; v = 0.5;} + else if(c == 'k') {u = 0.0; v = 0.5;} + else if(c == 'M') {u = 0.1; v = 0.5;} + else if(c == 'G') {u = 0.2; v = 0.5;} + else if(c == 'T') {u = 0.3; v = 0.5;} + else if(c == 'P') {u = 0.4; v = 0.5;} // i would love to say this sucks, but this is actually surprisingly easy to read and probably the most performant way of doing it + int charVal = c - '0'; // no string operations, no int parsing, no nothing, we just rawdog shit shit + if(charVal >= 0 && charVal <= 9) {u = 0.1 * charVal; v = 0.0;} + if(u == -1) {u = 0.8; v = 0.5;} + tess.setNormal(0F, 1F, 0F); + tess.addVertexWithUV(0.03135, -h + yOffset, w - zOffset, u, v + 0.5); + tess.addVertexWithUV(0.03135, h + yOffset, w - zOffset, u, v); + tess.addVertexWithUV(0.03135, h + yOffset, -w - zOffset, u + 0.1, v); + tess.addVertexWithUV(0.03135, -h + yOffset, -w - zOffset, u + 0.1, v + 0.5); + } + tess.draw(); + + RenderArcFurnace.fullbright(false); + + GL11.glPopMatrix(); + + FontRenderer font = Minecraft.getMinecraft().fontRenderer; + int height = font.FONT_HEIGHT; + + if(unit.label != null && !unit.label.isEmpty()) { + + GL11.glTranslated(0.01, 0.3125, 0); + int width = font.getStringWidth(unit.label); + float f3 = Math.min(0.0125F, 0.75F / Math.max(width, 1)); + GL11.glScalef(f3, -f3, f3); + GL11.glNormal3f(0.0F, 0.0F, -1.0F); + GL11.glRotatef(90, 0, 1, 0); + + RenderArcFurnace.fullbright(true); + font.drawString(unit.label, - width / 2, - height / 2, 0x00ff00); + RenderArcFurnace.fullbright(false); + } + GL11.glPopMatrix(); + } + + GL11.glPopMatrix(); + } + +} diff --git a/src/main/java/com/hbm/tileentity/TileMappings.java b/src/main/java/com/hbm/tileentity/TileMappings.java index a71101a50..ad2fc1d9c 100644 --- a/src/main/java/com/hbm/tileentity/TileMappings.java +++ b/src/main/java/com/hbm/tileentity/TileMappings.java @@ -405,6 +405,7 @@ public class TileMappings { put(TileEntityRBMKDisplay.class, "tileentity_rbmk_display"); put(TileEntityRBMKKeyPad.class, "tileentity_rbmk_keypad"); put(TileEntityRBMKGauge.class, "tileentity_rbmk_gauge"); + put(TileEntityRBMKNumitron.class, "tileentity_rbmk_numitron"); put(TileEntityRBMKInlet.class, "tileentity_rbmk_inlet"); put(TileEntityRBMKOutlet.class, "tileentity_rbmk_outlet"); put(TileEntityRBMKAutoloader.class, "tileentity_rbmk_autoloader"); diff --git a/src/main/java/com/hbm/tileentity/machine/rbmk/TileEntityRBMKNumitron.java b/src/main/java/com/hbm/tileentity/machine/rbmk/TileEntityRBMKNumitron.java new file mode 100644 index 000000000..2bbe3477b --- /dev/null +++ b/src/main/java/com/hbm/tileentity/machine/rbmk/TileEntityRBMKNumitron.java @@ -0,0 +1,165 @@ +package com.hbm.tileentity.machine.rbmk; + +import com.hbm.interfaces.IControlReceiver; +import com.hbm.inventory.gui.GUIScreenRBMKDisplay; +import com.hbm.tileentity.IGUIProvider; +import com.hbm.tileentity.TileEntityLoadedBase; +import com.hbm.tileentity.network.RTTYSystem; +import com.hbm.tileentity.network.RTTYSystem.RTTYChannel; +import com.hbm.util.BufferUtil; + +import io.netty.buffer.ByteBuf; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.Container; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.world.World; + +public class TileEntityRBMKNumitron extends TileEntityLoadedBase implements IGUIProvider, IControlReceiver { + + /* __________ + * / /| + * /________ / | + * | _______ | | + * ||_______|| | + * | _______ | | + * ||_______|| / + * |_________|/ + */ + + public DisplayUnit[] displays = new DisplayUnit[2]; + + public TileEntityRBMKNumitron() { + for(int i = 0; i < 2; i++) this.displays[i] = new DisplayUnit(i); + } + + @Override + public void updateEntity() { + + if(!worldObj.isRemote) { + + for(int i = 0; i < 2; i++) this.displays[i].update(); + + this.networkPackNT(50); + } + } + + @Override + public void serialize(ByteBuf buf) { + super.serialize(buf); + for(int i = 0; i < 2; i++) this.displays[i].serialize(buf); + } + + @Override + public void deserialize(ByteBuf buf) { + super.deserialize(buf); + for(int i = 0; i < 2; i++) this.displays[i].deserialize(buf); + } + + @Override + public void readFromNBT(NBTTagCompound nbt) { + super.readFromNBT(nbt); + + for(int i = 0; i < 2; i++) this.displays[i].readFromNBT(nbt, i); + } + + @Override + public void writeToNBT(NBTTagCompound nbt) { + super.writeToNBT(nbt); + + for(int i = 0; i < 2; i++) this.displays[i].writeToNBT(nbt, i); + } + + public class DisplayUnit { + + /** If the value should be pulled from the RTTY system every tick, otherwise only on state change */ + public boolean polling; + /** Label on the display as rendered on the panel */ + public String label = ""; + /** What channel to read values from */ + public String rtty = ""; + /** The current read value on the display */ + public int value; + /** Whether this gauge is visible on the panel */ + public boolean active; + + public DisplayUnit(int initialIndex) { + label = "Display " + (initialIndex + 1); + } + + public void update() { + if(!active) return; + if(rtty == null || rtty.isEmpty()) return; + + RTTYChannel chan = RTTYSystem.listen(worldObj, rtty); + int sigVal = 0; + + if(chan != null && chan.timeStamp < worldObj.getTotalWorldTime() - 1) chan = null; + + // always accept new signals + if(chan != null && chan.signal != null) { + try { sigVal = Integer.parseInt(chan.signal.toString()); } catch(Exception ex) { } + this.value = sigVal; + } else { + // if there's no new signal and we're polling, set to 0 + if(polling) this.value = 0; + } + } + + public void serialize(ByteBuf buf) { + buf.writeBoolean(active); + buf.writeBoolean(polling); + BufferUtil.writeString(buf, label); + BufferUtil.writeString(buf, rtty); + buf.writeInt(value); + } + + public void deserialize(ByteBuf buf) { + active = buf.readBoolean(); + polling = buf.readBoolean(); + label = BufferUtil.readString(buf); + rtty = BufferUtil.readString(buf); + value = buf.readInt(); + } + + public void readFromNBT(NBTTagCompound nbt, int index) { + this.active = nbt.getBoolean("active" + index); + this.polling = nbt.getBoolean("polling" + index); + this.label = nbt.getString("label" + index); + this.rtty = nbt.getString("rtty" + index); + this.value = nbt.getInteger("value" + index); + } + + public void writeToNBT(NBTTagCompound nbt, int index) { + nbt.setBoolean("active" + index, active); + nbt.setBoolean("polling" + index, polling); + nbt.setString("label" + index, label); + nbt.setString("rtty" + index, rtty); + nbt.setInteger("value" + index, value); + } + } + + @Override public Container provideContainer(int ID, EntityPlayer player, World world, int x, int y, int z) { return null; } + @Override public Object provideGUI(int ID, EntityPlayer player, World world, int x, int y, int z) { return new GUIScreenRBMKDisplay(this); } + + @Override + public boolean hasPermission(EntityPlayer player) { + return player.getDistanceSq(xCoord + 0.5, yCoord + 0.5, zCoord + 0.5) < 15 * 15; + } + + @Override + public void receiveControl(NBTTagCompound data) { + + int active = data.getByte("active"); + int polling = data.getByte("polling"); + for(int i = 0; i < 2; i++) { + this.displays[i].active = (active & (1 << i)) != 0; + this.displays[i].polling = (polling & (1 << i)) != 0; + } + + for(int i = 0; i < 2; i++) { + DisplayUnit display = this.displays[i]; + display.label = data.getString("label" + i); + display.rtty = data.getString("rtty" + i); + } + } +} diff --git a/src/main/resources/assets/hbm/lang/de_DE.lang b/src/main/resources/assets/hbm/lang/de_DE.lang index 2afa8b763..6b18c92ed 100644 --- a/src/main/resources/assets/hbm/lang/de_DE.lang +++ b/src/main/resources/assets/hbm/lang/de_DE.lang @@ -463,8 +463,10 @@ container.rbmkAutoloader=RBMK-Ladeautomat container.rbmkBoiler=RBMK Dampfkanal container.rbmkControl=RBMK Steuerstäbe container.rbmkControlAuto=RBMK Automatische Steuerstäbe +container.rbmkGauge=Redstone-over-Radio Meter container.rbmkHeater=RBMK Heizer container.rbmkKeyPad=Redstone-over-Radio Tastenfeld +container.rbmkNumitron=Redstone-over-Radio Ziffernanzeige container.rbmkOutgasser=RBMK Bestrahlungskanal container.rbmkReaSim=RBMK Brennstäbe (ReaSim) container.rbmkRod=RBMK Brennstäbe @@ -4904,11 +4906,13 @@ tile.rbmk_control_reasim.name=RBMK Steuerstäbe (ReaSim) tile.rbmk_control_reasim_auto.name=RBMK Automatische Steuerstäbe (ReaSim) tile.rbmk_crane_console.name=RBMK Kransteuerung tile.rbmk_display.name=RBMK Anzeigepanel +tile.rbmk_display_blank.name=Leeres Redstone-over-Radio Panel tile.rbmk_gauge.name=Redstone-over-Radio Meter tile.rbmk_heater.name=RBMK-Heizer tile.rbmk_key_pad.name=Redstone-over-Radio Tastenfeld tile.rbmk_loader.name=RBMK-Dampfadapter tile.rbmk_moderator.name=RBMK Graphitmoderator +tile.rbmk_numitron.name=Redstone-over-Radio Ziffernanzeige tile.rbmk_outgasser.name=RBMK Bestrahlungskanal tile.rbmk_reflector.name=RBMK Wolframcarbid-Moderator tile.rbmk_rod.name=RBMK Brennstäbe diff --git a/src/main/resources/assets/hbm/lang/en_US.lang b/src/main/resources/assets/hbm/lang/en_US.lang index 3e0fed257..aa6985374 100644 --- a/src/main/resources/assets/hbm/lang/en_US.lang +++ b/src/main/resources/assets/hbm/lang/en_US.lang @@ -871,8 +871,10 @@ container.rbmkAutoloader=RBMK Autoloader container.rbmkBoiler=RBMK Steam Channel container.rbmkControl=RBMK Control Rods container.rbmkControlAuto=RBMK Automatic Control Rods +container.rbmkGauge=Redstone-over-Radio Gauge container.rbmkHeater=RBMK Fluid Heater container.rbmkKeyPad=Redstone-over-Radio Keypad +container.rbmkNumitron=Redstone-over-Radio Numeric Display container.rbmkOutgasser=RBMK Irradiation Channel container.rbmkReaSim=RBMK Fuel Rod (ReaSim) container.rbmkRod=RBMK Fuel Rod @@ -6172,12 +6174,14 @@ tile.rbmk_control_reasim.name=RBMK Control Rods (ReaSim) tile.rbmk_control_reasim_auto.name=RBMK Automatic Control Rods (ReaSim) tile.rbmk_crane_console.name=RBMK Crane Console tile.rbmk_display.name=RBMK Display Panel +tile.rbmk_display_blank.name=Blank Redstone-over-Radio Panel tile.rbmk_gauge.name=Redstone-over-Radio Gauge tile.rbmk_heater.name=RBMK Fluid Heater tile.rbmk_key_pad.name=Redstone-over-Radio Keypad tile.rbmk_loader.name=RBMK Steam Connector tile.rbmk_loader.desc=Allows RBMKs to have both water and steam connections at the bottom$Place one water pipe below the RBMK column, then the connector,$then connect the steam duct to the connector. tile.rbmk_moderator.name=RBMK Graphite Moderator +tile.rbmk_numitron.name=Redstone-over-Radio Numeric Display tile.rbmk_outgasser.name=RBMK Irradiation Channel tile.rbmk_reflector.name=RBMK Tungsten Carbide Neutron Reflector tile.rbmk_rod.name=RBMK Fuel Channel diff --git a/src/main/resources/assets/hbm/models/rbmk/numitron.obj b/src/main/resources/assets/hbm/models/rbmk/numitron.obj new file mode 100644 index 000000000..0b3b6c84a --- /dev/null +++ b/src/main/resources/assets/hbm/models/rbmk/numitron.obj @@ -0,0 +1,79 @@ +# Blender v2.79 (sub 0) OBJ File: '' +# www.blender.org +o Plane +v 0.000000 0.718750 0.406250 +v 0.000000 0.406250 0.406250 +v 0.000000 0.718750 -0.406250 +v 0.000000 0.406250 -0.406250 +v 0.031250 0.687500 -0.375000 +v 0.031250 0.687500 0.375000 +v 0.031250 0.437500 0.375000 +v 0.031250 0.437500 -0.375000 +v 0.062500 0.687500 -0.375000 +v 0.062500 0.687500 0.375000 +v 0.062500 0.437500 0.375000 +v 0.062500 0.437500 -0.375000 +v 0.062500 0.718750 -0.406250 +v 0.062500 0.718750 0.406250 +v 0.062500 0.406250 0.406250 +v 0.062500 0.406250 -0.406250 +vt -0.000000 -0.000000 +vt 0.800000 0.363636 +vt -0.000000 0.363636 +vt 0.933333 0.363636 +vt 0.066667 0.454545 +vt 0.066667 0.363636 +vt 0.066667 0.863636 +vt 0.100000 0.500000 +vt 0.066667 0.500000 +vt 0.933333 0.500000 +vt 0.900000 0.862201 +vt 0.933333 0.863636 +vt -0.000000 0.454545 +vt 0.066667 0.909091 +vt -0.000000 0.909091 +vt 0.100000 0.863636 +vt 0.933333 0.454545 +vt 0.900000 0.498565 +vt 0.933333 0.909091 +vt 0.066667 1.000000 +vt 0.933333 1.000000 +vt 0.100000 0.454545 +vt 0.900000 0.459670 +vt 0.900000 0.914216 +vt 0.100000 0.909091 +vt 1.000000 0.909091 +vt 1.000000 0.454545 +vt 0.800000 -0.000000 +vn 1.0000 0.0000 0.0000 +vn 0.0000 -1.0000 0.0000 +vn 0.0000 0.0000 -1.0000 +vn 0.0000 0.0000 1.0000 +vn 0.0000 1.0000 0.0000 +s off +f 7/1/1 5/2/1 6/3/1 +f 4/4/2 15/5/2 2/6/2 +f 6/7/3 11/8/3 7/9/3 +f 8/10/4 9/11/4 5/12/4 +f 2/13/4 14/14/4 1/15/4 +f 9/11/1 14/14/1 10/16/1 +f 10/16/1 15/5/1 11/8/1 +f 11/8/1 16/17/1 12/18/1 +f 12/18/1 13/19/1 9/11/1 +f 1/20/5 13/19/5 3/21/5 +f 7/22/5 12/18/5 8/23/5 +f 5/24/2 10/16/2 6/25/2 +f 3/26/3 16/17/3 4/27/3 +f 7/1/1 8/28/1 5/2/1 +f 4/4/2 16/17/2 15/5/2 +f 6/7/3 10/16/3 11/8/3 +f 8/10/4 12/18/4 9/11/4 +f 2/13/4 15/5/4 14/14/4 +f 9/11/1 13/19/1 14/14/1 +f 10/16/1 14/14/1 15/5/1 +f 11/8/1 15/5/1 16/17/1 +f 12/18/1 16/17/1 13/19/1 +f 1/20/5 14/14/5 13/19/5 +f 7/22/5 11/8/5 12/18/5 +f 5/24/2 9/11/2 10/16/2 +f 3/26/3 13/19/3 16/17/3 diff --git a/src/main/resources/assets/hbm/textures/gui/machine/gui_rbmk_numitron.png b/src/main/resources/assets/hbm/textures/gui/machine/gui_rbmk_numitron.png new file mode 100644 index 0000000000000000000000000000000000000000..f340bfb02c4ca8c20a73e4b818294d2923be3d0b GIT binary patch literal 2618 zcmc)Mc~p|=9tZFjG&HR-Y%((k&83_%Q!~evv<6A7q`ZzRp<`xhWm>tsxIkH{sp*Vn zV!R4*R%@KIN`Wc9EN09ZfofjZ!mSS;jX z&Tl`3P@5a=_i`VIqPhPpp>H*L5?y}FEU*$gF20_p^W>WGxOb)4G$v|AgKh}%)PGKXu3y?d7BwdZp<6<<<^_jFw$$b_boD8CR{#?mfdd&--bEoq_Pr7cfs(TS;j)Z zJ8zL0Nl4&jts`q%VQ$-vWKGqrc}B?c3UXamtV%f(tWrxLb!mPiv{&O!mec4A8r33^ z#QWe0_ve2I{BGhjgyaVWw08oAKmCvJ4H9cKMp3ptCugF#>YzrcU>Z*VSkO>o)^=R*isFIl2rECI}SY8UrDovoGVo9d;tKw127U zAI1IY=W*o2CVaDMuLD=rU{eH?iHE(CjA_H8fSHgqh(?W@1VT zGCm=p0_XJ|UV+P}%Qz#M%;}jCoHPA`wb2cjbB;4>SCeTWzUZC@Ke99lDqmp+d(}bD z-(#+HYZPB{sGL$Hb-m*<7)#6YwWXmu%kc}cDY?Yd8zZvzKpy=X7#Q&Gt*D!vt7}YZ zpI$FZR>-q^!}jtc!6RP-LbcZEGouOw9IjaA1>aj4?kU+H?eLIX<#-IkaXPLQ;=ge7 za9C!_i_X$jgZWF}U`OfJ7e-h!$$Qxs?C+jj1g@vd%)&QJuXh(rG>C*B*JwF?!KC+6 z7GKwu_SODGQCq)S6qYiYfnnTaxw6Zzk`bX#8&ALIS)#!-Qve2HWWB~5q|>N zb?jRtG4@{j(bH7$+~@RxfdP;&3irU&2`Om@a+r3i-5kLb#LAn-mZrbj_aZKj2cA85 z&JEQCL{){$g@V4`;!? zH~%vJ-em7;!~0suT~t8aebOV|0C9tD)(oMA6Bm;*(bfUFG>YD$-j9WOf{rnS+-45; zeeCBRO_d7P^zz19N7%3AG_8@B){+M%ebaX1911L*h%dq^O+CY_@4gL+fd%JW3FFMq zC+KUPXHX~x&JSbbNQ>LM zjRr@#%SJ{zE(;s(FlLs15em;qRj(F&Ih~b EdVH&i@0!H~2Yq}X2)ILsx#!;jEL zQ>5H$WOXZ-p`jr-JfPQ(!63##K3QgEbm--@b>}p(BU;d-4ZnL@lm?pP%uCoX@|*GC zTG8P1AFGZMbRjmrS!TRfo3@uo158W3bNmCc{8Ow;>vfJNJy;qTGk~Y(8cPh&`p!2a zY>lJqjmAH9WdzY41*&~qg56Xdek;m|Z|wg;ch2!FHqkeezC25Ct3sfQ9WoMQT|$M1 zq2&RcF~@QeUuw_C*p9P3TT(5?XBE^5h~{2)t84xfpRx!UVKCQz)qb3no3+VbsM?(R zJVN$7997QY*ZQJ@W({;6)B%sXZ$uM{9nAC;4Ts}8TDL=;`c@DtiBJ z{lN5AP;UQN=g_KFR7r|la@_KMiQ7K&R+i*x>&vb{)R3(QRlU4qUBov!Y00Ew9${>5 ziWn?445`(gr~76@66t}RL)h3&n{*!50TBotV;RYTH7ao0xD;VJ&OB{2L)juiRHN&} zKnUDZ2vPpA(#uj3PjRx@_5SJ^xK{5CPzY^)UEruq?a2;JJm10w<>^n$(xEi-F-JrH z>|KzU;tHnZ!%z}+F5LV^&04@ydxqbTUF@pY55#q?{SHjqym-2VNj zFDmxOV5b{pYr-mfx?cd&ku_TVH79UOP^v$)TnG(=-#v^UE2!+77EYa|Rmjwoudx4D bJN81MQYo&;)DCr2e5t|1%?nk1FyzV~^u*s| literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/hbm/textures/models/network/numitron.png b/src/main/resources/assets/hbm/textures/models/network/numitron.png new file mode 100644 index 0000000000000000000000000000000000000000..398f752cc545a70931b41b63eaa97b7253b39f3c GIT binary patch literal 153 zcmeAS@N?(olHy`uVBq!ia0vp^{6Ngj!3HE3xL=O}QY^(zo*^7SP{WbZ0ptgGx;Tbt zOgwsFqu>Dp4(E&g=a~(J7H6xN6=)S{HpfQ%wdUkeP@1;;v-!+UmCYRy46!^0)+>V2 ywmemLuekPa?(BAz+nG~S*w!qoKK;)24Trr$m3XK7wRRDp*$kepelF{r5}E)Np)i&J literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/hbm/textures/models/network/numitron_lights.png b/src/main/resources/assets/hbm/textures/models/network/numitron_lights.png new file mode 100644 index 0000000000000000000000000000000000000000..438ad67240cb0b3f0344740fc558f5485135e237 GIT binary patch literal 712 zcmV;(0yq7MP)mse+y~=#bKDWLcUh*%!f0B1Ef8O+gsEZ##UGTwknvi$em_EkGY*9X3A2&C~ zYyHRGU*eZ;8y;`NZCN4@bjwq{#7m&-%jG5i()-8wm$=I(G+4@0bO@8|c9qYEV-gRH zca+3S$nj5kwqQs_Bqs?!G>K0vg0mNqSQ6))=Op=1Go{E#ytN2w^)dgmeZtlxZsn~- zP}0ZzKZ}SFeg{fPRDzVmr6MB1T7)D>`jmfjCt~dcB>UDPG-dtTBDlCu`t@G*ui9Ta zk`uTw%5(E`7N_Bqh!56yxWcCvPVd%|;@wv_ zfN~T00JY~?hUx7J*nj}64sC@uF%~*?w1YaN-%>sS9 uWbTDE$ADP>D)qIo!j