This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
MZeora's profile picture

[touchpoint] mon.write and touchpoint buttons.

Started by MZeora, 26 June 2015 - 10:33 PM
MZeora #1
Posted 27 June 2015 - 12:33 AM
Forgive me I don't know how to the spoiler tag, and thus I'm guessing forgive me if it doesn't work out.

That said. I need some help or at least a push in the right direction.

I'm using the FTB Infinity Modpack 1.6.1.
Computercraft 1.73
OpenPeripheral Core 0.3.1
'' Intergration 1.1.1
'' Addons 0.2.2

In the spoiler is my current code as I have it written. I am a programmer by profession, but Lua is not my strong suit… yet…

So here's the goal, it's an automatic XU's Liquid XP / MFR Mob Essense managment system using both Player XP and a XP Berry Farm. I have the computer hooked up to bundled cable to the Automous Activator and XP drain to crush the berries and to an XP Shower and MFR Sewer. I'd wanted to use the touchpoint api to control the redstone signals and thus do the action when I want it to be done, but at the same point I want to print the current contents of…
A) the DSU that keeps the berries,
B)/> The Liquid XP Tank (a bedrockium drum), and
C) the MFR Mob Essense Tank (another bedrockium drum)

So, I'd want to have the dynamic label that updates, but it looks like my holdup in the current methods I got is that os.pullEvent completely stalls the program from updating the stats I want. So I need some help to either make the os.pullEvent to be a bit more async so that it doesn't interfere with the rest of the system or find a way I can add dynamic text labels into the touchpoint system and just use the run() command verses the current method with the draw() command.

Thanks for reading this massive post and any enlightenment I can get to make this work the way I want would be EXCELLENT.

Spoiler

os.loadAPI("touchpoint");

local essenseDrum = "drum_2";
local liquidXpDrum = "drum_3";
local dsu = "deep_storage_unit_2";
local monLoc = "top";
local sleepFor = 1;
local redstoneLocation = "bottom";
local rsColorCrusher = colors.white;
local rsColorConvert = colors.blue;

redstone.setBundledOutput(redstoneLocation,rsColorConvert);

local ds1 = peripheral.wrap(dsu);
local eDrum = peripheral.wrap(essenseDrum);
local lDrum = peripheral.wrap(liquidXpDrum);
local mon = peripheral.wrap(monLoc);
local t = touchpoint.new(monLoc);

local drum0 = eDrum.getTankInfo();
local drum1 = lDrum.getTankInfo();
local item = ds1.getStoredItems();

function comma_value(n)
  local left,num,right = string.match(n,'^([^%d]*%d)(%d*)(.-)$')
  return left..(num:reverse():gsub('(%d%d%d)','%1,'):reverse())..right
end

function toggleCrusher()
  local rs = redstone.getBundledOutput(redstoneLocation);
 
  if rs == rsColorConvert then
    redstone.setBundledOutput(redstoneLocation,colors.combine(redstone.getBundledOutput(redstoneLocation),rsColorCrusher));
  elseif rs == rsColorCrusher then
    redstone.setBundledOutput(redstoneLocation,0);
  elseif rs == rsColorConvert+rsColorCrusher then
    redstone.setBundledOutput(redstoneLocation,rsColorConvert);
  elseif rs == 0 then
    redstone.setBundledOutput(redstoneLocation,rsColorCrusher); 
  end
 
  t:toggleButton("Crush")
end

function toggleConverter()
  local rs = redstone.getBundledOutput(redstoneLocation);
 
  if rs == rsColorCrusher then
    redstone.setBundledOutput(redstoneLocation,colors.combine(redstone.getBundledOutput(redstoneLocation),rsColorConvert));
  elseif rs == rsColorConvert then
    redstone.setBundledOutput(redstoneLocation,0);
  elseif rs == rsColorConvert+rsColorCrusher then
    redstone.setBundledOutput(redstoneLocation,rsColorCrusher);
  elseif rs == 0 then
    redstone.setBundledOutput(redstoneLocation,rsColorConvert);
  end
 
  t:toggleButton("Convert")
end

t:add("Crush",toggleCrusher,2,8,8,8);
t:add("Convert",toggleConverter,10,8,18,8);

function getAmount(drum)
  local amount = 0;
  -- drum should be the tank info table.
  if drum[1].contents ~= nil then
    amount = drum[1].contents.amount;
  end
 
  return amount;
end

function getName(drum)
  local name = "Empty";
  if drum[1].contents ~= nil then
    name = drum[1].contents.rawName
  end
 
  return name;
end

function getItemName()
  local name = "Empty";
 
  if item ~= nil then
    name = item.display_name;
  end
 
  return name;
end

function getItemQty()
  local amount = 0;
 
  if item ~= nil then
    amount = item.qty;
  end
 
  return amount;
end

while true do
  local itemstring = getItemName()..": "..comma_value(getItemQty());
 
  local xpstring = getName(drum1)..": "..comma_value(getAmount(drum1)).." mB";
  local esString = getName(drum0).."  : "..comma_value(getAmount(drum0)).." mB";
  local xpCap = drum1[1].capacity;
  local esCap = drum0[1].capacity;
 
  local xpPercentage = math.floor((getAmount(drum1)/xpCap)*100);
  local esPercentage = math.floor((getAmount(drum0)/esCap)*100);
 
  xpstring = xpstring.." "..xpPercentage.."%";
  esString = esString.." "..esPercentage.."%";
				   
  print(itemstring);
  print(xpstring);
  print(esString);
 
  t:draw()
  --t:run()
 
  mon.setTextColor(colors.white);
  mon.setBackgroundColor(colors.black);
  mon.setCursorPos(1,1);
  mon.write(itemstring);
  mon.setCursorPos(1,2);
  mon.write(xpstring);
  mon.setCursorPos(1,3);
  mon.write(esString);
  local event = {t:handleEvents(os.pullEvent())};
 
  if event[1] == "button_click" then
    if event[2] == "Crush" then
	  toggleCrusher()
    elseif event[2] == "Convert" then
	  toggleConverter()
    end 
  end
  sleep(sleepFor);
  drum0 = eDrum.getTankInfo();
  drum1 = lDrum.getTankInfo();
  item = ds1.getStoredItems();
 
  term.clear();
  mon.clear();
 
  term.setCursorPos(1,1);
  mon.setCursorPos(1,1);
end

Bomb Bloke #2
Posted 27 June 2015 - 07:54 AM
When you do this:

local event = {t:handleEvents(os.pullEvent())};

… your script is pulling an event from the front of the event queue, and passing it to touchpoint to inspect. If touchpoint recognises the event as being a mouse click targetting one of your buttons then it returns an event indicating which one - otherwise it returns the event which was actually passed to it.

With that in mind, consider the source of the sleep() function:

function sleep( nTime )
    local timer = os.startTimer( nTime or 0 )
    repeat
        local sEvent, param = os.pullEvent( "timer" )
    until param == timer
end

It's starting a timer with os.startTimer(), then pulling timer events over and over until it gets a match for the one it set.

So your solution is to simply mimic what sleep does in your own code. Instead of:

  local event = {t:handleEvents(os.pullEvent())};  -- Wait for as long as it takes to get any event.

  if event[1] == "button_click" then
    if event[2] == "Crush" then
          toggleCrusher()
    elseif event[2] == "Convert" then
          toggleConverter()
    end 
  end
  sleep(sleepFor);  -- Pause for an extra second.

… do:

  local timer = os.startTimer(sleepFor)

  while true do
    local event = {t:handleEvents(os.pullEvent())};  -- We're sure to get an event that'll break this loop within about a second.

    if event[1] == "button_click" then
      if event[2] == "Crush" then
            toggleCrusher()
      elseif event[2] == "Convert" then
            toggleConverter()
      end
      break
    elseif event[1] == "timer" and event[2] == timer then
      break
    end
  end
MZeora #3
Posted 27 June 2015 - 11:25 AM
Let me give that a try, thanks for the insight! One of the problems is that I don't want to break the loop, I want to keep it going the timer is just so I can read the information and read it out.

In my case in moving the timer inside the while loop and using the timer to break the os.pullEvent hold and makes things happen, it's not perfect as clicking the button and the redraw doesn't work the way I want it to do so… *shrugs* just not the best way about it but bugger it.