BigBlow_

Night-Weather_Controller

Oct 18th, 2025 (edited)
591
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 9.48 KB | None | 0 0
  1. -- Main control program: Day/Night and Weather management with clicker relay (non-blocking, with countdowns)
  2. -- All code in English, no accents
  3.  
  4. -- CONFIGURATION
  5.  
  6. local envDetector = "environment_detector_1"
  7. local invSource = "sophisticatedstorage:barrel_1"
  8. local clicker = "justdirethings:clickert1_1"
  9. local clickerRSrelay = "redstone_relay_3"
  10. local clickerRSrelaySide = "top"
  11. local brasierRSrelay = "redstone_relay_4"
  12. local brasierRSrelaySide = "bottom"
  13.  
  14. local delay = 1
  15. local pulseTime = 0.2
  16. local ritualCooldown = 30
  17. local disableRainClearDuration = 600
  18. local disableNightSkipDuration = 1200
  19.  
  20. local dayTablet = "ars_nouveau:ritual_sunrise"
  21. local weatherTablet = "ars_nouveau:ritual_cloudshaping"
  22. local rainItem = "minecraft:gunpowder"
  23. local thunderItem = "minecraft:lapis_block"
  24.  
  25. local textScale = 1  -- 1.0 = normal, 0.5-5
  26. local monitorRefresh = 0.5 --in seconds
  27.  
  28. -- STATE VARIABLES
  29. local rainClearEnabled = true
  30. local nightSkipEnabled = true
  31. local rainClearDisableTimer = nil
  32. local nightSkipDisableTimer = nil
  33. local currentAction = "Idle"
  34.  
  35. -- Ritual management
  36. local ritualActive = false
  37. local ritualType = nil
  38. local ritualStep = 0
  39. local ritualEndTime = 0
  40. local ritualTryTimer = 0
  41.  
  42. -- PERIPHERALS
  43. local env = peripheral.wrap(envDetector)
  44. local inv = peripheral.wrap(invSource)
  45. local click = peripheral.wrap(clicker)
  46. local clickRelay = peripheral.wrap(clickerRSrelay)
  47. local relay = peripheral.wrap(brasierRSrelay)
  48.  
  49. -- MONITORS
  50. local monitors = {}
  51. for _, name in pairs(peripheral.getNames()) do
  52.     if peripheral.getType(name) == "monitor" then
  53.         local mon = peripheral.wrap(name)
  54.         mon.setTextScale(textScale)
  55.         table.insert(monitors, mon)
  56.     end
  57. end
  58.  
  59. -- UTILITY
  60. local function pulseRelay(r, side)
  61.     r.setOutput(side, true)
  62.     sleep(pulseTime)
  63.     r.setOutput(side, false)
  64. end
  65.  
  66. local function sendItemToClicker(itemName)
  67.     local contents = click.list()
  68.     local empty = true
  69.     for _, _ in pairs(contents) do empty = false end
  70.     if not empty then return false end
  71.  
  72.     for slot, item in pairs(inv.list()) do
  73.         if item.name == itemName then
  74.             inv.pushItems(clicker, slot, 1)
  75.             pulseRelay(clickRelay, clickerRSrelaySide)
  76.             sleep(delay)
  77.             return true
  78.         end
  79.     end
  80.     return false
  81. end
  82.  
  83. -- RITUAL HANDLER (non-blocking)
  84. local function startRitual(type)
  85.     if ritualActive then return end
  86.     ritualActive = true
  87.     ritualType = type
  88.     ritualStep = 1
  89.     ritualEndTime = os.clock() + ritualCooldown
  90.     currentAction = type
  91. end
  92.  
  93. local function processRitual()
  94.     if not ritualActive then return end
  95.  
  96.     if os.clock() >= ritualTryTimer then
  97.         ritualTryTimer = os.clock() + 0.2 -- retry every 0.2s
  98.  
  99.         if ritualType == "Force Rain" then
  100.             if ritualStep == 1 and sendItemToClicker(weatherTablet) then ritualStep = 2 end
  101.             if ritualStep == 2 and sendItemToClicker(rainItem) then ritualStep = 3 end
  102.         elseif ritualType == "Force Thunder" then
  103.             if ritualStep == 1 and sendItemToClicker(weatherTablet) then ritualStep = 2 end
  104.             if ritualStep == 2 and sendItemToClicker(thunderItem) then ritualStep = 3 end
  105.         elseif ritualType == "Auto RainClear" and ritualStep == 1 then
  106.             if sendItemToClicker(weatherTablet) then ritualStep = 2 end
  107.         elseif ritualType == "Auto NightSkip" and ritualStep == 1 then
  108.             if sendItemToClicker(dayTablet) then ritualStep = 2 end
  109.         elseif ritualType == "Force Day" and ritualStep == 1 then
  110.             if sendItemToClicker(dayTablet) then ritualStep = 2 end
  111.         end
  112.  
  113.         -- Pulse relay on last step
  114.         if ritualStep == 2 or ritualStep == 3 then
  115.             pulseRelay(relay, brasierRSrelaySide)
  116.             ritualStep = 99
  117.         end
  118.     end
  119.  
  120.     if os.clock() >= ritualEndTime then
  121.         ritualActive = false
  122.         ritualType = nil
  123.         ritualStep = 0
  124.         currentAction = "Idle"
  125.     end
  126. end
  127.  
  128. -- AUTO FUNCTIONS
  129. local function autoRainClear()
  130.     if not rainClearEnabled and rainClearDisableTimer and os.clock() >= rainClearDisableTimer then
  131.         rainClearEnabled = true
  132.         rainClearDisableTimer = nil
  133.     end
  134.     if not rainClearEnabled or ritualActive then return end
  135.     if env.isRaining() then
  136.         startRitual("Auto RainClear")
  137.     end
  138. end
  139.  
  140. local function autoNightSkip()
  141.     if not nightSkipEnabled and nightSkipDisableTimer and os.clock() >= nightSkipDisableTimer then
  142.         nightSkipEnabled = true
  143.         nightSkipDisableTimer = nil
  144.     end
  145.     if not nightSkipEnabled or ritualActive then return end
  146.     local gameTime = os.time()
  147.     if gameTime >= 18.000 and gameTime < 24.000 then
  148.         startRitual("Auto NightSkip")
  149.     end
  150. end
  151.  
  152. -- FORCE FUNCTIONS
  153. local function ForceRain()
  154.     rainClearEnabled = false
  155.     rainClearDisableTimer = os.clock() + disableRainClearDuration
  156.     startRitual("Force Rain")
  157. end
  158.  
  159. local function ForceThunder()
  160.     rainClearEnabled = false
  161.     rainClearDisableTimer = os.clock() + disableRainClearDuration
  162.     startRitual("Force Thunder")
  163. end
  164.  
  165. local function ForceDay()
  166.     startRitual("Force Day")
  167. end
  168.  
  169. -- TOGGLE
  170. local function toggleRainClear()
  171.     if rainClearEnabled then
  172.         rainClearEnabled = false
  173.         rainClearDisableTimer = os.clock() + disableRainClearDuration
  174.     else
  175.         rainClearEnabled = true
  176.         rainClearDisableTimer = nil
  177.     end
  178. end
  179.  
  180. local function toggleNightSkip()
  181.     if nightSkipEnabled then
  182.         nightSkipEnabled = false
  183.         nightSkipDisableTimer = os.clock() + disableNightSkipDuration
  184.     else
  185.         nightSkipEnabled = true
  186.         nightSkipDisableTimer = nil
  187.     end
  188. end
  189.  
  190. -- DISPLAY
  191. local function drawMonitor(mon)
  192.     mon.clear()
  193.     mon.setCursorPos(1,1)
  194.     mon.setTextColor(colors.white)
  195.     local formattedTime = textutils.formatTime(os.time(), true)
  196.     mon.write("Time: " .. formattedTime)
  197.    
  198.     mon.setCursorPos(1,2)
  199.     local weather = env.isRaining() and "Rain" or "Clear"
  200.     mon.write("Weather: " .. weather)
  201.    
  202.     -- ACTION
  203.     mon.setCursorPos(1,3)
  204.     mon.setTextColor(colors.white)
  205.     mon.write("Action: ")
  206.     if currentAction == "Idle" then
  207.         mon.setTextColor(colors.white)
  208.     else
  209.         mon.setTextColor(colors.orange)
  210.     end
  211.     mon.write(currentAction)
  212.     if ritualActive then
  213.         local remaining = math.max(0, math.floor(ritualEndTime - os.clock()))
  214.         mon.write(" (" .. remaining .. "s)")
  215.     end
  216.     mon.setTextColor(colors.white)
  217.  
  218.     -- NIGHT SKIP STATUS
  219.     mon.setCursorPos(1,4)
  220.     mon.setTextColor(colors.white)
  221.     mon.write("Night Skip: ")
  222.     local nsRemaining = 0
  223.     if not nightSkipEnabled and nightSkipDisableTimer then
  224.         nsRemaining = math.max(0, math.floor(nightSkipDisableTimer - os.clock()))
  225.     end
  226.     if nightSkipEnabled then
  227.         mon.setTextColor(colors.green)
  228.     else
  229.         mon.setTextColor(colors.red)
  230.     end
  231.     mon.write(nightSkipEnabled and "Enabled" or "Disabled")
  232.     if nsRemaining > 0 then
  233.         mon.write(" (" .. nsRemaining .. "s)")
  234.     end
  235.     mon.setTextColor(colors.white)
  236.  
  237.     -- RAIN CLEAR STATUS
  238.     mon.setCursorPos(1,5)
  239.     mon.setTextColor(colors.white)
  240.     mon.write("Rain Clear: ")
  241.     local rcRemaining = 0
  242.     if not rainClearEnabled and rainClearDisableTimer then
  243.         rcRemaining = math.max(0, math.floor(rainClearDisableTimer - os.clock()))
  244.     end
  245.     if rainClearEnabled then
  246.         mon.setTextColor(colors.green)
  247.     else
  248.         mon.setTextColor(colors.red)
  249.     end
  250.     mon.write(rainClearEnabled and "Enabled" or "Disabled")
  251.     if rcRemaining > 0 then
  252.         mon.write(" (" .. rcRemaining .. "s)")
  253.     end
  254.     mon.setTextColor(colors.white)
  255.  
  256.     -- BUTTONS
  257.     -- Force actions first row
  258.     mon.setTextColor(colors.yellow)
  259.     mon.setCursorPos(1,7)
  260.     mon.write("[Force Day]")
  261.     mon.setTextColor(colors.lightBlue)
  262.     mon.setCursorPos(1,8)
  263.     mon.write("[Force Rain]")
  264.     mon.setTextColor(colors.blue)
  265.     mon.setCursorPos(1,9)
  266.     mon.write("[Force Thunder]")
  267.  
  268.     -- Toggle buttons second row with colored names only
  269.     -- Rain Clear
  270.     mon.setCursorPos(1,11)
  271.     mon.setTextColor(colors.white)
  272.     mon.write("[Toggle ")
  273.     if rainClearEnabled then
  274.         mon.setTextColor(colors.green)
  275.     else
  276.         mon.setTextColor(colors.red)
  277.     end
  278.     mon.write("Rain Clear")
  279.     mon.setTextColor(colors.white)
  280.     mon.write("]")
  281.  
  282.     -- Night Skip
  283.     mon.setCursorPos(1,12)
  284.     mon.setTextColor(colors.white)
  285.     mon.write("[Toggle ")
  286.     if nightSkipEnabled then
  287.         mon.setTextColor(colors.green)
  288.     else
  289.         mon.setTextColor(colors.red)
  290.     end
  291.     mon.write("Night Skip")
  292.     mon.setTextColor(colors.white)
  293.     mon.write("]")
  294. end
  295.  
  296. local function drawAllMonitors()
  297.     for _, mon in pairs(monitors) do
  298.         drawMonitor(mon)
  299.     end
  300. end
  301.  
  302. -- TOUCH HANDLER
  303. local function handleTouch(x, y)
  304.     if y == 7 then ForceDay() end
  305.     if y == 8 then ForceRain() end
  306.     if y == 9 then ForceThunder() end
  307.     if y == 11 then toggleRainClear() end
  308.     if y == 12 then toggleNightSkip() end
  309. end
  310.  
  311. -- LOOP FUNCTIONS
  312. local function updateLoop()
  313.     while true do
  314.         drawAllMonitors()
  315.         autoRainClear()
  316.         autoNightSkip()
  317.         processRitual()
  318.         sleep(monitorRefresh)
  319.     end
  320. end
  321.  
  322. local function touchLoop()
  323.     while true do
  324.         local event, side, x, y = os.pullEvent("monitor_touch")
  325.         handleTouch(x, y)
  326.     end
  327. end
  328.  
  329. -- RUN BOTH LOOPS
  330. parallel.waitForAny(updateLoop, touchLoop)
  331.  
Advertisement
Add Comment
Please, Sign In to add comment