Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Main control program: Day/Night and Weather management with clicker relay (non-blocking, with countdowns)
- -- All code in English, no accents
- -- CONFIGURATION
- local envDetector = "environment_detector_1"
- local invSource = "sophisticatedstorage:barrel_1"
- local clicker = "justdirethings:clickert1_1"
- local clickerRSrelay = "redstone_relay_3"
- local clickerRSrelaySide = "top"
- local brasierRSrelay = "redstone_relay_4"
- local brasierRSrelaySide = "bottom"
- local delay = 1
- local pulseTime = 0.2
- local ritualCooldown = 30
- local disableRainClearDuration = 600
- local disableNightSkipDuration = 1200
- local dayTablet = "ars_nouveau:ritual_sunrise"
- local weatherTablet = "ars_nouveau:ritual_cloudshaping"
- local rainItem = "minecraft:gunpowder"
- local thunderItem = "minecraft:lapis_block"
- local textScale = 1 -- 1.0 = normal, 0.5-5
- local monitorRefresh = 0.5 --in seconds
- -- STATE VARIABLES
- local rainClearEnabled = true
- local nightSkipEnabled = true
- local rainClearDisableTimer = nil
- local nightSkipDisableTimer = nil
- local currentAction = "Idle"
- -- Ritual management
- local ritualActive = false
- local ritualType = nil
- local ritualStep = 0
- local ritualEndTime = 0
- local ritualTryTimer = 0
- -- PERIPHERALS
- local env = peripheral.wrap(envDetector)
- local inv = peripheral.wrap(invSource)
- local click = peripheral.wrap(clicker)
- local clickRelay = peripheral.wrap(clickerRSrelay)
- local relay = peripheral.wrap(brasierRSrelay)
- -- MONITORS
- local monitors = {}
- for _, name in pairs(peripheral.getNames()) do
- if peripheral.getType(name) == "monitor" then
- local mon = peripheral.wrap(name)
- mon.setTextScale(textScale)
- table.insert(monitors, mon)
- end
- end
- -- UTILITY
- local function pulseRelay(r, side)
- r.setOutput(side, true)
- sleep(pulseTime)
- r.setOutput(side, false)
- end
- local function sendItemToClicker(itemName)
- local contents = click.list()
- local empty = true
- for _, _ in pairs(contents) do empty = false end
- if not empty then return false end
- for slot, item in pairs(inv.list()) do
- if item.name == itemName then
- inv.pushItems(clicker, slot, 1)
- pulseRelay(clickRelay, clickerRSrelaySide)
- sleep(delay)
- return true
- end
- end
- return false
- end
- -- RITUAL HANDLER (non-blocking)
- local function startRitual(type)
- if ritualActive then return end
- ritualActive = true
- ritualType = type
- ritualStep = 1
- ritualEndTime = os.clock() + ritualCooldown
- currentAction = type
- end
- local function processRitual()
- if not ritualActive then return end
- if os.clock() >= ritualTryTimer then
- ritualTryTimer = os.clock() + 0.2 -- retry every 0.2s
- if ritualType == "Force Rain" then
- if ritualStep == 1 and sendItemToClicker(weatherTablet) then ritualStep = 2 end
- if ritualStep == 2 and sendItemToClicker(rainItem) then ritualStep = 3 end
- elseif ritualType == "Force Thunder" then
- if ritualStep == 1 and sendItemToClicker(weatherTablet) then ritualStep = 2 end
- if ritualStep == 2 and sendItemToClicker(thunderItem) then ritualStep = 3 end
- elseif ritualType == "Auto RainClear" and ritualStep == 1 then
- if sendItemToClicker(weatherTablet) then ritualStep = 2 end
- elseif ritualType == "Auto NightSkip" and ritualStep == 1 then
- if sendItemToClicker(dayTablet) then ritualStep = 2 end
- elseif ritualType == "Force Day" and ritualStep == 1 then
- if sendItemToClicker(dayTablet) then ritualStep = 2 end
- end
- -- Pulse relay on last step
- if ritualStep == 2 or ritualStep == 3 then
- pulseRelay(relay, brasierRSrelaySide)
- ritualStep = 99
- end
- end
- if os.clock() >= ritualEndTime then
- ritualActive = false
- ritualType = nil
- ritualStep = 0
- currentAction = "Idle"
- end
- end
- -- AUTO FUNCTIONS
- local function autoRainClear()
- if not rainClearEnabled and rainClearDisableTimer and os.clock() >= rainClearDisableTimer then
- rainClearEnabled = true
- rainClearDisableTimer = nil
- end
- if not rainClearEnabled or ritualActive then return end
- if env.isRaining() then
- startRitual("Auto RainClear")
- end
- end
- local function autoNightSkip()
- if not nightSkipEnabled and nightSkipDisableTimer and os.clock() >= nightSkipDisableTimer then
- nightSkipEnabled = true
- nightSkipDisableTimer = nil
- end
- if not nightSkipEnabled or ritualActive then return end
- local gameTime = os.time()
- if gameTime >= 18.000 and gameTime < 24.000 then
- startRitual("Auto NightSkip")
- end
- end
- -- FORCE FUNCTIONS
- local function ForceRain()
- rainClearEnabled = false
- rainClearDisableTimer = os.clock() + disableRainClearDuration
- startRitual("Force Rain")
- end
- local function ForceThunder()
- rainClearEnabled = false
- rainClearDisableTimer = os.clock() + disableRainClearDuration
- startRitual("Force Thunder")
- end
- local function ForceDay()
- startRitual("Force Day")
- end
- -- TOGGLE
- local function toggleRainClear()
- if rainClearEnabled then
- rainClearEnabled = false
- rainClearDisableTimer = os.clock() + disableRainClearDuration
- else
- rainClearEnabled = true
- rainClearDisableTimer = nil
- end
- end
- local function toggleNightSkip()
- if nightSkipEnabled then
- nightSkipEnabled = false
- nightSkipDisableTimer = os.clock() + disableNightSkipDuration
- else
- nightSkipEnabled = true
- nightSkipDisableTimer = nil
- end
- end
- -- DISPLAY
- local function drawMonitor(mon)
- mon.clear()
- mon.setCursorPos(1,1)
- mon.setTextColor(colors.white)
- local formattedTime = textutils.formatTime(os.time(), true)
- mon.write("Time: " .. formattedTime)
- mon.setCursorPos(1,2)
- local weather = env.isRaining() and "Rain" or "Clear"
- mon.write("Weather: " .. weather)
- -- ACTION
- mon.setCursorPos(1,3)
- mon.setTextColor(colors.white)
- mon.write("Action: ")
- if currentAction == "Idle" then
- mon.setTextColor(colors.white)
- else
- mon.setTextColor(colors.orange)
- end
- mon.write(currentAction)
- if ritualActive then
- local remaining = math.max(0, math.floor(ritualEndTime - os.clock()))
- mon.write(" (" .. remaining .. "s)")
- end
- mon.setTextColor(colors.white)
- -- NIGHT SKIP STATUS
- mon.setCursorPos(1,4)
- mon.setTextColor(colors.white)
- mon.write("Night Skip: ")
- local nsRemaining = 0
- if not nightSkipEnabled and nightSkipDisableTimer then
- nsRemaining = math.max(0, math.floor(nightSkipDisableTimer - os.clock()))
- end
- if nightSkipEnabled then
- mon.setTextColor(colors.green)
- else
- mon.setTextColor(colors.red)
- end
- mon.write(nightSkipEnabled and "Enabled" or "Disabled")
- if nsRemaining > 0 then
- mon.write(" (" .. nsRemaining .. "s)")
- end
- mon.setTextColor(colors.white)
- -- RAIN CLEAR STATUS
- mon.setCursorPos(1,5)
- mon.setTextColor(colors.white)
- mon.write("Rain Clear: ")
- local rcRemaining = 0
- if not rainClearEnabled and rainClearDisableTimer then
- rcRemaining = math.max(0, math.floor(rainClearDisableTimer - os.clock()))
- end
- if rainClearEnabled then
- mon.setTextColor(colors.green)
- else
- mon.setTextColor(colors.red)
- end
- mon.write(rainClearEnabled and "Enabled" or "Disabled")
- if rcRemaining > 0 then
- mon.write(" (" .. rcRemaining .. "s)")
- end
- mon.setTextColor(colors.white)
- -- BUTTONS
- -- Force actions first row
- mon.setTextColor(colors.yellow)
- mon.setCursorPos(1,7)
- mon.write("[Force Day]")
- mon.setTextColor(colors.lightBlue)
- mon.setCursorPos(1,8)
- mon.write("[Force Rain]")
- mon.setTextColor(colors.blue)
- mon.setCursorPos(1,9)
- mon.write("[Force Thunder]")
- -- Toggle buttons second row with colored names only
- -- Rain Clear
- mon.setCursorPos(1,11)
- mon.setTextColor(colors.white)
- mon.write("[Toggle ")
- if rainClearEnabled then
- mon.setTextColor(colors.green)
- else
- mon.setTextColor(colors.red)
- end
- mon.write("Rain Clear")
- mon.setTextColor(colors.white)
- mon.write("]")
- -- Night Skip
- mon.setCursorPos(1,12)
- mon.setTextColor(colors.white)
- mon.write("[Toggle ")
- if nightSkipEnabled then
- mon.setTextColor(colors.green)
- else
- mon.setTextColor(colors.red)
- end
- mon.write("Night Skip")
- mon.setTextColor(colors.white)
- mon.write("]")
- end
- local function drawAllMonitors()
- for _, mon in pairs(monitors) do
- drawMonitor(mon)
- end
- end
- -- TOUCH HANDLER
- local function handleTouch(x, y)
- if y == 7 then ForceDay() end
- if y == 8 then ForceRain() end
- if y == 9 then ForceThunder() end
- if y == 11 then toggleRainClear() end
- if y == 12 then toggleNightSkip() end
- end
- -- LOOP FUNCTIONS
- local function updateLoop()
- while true do
- drawAllMonitors()
- autoRainClear()
- autoNightSkip()
- processRitual()
- sleep(monitorRefresh)
- end
- end
- local function touchLoop()
- while true do
- local event, side, x, y = os.pullEvent("monitor_touch")
- handleTouch(x, y)
- end
- end
- -- RUN BOTH LOOPS
- parallel.waitForAny(updateLoop, touchLoop)
Advertisement
Add Comment
Please, Sign In to add comment