From dbbe55a9906f1d97b49b3f25a869571a054acb89 Mon Sep 17 00:00:00 2001 From: Bob Date: Sat, 3 May 2025 17:54:31 +0200 Subject: [PATCH] RTTY control --- changelog | 1 + .../redstoneoverradio/IRORInteractive.java | 8 + .../blocks/network/RadioTorchController.java | 40 +++-- .../gui/GUIScreenRadioTorchController.java | 150 ++++++++++++++++++ .../gui/GUIScreenRadioTorchReader.java | 2 - .../inventory/recipes/AmmoPressRecipes.java | 7 +- .../hbm/tileentity/TileEntityProxyCombo.java | 16 +- .../java/com/hbm/tileentity/TileMappings.java | 1 + .../machine/storage/TileEntityBarrel.java | 26 ++- .../storage/TileEntityMachineFluidTank.java | 44 +++-- .../TileEntityRadioTorchController.java | 93 +++++++++++ .../gui/machine/gui_rtty_controller.png | Bin 1062 -> 1118 bytes .../textures/gui/processing/gui_crucible.png | Bin 11428 -> 12289 bytes 13 files changed, 360 insertions(+), 28 deletions(-) create mode 100644 src/main/java/com/hbm/inventory/gui/GUIScreenRadioTorchController.java create mode 100644 src/main/java/com/hbm/tileentity/network/TileEntityRadioTorchController.java diff --git a/changelog b/changelog index d97933113..8a3263181 100644 --- a/changelog +++ b/changelog @@ -24,6 +24,7 @@ * Sub-beams do not cause splash damage * Sub-beams will strike the initially hit entity again, meaning that the more sub-beams there are, the more powerful the initial strike ends up being * Renamed the default capacitor ammo to "capacitor (standard)" to avoid confusion +* Low wavelength capacitors now need niobium instead of silicon to make ## Fixed * Fixed a potential crash caused by cargo dropships landing on cargo docks with no satellite chip installed diff --git a/src/main/java/api/hbm/redstoneoverradio/IRORInteractive.java b/src/main/java/api/hbm/redstoneoverradio/IRORInteractive.java index eec685cdf..4e90ac4ad 100644 --- a/src/main/java/api/hbm/redstoneoverradio/IRORInteractive.java +++ b/src/main/java/api/hbm/redstoneoverradio/IRORInteractive.java @@ -7,6 +7,7 @@ public interface IRORInteractive extends IRORInfo { public static String EX_NULL = "Exception: Null Command"; public static String EX_NAME = "Exception: Multiple Name Separators"; + public static String EX_FORMAT = "Exception: Parameter in Invalid Format"; /** Runs a function on the ROR component, usually causing the component to change or do something. Returns are optional. */ public String runRORFunction(String name, String[] params); @@ -30,4 +31,11 @@ public interface IRORInteractive extends IRORInfo { String[] params = paramList.split(PARAM_SEPARATOR); return params; } + + public static int parseInt(String val, int min, int max) { + int result = 0; + try { result = Integer.parseInt(val); } catch(Exception x) { throw new RORFunctionException(EX_FORMAT); }; + if(result < min || result > max) throw new RORFunctionException(EX_FORMAT); + return result; + } } diff --git a/src/main/java/com/hbm/blocks/network/RadioTorchController.java b/src/main/java/com/hbm/blocks/network/RadioTorchController.java index 2857a1fc7..ce6a59105 100644 --- a/src/main/java/com/hbm/blocks/network/RadioTorchController.java +++ b/src/main/java/com/hbm/blocks/network/RadioTorchController.java @@ -1,12 +1,24 @@ package com.hbm.blocks.network; +import java.util.ArrayList; +import java.util.List; + +import com.hbm.blocks.ILookOverlay; +import com.hbm.inventory.gui.GUIScreenRadioTorchController; +import com.hbm.tileentity.network.TileEntityRadioTorchController; +import com.hbm.util.Compat; +import com.hbm.util.I18nUtil; + +import api.hbm.redstoneoverradio.IRORInteractive; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; +import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.inventory.Container; import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumChatFormatting; import net.minecraft.world.World; import net.minecraftforge.client.event.RenderGameOverlayEvent.Pre; +import net.minecraftforge.common.util.ForgeDirection; public class RadioTorchController extends RadioTorchBase { @@ -16,22 +28,32 @@ public class RadioTorchController extends RadioTorchBase { @Override public TileEntity createNewTileEntity(World world, int meta) { - return null; + return new TileEntityRadioTorchController(); } @Override - public Container provideContainer(int ID, EntityPlayer player, World world, int x, int y, int z) { - return null; + public boolean canBlockStay(World world, int x, int y, int z, ForgeDirection dir, Block b) { + TileEntity tile = Compat.getTileStandard(world, x - dir.offsetX, y - dir.offsetY, z - dir.offsetZ); + return tile instanceof IRORInteractive; + } + + @Override + public void printHook(Pre event, World world, int x, int y, int z) { + TileEntity te = world.getTileEntity(x, y, z); + + if(te instanceof TileEntityRadioTorchController) { + TileEntityRadioTorchController radio = (TileEntityRadioTorchController) te; + List text = new ArrayList(); + text.add(EnumChatFormatting.AQUA + "Freq: " + radio.channel); + ILookOverlay.printGeneric(event, I18nUtil.resolveKey(getUnlocalizedName() + ".name"), 0xffff00, 0x404000, text); + } } @Override @SideOnly(Side.CLIENT) public Object provideGUI(int ID, EntityPlayer player, World world, int x, int y, int z) { + TileEntity te = world.getTileEntity(x, y, z); + if(te instanceof TileEntityRadioTorchController) return new GUIScreenRadioTorchController((TileEntityRadioTorchController) te); return null; } - - @Override - public void printHook(Pre event, World world, int x, int y, int z) { - - } } diff --git a/src/main/java/com/hbm/inventory/gui/GUIScreenRadioTorchController.java b/src/main/java/com/hbm/inventory/gui/GUIScreenRadioTorchController.java new file mode 100644 index 000000000..52226681b --- /dev/null +++ b/src/main/java/com/hbm/inventory/gui/GUIScreenRadioTorchController.java @@ -0,0 +1,150 @@ +package com.hbm.inventory.gui; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +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.network.TileEntityRadioTorchController; +import com.hbm.util.Compat; +import com.hbm.util.I18nUtil; + +import api.hbm.redstoneoverradio.IRORInfo; +import api.hbm.redstoneoverradio.IRORValueProvider; +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.tileentity.TileEntity; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.common.util.ForgeDirection; + +public class GUIScreenRadioTorchController extends GuiScreen { + + private static ResourceLocation texture = new ResourceLocation(RefStrings.MODID + ":textures/gui/machine/gui_rtty_controller.png"); + protected TileEntityRadioTorchController rtty; + protected int xSize = 256; + protected int ySize = 204; + protected int guiLeft; + protected int guiTop; + protected GuiTextField frequency; + + public GUIScreenRadioTorchController(TileEntityRadioTorchController radio) { + this.rtty = radio; + + this.xSize = 256; + this.ySize = 42; + } + + @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; + + this.frequency = new GuiTextField(this.fontRendererObj, guiLeft + 25 + oX, guiTop + 17 + oY, 90 - oX * 2, 14); + this.frequency.setTextColor(0x00ff00); + this.frequency.setDisabledTextColour(0x00ff00); + this.frequency.setEnableBackgroundDrawing(false); + this.frequency.setMaxStringLength(10); + this.frequency.setText(rtty.channel == null ? "" : rtty.channel); + } + + @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.rttyController"); + this.fontRendererObj.drawString(name, this.guiLeft + this.xSize / 2 - this.fontRendererObj.getStringWidth(name) / 2, this.guiTop + 6, 4210752); + + if(guiLeft + 173 <= x && guiLeft + 173 + 18 > x && guiTop + 17 < y && guiTop + 17 + 18 >= y) { + func_146283_a(Arrays.asList(new String[] { rtty.polling ? "Polling" : "State Change" }), x, y); + } + if(guiLeft + 209 <= x && guiLeft + 209 + 18 > x && guiTop + 17 < y && guiTop + 17 + 18 >= y) { + func_146283_a(Arrays.asList(new String[] { "Save Settings" }), x, y); + } + if(guiLeft + 137 <= x && guiLeft + 137 + 18 > x && guiTop + 17 < y && guiTop + 17 + 18 >= y) { + ForgeDirection dir = ForgeDirection.getOrientation(rtty.getBlockMetadata()).getOpposite(); + TileEntity tile = Compat.getTileStandard(rtty.getWorldObj(), rtty.xCoord + dir.offsetX, rtty.yCoord + dir.offsetY, rtty.zCoord + dir.offsetZ); + if(tile instanceof IRORInfo) { + IRORInfo prov = (IRORInfo) tile; + String[] info = prov.getFunctionInfo(); + List lines = new ArrayList(); + lines.add("Usable functions:"); + for(String s : info) { + if(s.startsWith(IRORValueProvider.PREFIX_FUNCTION)) + lines.add(EnumChatFormatting.AQUA + s.substring(4)); + } + func_146283_a(lines, x, y); + } + } + } + + 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); + + this.frequency.drawTextBox(); + } + + @Override + protected void mouseClicked(int x, int y, int i) { + super.mouseClicked(x, y, i); + + this.frequency.mouseClicked(x, y, i); + + if(guiLeft + 173 <= x && guiLeft + 173 + 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(); + data.setBoolean("p", !rtty.polling); + PacketDispatcher.wrapper.sendToServer(new NBTControlPacket(data, rtty.xCoord, rtty.yCoord, rtty.zCoord)); + } + + 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(); + data.setString("c", this.frequency.getText()); + PacketDispatcher.wrapper.sendToServer(new NBTControlPacket(data, rtty.xCoord, rtty.yCoord, rtty.zCoord)); + } + } + + @Override + protected void keyTyped(char c, int i) { + if(this.frequency.textboxKeyTyped(c, i)) return; + + if(i == 1 || i == 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/GUIScreenRadioTorchReader.java b/src/main/java/com/hbm/inventory/gui/GUIScreenRadioTorchReader.java index 5c1793194..9a6a2ce7a 100644 --- a/src/main/java/com/hbm/inventory/gui/GUIScreenRadioTorchReader.java +++ b/src/main/java/com/hbm/inventory/gui/GUIScreenRadioTorchReader.java @@ -28,9 +28,7 @@ import net.minecraftforge.common.util.ForgeDirection; public class GUIScreenRadioTorchReader extends GuiScreen { protected static final ResourceLocation texture = new ResourceLocation(RefStrings.MODID + ":textures/gui/machine/gui_rtty_reader.png"); - public TileEntityRadioTorchReader rtty; - protected int xSize = 256; protected int ySize = 204; protected int guiLeft; diff --git a/src/main/java/com/hbm/inventory/recipes/AmmoPressRecipes.java b/src/main/java/com/hbm/inventory/recipes/AmmoPressRecipes.java index de3fd9e09..82d96a98e 100644 --- a/src/main/java/com/hbm/inventory/recipes/AmmoPressRecipes.java +++ b/src/main/java/com/hbm/inventory/recipes/AmmoPressRecipes.java @@ -40,6 +40,7 @@ public class AmmoPressRecipes extends SerializableRecipe { OreDictStack plastic = new OreDictStack(ANY_PLASTIC.ingot()); OreDictStack uranium = new OreDictStack(U238.ingot()); OreDictStack ferro = new OreDictStack(FERRO.ingot()); + OreDictStack nb = new OreDictStack(NB.ingot()); ComparableStack smokeful = new ComparableStack(Items.gunpowder); OreDictStack smokeless = new OreDictStack(ANY_SMOKELESS.dust()); ComparableStack rocket = new ComparableStack(ModItems.rocket_fuel); @@ -386,9 +387,9 @@ public class AmmoPressRecipes extends SerializableRecipe { null, silicon.copy(6), null, null, plastic, null)); recipes.add(new AmmoPressRecipe(DictFrame.fromOne(ModItems.ammo_standard, EnumAmmo.CAPACITOR_IR, 4), - null, plastic, null, - null, silicon.copy(4), null, - null, plastic, null)); + null, plastic, null, + null, nb, null, + null, plastic, null)); OreDictStack lPlate = new OreDictStack(PB.plate()); recipes.add(new AmmoPressRecipe(DictFrame.fromOne(ModItems.ammo_standard, EnumAmmo.TAU_URANIUM, 16), diff --git a/src/main/java/com/hbm/tileentity/TileEntityProxyCombo.java b/src/main/java/com/hbm/tileentity/TileEntityProxyCombo.java index b797d3136..da655737b 100644 --- a/src/main/java/com/hbm/tileentity/TileEntityProxyCombo.java +++ b/src/main/java/com/hbm/tileentity/TileEntityProxyCombo.java @@ -9,6 +9,8 @@ import com.hbm.inventory.fluid.tank.FluidTank; import api.hbm.energymk2.IEnergyReceiverMK2; import api.hbm.fluidmk2.IFluidConnectorMK2; import api.hbm.fluidmk2.IFluidReceiverMK2; +import api.hbm.redstoneoverradio.IRORInfo; +import api.hbm.redstoneoverradio.IRORValueProvider; import api.hbm.tile.IHeatSource; import com.hbm.inventory.material.Mats; import cpw.mods.fml.common.Loader; @@ -28,7 +30,7 @@ import net.minecraftforge.common.util.ForgeDirection; @Optional.Interface(iface = "com.hbm.handler.CompatHandler.OCComponent", modid = "opencomputers"), @Optional.Interface(iface = "li.cil.oc.api.network.SimpleComponent", modid = "opencomputers") }) -public class TileEntityProxyCombo extends TileEntityProxyBase implements IEnergyReceiverMK2, ISidedInventory, IFluidReceiverMK2, IHeatSource, ICrucibleAcceptor, SimpleComponent, OCComponent { +public class TileEntityProxyCombo extends TileEntityProxyBase implements IEnergyReceiverMK2, ISidedInventory, IFluidReceiverMK2, IHeatSource, ICrucibleAcceptor, SimpleComponent, OCComponent, IRORValueProvider { TileEntity tile; boolean inventory; @@ -512,4 +514,16 @@ public class TileEntityProxyCombo extends TileEntityProxyBase implements IEnergy return ((OCComponent) this.getTile()).invoke(method, context, args); return OCComponent.super.invoke(null, null, null); } + + @Override + public String[] getFunctionInfo() { + if(getTile() instanceof IRORInfo) return ((IRORInfo) getTile()).getFunctionInfo(); + return new String[0]; + } + + @Override + public String provideRORValue(String name) { + if(getTile() instanceof IRORValueProvider) return ((IRORValueProvider) getTile()).provideRORValue(name); + return ""; + } } diff --git a/src/main/java/com/hbm/tileentity/TileMappings.java b/src/main/java/com/hbm/tileentity/TileMappings.java index 5e97c11ad..33f3b124a 100644 --- a/src/main/java/com/hbm/tileentity/TileMappings.java +++ b/src/main/java/com/hbm/tileentity/TileMappings.java @@ -429,6 +429,7 @@ public class TileMappings { put(TileEntityRadioTorchCounter.class, "tileentity_rtty_counter"); put(TileEntityRadioTorchLogic.class, "tileentity_rtty_logic"); put(TileEntityRadioTorchReader.class, "tileentity_rtty_reader"); + put(TileEntityRadioTorchController.class, "tileentity_rtty_controller"); put(TileEntityRadioTelex.class, "tileentity_rtty_telex"); put(TileEntityDroneWaypoint.class, "tileentity_drone_waypoint"); diff --git a/src/main/java/com/hbm/tileentity/machine/storage/TileEntityBarrel.java b/src/main/java/com/hbm/tileentity/machine/storage/TileEntityBarrel.java index 07567418d..5473c0740 100644 --- a/src/main/java/com/hbm/tileentity/machine/storage/TileEntityBarrel.java +++ b/src/main/java/com/hbm/tileentity/machine/storage/TileEntityBarrel.java @@ -3,6 +3,7 @@ package com.hbm.tileentity.machine.storage; import api.hbm.energymk2.IEnergyReceiverMK2.ConnectionPriority; import api.hbm.fluidmk2.FluidNode; import api.hbm.fluidmk2.IFluidStandardTransceiverMK2; +import api.hbm.redstoneoverradio.IRORInteractive; import api.hbm.redstoneoverradio.IRORValueProvider; import java.util.HashSet; @@ -46,7 +47,7 @@ import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; @Optional.InterfaceList({@Optional.Interface(iface = "li.cil.oc.api.network.SimpleComponent", modid = "opencomputers")}) -public class TileEntityBarrel extends TileEntityMachineBase implements SimpleComponent, IFluidStandardTransceiverMK2, IPersistentNBT, IGUIProvider, CompatHandler.OCComponent, IFluidCopiable, IRORValueProvider { +public class TileEntityBarrel extends TileEntityMachineBase implements SimpleComponent, IFluidStandardTransceiverMK2, IPersistentNBT, IGUIProvider, CompatHandler.OCComponent, IFluidCopiable, IRORValueProvider, IRORInteractive { protected FluidNode node; protected FluidType lastType; @@ -408,6 +409,8 @@ public class TileEntityBarrel extends TileEntityMachineBase implements SimpleCom PREFIX_VALUE + "type", PREFIX_VALUE + "fill", PREFIX_VALUE + "fillpercent", + PREFIX_FUNCTION + "setmode" + NAME_SEPARATOR + "mode", + PREFIX_FUNCTION + "setmode" + NAME_SEPARATOR + "mode" + PARAM_SEPARATOR + "fallback", }; } @@ -418,4 +421,25 @@ public class TileEntityBarrel extends TileEntityMachineBase implements SimpleCom if((PREFIX_VALUE + "fillpercent").equals(name)) return "" + (tank.getFill() * 100 / tank.getMaxFill()); return null; } + + @Override + public String runRORFunction(String name, String[] params) { + + if((PREFIX_FUNCTION + "setmode").equals(name) && params.length > 0) { + int mode = IRORInteractive.parseInt(params[0], 0, 3); + + if(mode != this.mode) { + this.mode = (short) mode; + this.markChanged(); + return null; + } else if(params.length > 1) { + int altmode = IRORInteractive.parseInt(params[1], 0, 3); + this.mode = (short) altmode; + this.markChanged(); + return null; + } + return null; + } + return null; + } } diff --git a/src/main/java/com/hbm/tileentity/machine/storage/TileEntityMachineFluidTank.java b/src/main/java/com/hbm/tileentity/machine/storage/TileEntityMachineFluidTank.java index 2e456aa24..b8f4c199f 100644 --- a/src/main/java/com/hbm/tileentity/machine/storage/TileEntityMachineFluidTank.java +++ b/src/main/java/com/hbm/tileentity/machine/storage/TileEntityMachineFluidTank.java @@ -3,6 +3,7 @@ package com.hbm.tileentity.machine.storage; import api.hbm.energymk2.IEnergyReceiverMK2.ConnectionPriority; import api.hbm.fluidmk2.FluidNode; import api.hbm.fluidmk2.IFluidStandardTransceiverMK2; +import api.hbm.redstoneoverradio.IRORInteractive; import api.hbm.redstoneoverradio.IRORValueProvider; import com.hbm.blocks.BlockDummyable; @@ -55,7 +56,7 @@ import java.util.List; import java.util.Random; @Optional.InterfaceList({@Optional.Interface(iface = "li.cil.oc.api.network.SimpleComponent", modid = "opencomputers")}) -public class TileEntityMachineFluidTank extends TileEntityMachineBase implements SimpleComponent, OCComponent, IFluidStandardTransceiverMK2, IPersistentNBT, IOverpressurable, IGUIProvider, IRepairable, IFluidCopiable, IRORValueProvider { +public class TileEntityMachineFluidTank extends TileEntityMachineBase implements SimpleComponent, OCComponent, IFluidStandardTransceiverMK2, IPersistentNBT, IOverpressurable, IGUIProvider, IRepairable, IFluidCopiable, IRORValueProvider, IRORInteractive { protected FluidNode node; protected FluidType lastType; @@ -537,14 +538,10 @@ public class TileEntityMachineFluidTank extends TileEntityMachineBase implements @Optional.Method(modid = "OpenComputers") public Object[] invoke(String method, Context context, Arguments args) throws Exception { switch (method) { - case "getFluidStored": - return getFluidStored(context, args); - case "getMaxStored": - return getMaxStored(context, args); - case "getTypeStored": - return getTypeStored(context, args); - case "getInfo": - return getInfo(context, args); + case "getFluidStored": return getFluidStored(context, args); + case "getMaxStored": return getMaxStored(context, args); + case "getTypeStored": return getTypeStored(context, args); + case "getInfo": return getInfo(context, args); } throw new NoSuchMethodException(); } @@ -555,14 +552,37 @@ public class TileEntityMachineFluidTank extends TileEntityMachineBase implements PREFIX_VALUE + "type", PREFIX_VALUE + "fill", PREFIX_VALUE + "fillpercent", + PREFIX_FUNCTION + "setmode" + NAME_SEPARATOR + "mode", + PREFIX_FUNCTION + "setmode" + NAME_SEPARATOR + "mode" + PARAM_SEPARATOR + "fallback", }; } @Override public String provideRORValue(String name) { - if("type".equals(name)) return tank.getTankType().getName(); - if("fill".equals(name)) return "" + tank.getFill(); - if("fillpercent".equals(name)) return "" + (tank.getFill() * 100 / tank.getMaxFill()); + if((PREFIX_VALUE + "type").equals(name)) return tank.getTankType().getName(); + if((PREFIX_VALUE + "fill").equals(name)) return "" + tank.getFill(); + if((PREFIX_VALUE + "fillpercent").equals(name)) return "" + (tank.getFill() * 100 / tank.getMaxFill()); + return null; + } + + @Override + public String runRORFunction(String name, String[] params) { + + if((PREFIX_FUNCTION + "setmode").equals(name) && params.length > 0) { + int mode = IRORInteractive.parseInt(params[0], 0, 3); + + if(mode != this.mode) { + this.mode = (short) mode; + this.markChanged(); + return null; + } else if(params.length > 1) { + int altmode = IRORInteractive.parseInt(params[1], 0, 3); + this.mode = (short) altmode; + this.markChanged(); + return null; + } + return null; + } return null; } } \ No newline at end of file diff --git a/src/main/java/com/hbm/tileentity/network/TileEntityRadioTorchController.java b/src/main/java/com/hbm/tileentity/network/TileEntityRadioTorchController.java new file mode 100644 index 000000000..b42d2727c --- /dev/null +++ b/src/main/java/com/hbm/tileentity/network/TileEntityRadioTorchController.java @@ -0,0 +1,93 @@ +package com.hbm.tileentity.network; + +import com.hbm.interfaces.IControlReceiver; +import com.hbm.tileentity.TileEntityLoadedBase; +import com.hbm.tileentity.network.RTTYSystem.RTTYChannel; +import com.hbm.util.BufferUtil; +import com.hbm.util.Compat; + +import api.hbm.redstoneoverradio.IRORInteractive; +import api.hbm.redstoneoverradio.RORFunctionException; +import io.netty.buffer.ByteBuf; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.common.util.ForgeDirection; + +public class TileEntityRadioTorchController extends TileEntityLoadedBase implements IControlReceiver { + + public String channel; + public String prev; + public boolean polling = false; + + @Override + public void updateEntity() { + + if(!worldObj.isRemote) { + + if(channel != null && !channel.isEmpty()) { + ForgeDirection dir = ForgeDirection.getOrientation(this.getBlockMetadata()).getOpposite(); + + TileEntity tile = Compat.getTileStandard(worldObj, xCoord + dir.offsetX, yCoord + dir.offsetY, zCoord + dir.offsetZ); + + if(tile instanceof IRORInteractive) { + IRORInteractive ror = (IRORInteractive) tile; + + RTTYChannel chan = RTTYSystem.listen(worldObj, channel); + if(chan != null) { + String rec = "" + chan.signal; + if(this.polling || !rec.equals(prev)) { + try { + if(rec != null && !rec.isEmpty()) ror.runRORFunction(IRORInteractive.PREFIX_FUNCTION + IRORInteractive.getCommand(rec), IRORInteractive.getParams(rec)); + } catch(RORFunctionException ex) { } + prev = rec; + } + } + } + } + + networkPackNT(50); + } + } + + @Override + public void serialize(ByteBuf buf) { + buf.writeBoolean(this.polling); + BufferUtil.writeString(buf, channel); + } + + @Override + public void deserialize(ByteBuf buf) { + this.polling = buf.readBoolean(); + channel = BufferUtil.readString(buf); + } + + @Override + public void readFromNBT(NBTTagCompound nbt) { + super.readFromNBT(nbt); + this.polling = nbt.getBoolean("p"); + channel = nbt.getString("c"); + this.prev = nbt.getString("prev"); + } + + @Override + public void writeToNBT(NBTTagCompound nbt) { + super.writeToNBT(nbt); + nbt.setBoolean("p", polling); + nbt.setString("c", channel); + if(prev != null) nbt.setString("prev", prev); + } + + @Override + public void receiveControl(NBTTagCompound data) { + if(data.hasKey("p")) this.polling = data.getBoolean("p"); + if(data.hasKey("c")) channel = data.getString("c"); + + this.markDirty(); + } + + @Override + public boolean hasPermission(EntityPlayer player) { + return player.getDistance(xCoord + 0.5, yCoord + 0.5, zCoord + 0.5) < 16D; + } +} diff --git a/src/main/resources/assets/hbm/textures/gui/machine/gui_rtty_controller.png b/src/main/resources/assets/hbm/textures/gui/machine/gui_rtty_controller.png index 65ab150c878594e5f5c81259df88539fb5be9ae1..3b9b4d095e07b4a92736ace24fbc96c5cdb9c76c 100644 GIT binary patch delta 894 zcmV-^1A+Xe2;K;gGk*jXNklg&UVCHgd@Wq|5F#wiMYeofN!4`lQ|zcO2XX*aPNZm-+pq69)^!2r>Wpm}S`_ z7McKZP_+MPK3u;$QeS{Wx_tgB;&$wxg~1P5dHd#d#BIf2M1Ly)K7IajoL&J3as7T4 z5fRhrG|rYc82pfzv+lb9r%C`o#smOlOaMT}1OQ}A06@kB0Ax%6K*j_BWJ~}+#smOl zOaMT}&NprR<=5X1)ej!Q&p*9L($15wzTUfyvMl4r?=KVdMt@S;7yuCw7Z(>hH$EDT zVm6!Y-45GXet+Hjpe)O%>pJNhye!MT9)Ifnd8p0+h=};>-#>S1{D)^R@4XRsZHMi& zU-wjYeUsO9owOgTRCOJb@p$WPxqDCm6i?DTS*mt`G#(TH%|ADn-~RD;L_~c2?&-bj zbMxD~+F`h=+u3~6Y`bYY{jyU9ux=*rn&DLdr=zN>n14(rJ8w^IQ{WsUjOIZYO%qWR ziw#Y4(ATBQRu#ay>+OnQT_vCb;IRy54WKBZ>QM+JsQ^+{2(YWZRRDLEXaA+!`Vs<3 zDuAx*UAMz7s;atoecgb1=>2k}0${L~2XcFmZ@MoFDgd@J8INxUTTw(6i}HGT^}lN{ zW~FJJaer^sM}i|#0kE~nWD@fs-d^oL^y>d0%m;lt40<3*1@O)9n^*tWJ&xg8RSB5+ zhsXB-*x9B^fF(Vg`RBH(0NOKr*Nnfe9ZpA|X8ykPBVuXSV>=Yr-F_sF1z>M|nECtA zhau_=fYE3a&qgozexg+Ea2)ePdO0nf0Wh1*l7AdpnyMWRuWy52f6^%;qWN(BE+U*B z9CC2|{$?VcPN#ko5OO8}AY%dmGBPj!=guRdxP1PqdHd$||26`rZTZNA=IZL|XdM9# zXF8omtT;5Ozu#E|QYs=Min1*C9`v{SLHl)_BhcwQBF#w+fZ@6OCSX<9i(fF^;?j4p zVOF^8284_W0LWNTmSvM@4ZtEG42(4Z$e0QMGPbAyoMZvAa~A+kvH3AY*HP6}V3)SpXi#$^fv+4|(tr0CF}SkDIvpC7^x(lTib`lVAe|7~oO;2a26- U4Rrg)*#H0l07*qoM6N<$f}5S7_5c6? delta 838 zcmV-M1G)U(2&M>-Gk*i!Nkl+k=p%+Du6WD>3DY zhMU-{*k(%#qb+j*bi~u_N(d-{A~!$}wJAa}nd~^uk3Bi|c^+w$apIhuiRQfia_rbe z+^YlVLvij7G+A}5{&4s1tQ~=|x_>{=T;J4rZIA3pI zgznxiA|hfon?)p630!P082pfzi}qE3u@V4~F#!M>69AAg0RR~j0FW^O02vbikTC%O z8501IF#!M>69AC0%Uuut@Z(QU)em~`{dZq=($2F_K0CRMvMl4=;;(=IJgV_;p1*wX zk9cf59A^7{@58*R;$}KM_%YJ5R{#{xx_Pm#+5x(;R{+%iEN{Q~`{g{yED3c~vccsq2VhaFW>tpPBZOyc?E z<;gG9RXad;S_5FQSakB$(yrR!>6K*})#_OL1f|{eSk&>*PBNbZc`$qQ1SoJzGa$%u<{H zjQF@ij-iBpBscgYB8svsPagFD@0U&T4+NTBMs#zL1z>pAM*_~P>i&$X2i!U)9EQto zK**Q?fQ%JoS=JrR0hk1YfiVXF8B+m3#_lTs7kz;2tOLMBA0R*W0zk$D0Ax%6K*j_B zWFD;XtiUN<^a1F{qXA%+AM)TM0OV{soz}5D6VRzYlaT|plb{0*7|^T#05sVwbVT`I Q0ssI207*qoM6N<$g6xipK>z>% diff --git a/src/main/resources/assets/hbm/textures/gui/processing/gui_crucible.png b/src/main/resources/assets/hbm/textures/gui/processing/gui_crucible.png index 684157aa2886f97fa0dcbfcd8259ec2237efd7c1..44dfb0be6bdd8e066b8a5a456c0460526fae6f3e 100644 GIT binary patch literal 12289 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 Tid`_%58c$%(|01#lAY|!$TmrgvW$Ia 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