Updated to 1.85! Admin Support!
This program features:
- Full Account Manipulation
- (Almost!) Complete IRC Client and Server System
- OP System
- Complete E-Mail Client-Client System
- Contacts System
- Complete Filebrowser
- Working Update Feature (Possibly auto update in the next version!)
- Custom read function that allows for simple character limiting and preventing the entire line being cleared when reading
- Auto Updating
- Admin Support
!WARNING!
- The IRC option will not work unless you have the IRC server program running on the computer of your choice!
OPTIONAL FEATURES:
- Random 10,000 key generator
- Key server for basic anti-piracy
Cannon OS features a glamorous custom GUI and useful utilities while still allowing for full user manipulation of the Craft OS system underneath it. This is my most complete and lengthy project so it does contain some sloppy code that will be cleaned up in newer versions (if there are any). Despite the mess that is the source code, Cannon OS is completely functional to my knowledge and testing.
However, in the case that you may find a bug or an issue feel free to post or PM me the complaint/problem!
Screenshots:
Spoiler
http://imgur.com/a/PI9GvIRC Commands: !kick <user>, !exit
Email Quick Notes:
- Under the recipient field during composing the mail, you can enter the name of a contact and the correct ID will be set for you!
Code:
Spoiler
Cannon OS:Spoiler
oldpullEvent = os.pullEvent
os.pullEvent = os.pullEventRaw
-- Cannon OS by PaymentOption --
VERSION = 1.85
--------------------------------
rednet.open("top")
rednet.open("bottom")
rednet.open("back")
rednet.open("front")
rednet.open("right")
rednet.open("left")
--[[ Notes:
User information like passwords are located in the User/<computerID>/.info.
E-Mails are stored in the /Mail Directory.
E-Mail preferences are stored in /Mail/.prefs.
All printing functions like PrintMenu and PrintMainScreen do not clear the screen first; you must clear it before using them.
--]]
-- VARIABLES --
-- Update and Service Variables --
nServerID = 12 -- Update and key check server ID
----------------------------------
-- Screen Variables --
screenWidth, screenHeight = term.getSize()
selection = 1
sMenuState = "main"
----------------------
-- Account Variables --
sUserName = ""
sPassword = ""
bNewUser = true
bLogin = true
bAdmin = true -- Switch to false to disable the following features: CraftOS, Computer, Email, Account Manipulation
-----------------------
-- Authenticity Variables --
sLocalKey = ""
bIsAuthentic = false -- If the key entered by the user upon installation is correct, then this should be true
----------------------------
-- Mail --
if(fs.isDir("Mail")) then nMail = #(fs.list("Mail"))-1
else nMailCount = 0 end
----------
---------------
-- Software Validation --
function checkKey(sKey)
rednet.send(nServerID, "CHECKMYKEY")
rednet.send(nServerID, tostring(sKey))
sender, message = rednet.receive(1)
if sender == nServerID then
if message ~= "authentic" then bAuthentic = false; return false
else bAuthentic = true; return true end
end
end
function getKey()
if fs.exists(".key") then return end
if bIsAuthentic == true then return end -- To avoid embarassing double authentication!
clear()
printMainScreen()
sleep(2)
clear()
printBorder()
cPrint(3, "Welcome!")
cPrint(5, "You're about to install:")
cPrint(6, "Cannon OS V:"..VERSION.."!")
cPrint(7, " The installation wizard will walk you")
cPrint(8, " through product validation to installation.")
cPrint(10, "Before you continue, make sure that you have")
cPrint(11, " the product key given by your distributor.")
cPrint(15, "[ Continue ]")
while true do
event, key = os.pullEvent("key")
if key == 28 then break end
end
clear()
printBorder()
rPrint(17, "Cannon OS Version: "..VERSION.."*")
rPrint(16, "Software: LOCKED*")
cPrint(8, "Please enter your product key here:")
term.setCursorPos(15, 9); write("Key: ")
local sProductKey = newRead()
if checkKey(sProductKey) then
clear()
printBorder()
cPrint(9, "Congradulations,")
cPrint(10, "Your software has successfully been")
cPrint(11, "VALIDATED!")
sleep(3)
local file = fs.open(".key", "w")
file.writeLine(sProductKey)
file.close()
bIsAuthentic = true
else
clear()
printBorder()
cPrint(8, "I'm sorry, but the key")
cPrint(9, "entered doesn't seem to be valid.")
sleep(3)
os.shutdown()
end
end
-------------------------
-- Helper Functions --
function cPrint(height, string)
local xPos = screenWidth/2 - string.len(string)/2
term.setCursorPos(xPos, height); term.write(string)
end
function rPrint(height, string)
local xPos = screenWidth - string.len(string)
term.setCursorPos(xPos, height); term.write(string)
end
function clear() term.clear(); term.setCursorPos(1,1) end
function printBorder()
write(" "..string.rep("*", screenWidth-2).."n")
for i=1, screenHeight-2 do
write(" *"..string.rep(" ", screenWidth-4).."*n")
end
write(" "..string.rep("*", screenWidth-2))
end
function customWrite(height, string)
term.setCursorPos(3, height)
term.write(string)
end
function clearCenter()
cPrint(2, "* "..sUserName.." *")
cPrint(3, "*"..string.rep("*", string.len(sUserName)+2).."*")
rPrint(17, "Cannon OS Version: "..VERSION.. "*")
local line = 4
term.setCursorPos(34, 3); term.write(" ") -- Remove the very top part of the cannon logo
repeat
term.setCursorPos(1, line); term.clearLine()
line = line+1
until line == 12
line = 4
term.setCursorPos(1, 4)
repeat
write(" *"..string.rep(" ", screenWidth-4).."*n")
line = line+1
until line == 12
end
function printContainer()
term.setCursorPos(4, 5); term.write(string.rep("*", screenWidth-6))
local y = 6
for i=1, screenHeight - 13 do
term.setCursorPos(4, y); term.write("*"..string.rep(" ", screenWidth-8).."*")
y = y+1
end
term.setCursorPos(4, 11); term.write(string.rep("*", screenWidth-6))
end
-- Perfecting the pullEvent backspace attempt 1! --
function newRead( _charLimit, _ReplaceChar) -- The filter can either be a 1, 0, or nil. 1 is Numbers only, 0 is letters only, and nil is both
local sMessage = ""
term.setCursorBlink(true)
local originalCursorX, originalCursorY = term.getCursorPos()
while true do
local cursorX, cursorY = term.getCursorPos()
local event, p1 = os.pullEvent()
if _charLimit ~= nil then
if string.len(sMessage) == _charLimit then term.setCursorBlink(false); return sMessage end
end
if event == "char" then sMessage = sMessage..p1
--[[elseif event == "key" then -- The escape key has keyID 1 so: 0 = keyID: 11, 1 = keyID: 2, 2 = keyID : 3 etc etc....
if p1 == 11 or p1 == 2 or p1 == 3 or p1 == 4 or p1 == 5 or p1 == 6 or p1 == 7 or p1 == 8 or p1 == 9 or p1 == 10 then
-- 0 1 2 3 4 5 6 7 8 9
sMessage = sMessage..(p1-1)
end--]]
end
if event == "key" and p1 == 28 then term.setCursorBlink(false); return sMessage end-- Enter key; end the loop and let's see the string
if event == "key" and p1 == 14 then -- Backspace...
sMessage = string.sub(sMessage, 1, string.len(sMessage)-1)
-- Set our message to the substring of the first charcter
-- To the length of the message minus 1 to achieve one less letter.
term.setCursorPos(originalCursorX, cursorY)
term.write(sMessage.." ") -- Adding this empty space clears the removed character from the line, but may pose future issues
end
term.setCursorPos(originalCursorX, cursorY); term.write(string.rep(" ", string.len(sMessage)))
-- Clear the previous line just in case we get a new line
-- Now write the message on the new line
if _ReplaceChar ~= nil then
term.setCursorPos(originalCursorX, cursorY)
term.write(string.rep( _ReplaceChar, string.len(sMessage) ))
else
term.setCursorPos(originalCursorX, cursorY)
term.write(sMessage)
end
end
end
----------------------
-- System Functions --
function checkInstalltion()
if fs.exists("SYSTEM/.installed") then return true
else return false end
end
function runShell() shell.run("/rom/programs/shell") end
function getVersion() return VERSION end
function checkVersion()
local sCommand = "get"
if sCommand == "get" then
local sCode = "c17Hgq1A"
local sPath = ".tempVersion"
while true do
local response = http.get(
"http://pastebin.com/raw.php?i="..textutils.urlEncode( sCode )
)
if response then
local sResponse = response.readAll()
response.close()
if tonumber(sResponse) > VERSION then return true
else return false end
break
else return false end
end
end
end
function updateSelf()
local sCommand = "get"
if sCommand == "get" then
local sCode = "6a92bGGZ"
local sFile = "startup"
local sPath = shell.resolve( sFile )
while true do
local response = http.get(
"http://pastebin.com/raw.php?i="..textutils.urlEncode( sCode )
)
if response then
local sResponse = response.readAll()
response.close()
local file = fs.open( sPath, "w" )
file.write( sResponse )
file.close()
break
else return false end
end
end
end
function checkDirs()
if not fs.isDir("Mail") then shell.run("rom/programs/mkdir", "Mail"); nMailCount = (#(fs.list("/Mail"))) end
if not fs.isDir("User") then shell.run("rom/programs/mkdir", "User"); shell.run("rom/programs/mkdir", "User/"..tostring(os.getComputerID())) end
if not fs.isDir("User/"..tostring(os.getComputerID()).."/Projects") then shell.run("rom/programs/mkdir", "User/"..tostring(os.getComputerID()).."/Projects") end
if not fs.isDir("User/"..tostring(os.getComputerID()).."/Desktop") then shell.run("rom/programs/mkdir", "User/"..tostring(os.getComputerID()).."/Desktop") end
if not fs.isDir("User/"..tostring(os.getComputerID()).."/Desktop/Shortcuts") then shell.run("rom/programs/mkdir", "User/"..tostring(os.getComputerID()).."/Desktop/Shortcuts") end
if not fs.isDir("User/"..tostring(os.getComputerID()).."/Files") then shell.run("rom/programs/mkdir", "User/"..tostring(os.getComputerID()).."/Files") end
if not fs.isDir("Mail/Contacts") then shell.run("rom/programs/mkdir", "Mail/Contacts") end
if not fs.isDir("SYSTEM") then shell.run("rom/programs/mkdir", "SYSTEM") end
if not fs.exists("SYSTEM/Version") then
local file = fs.open("SYSTEM/Version", "w"); file.writeLine(tostring(VERSION))
file.close()
end
file = fs.open("SYSTEM/.installed", "w")
file.writeLine("TRUE")
file.close()
end
function checkUserInformation()
if fs.exists("User/"..os.getComputerID().."/.info") then
local file = fs.open("User/"..os.getComputerID().."/.info", "r")
sUserName = file.readLine()
sPassword = file.readLine()
file.close()
bNewUser = false
else
bNewUser = true
end
end
function getUserInformation()
if bNewUser == false then return nil -- This is to prevent accidental account resets
else
printNewUserScreen()
end
end
function handleLogin()
if fs.exists(".login") then
file = fs.open(".login", "r")
fileContents = file.readAll()
file.close()
fs.delete(".login")
bLogin = false
if fileContents == "false" then return end
end
if bNewUser == false then
printMainScreen(); sleep(2)
clear()
printBorder()
cPrint(4, "***************************")
cPrint(5, "* Identification required *")
cPrint(6, "***************************")
cPrint(8, "Username: ")
cPrint(9, "Password: ")
rPrint(17, "Cannon OS Version: "..VERSION.."*")
rPrint(16, "LOCKED*")
term.setCursorPos(screenWidth/2 - string.len("Username: ")/2 + string.len("Username: "), 8)
local tempUserName = newRead(14, nil)
term.setCursorPos(screenWidth/2 - string.len("Password: ")/2 + string.len("Password: "), 9)
local tempPassword = newRead(14, "*")
if tempUserName == sUserName and tempPassword == sPassword then
rPrint(16, "UNLOCKED*")
cPrint(11, "**********************")
cPrint(12, "* Successfull login! *")
cPrint(13, "**********************")
sleep(2)
return
else
cPrint(11, "************************")
cPrint(12, "* Unsuccessfull login! *")
cPrint(13, "************************")
sleep(2)
os.shutdown()
end
end
end
function printInstallation()
if checkInstalltion() then return end
printBorder()
cPrint(4, "*************************")
cPrint(5, "* Installation Progress *")
cPrint(6, "*************************")
local progressPosition = 6; -- X position to represent where the progress bars will be drawn
local nProgressPercent = 0;
cPrint(8, " * "..string.rep("*", screenWidth - 6))
cPrint(9, " * *"..string.rep(" ", screenWidth - 8).."*")
cPrint(10, " * "..string.rep("*", screenWidth - 6))
cPrint(12, "********")
cPrint(13, "* "..string.rep(" ", string.len("100%")).." *")
cPrint(14, "********")
for i=1, 80 do
if i%2 == 0 then
term.setCursorPos(progressPosition, 9); term.write("|")
progressPosition = progressPosition+1
sleep(0.2)
end
nProgressPercent = nProgressPercent+1
if nProgressPercent == 75 then nProgressPercent = 95 end
if nProgressPercent == 95 then sleep(1.1) end
term.setCursorPos(24, 13); term.write(nProgressPercent)
end
checkDirs()
end
-- Background Processes --
function checkMail(sender, message)
if string.find(message, "CANNONMAILMESSAGE") then
local file = fs.open("Mail/Unread"..nMailCount, "w")
message = string.gsub(message, "CANNONMAILMESSAGE", "")
file.write(tostring(sender).."n"..tostring(message))
file.close()
nMailCount = nMailCount+1
end
end
--------------------------
----------------------
-- Menues and other screens --
function printNewUserScreen()
if bNewUser == false then return end
local bPasswordsMatch = false
printBorder()
printWelcome()
sleep(3)
clear()
printBorder()
cPrint(2, "* New User *")
cPrint(3, "************")
rPrint(17, "Cannon OS Version: "..VERSION.."*")
cPrint(6, "Username: ")
cPrint(7, "Password: ")
cPrint(8, " Confirm: ")
cPrint(12, "************************")
cPrint(13, "*Password not optional!*")
cPrint(14, "************************")
term.setCursorPos(screenWidth/2-string.len("Username: ")/2+string.len("Username: "), 6)
sUserName = newRead(14, nil)
if string.len(sUserName) > 14 then
cPrint(10, "Username is too long!"); sleep(1.3)
term.setCursorPos(1, 10); term.clearLine() -- Clear the line 10
term.write(" *"..string.rep(" ", screenWidth-4).."*")
term.setCursorPos(1, 6); term.clearLine() -- Clear the line
term.write(" *"..string.rep(" ", screenWidth-4).."*")
cPrint(6, "Username: ")
term.setCursorPos(screenWidth/2-string.len("Username: ")/2+string.len("Username: "), 6)
sUserName = newRead(14, nil)
end
while bPasswordsMatch == false do
term.setCursorPos(screenWidth/2-string.len("Password: ")/2+string.len("Password: "), 7)
sPassword = newRead(14, "*")
if sPassword ~= nil and sPassword ~= "" then
term.setCursorPos(screenWidth/2-string.len(" Confirm: ")/2+string.len(" Confirm: "), 8)
local sConfirm = newRead(14, "*")
if sConfirm ~= sPassword then
cPrint(10, "Passwords do not match!"); sleep(1.3)
term.setCursorPos(1, 10); term.clearLine() -- Clear the line 10
term.write(" *"..string.rep(" ", screenWidth-4).."*")
term.setCursorPos(1, 7); term.clearLine() -- Clear the line 7
term.write(" *"..string.rep(" ", screenWidth-4).."*")
cPrint(7, "Password: ")
term.setCursorPos(1, 8); term.clearLine() -- Clear the line 8
term.write(" *"..string.rep(" ", screenWidth-4).."*")
cPrint(8, " Confirm: ")
else sPassword = sConfirm; bPasswordsMatch = true end
else sPassword = ""
end
end
local file = fs.open("User/"..os.getComputerID().."/.info", "w")
file.writeLine(tostring(sUserName))
if sPassword == "" then file.writeLine("N/A")
else file.writeLine(tostring(sPassword))
end
file.close()
cPrint(10, "Account '"..sUserName.. "' succesfully created!"); sleep(1.3)
end
function printWelcome()
customWrite(3, "__ __ _ ")
customWrite(4, " / / | | ")
customWrite(5, " / / /___| | ___ ___ _ __ ___ ___ ")
customWrite(6, " / / // _ |/ __|/ _ | '_ ' _ / _ ")
customWrite(7, " / /| __/ | (__| (_) | | | | | | __/")
customWrite(8, " / / ___|_|___|___/|_| |_| |_|___|")
customWrite(9, " _ _ ")
customWrite(10, " | | | | ")
customWrite(11, " | | | |___ ___ _ __ ")
customWrite(12, " | | | / __|/ _ '__|")
customWrite(13, " | |__| __ __/ | ")
customWrite(14, " ____/|___/___|_| ")
rPrint(17, "Cannon OS Version: "..VERSION.."*")
end
function printMainScreen()
printBorder()
customWrite(2, " ________")
customWrite(3, " | ______o|")
customWrite(4, " _______________ ||__---_||")
customWrite(5, " | ___________ || ______ |")
customWrite(6, " | | | |||______||")
customWrite(7, " | | Cannon OS | ||--------|")
customWrite(8, " | | By | || O |")
customWrite(9, " | | Payment | || | |")
customWrite(10, " | '-----------' || | |")
customWrite(11, " |_____________-_|| | |")
customWrite(12, " __/_________ |::::::::|")
customWrite(13, " ________________'-.__")
customWrite(14, " /:::::::::':::':: .---.")
customWrite(15, " /::======::: .:.::: _) ")
customWrite(16, ' """""""""""""""""""" -----')
term.setCursorPos(3, 17); term.write("By PaymentOption")
rPrint(17, "Version: "..VERSION.. "*")
end
function printLogo()
term.setCursorPos(34, 3); term.write("__")
customWrite(4, " / ")
customWrite(5, " .-. | |")
customWrite(6, " * _.-' __/")
customWrite(7, " .-' ")
customWrite(8, " / _/")
customWrite(9, " | _ /")
customWrite(10, " | /_'")
customWrite(11, " _____/")
end
function printLogout()
term.setCursorPos(34, 3); term.write(" ")
clearCenter()
cPrint(5, "********")
cPrint(6, "*Logout*")
cPrint(7, "********")
cPrint(8, "/ ")
cPrint(9, "***************")
cPrint(10, "*[ Yes ] No *")
cPrint(11, "***************")
while true do
event, key = os.pullEvent("key")
if key == 205 and selection < 2 then selection = 2
elseif key == 203 and selection > 1 then selection = 1
elseif key == 28 and selection == 1 then os.reboot()
elseif key == 28 and selection == 2 then sMenuState = "main"; selection = 6; break
end
if selection == 1 then cPrint(10, "*[ Yes ] No *")
else cPrint(10, "* Yes [ No ]*") end
end
end
function printMainMenu()
printBorder()
cPrint(2, "* "..sUserName.." *")
cPrint(3, "*"..string.rep("*", string.len(sUserName)+2).."*")
rPrint(17, "Cannon OS Version: "..VERSION.. "*")
if sMenuState == "main" then printLogo(); rPrint(2, "Mail: "..nMailCount.."*") end
if selection == 1 then cPrint(13, "[ Computer ] Craft OS IRC ")
cPrint(15, " E-Mail Account Update ")
end
if selection == 2 then cPrint(13, " Computer [ Craft OS ] IRC ")
cPrint(15, " E-Mail Account Update ")
end
if selection == 3 then cPrint(13, " Computer Craft OS [ IRC ] ")
cPrint(15, " E-Mail Account Update ")
end
if selection == 4 then cPrint(13, " Computer Craft OS IRC ")
cPrint(15, "[ E-Mail ] Account Update ")
end
if selection == 5 then cPrint(13, " Computer Craft OS IRC ")
cPrint(15, " E-Mail [ Account ] Update ")
end
if selection == 6 then cPrint(13, " Computer Craft OS IRC ")
cPrint(15, " E-Mail Account [ Update ] ")
end
end
------------------------------
-- Mail related things --
function loadContacts()
local tContacts = fs.list("Mail/Contacts")
for i=1, #tContacts do -- Set the correct computer adress found
local file = fs.open("Mail/Contacts/"..tContacts[i], "r")
local fileContents = file.readAll()
file.close()
tContacts[i] = { name = tContacts[i], id = fileContents }
end
return tContacts
end
function mailMenu()
recipientID = 0
sLine1 = "" -- The message will be split into two lines due to lack of multiline functionality of newread()
sLine2 = ""
sMessage = "" -- The two lines will be combined into the whole message in this variable
selection = 1
nMailCount = 0
screenWidth, screenHeight = term.getSize()
function cPrint(height, string)
local xPos = screenWidth/2 - string.len(string)/2
term.setCursorPos(xPos, height)
term.write(string)
end
function rPrint(height, string)
local xPos = screenWidth - string.len(string)
term.setCursorPos(xPos, height)
term.write(string)
end
clearCenter() -- Remove the cannon logo
local function sendMessage()
sMessage = ";alkdjien".."n"..sMessage
rednet.send(tonumber(recipientID), sMessage)
end
local function printMailMenu()
rPrint(2, "Mail: "..tostring((#(fs.list("Mail"))-1).."*"))
cPrint(5, "***********")
if selection == 1 then cPrint(6, "*[ Write ]*")
else cPrint(6, "* Write *") end
if selection == 2 then cPrint(7, "*[ eMail ]*")
else cPrint(7, "* eMail *") end
if selection == 3 then cPrint(8, "*[ Cont. ]*")
else cPrint(8, "* Cont. *") end
if selection == 4 then cPrint(9, "*[ Leave ]*")
else cPrint(9, "* Leave *") end
cPrint(10, "***********")
-- End these damn lines ^^
end
local function printRevise()
local nSelect = 1 -- Too much sharing of the 'select' variable
local function cDraw(width, height, string)
term.setCursorPos(width, height)
term.write(string)
end
local function printRevMenu()
cDraw(29, 5, "*****************")
if nSelect == 1 then cDraw(29, 6, "*[ Send ] Exit *")
else cDraw(29, 6, "* Send [ Exit ]*") end
cDraw(29, 7, "*****************")
end
while true do
printRevMenu()
event, key = os.pullEvent("key")
-- Freakin' lines man ^^
if key == 205 and nSelect == 1 then nSelect = nSelect+1
elseif key == 203 and nSelect == 2 then nSelect = nSelect-1
elseif key == 28 and nSelect == 1 then sendMessage(); clearCenter(); term.setCursorPos(4, 12); term.write(string.rep(" ", 42)); break
elseif key == 28 and nSelect == 2 then clearCenter(); break
end
end
end
local function composeMail()
clearCenter()
term.setCursorPos(4, 5); term.write("****************************")
term.setCursorPos(4, 6); term.write("*Recipient: *") -- 15 is the x position for the retrieving of 'recipietID'
term.setCursorPos(4, 7); term.write("****************************")
term.setCursorPos(4, 9); term.write(string.rep("*", 42))
term.setCursorPos(4, 10); term.write("*"..string.rep(" ", 40).."*") -- 2 lines to write the body of the message; 38 spaces per line
term.setCursorPos(4, 11); term.write("*"..string.rep(" ", 40).."*")
term.setCursorPos(4, 12); term.write(string.rep("*", 42))
term.setCursorPos(15, 6) -- Get the recipient ID
recipientID = newRead(14) -- If they entered a contact name then find the id
local tContacts = loadContacts()
for i=1, #tContacts do
if tostring(recipientID) == tContacts[i].name then recipientID = tContacts[i].id end
end
term.setCursorPos(6, 10); sLine1 = newRead(38) -- Character only filter
term.setCursorPos(6, 11); sLine2 = newRead(38)
sMessage = sLine1.." "..sLine2
printRevise()
end
local function contacts()
local nSelect = 1
local scroll = 0;
local tContacts = fs.list("Mail/Contacts")
local function printContacts()
local y = 6
local tContacts = loadContacts()
for i = 1+scroll, #tContacts do
term.setCursorPos(5, y)
if nSelect == i then term.write("[ "..tContacts[i].name.." ]")
else term.write(" "..tContacts[i].name.." ") end
term.setCursorPos(43, y); term.write(tContacts[i].id)
y = y+1
if y == 11 then break end
end
term.setCursorPos(4, 3); term.write("********************")
term.setCursorPos(4, 4); term.write("* Ctrl:New Contact *")
end
while true do
clearCenter()
printContainer()
printContacts()
local event, key = os.pullEvent("key")
if key == 208 and nSelect < #(fs.list("Mail/Contacts")) then
if nSelect >= 4 and scroll < #tContacts then scroll = scroll+1; nSelect = nSelect+1
else nSelect = nSelect+1 end
elseif key == 200 and nSelect > 1 then
if nSelect >= 4 and scroll > 0 then scroll = scroll-1; nSelect = nSelect-1
else nSelect = nSelect-1 end
elseif key == 29 or key == 157 then
term.setCursorPos(5, 6); term.write(string.rep(" ", screenWidth-8))
term.setCursorPos(5, 6); term.write("Contact Name: ")
local sContact = newRead(14)
term.setCursorPos(5, 6); term.write(string.rep(" ", screenWidth-8))
term.setCursorPos(5, 6); term.write("Contact ID: ")
local nContactID = newRead(14)
local file = fs.open("Mail/Contacts/"..sContact, "w")
file.write(tostring(nContactID))
file.close()
elseif key == 14 then break
elseif key == 28 then
nSelected = 1
while true do
if nSelected == 1 then
term.setCursorPos(5, 6)
term.write("Delete? [ Yes ] No ")
else
term.setCursorPos(5, 6)
term.write("Delete? Yes [ No ]")
end
local event, key = os.pullEvent("key")
if key == 205 and nSelected == 1 then nSelected = nSelected+1
elseif key == 203 and nSelected == 2 then nSelected = nSelected-1
elseif key == 28 and nSelected == 1 then
local tContacts = loadContacts()
for i=1, #tContacts do
if nSelected == i then fs.delete("Mail/Contacts/"..tContacts[i].name) end
end
break
elseif key == 28 and nSelected == 2 then break
end
end
end
end
end
while true do
printMailMenu()
event, key = os.pullEvent("key")
if key == 200 and selection > 1 then selection = selection-1
elseif key == 208 and selection < 4 then selection = selection+1
elseif key == 28 and selection == 1 then composeMail(); sMenuState = "main"; break
elseif key == 28 and selection == 2 then readMail(); sMenuState = "main"; break
elseif key == 28 and selection == 3 then contacts(); selection = 1; term.setCursorPos(4, 3); term.write(string.rep(" ", 17)); clearCenter();
elseif key == 28 and selection == 4 then selection = 4; sMenuState = "main"; break
end
end
end
function newMessage(nSender, sContents)
rPrint(2, "Mail: "..nMailCount.."*")
sMenuState = "newMessage"
local nSelect = 1
local bReading = false -- This is to handle whether or not we should print the reception menu
clearCenter()
local function printMessageMenu()
cPrint(5, "*****************")
cPrint(6, "* New Message *")
cPrint(7, "*****************")
if nSelect == 1 then cPrint(8, "*[ Read ] Exit *")
else cPrint(8, "* Read [ Exit ]*") end
cPrint(9, "*****************")
end
while true do
if not bReading then printMessageMenu() end
local event, key = os.pullEvent("key")
if key == 205 then nSelect = nSelect+1
elseif key == 203 then nSelect = nSelect-1
elseif key == 28 and nSelect == 1 then
nMailCount = nMailCount-1
bReading = true
clearCenter()
term.setCursorPos(4, 5); term.write("From: "..nSender)
term.setCursorPos(4, 6); term.write("******"..string.rep("*", string.len(nSender)))
term.setCursorPos(4, 7)
if string.len(sContents) > 42 then
local sContentsLine1 = string.sub(sContents, 1, 42) -- Split the message into two lines if it is greater than 38
local sContentsLine2 = string.sub(sContents, 43, string.len(sContents))
term.write(sContentsLine1)
term.setCursorPos(4, 9)
term.write(sContentsLine2)
else
term.write(sContents)
end
break -- Print the message then end
elseif key == 28 and nSelect == 2 then
clearCenter()
sMenuState = "main"
return
end
end
while true do
cPrint(9, "**********")
cPrint(10, "*[ Exit ]*")
cPrint(11, "**********")
local event, key = os.pullEvent("key")
if key == 28 then sMenuState = "main"; break end
end
end
function readMail()
local sFileOpen = ""
sMenuState = "archive"
clearCenter()
if #(fs.list("Mail"))-1 == 0 then
cPrint(6, "***************")
cPrint(7, "* No messages *")
cPrint(8, "***************")
sleep(1.3)
clearCenter()
cPrint(12, " ") -- Clear line 12
return
end
term.setCursorPos(4, 5); term.write(string.rep("*", screenWidth-6))
local y = 6
for i=1, screenHeight - 13 do
term.setCursorPos(4, y); term.write("*"..string.rep(" ", screenWidth-8).."*")
y = y+1
end
term.setCursorPos(4, 11); term.write(string.rep("*", screenWidth-6))
local tMessages = fs.list("Mail")
local nSelections = #tMessages -- How many selections for mail we have
local nSelected = 1
local function clearMessageRectangle()
local y = 6
for i=1, 5 do
term.setCursorPos(5, y); term.write(string.rep(" ", screenWidth - 8))
y = y+1
end
end
local function printMessages()
term.setCursorPos(5, 13); term.write(string.rep(" ", screenWidth - (string.len("*********************")+2)))
term.setCursorPos(screenWidth - (string.len("*********************")+2), 13)
term.write("*********************")
term.setCursorPos(screenWidth - (string.len("* Backspace to exit *")+2), 12)
term.write("* Backspace to exit *")
tMessages = fs.list("Mail")
for i=1, #tMessages do
if tMessages[i] == "Contacts" then table.remove(tMessages, i) end
end -- Remove the 'Contacts' directory from the list
term.setCursorPos(4, 5); term.write(string.rep("*", screenWidth-6))
local y = 6
for i=1, screenHeight - 13 do
term.setCursorPos(4, y); term.write("*"..string.rep(" ", screenWidth-8).."*")
y = y+1
end
term.setCursorPos(4, 11); term.write(string.rep("*", screenWidth-6))
local recX = 6
local recY = 6 -- Positions to hold the x and y coords of where we'll draw the mail
for i=1, #tMessages do
if recX > 41 or recX+string.len(tMessages[i]) > 41 then
recY = recY+2
recX = 6
end
if recY >= 10 then break end
if nSelected == i then recX = recX-1 end
term.setCursorPos(recX, recY)
if nSelected == i then term.write("["..tMessages[i].."]"); recX = recX+1 end
if nSelected ~= i then term.write(tMessages[i]) end
if nSelected == i then
recX = recX + string.len(tMessages[i]) + 2 -- The 2 is for the spaces between the options
else recX = recX + string.len(tMessages[i]) + 2 end
end
end
while true do
cPrint(12, " ") -- Clear the last line from the 'return' or 'delete' menu from reading a message
printMessages()
local event, key = os.pullEvent("key")
if key == 205 and nSelected < #tMessages then nSelected = nSelected+1
elseif key == 203 and nSelected > 1 then nSelected = nSelected-1
elseif key == 14 then clearCenter(); term.setCursorPos(5, 12); term.write(string.rep(" ", screenWidth - 7)); term.setCursorPos(5, 13); term.write(string.rep(" ", screenWidth - 7)); cPrint(13, " Computer Craft OS File Browser "); return
elseif key == 28 then
clearCenter()
local sFileOpen = "Mail/"..tMessages[nSelected]
local file = fs.open("Mail/"..tMessages[nSelected], "r")
local nSender = file.readLine()
local sMessage = file.readAll(); -- We'll be using the File Contents as the message to read
file.close()
sMessage = string.gsub(sMessage, tostring(nSender), "") -- Get the message string without the sender
if string.len(sMessage) > 38 then
local sMessageLine1 = string.sub(sMessage, 1, 19)
local sMessageLine2 = string.sub(sMessage, 20, 38)
end
term.setCursorPos(4, 3); term.write("From: "..nSender)
term.setCursorPos(4, 4); term.write("******"..string.rep("*", string.len(tostring(nSender))))
term.setCursorPos(4, 5)
if sMessageLine1 ~= nil then
term.write(sMessageLine1)
term.setCursorPos(4, 6)
term.write(sMessageLine2)
else
term.write(sMessage)
end
nSelected = 1 -- Reset the selection for the 'back' or 'delete' option
term.setCursorPos(5, 12); term.write(string.rep(" ", screenWidth - 7)); term.setCursorPos(5, 13); term.write(string.rep(" ", screenWidth - 7))
while true do
cPrint(10, "*********************")
if nSelected == 1 then cPrint(11, "*[ Return ] Delete *")
else cPrint(11, "* Return [ Delete ]*") end
cPrint(12, "*********************")
--
local event, key = os.pullEvent("key")
if key == 205 and nSelected == 1 then nSelected = 2
elseif key == 203 and nSelected == 2 then nSelected = 1
elseif key == 28 and nSelected == 1 then term.setCursorPos(4, 3); term.write(string.rep(" ", string.len("From: "..nSender))); term.setCursorPos(4, 4); term.write(string.rep(" ", string.len("From: "..nSender))) break
elseif key == 28 and nSelected == 2 then
fs.delete(sFileOpen)
sFileOpened = ""
nSelected = 1
term.setCursorPos(4, 3); term.write(string.rep(" ", string.len("From: "..nSender)))
term.setCursorPos(4, 4); term.write(string.rep(" ", string.len("From: "..nSender)))
break
end
end
end
end
end
-------------------------
-- Filbrowser --
function fileBrowser()
sMenuState = "browseing"
clearCenter()
local scroll = 0
local y = 0
local sObjectName = ""
local sObjectType = ""
local nObjectHeight = 0
local nSelect = 1
local tFiles = {}
local function printOptionMenu()
local previousSelection = nSelect
nSelect = 1
while true do
term.setCursorPos(6, 8); term.write(string.rep(" ", 40))
if nSelect == 1 and sObjectType == "File" then cPrint(8, "[Run] Edit Delete Exit ")
elseif nSelect == 2 and sObjectType == "File" then cPrint(8, " Run [Edit] Delete Exit ")
elseif nSelect == 3 and sObjectType == "File" then cPrint(8, " Run Edit [Delete] Exit ")
elseif nSelect == 4 and sObjectType == "File" then cPrint(8, " Run Edit Delete [Exit]")
end
local event, key = os.pullEvent("key")
if key == 205 and nSelect < 4 then nSelect = nSelect+1
elseif key == 203 and nSelect > 1 then nSelect = nSelect-1
elseif key == 14 or key == 28 and nSelect == 4 then nSelect = previousSelection; return false
elseif nSelect == 1 and key == 28 then clear(); shell.run(sObjectName); sMenuState = "main"; return true
elseif nSelect == 2 and key == 28 then clear(); shell.run("edit", sObjectName); sMenuState = "main"; return true
elseif nSelect == 3 and key == 28 then fs.delete(shell.dir().."/"..sObjectName); sMenuState = "main"; return true
end
end
end
local function printFileContainer()
term.setCursorPos(4, 5); term.write(string.rep("*", screenWidth-6))
local y = 6
for i=1, screenHeight - 13 do
term.setCursorPos(4, y); term.write("*"..string.rep(" ", screenWidth-8).."*")
y = y+1
end
term.setCursorPos(4, 11); term.write(string.rep("*", screenWidth-6))
end
local function printFiles()
local sDir = shell.dir()
clearCenter()
printFileContainer() -- This is the rectangle we'll be displaying the options in
y = 6
tFiles = fs.list( sDir )
for i=1+scroll, #tFiles do
if i == nSelect then nObjectHeight = y end
sObjectName = tostring(shell.dir()).."/"..tFiles[nSelect]
if fs.isDir(tostring(shell.dir()).."/"..tFiles[nSelect]) then sObjectType = "Dir"
else sObjectType = "File"
end
term.setCursorPos(6, y)
if nSelect == i then term.write("["..tFiles[i].."]")
else term.write(" "..tFiles[i].." ") end
if fs.isDir(tostring(shell.dir()).."/"..tFiles[i]) then term.setCursorPos(42, y); term.write("D ")
else term.setCursorPos(42, y); term.write("F ") end
y = y+1
if y == 11 then break end
end
end
while true do
printFiles()
local event, key = os.pullEvent("key")
if key == 200 and nSelect == 1 then nSelect = 1
elseif key == 208 and nSelect == #tFiles then nSelect = #tFiles
elseif key == 208 and nSelect < #tFiles then
if nSelect >= 5 and scroll < #tFiles then scroll = scroll+1; nSelect = nSelect+1
else nSelect = nSelect+1 end
elseif key == 200 and nSelect > 1 then
if nSelect >= 5 and scroll > 0 then scroll = scroll-1; nSelect = nSelect-1
else nSelect = nSelect-1 end
elseif key == 28 and sObjectType == "File" then
if printOptionMenu() then return end
elseif key == 28 and sObjectType == "Dir" then shell.setDir(sObjectName); scroll = 0; nSelect = 1
elseif key == 14 and shell.dir() ~= "" then shell.run("cd", ".."); scroll = 0; nSelect = 1
elseif key == 14 and shell.dir() == "/" or shell.dir() == "" then sMenuState = "main"; break
end
end
end
----------------
-- IRC Client --
function IRC_Client()
sMenuState = "irc"
-- VARS --
local sServerName = ""
local nServerID = 0
local bConnected = false
local sUserName = ""
local sText = ""
nConversationY = 3
----------
-- Helper local functions --
local function newReadIRC( _charLimit, _ReplaceChar) -- The filter can either be a 1, 0, or nil. 1 is Numbers only, 0 is letters only, and nil is both
local sMessage = ""
term.setCursorBlink(true)
local originalCursorX, originalCursorY = term.getCursorPos()
while true do
local cursorX, cursorY = term.getCursorPos()
local event, p1, p2 = os.pullEvent()
if _charLimit ~= nil then
if string.len(sMessage) == _charLimit then term.setCursorBlink(false); return sMessage end
end
if event == "char" then sMessage = sMessage..p1
--[[elseif event == "key" then -- The escape key has keyID 1 so: 0 = keyID: 11, 1 = keyID: 2, 2 = keyID : 3 etc etc....
if p1 == 11 or p1 == 2 or p1 == 3 or p1 == 4 or p1 == 5 or p1 == 6 or p1 == 7 or p1 == 8 or p1 == 9 or p1 == 10 then
-- 0 1 2 3 4 5 6 7 8 9
sMessage = sMessage..(p1-1)
end--]]
end
if event == "key" and p1 == 28 then
term.setCursorBlink(false)
term.setCursorPos(1, screenHeight)
term.write(string.rep(" ", screenWidth))
return sMessage
end-- Enter key; end the loop and let's see the string
if event == "key" and p1 == 14 then -- Backspace...
sMessage = string.sub(sMessage, 1, string.len(sMessage)-1)
-- Set our message to the substring of the first charcter
-- To the length of the message minus 1 to achieve one less letter.
term.setCursorPos(originalCursorX, cursorY)
term.write(sMessage.." ") -- Adding this empty space clears the removed character from the line, but may pose future issues
end
if event == "rednet_message" and p1 == nServerID then
if nConversationY == 10 then
for i=3, 14 do
term.setCursorPos(3, i); term.write(string.rep(" ", screenWidth-4))
end
term.setCursorPos(3, 2); term.write(sServerName..":")
term.setCursorPos(5, screenHeight-1)
nConversationY = 3
end
if p1 == nServerID and p2 == "dlskjfiejdlijfklsdj" then bConnected = false; return nil end
term.setCursorPos(3, nConversationY); term.write(p2)
nConversationY = nConversationY+1
term.setCursorPos(string.len(sMessage)+6, screenHeight)
end
term.setCursorPos(originalCursorX, cursorY); term.write(string.rep(" ", string.len(sMessage)))
-- Clear the previous line just in case we get a new line
-- Now write the message on the new line
if _ReplaceChar ~= nil then
term.setCursorPos(originalCursorX, cursorY)
term.write(string.rep( _ReplaceChar, string.len(sMessage) ))
else
term.setCursorPos(originalCursorX, cursorY)
term.write(sMessage)
end
end
end
----------------------
-- Input related local functions --
local function getInput()
cPrint(4, "IRC Version: Beta 1.0")
cPrint(5, "Server ID: ")
cPrint(6, " Username: ")
rPrint(17, "Common channels: 146, 174, 175, 176, 177*")
term.setCursorPos(screenWidth/2 - string.len("Server ID: ")/2 + string.len("Server ID: "), 5)
nServerID = tonumber(newRead(5))
term.setCursorPos(screenWidth/2 - string.len(" Username: ")/2 + string.len(" Username: "), 6)
sUserName = newRead(14)
end
-----------------------------
-- Networking related local functions --
local function connectToServer()
if bConnected == true then return nil end
if nServerID ~= nil then
rednet.send(tonumber(nServerID), "dlsk;fje3ijoidsjfl")
sender, message = rednet.receive(0.2)
if sender == nServerID and message == "a;sodifu39798d0f3" then
rednet.send(tonumber(nServerID), tostring(sUserName))
sender, message = rednet.receive(0.1)
if sender == nServerID and message == "ifjdslfije" then
bConnected = true
sender, message = rednet.receive(0.2)
if sender == nServerID then sServerName = message end
end
end
else os.shutdown() end
end
local function sendMessage( _sMessage )
rednet.send( tonumber(nServerID), _sMessage )
end
----------------------------------
printBorder()
getInput()
connectToServer()
clear()
printBorder()
term.setCursorPos(3, 2); term.write(sServerName..":")
term.setCursorPos(3, screenHeight-1); term.write("> ")
while bConnected do
if nConversationY == 10 then
for i=3, 14 do
term.setCursorPos(3, i); term.write(string.rep(" ", screenWidth-4))
end
term.setCursorPos(3, 2); term.write(sServerName..":")
term.setCursorPos(5, screenHeight-1)
nConversationY = 3
end
sText = newReadIRC(screenWidth-7) -- This will be our disconnection message: dslifj
if sText == "!exit" then clear(); sMenuState = "main"; break end
if sText == nil then term.setCursorBlink(false); sMenuState = "main"; break end
if sText ~= sUserName then sendMessage(sText)
else nConversationY = nConversationY-1 end
sText = ""
term.setCursorPos(3, screenHeight-1); term.write(string.rep(" ", screenWidth-4))
term.setCursorPos(3, screenHeight-1); term.write("> ")
term.setCursorPos(2, screenHeight); term.write(string.rep("*", screenWidth-2))
term.setCursorPos(5, screenHeight-1)
end
clear()
sMenuState = "main"
end
---------------------
-- Account --
function editAccount()
sMenuState = "account"
local nSelect = 1
clearCenter()
local function printInfoContainer()
term.setCursorPos(4, 5); term.write(string.rep("*", screenWidth-6))
local y = 6
for i=1, screenHeight - 13 do
term.setCursorPos(4, y); term.write("*"..string.rep(" ", screenWidth-8).."*")
y = y+1
end
term.setCursorPos(4, 11); term.write(string.rep("*", screenWidth-6))
end
printInfoContainer()
while true do
if nSelect == 3 then sMenuState = "main"; break end
term.setCursorPos(5, 7); term.write("Username: "..sUserName)
term.setCursorPos(5, 8); term.write("Password: "..string.rep("*", string.len(sPassword)))
if nSelect == 1 then term.setCursorPos((screenWidth-6)-(string.len("[ Change ]*")-4), 7); term.write("[ Change ]*")
else term.setCursorPos((screenWidth-6)-(string.len("[ Change ]*")-4), 7); term.write(" Change *") end
if nSelect == 2 then term.setCursorPos((screenWidth-6)-(string.len("[ Change ]*")-4), 8); term.write("[ Change ]*")
else term.setCursorPos((screenWidth-6)-(string.len("[ Change ]*")-4), 8); term.write(" Change *") end
local event, key = os.pullEvent("key")
if key == 208 and nSelect == 1 then nSelect = nSelect+1
elseif key == 200 and nSelect == 2 then nSelect = nSelect-1
elseif key == 28 and nSelect == 1 then
term.setCursorPos(5, 7); term.write(string.rep(" ", screenWidth-8))
term.setCursorPos(5, 7); term.write("New Username: ")
sUserName = newRead(14)
term.setCursorPos(5, 7); term.write(string.rep(" ", screenWidth-8))
local file = fs.open("User/"..os.getComputerID().."/.info", "w")
file.write(sUserName.."n"..sPassword)
file.close()
elseif key == 28 and nSelect == 2 then
term.setCursorPos(5, 8); term.write(string.rep(" ", screenWidth-8))
term.setCursorPos(5, 8); term.write("Old Password: ")
local sCheckPassword = newRead(14, "*")
if sCheckPassword == sPassword then
term.setCursorPos(5, 8); term.write(string.rep(" ", screenWidth-8))
term.setCursorPos(5, 8); term.write("New Password: ")
sPassword = newRead(14, "*")
local file = fs.open("User/"..os.getComputerID().."/.info", "w")
file.write(sUserName.."n"..sPassword)
file.close()
end
term.setCursorPos(5, 8); term.write(string.rep(" ", screenWidth-8))
elseif key == 14 then nSelect = 3
end
end
end
-------------
function printError()
sMenuState = "perms"; clearCenter()
cPrint(6, "*********************")
cPrint(7, "* Restricted Access *")
cPrint(8, "*********************")
sleep(2)
sMenuState = "main"
end
clear()
getKey() -- b8v2a6b8i1e2j8g91
clear()
printInstallation()
clear()
checkUserInformation()
getUserInformation()
handleLogin()
if bLogin then
if checkVersion() then
sMenuState = "updateScreen"
clear()
printBorder()
rPrint(17, "Cannon OS Version: "..VERSION.."*")
cPrint(6, "********************")
cPrint(7, "* Update Available *")
cPrint(8, "********************")
local select = 1
while true do
if select == 1 then cPrint(9, "* [ Yes ] No *")
else cPrint(9, "* Yes [ No ] *")
end
cPrint(10, "********************")
local event, key = os.pullEvent("key")
if key == 205 and select == 1 then select = 2
elseif key == 203 and select == 2 then select = 1
elseif key == 28 and select == 1 then clear(); printBorder(); rPrint(17, "Cannon OS Version: "..VERSION.."*"); fs.delete("SYSTEM"); fs.delete("User"); term.setCursorPos(screenWidth/2-string.len("Updating...")/2, 9); textutils.slowPrint("Updating..."); updateSelf(); shell.run("startup")
elseif key == 28 and select == 2 then sMenuState = "main"; clearCenter(); break
end
end
end
end
-- Main OS Loop --
while true do
clear()
nMailCount = #(fs.list("Mail"))-1 -- -1 To eliminate the 'Contacts' directory from the list
printMainMenu()
event, key, p2 = os.pullEvent() -- Key will be p1, laziness has struck again
if event == "key" and key == 205 and selection < 6 and selection ~= 3 then selection = selection+1
elseif event == "key" and key == 203 and selection > 1 and selection ~= 4 then selection = selection-1
elseif event == "key" and key == 208 and selection < 6 and selection+3 <= 6 then selection = selection+3
elseif event == "key" and key == 200 and selection > 1 and selection-3 >= 1 then selection = selection-3
elseif event == "key" and key == 28 and selection == 6 then
clear(); printBorder(); rPrint(17, "Cannon OS Version: "..VERSION.."*"); term.setCursorPos(screenWidth/2-string.len("Updating...")/2, 9); textutils.slowPrint("Updating...")
if not updateSelf() then cPrint(9, "Update Failed"); sleep(1.3); shell.run("startup")
else fs.delete("SYSTEM"); fs.delete("User"); cPrint(9, "Update Successfull"); sleep(1.3); shell.run("startup")
end
elseif event == "key" and key == 28 and selection == 2 and bAdmin then clear(); shell.run("shell")-- If exit to Craft OS
elseif event == "key" and key == 28 and selection == 2 and not bAdmin then printError()
elseif event == "key" and key == 28 and selection == 4 and bAdmin then mailMenu()
elseif event == "key" and key == 28 and selection == 4 and not bAdmin then printError()
elseif event == "key" and key == 28 and selection == 1 and bAdmin then fileBrowser()
elseif event == "key" and key == 28 and selection == 1 and not bAdmin then printError()
elseif event == "key" and key == 28 and selection == 3 then clear(); IRC_Client()
elseif event == "key" and key == 28 and selection == 5 and bAdmin then editAccount()
elseif event == "key" and key == 28 and selection == 5 and not bAdmin then printError()
elseif event == "rednet_message" then
if string.find( p2, ";alkdjien") then
p2 = string.sub( p2, string.len(";alkdjien"), string.len( p2 ))
p2 = string.sub( p2, 3, string.len( p2 )) -- 3 to remove the n from the message
local file = fs.open("Mail/message"..#(fs.list("Mail"))+1, "w")
file.writeLine(key)
file.writeLine(p2)
file.close()
nMailCount = nMailCount+1
newMessage(key, p2) -- Key being the senderID and p2 being the message received
end
elseif event == "reboot" then selection = 1; sMenuState = "logout"; printLogout()
end
end
------------------
os.pullEvent = oldpullEvent
IRC Server:
Spoiler
-- IRC server by PaymentOption for Cannon OS --
VERSION = "Alpha 0.0.1"
-----------------------------------------------
rednet.open("top"); rednet.open("bottom")
rednet.open("front"); rednet.open("back")
rednet.open("right"); rednet.open("left")
-- VARS --
tUsers = {} -- Each user will have their computer ID and a set username
nOP = 0 -- This will be the user with Operator priveleges
sServerName = "testServer"
tConversation = {} -- This is where we will store each line of the conversation: {user, message}
----------
-- Connection related functions --
function connectUser( _nSender)
rednet.send( _nSender, "a;sodifu39798d0f3") -- This will be our request for their username: a;sodifu39798d0f3
sender, message = rednet.receive(0.2)
if sender == _nSender then
tUsers[#tUsers+1] = {name = message, id = _nSender}
rednet.send( _nSender, "ifjdslfije") -- This will be our connection confirmation message: ifjdslfije
sleep(0.1); rednet.send( _nSender, tostring( sServerName ) ) -- Give the user the designated server name
print("User: "..sender.." Connected")
else print("User: ".._nSender.." not Connected") end
if #tUsers == 1 then nOP = tUsers[1].id; tUsers[1].name = "@"..tUsers[1].name end
end
----------------------------------
-- Converstaion related functions --
function logMessage( _nSender, _sMessage)
if _sMessage == "dslifj" then
for i=1, #tUsers do
if tUsers[i].id == _nSender then table.remove( tUsers, i); print("User: ".._nSender.." Disconnected")
return true end
end
end
if _nSender == nOP then
if string.find( _sMessage, "!kick" ) then
local nKickUser = tonumber(string.sub( _sMessage, string.len("!kick "), string.len( _sMessage )))
for i=1, #tUsers do -- This will be our kicked notificatio message: dlskjfiejdlijfklsdj
if tUsers[i].id == nKickUser then table.remove( tUsers, i); rednet.send( nKickUser, "dlskjfiejdlijfklsdj") end
end
end
end
tConversation[#tConversation+1] = {user = tonumber(_nSender), message = tostring(_sMessage)}
local senderIndex = 0 -- We'll store the index number of the user who sent the message here for sending references
if #tUsers > 0 then
for i=1, #tUsers do
if tUsers[i].id == _nSender then senderIndex = i end
end
end
if #tUsers > 0 then
for i=1, #tUsers do
for i = 1, #tUsers do
if _sMessage == tUsers[i].name or _sMessage == "@"..tUsers[i].name then return false end
end
rednet.send(tUsers[i].id, tostring(tUsers[senderIndex].name).."> ".._sMessage)
end
end
end
------------------------------------
term.clear(); term.setCursorPos(1,1)
while true do
sender, message = rednet.receive()
if message == "dlsk;fje3ijoidsjfl" then -- This will be our connection request message: dlsk;fje3ijoidsjfl
connectUser( sender )
end
if sender == nOP and string.find( message, "!kick " ) then
local sTemp = string.sub( message, string.len("!kick "), string.len(message))
local sKickUser = string.sub(sTemp, 2, string.len(sTemp))
for i=1, #tUsers do -- This will be our kicked notification message: dlskjfiejdlijfklsdj
if tUsers[i].name == sKickUser then rednet.send( tUsers[i].id, "dlskjfiejdlijfklsdj"); table.remove( tUsers, i) end
end
elseif #tUsers > 0 then
for i=1, #tUsers do
if tUsers[i].id == sender then logMessage( sender, message ) end
end
end
end
Key Generator:
Spoiler
local tCharacters = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}
local sKey = ""
local nKeys = 10000
function keyGen()
local key = ""
for i=1, 9 do
key = key..tCharacters[math.random(1,26)]..tostring(math.random(1,9))
end
return key
end
file = fs.open("keyList", "w")
repeat
sKey = keyGen()
file.writeLine(tostring(sKey))
sKey = ""
nKeys = nKeys-1
until nKeys == 0
file.close()
Key Validation Server:
Spoiler
--[[
function checkKey(sKey)
rednet.send(nServerID, tostring(sKey))
sender, message = rednet.receive(1)
if sender == nServerID then
if message ~= "authentic" then bAuthentic = false; return false
else bAuthentic = true; return true end
end
end
--]]
rednet.open("top")
rednet.open("bottom")
rednet.open("back")
rednet.open("front")
rednet.open("right")
rednet.open("left")
while true do
sender, message = rednet.receive()
if message == "CHECKMYKEY" then
print("Checking KEY")
confirmSender, message = rednet.receive(0.8)
if confirmSender == sender then
file = fs.open("keyList", "r")
for i=1, 10000 do
local fileContents = file.readLine()
if fileContents == message then rednet.send(confirmSender, "authentic"); print("Key confirmed"); break end
end
file.close()
else print("Lost connection...") end
end
end
LICENSE:
You are welcome to use this software as long as you give me credit for it. If you want to use it as base code or something along those lines then PM me for permission!
Feel free to comment and CONSTRUCTIVELY criticize.