This fairly simple program will display Real World time for up to three timezones (pulling time from time.org) and Minecraft world (local) time on the computer as well as on any number of wired attached monitors. I wrote it for a gathering area of sorts on my servers (the area serves as a transit station). The players on my server seem to think it is fun to have going. We have a chunk loader in this area, so the program is constantly active. This version is cleaner and pretty well de-bugged. Let me know what you think. The program uses http access as well as the parallel API to update the displays of time.
Change Log
- Added screenshots to this page
- Added Parallel functionality in coroutines (thanks [member='Lyqyd'] for the info)
- Remove a debug feature (no longer necessary)
- Resolved issue where not booting (or very slow booting) on computer startup
- Cut down on number of calls to refreshTime()
- Added some commenting and reorganized code
- Created a new API to obtain real world date and time. The Real World Time API is now in beta.
Features
- Will print to computer (normal or advanced) as well as any specified monitors
- Can specify city names and timezones in the time{} array.
- Can specify and add new monitors in the monitors{} array.
- Adjusts for color or non-color monitors
- Attempts to maximize display size based on length of the longest city name while having at least 8 display lines.
- Utilizes http access and pulls time from http://www.timeapi.org
- Utilizes Parallel API for individual timer intervals on real world and Minecraft world time.
Usage
- Place computer, type in
pastebin get AUQfZjRK startup
- Restart computer
- Attach a wired modem to the computer, and use network cable and additional wired modems to attach additional monitors of any size (with or without color capability)
- For each monitor, modify the code, specifying the monitor label where indicated in the examples (i.e., monitor_1)
- To change time zones, use any timezone designation consistent with the API of http://www.timeapi.org.
Code
-----------------------------------------------------------------------
--[[ TimeDisplays v 2.0
by Surferpup
This program displays real world for 3 time zone
and minecraft time on a computer and (optionally)
on as many wired monitors as are declared.
The program as configured does not have any monitors declared.
Simply go to the monitor section and uncomment/add monitor lines
as necessary.
The program will take advantage of color computers and monitors.
Save this program as startup if you want it to run on block load.
]]
-----------------------------------------------------------------------
local mcInterval = 1 -- the polling interval for Minecraft Time updates
local rwInterval= 60 -- the polling world for real world time updates
-----------------------------------------------------------------------
-- MONITORS
-- You can have as many as you'd like
-- you need to change this to your monitor labels
-- format [n] = peripheral.wrap("monitor_label)
-- Don't forget commas between all BUT the last entry
--
-- I formated three for you and commented them out.
------------------------------------------------------------------------
local monitors = {
-- [1]=peripheral.wrap("monitor_0");
-- [2]=peripheral.wrap("monitor_1");
-- [3]=peripheral.wrap("monitor_2");
}
-----------------------------------------------------------------------
-- TIME ZONES
-- 3 real world and 1 local (minecraft) time zone
-- change zone to be a zone recognized by www.timeapi.org
-- go to timeapi.org and get your own strings using the same exact format
------------------------------------------------------------------------
local time = {
[1]={city="Sioux Falls",color=colors.lightBlue,time="NOW",zone = "cst"}, -- central
[2]={city="Osaka",color=colors.yellow,time="NOW",zone = "utc"}, -- universal
[3]={city="Livermore",color=colors.lime,time="NOW",zone = "pst"}, -- pacific
[4]={city="Local",color=colors.pink,time="NOW",zone = ""} -- This is minecraft time
}
function refreshTime()
for i = 1,3 do
time[i].time=(http.get("http://www.timeapi.org/"..(time[i].zone).."/now?format=%25l:%25M%20%25p").readAll())
end
time[4].time= textutils.formatTime(os.time(), false)
end
------------------------------------------------------------------------
-- OTHER LOCAL VARIABLES
local minecraftTimer,realWorldTimer,rwTime,mcWorldTime,maxLabelSize
------------------------------------------------------------------------
-- FUNCTIONS
function pad(width,text)
return (string.rep(" ",width-string.len(text))..text)
end
local function clearAllScreens()
term.clear()
for i = 1,#monitors do
monitors[i].clear()
end
end
function calculateMaxLabelSize() -- city names vary in size
local maxLabelSize = 0
for i= 1,4 do
if #(time[i].city)>maxLabelSize then
maxLabelSize = #(time[i].city)
end
end
return maxLabelSize
end
local function setScale(maxLabelSize) -- fit city names to varying size monitors
for i = 1,#monitors do
for j=10,1,-1 do
monitors[i].setTextScale(j/2)
local mX,mY = monitors[i].getSize()
if mY>=8 then
if mX>maxLabelSize then
break
end
end
end
end
end
function displayRealWorldTime()
while true do
local e = {os.pullEvent()} -- this will yield back to main loop
if (e[1] == "timer" and e[2] == realWorldTimer) or e[1]=="start" then
refreshTime()
for t = 1,4 do
if term.isColor() then
term.setTextColor(tonumber(time[t].color))
else
term.setTextColor(colors.white)
end
term.setCursorPos(1,t)
term.clearLine()
x,_ = term.getSize()
term.write(pad(x,time[t].time))
term.setCursorPos(1,t)
term.write(time[t].city)
end
term.setTextColor(colors.white) -- reset terminal to default color
for i = 1,#monitors do
for t = 1,4 do
local x,_ = monitors[i].getSize()
monitors[i].setCursorPos(1,2*t-1)
monitors[i].clearLine()
if monitors[i].isColor() then
monitors[i].setTextColor(tonumber(time[t].color))
else
monitors[i].setTextColor(colors.white)
end
monitors[i].write(time[t].city)
monitors[i].setCursorPos(1,t*2)
monitors[i].write(pad(x,time[t].time))
end
end
realWorldTimer = os.startTimer(rwInterval)
end
end
end
function displayMinecraftWorldTime()
while true do
local e = {os.pullEvent()} -- this will yield back to main loop
if (e[1] == "timer" and e[2] == minecraftTimer) or e[1]=="start" then
time[4].time= textutils.formatTime(os.time(), false)
for i = 1,#monitors do
monitors[i].setCursorPos(1,8)
monitors[i].clearLine()
if monitors[i].isColor() then
monitors[i].setTextColor(tonumber(time[4].color))
end
local x,_ = monitors[i].getSize()
monitors[i].write(pad(x,time[4].time))
end
term.setCursorPos(1,4)
term.clearLine()
if term.isColor() then
term.setTextColor(tonumber(time[4].color))
end
x,_ = term.getSize()
term.write(pad(x,time[4].time))
term.setCursorPos(1,4)
term.write(time[4].city)
if term.isColor()
then term.setTextColor(colors.white)
end
minecraftTimer=os.startTimer(mcInterval)
end
end
end
local function realWorldTime() -- coroutine driver in parallel
local tFilter = nil
local eventData = {}
local r = rwTime -- coroutine
while true do
if r then
if tFilter == nil or tFilter == eventData[1] or eventData[1] == "terminate" then
local ok, param = coroutine.resume( r, unpack(eventData) )
if not ok then
error( param )
else
tFilter = param
end
if coroutine.status( r ) == "dead" or eventData[1] == "terminate" then
r = nil
event = "terminate"
return
end
end
end
eventData = { os.pullEventRaw() }
end
end
local function mineCraftTime() -- coroutine driver in parallel
local tFilter = nil
local eventData = {}
local r = mcWorldTime --coroutine
while true do
if r then
if tFilter == nil or tFilter == eventData[1] or eventData[1] == "terminate" then
local ok, param = coroutine.resume( r, unpack(eventData) )
if not ok then
error( param )
else
tFilter = param
end
if coroutine.status( r ) == "dead" or eventData[1] == "terminate" then
r = nil
event = "terminate"
return
end
end
end
eventData = { os.pullEventRaw() }
end
end
local function start()
sleep(.5)
os.queueEvent("start")
return
end
-----------------------------------------------------------------------
-- MAIN PROGRAM
-----------------------------------------------------------------------
minecraftTimer = 0
realWorldTimer = 0
-- create coroutines
rwTime = coroutine.create(displayRealWorldTime)
mcWorldTime = coroutine.create(displayMinecraftWorldTime)
-- calculate maxLabelSize
maxLabelSize = calculateMaxLabelSize()
-- set Scale for Monitors
setScale(maxLabelSize)
clearAllScreens()
-- Start Parallel functions
--
--[[
The program uses coroutines in conjuction with
parallel functions. The first function (start) will
queue a start event. The next two functions drive
coroutines which update minecraft time or real world time.
Thanks to Lyqyd on ComputerCraft forums for the
ideas behind the coroutine driving functions running
in parallel
]]
parallel.waitForAll(start,mineCraftTime,realWorldTime)
Paste bin link: http://pastebin.com/AUQfZjRK
Thanks to Lyqyd, theoriginalbit, Death and Bubba for the help.