MtnMCG

sethmc diamond atm turtle

Dec 18th, 2025 (edited)
46
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.39 KB | None | 0 0
  1. -- Turtle Diamond ATM Script (diamond_turtle_atm.lua)
  2. -- Secure Transaction Logic: Acquire -> Verify -> Server -> Commit/Revert
  3.  
  4. local modem = peripheral.find("modem")
  5. if not modem then error("No modem found") end
  6. modem.open(1) -- Open channel 1 for communication with server
  7. modem.open(4) -- Open channel 4 for communication with Diamond ATM terminal
  8.  
  9. local function debug(message)
  10. print(os.date("%H:%M:%S") .. ": " .. message)
  11. end
  12.  
  13. local function sendToServer(message)
  14. modem.transmit(1, 1, message)
  15. local timer = os.startTimer(5)
  16. while true do
  17. local event, id, channel, replyChannel, response = os.pullEvent()
  18. if event == "modem_message" and channel == 1 then
  19. return response
  20. elseif event == "timer" and id == timer then
  21. return nil
  22. end
  23. end
  24. end
  25.  
  26. local function sendToATM(message)
  27. modem.transmit(4, 4, message)
  28. end
  29.  
  30. local function findBlock(blockType)
  31. for i = 1, 4 do
  32. local success, data = turtle.inspect()
  33. if success and data.name:find(blockType) then
  34. return true
  35. end
  36. turtle.turnRight()
  37. end
  38. return false
  39. end
  40.  
  41. local function isDiamond(item)
  42. return item and item.name == "minecraft:diamond"
  43. end
  44.  
  45. -- Helper to dump specific item type to front
  46. local function dumpItems(itemCheckFn)
  47. for i = 1, 16 do
  48. local item = turtle.getItemDetail(i)
  49. if item and itemCheckFn(item) then
  50. turtle.select(i)
  51. turtle.drop()
  52. end
  53. end
  54. turtle.select(1)
  55. end
  56.  
  57. -- Securely acquire X diamonds from front inventory (Barrel or Chest)
  58. -- Keeps diamonds in turtle inventory. Returns success, message.
  59. -- If targetAmount is "max", grabs everything valid.
  60. local function acquireDiamonds(targetAmount)
  61. local acquired = 0
  62. local isMax = (targetAmount == "max")
  63.  
  64. while true do
  65. local needed = 64
  66. if not isMax then
  67. needed = targetAmount - acquired
  68. if needed > 64 then needed = 64 end
  69. if needed <= 0 then break end
  70. end
  71.  
  72. -- Try to suck needed amount
  73. if turtle.suck(needed) then
  74. -- Verify what we just sucked
  75. local foundInvalid = false
  76. for i = 1, 16 do
  77. local item = turtle.getItemDetail(i)
  78. if item and not isDiamond(item) then
  79. -- Junk item, spit it back
  80. turtle.select(i)
  81. turtle.drop()
  82. turtle.select(1)
  83. foundInvalid = true
  84. end
  85. end
  86.  
  87. if foundInvalid and not isMax then
  88. -- If we found invalid items during a specific request, we might want to fail or just retry?
  89. -- simple retry logic: just continue loop, we counted valid ones below
  90. end
  91.  
  92. -- Recount total diamonds in inventory to update progress
  93. local currentTotal = 0
  94. for i = 1, 16 do
  95. local item = turtle.getItemDetail(i)
  96. if item and isDiamond(item) then
  97. currentTotal = currentTotal + item.count
  98. end
  99. end
  100.  
  101. -- If we haven't increased, break (empty source)
  102. if currentTotal <= acquired then
  103. break
  104. end
  105. acquired = currentTotal
  106. else
  107. break -- Sucking failed (empty)
  108. end
  109. end
  110.  
  111. if isMax then
  112. if acquired > 0 then
  113. return true, acquired
  114. else
  115. return false, "No Diamonds Found"
  116. end
  117. else
  118. if acquired >= targetAmount then
  119. return true, acquired
  120. else
  121. return false, "Insufficient Diamonds: Found " .. acquired .. " of " .. targetAmount
  122. end
  123. end
  124. end
  125.  
  126. -- Dumps ALL diamonds in inventory to front
  127. local function commitDiamonds()
  128. dumpItems(isDiamond)
  129. end
  130.  
  131. local function handleDeposit(studentId, password, amount)
  132. local isMax = (amount == "max")
  133. local targetDiamonds = 0
  134. if not isMax then
  135. targetDiamonds = amount -- 1 Eddie = 1 Diamond
  136. end
  137.  
  138. if isMax then
  139. debug("Deposit: MAX Eddies")
  140. else
  141. debug("Deposit: " .. amount .. " Eddies (" .. targetDiamonds .. " Diamonds)")
  142. end
  143.  
  144. if not findBlock("barrel") then
  145. sendToATM({action="complete", success=false, error="Barrel not found"})
  146. return
  147. end
  148.  
  149. -- 1. Acquire from Barrel
  150. local success, result = acquireDiamonds(isMax and "max" or targetDiamonds)
  151. if not success then
  152. sendToATM({action="complete", success=false, error=result or "Failed to collect diamonds"})
  153. -- Refund what we grabbed back to Barrel
  154. commitDiamonds()
  155. return
  156. end
  157.  
  158. local totalDiamonds = result
  159. -- 1 Diamond = 1 Eddie, so no remainder calculation needed usually.
  160. local eddies = totalDiamonds
  161.  
  162. if eddies <= 0 then
  163. sendToATM({action="complete", success=false, error="No diamonds found"})
  164. commitDiamonds()
  165. return
  166. end
  167.  
  168. -- 2. Server Update
  169. local response = sendToServer({type="update_balance", studentId=studentId, password=password, action="deposit", amount=eddies})
  170.  
  171. if response and response.type == "balance_update_response" and response.success then
  172. -- 3. Success: Move to Chest
  173. if findBlock("chest") then
  174. commitDiamonds() -- Dump to chest
  175. sendToATM({action="complete", success=true, newBalance=response.result, amountDeposited=eddies})
  176. else
  177. -- Critical Error: Chest missing after transaction!
  178. debug("CRITICAL: Chest missing during deposit commit!")
  179. -- Attempt to return to barrel to be safe
  180. if findBlock("barrel") then
  181. commitDiamonds()
  182. sendToATM({action="complete", success=true, newBalance=response.result, warning="System Error: Chest full/missing. Diamonds returned to barrel but balance updated. Contact Admin.", amountDeposited=eddies})
  183. else
  184. sendToATM({action="complete", success=true, newBalance=response.result, warning="System Error: Diamonds stuck in Turtle.", amountDeposited=eddies})
  185. end
  186. end
  187. else
  188. -- 4. Fail: Refund to Barrel
  189. debug("Server deposit failed: " .. (response and response.message or "Timeout"))
  190. if findBlock("barrel") then
  191. commitDiamonds() -- Dump back to barrel
  192. end
  193. sendToATM({action="complete", success=false, error="Server rejected deposit"})
  194. end
  195. end
  196.  
  197. local function handleWithdraw(studentId, password, amount)
  198. local diamondAmount = amount
  199. debug("Withdraw: " .. amount .. " Eddies (" .. diamondAmount .. " Diamonds)")
  200.  
  201. -- 0. Check Balance First (Quick fail)
  202. local balanceResponse = sendToServer({type="get_balance", studentId=studentId, password=password})
  203. if not (balanceResponse and balanceResponse.type == "balance_response") then
  204. sendToATM({action="complete", success=false, error="Failed to retrieve balance"})
  205. return
  206. end
  207. if tonumber(balanceResponse.balance) < amount then
  208. sendToATM({action="complete", success=false, error="Insufficient balance"})
  209. return
  210. end
  211.  
  212. if not findBlock("chest") then
  213. sendToATM({action="complete", success=false, error="Chest not found"})
  214. return
  215. end
  216.  
  217. -- 1. Acquire from Chest
  218. local success, msg = acquireDiamonds(diamondAmount)
  219. if not success then
  220. sendToATM({action="complete", success=false, error=msg or "ATM empty/low funds"})
  221. -- Revert to Chest
  222. commitDiamonds()
  223. return
  224. end
  225.  
  226. -- 2. Server Update
  227. local response = sendToServer({type="update_balance", studentId=studentId, password=password, action="withdraw", amount=amount})
  228.  
  229. if response and response.type == "balance_update_response" and response.success then
  230. -- 3. Success: Move to Barrel
  231. if findBlock("barrel") then
  232. commitDiamonds() -- Dump to barrel
  233. sendToATM({action="complete", success=true, newBalance=response.result})
  234. else
  235. debug("CRITICAL: Barrel missing during withdraw commit!")
  236. -- Refund to Chest? But user already paid on server.
  237. -- This is a 'money lost' scenario for user if we refund.
  238. -- Better to keep trying or dump?
  239. -- In production, we'd log this. Here, we return to Chest to save the diamonds and error out.
  240. -- User loses balance but ATM keeps diamonds. Admin intervention needed.
  241. commitDiamonds()
  242. sendToATM({action="complete", success=false, error="Hardware error: Barrel missing. Diamonds retained in ATM. Contact Admin."})
  243. end
  244. else
  245. -- 4. Fail: Revert to Chest
  246. commitDiamonds()
  247. sendToATM({action="complete", success=false, error="Server rejected withdraw"})
  248. end
  249. end
  250.  
  251. while true do
  252. local event, side, channel, replyChannel, message = os.pullEvent("modem_message")
  253. if channel == 4 then
  254. if message.action == "deposit" then
  255. handleDeposit(message.studentId, message.password, message.amount)
  256. elseif message.action == "withdraw" then
  257. handleWithdraw(message.studentId, message.password, message.amount)
  258. end
  259. end
  260. end
  261.  
Add Comment
Please, Sign In to add comment