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

Server Restarts -> Script Loops break. :(

Started by FallenMoons, 13 May 2015 - 08:59 PM
FallenMoons #1
Posted 13 May 2015 - 10:59 PM
I have 2 PCs running 2 monitors each. They have GUI buttons on them to open and close the door. When I restart the server the buttons are still displayed and the PC's terminal still shows it's in a loop but the buttons no longer work. I have to restart them to get them to work. Any ideas?
Cranium #2
Posted 13 May 2015 - 11:25 PM
It might help if you post the code that you're using, so we can see if there's a problem with it.
FallenMoons #3
Posted 13 May 2015 - 11:46 PM
It might help if you post the code that you're using, so we can see if there's a problem with it.

Sorry, I just didn't think it was relevant as it doesn't seem to be an issue with the script, rather with CC. But here it is!

Here's the program "door", it just gets ran from startup using "shell.run("door")"
Spoiler

os.loadAPI("touchpoint")
local o = touchpoint.new("monitor_2")
local i = touchpoint.new("monitor_3")
local state = "open"
function toggleState()
if state == "open" then
  o:rename("Open", "Close")
  i:rename("Open", "Close")
  o:toggleButton("Close")
  i:toggleButton("Close")
  state = "closed"
  rs.setOutput("top", false)
else
  o:rename("Close", "Open")
  i:rename("Close", "Open")
  o:toggleButton("Open")
  i:toggleButton("Open")
  state = "open"
  rs.setOutput("top", true)
end
end
o:add("Open", nil, 1, 1, 7, 5, colors.lime, colors.red)
i:add("Open", nil, 1, 1, 7, 5, colors.lime, colors.red)
while true do
o:draw()
i:draw()
local event = {i:handleEvents(o:handleEvents(os.pullEvent()))}
if event[1] == "button_click" then
  toggleState()
end
end

Now, as you can see I'm using lyqyd's touchpoint gui buttons API which is the code below, you can also find it here: http://www.computerc...touchpoint-api/
Spoiler

local function setupLabel(buttonLen, minY, maxY, name)
local labelTable = {}
if type(name) == "table" then
  for i = 1, #name do
   labelTable[i] = name[i]
  end
  name = name.label
elseif type(name) == "string" then
  local buttonText = string.sub(name, 1, buttonLen - 2)
  if #buttonText < #name then
   buttonText = " "..buttonText.." "
  else
   local labelLine = string.rep(" ", math.floor((buttonLen - #buttonText) / 2))..buttonText
   buttonText = labelLine..string.rep(" ", buttonLen - #labelLine)
  end
  for i = 1, maxY - minY + 1 do
   if maxY == minY or i == math.floor((maxY - minY) / 2) + 1 then
	labelTable[i] = buttonText
   else
	labelTable[i] = string.rep(" ", buttonLen)
   end
  end
end
return labelTable, name
end
local Button = {
draw = function(self)
  local old = term.redirect(self.mon)
  term.setTextColor(colors.white)
  term.setBackgroundColor(colors.black)
  term.clear()
  for name, buttonData in pairs(self.buttonList) do
   if buttonData.active then
	term.setBackgroundColor(buttonData.activeColor)
	term.setTextColor(buttonData.activeText)
   else
	term.setBackgroundColor(buttonData.inactiveColor)
	term.setTextColor(buttonData.inactiveText)
   end
   for i = buttonData.yMin, buttonData.yMax do
	term.setCursorPos(buttonData.xMin, i)
	term.write(buttonData.label[i - buttonData.yMin + 1])
   end
  end
  if old then
   term.redirect(old)
  else
   term.restore()
  end
end,
add = function(self, name, func, xMin, yMin, xMax, yMax, inactiveColor, activeColor, inactiveText, activeText)
  local label, name = setupLabel(xMax - xMin + 1, yMin, yMax, name)
  if self.buttonList[name] then error("button already exists", 2) end
  local x, y = self.mon.getSize()
  if xMin < 1 or yMin < 1 or xMax > x or yMax > y then error("button out of bounds", 2) end
  self.buttonList[name] = {
   func = func,
   xMin = xMin,
   yMin = yMin,
   xMax = xMax,
   yMax = yMax,
   active = false,
   inactiveColor = inactiveColor or colors.red,
   activeColor = activeColor or colors.lime,
   inactiveText = inactiveText or colors.white,
   activeText = activeText or colors.white,
   label = label,
  }
  for i = xMin, xMax do
   for j = yMin, yMax do
	if self.clickMap[i][j] ~= nil then
	 --undo changes
	 for k = xMin, xMax do
	  for l = yMin, yMax do
	   if self.clickMap[k][l] == name then
		self.clickMap[k][l] = nil
	   end
	  end
	 end
	 self.buttonList[name] = nil
	 error("overlapping button", 2)
	end
	self.clickMap[i][j] = name
   end
  end
end,
remove = function(self, name)
  if self.buttonList[name] then
   local button = self.buttonList[name]
   for i = button.xMin, button.xMax do
	for j = button.yMin, button.yMax do
	 self.clickMap[i][j] = nil
	end
   end
   self.buttonList[name] = nil
  end
end,
run = function(self)
  while true do
   self:draw()
   local event = {self:handleEvents(os.pullEvent(self.side == "term" and "mouse_click" or "monitor_touch"))}
   if event[1] == "button_click" then
	self.buttonList[event[2]].func()
   end
  end
end,
handleEvents = function(self, ...)
  local event = {...}
  if #event == 0 then event = {os.pullEvent()} end
  if (self.side == "term" and event[1] == "mouse_click") or (self.side ~= "term" and event[1] == "monitor_touch" and event[2] == self.side) then
   local clicked = self.clickMap[event[3]][event[4]]
   if clicked and self.buttonList[clicked] then
	return "button_click", clicked
   end
  end
  return unpack(event)
end,
toggleButton = function(self, name, noDraw)
  self.buttonList[name].active = not self.buttonList[name].active
  if not noDraw then self:draw() end
end,
flash = function(self, name, duration)
  self:toggleButton(name)
  sleep(tonumber(duration) or 0.15)
  self:toggleButton(name)
end,
rename = function(self, name, newName)
  self.buttonList[name].label, newName = setupLabel(self.buttonList[name].xMax - self.buttonList[name].xMin + 1, self.buttonList[name].yMin, self.buttonList[name].yMax, newName)
  if not self.buttonList[name] then error("no such button", 2) end
  if name ~= newName then
   self.buttonList[newName] = self.buttonList[name]
   self.buttonList[name] = nil
   for i = self.buttonList[newName].xMin, self.buttonList[newName].xMax do
	for j = self.buttonList[newName].yMin, self.buttonList[newName].yMax do
	 self.clickMap[i][j] = newName
	end
   end
  end
  self:draw()
end,
}
function new(monSide)
local buttonInstance = {
  side = monSide or "term",
  mon = monSide and peripheral.wrap(monSide) or term.current(),
  buttonList = {},
  clickMap = {},
}
local x, y = buttonInstance.mon.getSize()
for i = 1, x do
  buttonInstance.clickMap[i] = {}
end
setmetatable(buttonInstance, {__index = Button})
return buttonInstance
end

EDIT: Forgot to mention that the computers are connected via wired network modems and cables. That's why the peripherals are "monitor_0" etc and not "left" or "right" etc.
Edited on 13 May 2015 - 09:47 PM
Bomb Bloke #4
Posted 14 May 2015 - 01:13 AM
Hmm. Does it make a difference if you stick a sleep(0) up the top of the script?
flaghacker #5
Posted 14 May 2015 - 08:07 AM
Are you talking about actually restarting the Minecraft server? In that case computers will always terminate their programs.
FallenMoons #6
Posted 15 May 2015 - 01:13 AM
Are you talking about actually restarting the Minecraft server? In that case computers will always terminate their programs.

Yes. When stopping the actual minecraft server and restarting it when I log back in the monitors still show the GUI but clicking on them doesnt do anything. Then if I go and look at the computer there is no input available, meaning it's still in the loop. So I have to terminate and re-run the program or restart the PC then everything works again.
mercwear #7
Posted 15 May 2015 - 04:26 AM
I am having the same issue with 1.7. The startup program will run when the server restarts however the monitor output does not work until I open the GUI for the actual computer. Once I open the GUI the monitor will begin responding correctly (even though I did not restart the program).
Bomb Bloke #8
Posted 15 May 2015 - 04:35 AM
Does it make a difference if you stick a sleep(0) up the top of the script?