Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local component = require("component")
- local term = require("term")
- local event = require("event")
- local keyboard = require("keyboard")
- local gpu = component.gpu
- local internet = component.internet
- local filesystem = require("filesystem")
- local computer = require("computer")
- local function getGPUTier()
- local w, h = gpu.maxResolution()
- if w == 50 and h == 16 then
- return 1
- elseif w == 80 and h == 25 then
- return 2
- else
- return 3
- end
- end
- local isColorSupported = false
- if gpu and gpu.maxDepth then
- isColorSupported = gpu.maxDepth() > 1
- end
- local servers = {
- {address = "atw.hu.eu.dal.net", port = 6667},
- {address = "bifrost.ca.us.dal.net", port = 6667},
- {address = "bitcoin.uk.eu.dal.net", port = 6667},
- {address = "choopa.nj.us.dal.net", port = 6667},
- {address = "halcyon.il.us.dal.net", port = 6667},
- {address = "istana.il.us.dal.net", port = 6667},
- {address = "lair.nl.eu.dal.net", port = 6667},
- {address = "lion.tx.us.dal.net", port = 6667},
- {address = "punch.wa.us.dal.net", port = 6667},
- {address = "sakura.jp.as.dal.net", port = 6667},
- {address = "serenity.fl.us.dal.net", port = 6667},
- {address = "nonstop.ix.me.dal.net", port = 6667},
- }
- local selectedServerIndex = 1
- local username = "User"
- local socket = nil
- local currentChannel = nil
- local messageBuffer = {}
- local maxBufferSize = 49
- local currentBufferIndex = 1
- local function saveUsername()
- local file = io.open("/home/dalnet_username.txt", "w")
- if file then
- file:write(username)
- file:close()
- end
- end
- local function loadUsername()
- local file = io.open("/home/dalnet_username.txt", "r")
- if file then
- username = file:read("*all")
- file:close()
- end
- end
- loadUsername()
- local function drawLogo()
- if getGPUTier() == 1 then
- return
- end
- local logo = {
- " ________ ________ ________ ________ ___ ________ _______ _________ ",
- "|\\ __ \\|\\ ____\\ |\\ ___ \\|\\ __ \\|\\ \\ |\\ ___ \\|\\ ___ \\|\\___ ___\\ ",
- "\\ \\ \\|\\ \\ \\ \\___| \\ \\ \\_|\\ \\ \\ \\|\\ \\ \\ \\ \\ \\ \\\\ \\ \\ \\ __/\\|___ \\ \\_| ",
- " \\ \\ \\\\\\ \\ \\ \\ \\ \\ \\ \\\\ \\ \\ __ \\ \\ \\ \\ \\ \\\\ \\ \\ \\ \\_|/__ \\ \\ \\ ",
- " \\ \\ \\\\\\ \\ \\ \\____ \\ \\ \\_\\\\ \\ \\ \\ \\ \\ \\ \\____\\ \\ \\\\ \\ \\ \\ \\_|\\ \\ \\ \\ \\ ",
- " \\ \\_______\\ \\_______\\ \\ \\_______\\ \\__\\ \\__\\ \\_______\\ \\__\\\\ \\__\\ \\_______\\ \\ \\__\\",
- " \\|_______|\\|_______| \\|_______|\\|__|\\|__|\\|_______|\\|__| \\|__|\\|_______| \\|__|"
- }
- local width, height = gpu.getResolution()
- local startY = height - #logo - 1
- for i, line in ipairs(logo) do
- gpu.set(1, startY + i, line)
- end
- end
- local function drawServerList()
- local oldForeground = gpu.getForeground()
- local oldBackground = gpu.getBackground()
- gpu.setBackground(0x000000)
- term.clear()
- for i, server in ipairs(servers) do
- if i == selectedServerIndex then
- if getGPUTier() == 1 then
- gpu.set(1, i, "-> " .. string.format("%d. %s:%d", i, server.address, server.port))
- else
- gpu.setForeground(0x00FF00)
- gpu.set(1, i, string.format("%d. %s:%d", i, server.address, server.port))
- gpu.setForeground(0xFFFFFF)
- end
- else
- gpu.set(1, i, string.format("%d. %s:%d", i, server.address, server.port))
- end
- end
- gpu.setForeground(0xFFFFFF)
- gpu.set(1, #servers + 2, "Press N to change username. Current username: " .. username)
- gpu.set(1, #servers + 3, "Use arrow keys to navigate, Enter to connect, X to exit")
- drawLogo()
- gpu.setForeground(oldForeground)
- gpu.setBackground(oldBackground)
- end
- local function changeNickname()
- term.write("\nEnter new nickname: ")
- local newNick = term.read()
- newNick = newNick:gsub("\n", "")
- if socket then
- socket.write("NICK " .. newNick .. "\r\n")
- end
- username = newNick
- saveUsername()
- return newNick
- end
- local function readWithTimeout(socket, timeout)
- local start = computer.uptime()
- local buffer = ""
- while computer.uptime() - start < timeout do
- local chunk = socket.read(1024)
- if chunk then
- buffer = buffer .. chunk
- if buffer:find("\n") then
- return buffer
- end
- end
- os.sleep(0.1)
- end
- return buffer ~= "" and buffer or nil
- end
- local function addMessage(message)
- table.insert(messageBuffer, message)
- if #messageBuffer > maxBufferSize then
- table.remove(messageBuffer, 1)
- end
- currentBufferIndex = #messageBuffer
- end
- local function displayBuffer()
- term.clear()
- local startIndex = math.max(1, currentBufferIndex - maxBufferSize + 1)
- for i = startIndex, currentBufferIndex do
- print(messageBuffer[i] or "")
- end
- end
- local function connectToServer(server)
- term.clear()
- addMessage("Connecting to " .. server.address .. " as " .. username)
- displayBuffer()
- socket = internet.connect(server.address, server.port)
- if not socket then
- addMessage("Failed to connect to " .. server.address)
- displayBuffer()
- return nil
- end
- local timeout = 10
- local start = computer.uptime()
- while not socket.finishConnect() do
- if computer.uptime() - start > timeout then
- addMessage("Connection timed out")
- displayBuffer()
- return nil
- end
- os.sleep(0.1)
- end
- socket.write("NICK " .. username .. "\r\n")
- socket.write("USER " .. username .. " 0 * :" .. username .. "\r\n")
- local connected = false
- local timeout = 30
- local start = computer.uptime()
- while computer.uptime() - start < timeout do
- local response = readWithTimeout(socket, 1)
- if response then
- for line in response:gmatch("[^\r\n]+") do
- addMessage(line)
- if line:find("433") then
- addMessage("Nickname is already in use. Please choose a different nickname.")
- displayBuffer()
- username = changeNickname()
- socket.write("NICK " .. username .. "\r\n")
- elseif line:find("001") then
- addMessage("Successfully connected to " .. server.address .. " as " .. username)
- connected = true
- break
- end
- end
- displayBuffer()
- end
- if connected then break end
- end
- if not connected then
- addMessage("Connection timed out or failed")
- displayBuffer()
- socket.close()
- return nil
- end
- return socket
- end
- local function disconnectFromServer()
- if socket then
- socket.write("QUIT :Disconnecting\r\n")
- socket.close()
- socket = nil
- currentChannel = nil
- addMessage("Disconnected from server.")
- displayBuffer()
- return true
- end
- return false
- end
- local function exitChannel()
- if currentChannel then
- socket.write("PART " .. currentChannel .. " :Leaving\r\n")
- addMessage("Left channel: " .. currentChannel)
- currentChannel = nil
- displayBuffer()
- return true
- end
- return false
- end
- local function ping()
- if not socket then
- addMessage("Not connected to a server.")
- return
- end
- local serverStart = computer.uptime()
- socket.write("PING :serverping\r\n")
- local serverPingReceived = false
- local timeout = computer.uptime() + 5
- while computer.uptime() < timeout do
- local response = readWithTimeout(socket, 0.1)
- if response then
- for line in response:gmatch("[^\r\n]+") do
- if line:find("PONG :serverping") then
- local serverEnd = computer.uptime()
- local serverPing = (serverEnd - serverStart) * 1000
- addMessage(string.format("Server ping: %.2f ms", serverPing))
- serverPingReceived = true
- break
- end
- end
- end
- if serverPingReceived then break end
- end
- if not serverPingReceived then
- addMessage("Server ping timed out.")
- end
- if currentChannel then
- local channelStart = computer.uptime()
- socket.write("PRIVMSG " .. currentChannel .. " :\001PING " .. channelStart .. "\001\r\n")
- local channelPingReceived = false
- timeout = computer.uptime() + 5
- while computer.uptime() < timeout do
- local response = readWithTimeout(socket, 0.1)
- if response then
- for line in response:gmatch("[^\r\n]+") do
- if line:find("NOTICE .* :\001PING (.+)\001") then
- local channelEnd = computer.uptime()
- local pingTime = line:match("NOTICE .* :\001PING (.+)\001")
- local channelPing = (channelEnd - tonumber(pingTime)) * 1000
- addMessage(string.format("Channel ping: %.2f ms", channelPing))
- channelPingReceived = true
- break
- end
- end
- end
- if channelPingReceived then break end
- end
- if not channelPingReceived then
- addMessage("Channel ping timed out.")
- end
- else
- addMessage("Not connected to a channel.")
- end
- displayBuffer()
- end
- local function showHelp()
- addMessage("Available commands:")
- addMessage(":helpoc - Show this help message")
- addMessage("connect #channel - Join a channel")
- addMessage("exit - Leave the current channel")
- addMessage("disconnect - Disconnect from the server")
- addMessage("ping - Ping the server and current channel")
- displayBuffer()
- end
- local function handleUserInput(isCommand)
- local prefix = isCommand and "Command" or "Chat"
- term.write("\n" .. prefix .. "> ")
- local input = term.read()
- if input then
- input = input:gsub("\n", "")
- if isCommand then
- if input:match("^connect #") then
- currentChannel = input:match("^connect (.+)$")
- socket.write("JOIN " .. currentChannel .. "\r\n")
- elseif input == "disconnect" then
- return disconnectFromServer()
- elseif input == "exit" then
- return exitChannel()
- elseif input == ":helpoc" then
- showHelp()
- elseif input == "ping" then
- ping()
- else
- socket.write(input .. "\r\n")
- end
- else
- if currentChannel then
- socket.write("PRIVMSG " .. currentChannel .. " :" .. input .. "\r\n")
- addMessage("<" .. username .. "> " .. input)
- else
- addMessage("Not connected to a channel. Use 'connect #channel' to join one.")
- end
- end
- displayBuffer()
- end
- return false
- end
- local function handleServerCommunication()
- addMessage("Connected to server. Press Ctrl for chat, Alt for commands.")
- addMessage("Use 'connect #channel' to join a channel, 'exit' to leave a channel, and 'disconnect' to disconnect from the server.")
- addMessage("Use 'ping' to ping the server and current channel.")
- addMessage("Use Up/Down arrows or PageUp/PageDown to scroll through messages.")
- displayBuffer()
- while true do
- local data = readWithTimeout(socket, 0.1)
- if data then
- for line in data:gmatch("[^\r\n]+") do
- if line:find("PING") then
- local pingId = line:match("PING :(.+)")
- socket.write("PONG :" .. pingId .. "\r\n")
- elseif line:match("PRIVMSG .* :\001PING ") then
- local user = line:match("^:([^!]+)")
- local pingTime = line:match("PRIVMSG .* :\001PING (.+)\001")
- socket.write("NOTICE " .. user .. " :\001PING " .. pingTime .. "\001\r\n")
- else
- addMessage(line)
- end
- end
- displayBuffer()
- end
- local eventName, _, char, code = event.pull(0.1)
- if eventName == "key_down" then
- if code == 29 then
- if handleUserInput(false) then return end
- elseif code == 56 then
- if handleUserInput(true) then return end
- elseif code == 200 then
- currentBufferIndex = math.max(1, currentBufferIndex - 1)
- displayBuffer()
- elseif code == 208 then
- currentBufferIndex = math.min(#messageBuffer, currentBufferIndex + 1)
- displayBuffer()
- elseif code == 201 then
- currentBufferIndex = math.max(1, currentBufferIndex - maxBufferSize)
- displayBuffer()
- elseif code == 209 then
- currentBufferIndex = math.min(#messageBuffer, currentBufferIndex + maxBufferSize)
- displayBuffer()
- end
- end
- end
- end
- local function main()
- while true do
- drawServerList()
- local eventName, _, char, code = event.pull("key_down")
- if char == 120 or char == 88 then
- print("Exiting program...")
- os.exit()
- elseif code == 200 then
- selectedServerIndex = math.max(1, selectedServerIndex - 1)
- elseif code == 208 then
- selectedServerIndex = math.min(#servers, selectedServerIndex + 1)
- elseif code == 203 then
- selectedServerIndex = math.max(1, selectedServerIndex - 1)
- elseif code == 205 then
- selectedServerIndex = math.min(#servers, selectedServerIndex + 1)
- elseif char == 110 or char == 78 then
- username = changeNickname()
- elseif code == 28 then
- term.clear()
- socket = connectToServer(servers[selectedServerIndex])
- if not socket then
- addMessage("Connection failed. Press any key to return to server list.")
- displayBuffer()
- event.pull("key_down")
- else
- if isColorSupported then
- gpu.setResolution(gpu.maxResolution())
- gpu.setBackground(0x000000)
- gpu.setForeground(0xFFFFFF)
- end
- handleServerCommunication()
- end
- end
- end
- end
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement