MtnMCG

sethmc server.lua

Dec 15th, 2025 (edited)
56
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.28 KB | None | 0 0
  1. -- Server startup.lua
  2.  
  3. local modem = peripheral.find("modem")
  4. if not modem then error("No modem found. Please attach a wireless modem.") end
  5.  
  6. local disk = peripheral.find("drive")
  7. if not disk then error("No disk drive found. Please attach a disk drive.") end
  8.  
  9. modem.open(1) -- Use channel 1 for all communications
  10.  
  11. local diskMount = disk.getMountPath()
  12. if not diskMount then error("No disk inserted. Please insert a disk.") end
  13.  
  14. local function setup()
  15. if not fs.exists(diskMount .. "/students") then fs.makeDir(diskMount .. "/students") end
  16. if not fs.exists(diskMount .. "/news.txt") then
  17. local file = fs.open(diskMount .. "/news.txt", "w")
  18. file.write("Welcome to the college!")
  19. file.close()
  20. end
  21. if not fs.exists(diskMount .. "/student.lua") then
  22. error("student.lua not found on the disk. Please create this file.")
  23. end
  24.  
  25. -- Launch Dashboard in new tab if multishell is available
  26. if multishell then
  27. -- Check if already running? uniqueID?
  28. -- Simply launching it is fine, user can close duplicate tabs.
  29. -- We'll just assume server runs once.
  30. local dashboardPath = diskMount .. "/tracking_dashboard.lua"
  31. if fs.exists(dashboardPath) then
  32. multishell.launch({}, dashboardPath)
  33. print("Launched Tracking Dashboard in background tab.")
  34. else
  35. print("Dashboard not found at: " .. dashboardPath)
  36. end
  37. else
  38. print("Multishell not available.")
  39. end
  40. print("Server setup complete. Files stored on disk.")
  41. end
  42.  
  43. local function createAccount(studentId, password)
  44. local studentDir = diskMount .. "/students/" .. studentId
  45. if fs.exists(studentDir) then
  46. return false, "Account already exists"
  47. end
  48. fs.makeDir(studentDir)
  49. local passFile = fs.open(studentDir .. "/password.txt", "w")
  50. passFile.write(password)
  51. passFile.close()
  52. local balanceFile = fs.open(studentDir .. "/balance.txt", "w")
  53. balanceFile.write("0") -- Initial balance of 0
  54. balanceFile.close()
  55. return true, "Account created successfully"
  56. end
  57.  
  58. local function verifyLogin(studentId, password)
  59. local studentDir = diskMount .. "/students/" .. studentId
  60. if not fs.exists(studentDir) then return false, "Account not found" end
  61. local passFile = fs.open(studentDir .. "/password.txt", "r")
  62. local storedPass = passFile.readAll():gsub("%s+$", "") -- Trim trailing whitespace
  63. passFile.close()
  64. return storedPass == password, storedPass == password and "Login successful" or "Incorrect password"
  65. end
  66.  
  67.  
  68.  
  69. local function handleBalance(studentId, action, amount)
  70. local balanceFile = fs.open(diskMount .. "/students/" .. studentId .. "/balance.txt", "r")
  71. local balance = tonumber(balanceFile.readAll()) or 0
  72. balanceFile.close()
  73. print("Processing balance update for " .. studentId)
  74. print("Current balance: " .. balance)
  75. print("Action: " .. action .. ", Amount: " .. amount)
  76. if action == "deposit" then
  77. balance = balance + amount
  78. elseif action == "withdraw" then
  79. if balance >= amount then
  80. balance = balance - amount
  81. else
  82. print("Insufficient funds. Transaction failed.")
  83. return false, "Insufficient funds"
  84. end
  85. end
  86. balanceFile = fs.open(diskMount .. "/students/" .. studentId .. "/balance.txt", "w")
  87. balanceFile.write(tostring(balance))
  88. balanceFile.close()
  89. print("New balance: " .. balance)
  90. print("Transaction successful")
  91. return true, balance
  92. end
  93.  
  94. local function getEmails(studentId)
  95. local emailPath = diskMount .. "/students/" .. studentId .. "/emails.txt"
  96. if not fs.exists(emailPath) then return {} end
  97. local file = fs.open(emailPath, "r")
  98. local data = file.readAll()
  99. file.close()
  100. return textutils.unserialize(data) or {}
  101. end
  102.  
  103. local function saveEmails(studentId, emails)
  104. local emailPath = diskMount .. "/students/" .. studentId .. "/emails.txt"
  105. local file = fs.open(emailPath, "w")
  106. file.write(textutils.serialize(emails))
  107. file.close()
  108. end
  109.  
  110. local function sendEmail(senderId, recipientId, subject, body)
  111. local recipientDir = diskMount .. "/students/" .. recipientId
  112. if not fs.exists(recipientDir) then
  113. return false, "Recipient not found"
  114. end
  115.  
  116. local emails = getEmails(recipientId)
  117. table.insert(emails, 1, { -- Insert at beginning (newest first)
  118. id = os.epoch("utc"), -- Simple unique ID logic
  119. sender = senderId,
  120. subject = subject,
  121. body = body,
  122. timestamp = os.epoch("local"), -- Use local time for display
  123. read = false
  124. })
  125. saveEmails(recipientId, emails)
  126. return true, "Email sent successfully"
  127. end
  128.  
  129. local function deleteEmail(studentId, emailIndex)
  130. local emails = getEmails(studentId)
  131. if emails[emailIndex] then
  132. table.remove(emails, emailIndex)
  133. saveEmails(studentId, emails)
  134. return true, "Email deleted"
  135. else
  136. return false, "Email not found"
  137. end
  138. end
  139.  
  140. local function handleRequests()
  141. print("Server is running. Waiting for requests...")
  142. while true do
  143. local event, side, channel, replyChannel, message, distance = os.pullEvent("modem_message")
  144. if type(message) == "table" then
  145. if message.type == "request_update" then
  146. local file = fs.open(diskMount .. "/student.lua", "r")
  147. local content = file.readAll()
  148. file.close()
  149. modem.transmit(replyChannel, 1, {type = "update", content = content})
  150. print("Sent student.lua update to a device")
  151. elseif message.type == "create_account" then
  152. if message.studentId and message.password then
  153. local success, msg = createAccount(message.studentId, message.password)
  154. modem.transmit(replyChannel, 1, {type = "account_response", success = success, message = msg})
  155. else
  156. modem.transmit(replyChannel, 1, {type = "error", message = "Invalid account creation request"})
  157. end
  158. elseif message.type == "login" then
  159. if message.studentId and message.password then
  160. local success, msg = verifyLogin(message.studentId, message.password)
  161. modem.transmit(replyChannel, 1, {type = "login_response", success = success, message = msg})
  162. else
  163. modem.transmit(replyChannel, 1, {type = "error", message = "Invalid login request"})
  164. end
  165. elseif message.type == "get_news" then
  166. local newsFile = fs.open(diskMount .. "/news.txt", "r")
  167. local news = newsFile.readAll()
  168. newsFile.close()
  169. modem.transmit(replyChannel, 1, {type = "news", content = news})
  170.  
  171. elseif message.type == "get_balance" then
  172. if message.studentId and message.password then
  173. local success, msg = verifyLogin(message.studentId, message.password)
  174. if success then
  175. local balanceFile = fs.open(diskMount .. "/students/" .. message.studentId .. "/balance.txt", "r")
  176. local balance = balanceFile.readAll()
  177. balanceFile.close()
  178. modem.transmit(replyChannel, 1, {type = "balance_response", balance = balance})
  179. else
  180. modem.transmit(replyChannel, 1, {type = "error", message = msg})
  181. end
  182. else
  183. modem.transmit(replyChannel, 1, {type = "error", message = "Invalid balance request"})
  184. end
  185. elseif message.type == "update_balance" then
  186. if message.studentId and message.password and message.action and message.amount then
  187. local success, msg = verifyLogin(message.studentId, message.password)
  188. if success then
  189. local success, result = handleBalance(message.studentId, message.action, message.amount)
  190. modem.transmit(replyChannel, 1, {type = "balance_update_response", success = success, result = result})
  191. else
  192. modem.transmit(replyChannel, 1, {type = "error", message = msg})
  193. end
  194. else
  195. modem.transmit(replyChannel, 1, {type = "error", message = "Invalid balance update request"})
  196. end
  197. elseif message.type == "verify_student" then
  198. if message.recipientId then
  199. local recipientDir = diskMount .. "/students/" .. message.recipientId
  200. local exists = fs.exists(recipientDir)
  201. modem.transmit(replyChannel, 1, {exists = exists})
  202. else
  203. modem.transmit(replyChannel, 1, {type = "error", message = "Invalid student verification request"})
  204. end
  205. elseif message.type == "transfer_money" then
  206. if message.studentId and message.password and message.recipientId and message.amount then
  207. local success, msg = verifyLogin(message.studentId, message.password)
  208. if success then
  209. local senderBalanceFile = fs.open(diskMount .. "/students/" .. message.studentId .. "/balance.txt", "r")
  210. local senderBalance = tonumber(senderBalanceFile.readAll()) or 0
  211. senderBalanceFile.close()
  212.  
  213. local recipientBalanceFile = fs.open(diskMount .. "/students/" .. message.recipientId .. "/balance.txt", "r")
  214. local recipientBalance = tonumber(recipientBalanceFile.readAll()) or 0
  215. recipientBalanceFile.close()
  216.  
  217. local expectedSenderBalance = senderBalance - message.amount
  218. local expectedRecipientBalance = recipientBalance + message.amount
  219.  
  220. if expectedSenderBalance >= 0 then
  221. local withdrawSuccess, _ = handleBalance(message.studentId, "withdraw", message.amount)
  222. if withdrawSuccess then
  223. local depositSuccess, _ = handleBalance(message.recipientId, "deposit", message.amount)
  224. if depositSuccess then
  225. -- Verify balances
  226. senderBalanceFile = fs.open(diskMount .. "/students/" .. message.studentId .. "/balance.txt", "r")
  227. local newSenderBalance = tonumber(senderBalanceFile.readAll()) or 0
  228. senderBalanceFile.close()
  229.  
  230. recipientBalanceFile = fs.open(diskMount .. "/students/" .. message.recipientId .. "/balance.txt", "r")
  231. local newRecipientBalance = tonumber(recipientBalanceFile.readAll()) or 0
  232. recipientBalanceFile.close()
  233.  
  234. if newSenderBalance == expectedSenderBalance and newRecipientBalance == expectedRecipientBalance then
  235. modem.transmit(replyChannel, 1, {success = true, newBalance = newSenderBalance})
  236. else
  237. -- Revert transaction
  238. handleBalance(message.studentId, "deposit", message.amount)
  239. handleBalance(message.recipientId, "withdraw", message.amount)
  240. modem.transmit(replyChannel, 1, {success = false, message = "Transaction verification failed"})
  241. end
  242. else
  243. handleBalance(message.studentId, "deposit", message.amount)
  244. modem.transmit(replyChannel, 1, {success = false, message = "Failed to deposit to recipient"})
  245. end
  246. else
  247. modem.transmit(replyChannel, 1, {success = false, message = "Failed to withdraw from sender"})
  248. end
  249. else
  250. modem.transmit(replyChannel, 1, {success = false, message = "Insufficient funds"})
  251. end
  252. else
  253. modem.transmit(replyChannel, 1, {success = false, message = msg})
  254. end
  255. else
  256. modem.transmit(replyChannel, 1, {success = false, message = "Invalid transfer request"})
  257. end
  258. elseif message.type == "send_email" then
  259. if message.studentId and message.password and message.recipientId and message.subject and message.body then
  260. local success, msg = verifyLogin(message.studentId, message.password)
  261. if success then
  262. local sent, result = sendEmail(message.studentId, message.recipientId, message.subject, message.body)
  263. modem.transmit(replyChannel, 1, {type = "email_response", success = sent, message = result})
  264. else
  265. modem.transmit(replyChannel, 1, {type = "error", message = msg})
  266. end
  267. else
  268. modem.transmit(replyChannel, 1, {type = "error", message = "Invalid send email request"})
  269. end
  270. elseif message.type == "get_inbox" then
  271. if message.studentId and message.password then
  272. local success, msg = verifyLogin(message.studentId, message.password)
  273. if success then
  274. local emails = getEmails(message.studentId)
  275. modem.transmit(replyChannel, 1, {type = "inbox_response", emails = emails})
  276. else
  277. modem.transmit(replyChannel, 1, {type = "error", message = msg})
  278. end
  279. else
  280. modem.transmit(replyChannel, 1, {type = "error", message = "Invalid inbox request"})
  281. end
  282. elseif message.type == "delete_email" then
  283. if message.studentId and message.password and message.emailIndex then
  284. local success, msg = verifyLogin(message.studentId, message.password)
  285. if success then
  286. local deleted, result = deleteEmail(message.studentId, message.emailIndex)
  287. modem.transmit(replyChannel, 1, {type = "email_response", success = deleted, message = result})
  288. else
  289. modem.transmit(replyChannel, 1, {type = "error", message = msg})
  290. end
  291. else
  292. modem.transmit(replyChannel, 1, {type = "error", message = "Invalid delete email request"})
  293. end
  294. elseif message.type == "track_location" then
  295. if message.studentId and message.x and message.y and message.z then
  296. -- No login required for tracking? Or should we verify password?
  297. -- Ideally verify, but passive tracking might lack access to password constant?
  298. -- Let's Require studentId. We'll verify existence of folder.
  299. local studentDir = diskMount .. "/students/" .. message.studentId
  300. if fs.exists(studentDir) then
  301. local historyPath = studentDir .. "/location_history.txt"
  302. local file = fs.open(historyPath, "a")
  303. -- Format: Timestamp | x,y,z
  304. file.writeLine(os.epoch("local") .. "|" .. message.x .. "," .. message.y .. "," .. message.z)
  305. file.close()
  306. -- Also update 'current' for fast lookup? Dashboard can just read last line.
  307. end
  308. end
  309. end
  310. end
  311. end
  312. end
  313.  
  314. setup()
  315. handleRequests()
Advertisement
Add Comment
Please, Sign In to add comment