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

[SOLVED] Having problems setting textScale - wth am I doing wrong?

Started by Dog, 24 June 2016 - 07:59 PM
Dog #1
Posted 24 June 2016 - 09:59 PM
I'm actually having two problems. For reference, both blocks of code do essentially the same thing (2 different approaches) - the only functional difference is that block A only looks for 'remotely' connected monitors, block B looks for all connected monitors.

Problem 1: In both chunks of code, my monitors never set the text scale to 3 - they do everything else just fine, except that one thing - what am I doing wrong?
Problem 2: In code block A both of my monitors are found; in code block B only 1 is found - both monitors are attached via modem/network cable (modems are on) - what did I do wrong?

Spoiler

local mon = { }
for _, side in pairs(rs.getSides()) do
  if peripheral.getType(side) == "modem" and not peripheral.call(side, "isWireless") then
    for _, name in pairs(peripheral.call(side, "getNamesRemote")) do
      if peripheral.getType(name) == "monitor" then
        peripheral.call(name, "setTextScale", 1)
        local x, y = peripheral.call(name, "getSize")
        if x == 18 and y == 5 then
          peripheral.call(name, "setTextScale", 3) --# doesn't happen for some reason
          mon[#mon + 1] = peripheral.wrap(name)
          --mon[#mon].setTextScale(3) --# doesn't work either
        end
      end
    end
  end
end

Spoiler

local mon = {
  peripheral.find("monitor",
    function(name, object)
      object.setTextScale(1)
      local x, y = object.getSize()
      if x == 18 and y == 5 then
        object.setTextScale(3) --# doesn't happen for some reason
        return true
      else
        return false
      end
    end
  )
}

I'm using this code in a countdown timer - everything works, except all the text is at textScale 1 instead of 3 and I can't figure out why - the above code is the only place is the program that calls setTextScale so I'm reasonably sure it's not happening somewhere else in the program. For reference, the entire program…
Spoiler

local nHours = 0 --# leave this at 0
local nMinutes = 0
local nSeconds = 30
local totalTime = (nHours * 36000) + (nMinutes * 600) + (nSeconds * 10)
local hours, minutes, seconds, sHours, sMinutes, sSeconds, sTenths, countdownTimer
local lcGate = false
local gate = peripheral.find("stargate")
if not gate then lcGate = true gate = peripheral.find("StargateBase") end
if not gate then error("No Stargate located") end
local mon = { }
for _, side in pairs(rs.getSides()) do
  if peripheral.getType(side) == "modem" and not peripheral.call(side, "isWireless") then
    for _, name in pairs(peripheral.call(side, "getNamesRemote")) do
      if peripheral.getType(name) == "monitor" then
        peripheral.call(name, "setTextScale", 1)
        local x, y = peripheral.call(name, "getSize")
        if x == 18 and y == 5 then
          peripheral.call(name, "setTextScale", 3)
          mon[#mon + 1] = peripheral.wrap(name)
          --mon[#mon].setTextScale(3)
        end
      end
    end
  end
end

local function cdTimer()
  local continue, timer, sgEvent, _, new_State, old_State = false
  while true do
    if lcGate then
      os.pullEvent("connect")
      continue = true
    else
      sgEvent, _, new_State, old_State = os.pullEvent("sgStargateStateChange")
      if new_State == "Connected" then continue = true end
    end
    if continue then
      if mon[1] then
        for i = 1, #mon do
          mon[i].setTextColor(colors.white)
        end
      end
      for i = totalTime, 0, -1 do
        hours = totalTime > 35999 and math.floor(totalTime / 36000) or 0
        sHours = tostring(hours)
        minutes = totalTime > 599 and math.floor((totalTime - (hours * 36000)) / 600) or 0 
        sMinutes = minutes > 9 and tostring(minutes) or "0" .. tostring(minutes)
        seconds = totalTime > 9 and math.floor((totalTime - ((hours * 36000) + (minutes * 600))) / 10) or 0
        sSeconds = seconds > 9 and tostring(seconds) or "0" .. tostring(seconds)
        sTenths = tostring(math.floor(totalTime - ((hours * 36000) + (minutes * 600) + (seconds * 10))))
        if totalTime == 0 then
          continue = false
          if lcGate then
            pcall(gate.disengageStargate)
          else
            gate.disconnect()
          end
        end
        if mon[1] then
          for i = 1, #mon do
            mon[i].setCursorPos(1, 1)
            if totalTime == 0 and mon[i].isColor() then mon[i].setTextColor(colors.red) end
            mon[i].write(sMinutes .. ":" .. sSeconds .. ":" .. sTenths .. " ")
          end
        end
        if totalTime > 0 then
          countdownTimer = os.startTimer(0.1)
          while true do
            _, timer = os.pullEvent("timer")
            if timer == countdownTimer then
              totalTime = totalTime - 1
              break
            end
          end
        end
      end
    end
  end
end

local function gateLiaison()
  shell.run("/gateLiaison")
end

parallel.waitForAny(cdTimer, gateLiaison)
Edited on 25 June 2016 - 04:59 AM
Dog #2
Posted 24 June 2016 - 10:16 PM
Trying to edit the OP just makes a mess of it, so please pardon my double post - I forgot to add that I'm using CC 1.75, LanteaCraft build 21, and Gopher's Peripherals 2.2pr1 on MC 1.7.10 with Forge 10.13.4.1558. The code in the OP is copied/pasted from the working code and not retyped.
Edited on 24 June 2016 - 08:18 PM
The_Cat #3
Posted 24 June 2016 - 10:54 PM
Block B:


local mon = {
  peripheral.find("monitor",
	function(name, object)
	  object.setTextScale(1)
	  local x, y = object.getSize()
	  if x == 18 and y == 5 then
		object.setTextScale(3) --# doesn't happen for some reason
		return true
	  else
		return false
	  end
	end
  )
}
--# With two monitors attached
mon[1].write("Monitor_1")
mon[2].write("Monitor_2")
(This found both monitors for me)
The text scale worked fine.
Edited on 24 June 2016 - 08:55 PM
Dog #4
Posted 24 June 2016 - 11:19 PM
So it works for you, but not for me? Hmmm…well, that's frustrating.

I just wrote a dedicated block of code to set the textScale and do a couple other things and it get's completely ignored (as if there were no monitors); yet code that executes after this still displays the timer on both monitors (using block A) - just in the wrong textScale.

Here's what I added below blockA and before the cdTimer() function:

if mon[1] then
  for i = 1, #mon do
    mon[i].clear()
    mon[i].setTextScale(2.5)
    if mon[i].isColor() then mon[i].setTextColor(colors.red) end
    mon[i].setCursorPos(1, 1)
    mon[i].write("00:00:0")
  end
end

Could this be due to some kind of world corruption or the version of forge I'm using?
Edited on 24 June 2016 - 09:22 PM
The_Cat #5
Posted 24 June 2016 - 11:27 PM
This might be a silly question but…


if x == 18 and y == 5 then
				object.setTextScale(3) --# doesn't happen for some reason
				return true
		  else
				return false
		  end
You sure you got the right size monitors? (1x2)
Edited on 24 June 2016 - 09:33 PM
Dog #6
Posted 24 June 2016 - 11:47 PM
Yep - 2 wide by 1 tall. This is the strangest thing. I know the monitors are getting wrapped because they are displaying the timer, but other blocks of code seem to be ignored. I just tried the program in another world (with SGCraft instead of LanteaCraft) and it isn't seeing the monitors at all (I'm guessing because the textScale isn't getting set right, so the measurements are never right). I am so stumped…

EDIT: Restarted the SGCraft world and the monitors are now being detected. But I'm now seeing the exact same problem as in my LanteaCraft world. The monitors are detected, but my new block of code is still skipped. So the timer shows, but in the wrong textScale.

I'm starting to doubt that this is world corruption and starting to wonder if it's a Forge issue. Just out of curiosity - what version of Forge are you running, The_Cat?
Edited on 24 June 2016 - 09:56 PM
Lignum #7
Posted 24 June 2016 - 11:59 PM
ComputerCraft used to have (still has?) a bug where setTextScale doesn't do anything. It's usually fixed by changing the background/text colour to something else and setting it back again.
Dog #8
Posted 25 June 2016 - 12:04 AM
ComputerCraft used to have (still has?) a bug where setTextScale doesn't do anything. It's usually fixed by changing the background/text colour to something else and setting it back again.

Well that's really useful to know - thanks :)/>

Now if I can just figure out why my 'new' block of code is being skipped as if there were no monitors. If I add the following code just above my 'new' block of code, it correctly shows the number of monitors, but the 'new' block of code is entirely skipped, as if there were no monitors.

print(tostring(#mon))
os.pullEvent("key")

The 'new' block of code I'm referring to is in post #4.

Thanks for the help so far, The_Cat and Lignum - much appreciated :)/>


EDIT: Update - changing text/background color isn't helping. Here's my current monitor discovery code (very ugly) with some comments as to what I've been able to verify is or isn't happening
Spoiler

local mon = { }
for _, side in pairs(rs.getSides()) do
  if peripheral.getType(side) == "modem" and not peripheral.call(side, "isWireless") then
    for _, name in pairs(peripheral.call(side, "getNamesRemote")) do
      if peripheral.getType(name) == "monitor" then
        peripheral.call(name, "setTextScale", 1)
        local x, y = peripheral.call(name, "getSize")
        if x == 18 and y == 5 then
          mon[#mon + 1] = peripheral.wrap(name)
          mon[#mon].setBackgroundColor(colors.white) --# this gets executed
          mon[#mon].setBackgroundColor(colors.black) --# this gets executed
          mon[#mon].setTextColor(colors.black)
          if mon[#mon].isColor() then
            mon[#mon].setTextColor(colors.red)
          else
            mon[#mon].setTextColor(colors.white)
          end
          mon[#mon].setTextScale(2.5)                --# this doesn't get executed
          mon[#mon].clear()                          --# this gets executed
          mon[#mon].setCursorPos(1, 1)
          mon[#mon].write("00:00:0")                 --# this doesn't get executed
        end
      end
    end
  end
end

By remarking out either the black or white background color I was able to verify that the background color is being set and the monitor is being cleared with that background color. What I don't understand is why the textScale isn't being set and why the text isn't being written to the monitors.
Edited on 24 June 2016 - 10:21 PM
Lignum #9
Posted 25 June 2016 - 12:30 AM
Have you tried re-placing the monitors or reproducing this in a separate world? This is indeed quite odd, since it also seems to work fine for me.
As for the text scale problem, I might've thought of something else when proposing the text colour thing; However this bug seems to match your description. I feel like both of these problems are related in some way.
Dog #10
Posted 25 June 2016 - 12:39 AM
I broke and replaced one of the monitor arrays, but I'll try that again…and I've tried in two different worlds (one with LanteaCraft and one with SGCraft since that's what the program is written for). I'm really at a loss as to what's going on.

That bug does seem to match my problem very closely. Just out of curiosity, since it's working for you, what version of Forge are you testing under?
Lignum #11
Posted 25 June 2016 - 12:45 AM
Just out of curiosity, since it's working for you, what version of Forge are you testing under?

I'm running Forge 1.8.9-11.15.1.1890 on the SwitchCraft modpack.
Edited on 24 June 2016 - 10:45 PM
Dog #12
Posted 25 June 2016 - 12:56 AM
Darn - you're in 1.8.9 and I'm in 1.7.10 - I guess I won't be trying your version of Forge :/

EDIT: I'm utterly stumped. I've tried several variations on changing text color/background color/textScale around and back and nothing seems to work. I've verified (though print statements) that the monitors are being detected, so I guess I'm just getting bitten by this bug.

I finally found a place in the code I could get the monitor to change textScale, it's ugly, but it works. But I'm still unable to write any text to the monitor prior to starting the timer. I'm open to ideas if anyone has any to offer :)/>
Edited on 25 June 2016 - 12:03 AM
Bomb Bloke #13
Posted 25 June 2016 - 03:38 AM
Just reading the code, both blocks look ok to me, though A will miss any monitors directly touching the computer (any particular reason you're avoiding peripheral.getNames()?), whereas B should get all monitors of the correct size.

What I don't get is why you're bothering to set the scale to 1. Why not just set it directly to 3, and then measure the dimensions?

Trying to edit the OP just makes a mess of it

What sort of mess?

If it removes all the line breaks, that's been happening for me too, though I'm not sure why. I've found that avoiding the quick editor and going directly to the full post editor (middle-click the "edit" link) works around it.
Dog #14
Posted 25 June 2016 - 04:55 AM
Just reading the code, both blocks look ok to me, though A will miss any monitors directly touching the computer (any particular reason you're avoiding peripheral.getNames()?), whereas B should get all monitors of the correct size.
The difference in detection (all vs. only remote) is intentional actually. The program this is written to supplement only sees 'remote' monitors and I've never bothered to remove that limitation, so I kept that limitation in code block A which I've ended up using for now.

I only have one reason for not using peripheral.getNames() - as dumb as it may make me seem, I wasn't even aware of it. Thanks for pointing it out.

What I don't get is why you're bothering to set the scale to 1. Why not just set it directly to 3, and then measure the dimensions?
Point taken :)/> I was under the impression that changing textScale helped avoid some of the issues I have apparently run in to (from previous AaP threads). I'll make the suggested change and see how that works.

Trying to edit the OP just makes a mess of it

What sort of mess?

If it removes all the line breaks, that's been happening for me too, though I'm not sure why. I've found that avoiding the quick editor and going directly to the full post editor (middle-click the "edit" link) works around it.
For me it was not respecting my code indentation and left justifying all the code. Now that I think about it, I could have just re-pasted the code back in after editing - apologies that it didn't occur to me when I double-posted. I wasn't aware of the middle click feature - thanks for that…very handy :)/>


EDIT: I finally figured out what's going on - thanks to BombBloke for making me re-examine my approach to detecting peripherals and monitor sizes. This program supplements another program that also uses a similar detection routine that sets the textScale to 1 on all monitors detected (to determine their size) and clears them before setting their individual textScales. When this program called the other program all the monitors would be set to textScale 1 and be cleared; thus defeating my attempts to set the textScale and put text on the monitors. This occured to me when I set the monitors to textScale 2.5 and they were detected, but only displayed text at textScale 1, and only after the timer started. Bottom line - it was my fault, not a bug or problem in ComputerCraft - I was thinking in a vacuum and not considering the program this one was calling.
Edited on 25 June 2016 - 03:17 AM