Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local selfName = "computer_3"
- local ioChestName = "minecraft:shulker_box_0"
- local vaultChestType = "ironchest:obsidian_chest"
- local monitorName = "monitor_0"
- local chatBoxName = "chatBox_0"
- local plyrDetectorName = "playerDetector_0"
- local modemName = "modem_1"
- local coinName = "minecraft:enchanted_golden_apple"
- local coinDisplayName = "BodCoin"
- local coinNbt = "a86eafd0148c1abb39f9b1e9e5d3cb70"
- local coinMaxStackSize = 64
- local itemDisplayNameScreen = "Enchanted Golden Apple"
- local bodCoinPerCoin = 100000
- local bgColor = colors.blue
- local acColor = colors.white
- local textScale = 0.85
- --------
- local ioChest = peripheral.wrap(ioChestName)
- local vaultChests = { peripheral.find(vaultChestType) }
- local monitor = peripheral.wrap(monitorName)
- monitor.setTextScale(textScale)
- local monWidth, monHeight = monitor.getSize()
- rednet.open(modemName)
- function Load(file)
- local file = fs.open(file, "r")
- if file == nil then
- return {}
- end
- local toRet = textutils.unserialise(file.readAll())
- file.close()
- return toRet
- end
- local bankAccounts = Load("bankAccounts")
- local passwords = Load("passwords")
- local pendingTransactions = Load("pendingTransactions")
- local completedTransactions = Load("completedTransactions")
- function Save(file, data)
- local file = fs.open(file, "w")
- file.write(textutils.serialise(data))
- file.close()
- end
- function CommaValue(amount)
- local formatted = amount
- while true do
- formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1,%2')
- if (k==0) then
- break
- end
- end
- return formatted
- end
- function RandomString(len)
- --https://www.codegrepper.com/code-examples/lua/how+to+generate+a+random+string+in+lua
- local res = ""
- for i = 1, len do
- res = res .. string.char(math.random(97, 122))
- end
- return res
- end
- function Store(ioSlot, count)
- local toMove = count
- for chestName, chest in pairs(vaultChests) do
- local chestItems = chest.list()
- for slot = 1, chest.size() do
- if chestItems[slot] == nil or chestItems[slot].count < coinMaxStackSize then
- toMove = toMove - vaultChests[chestName].pullItems(ioChestName, ioSlot, toMove, slot)
- if toMove == 0 then
- return
- end
- end
- end
- end
- error("Run out of storage in vault!")
- end
- function Get(count)
- local toMove = count
- for chestName, chest in pairs(vaultChests) do
- local chestItems = chest.list()
- for slot = 1, chest.size() do
- if chestItems[slot] ~= nil then
- toMove = toMove - vaultChests[chestName].pushItems(ioChestName, slot, toMove)
- if toMove == 0 then
- return
- end
- end
- end
- end
- error("Run out of items in vault!")
- end
- function AcceptCoins(playerName)
- local coinsAccepted = 0
- for i = 1, ioChest.size() do
- local item = ioChest.getItemDetail(i)
- if item ~= nil and item.name == coinName and item.displayName == coinDisplayName and item.nbt == coinNbt then
- Store(i, item.count)
- coinsAccepted = coinsAccepted + item.count
- end
- end
- print("Accepted " .. tostring(coinsAccepted) .. " items from " .. playerName)
- AddBalance(playerName, coinsAccepted * bodCoinPerCoin)
- return coinsAccepted
- end
- function WithdrawCoins(playerName, amt)
- local amtWithdrawn = 0
- while amtWithdrawn < amt do
- if AddBalance(playerName, -bodCoinPerCoin) == nil then
- return amtWithdrawn
- end
- Get(1)
- amtWithdrawn = amtWithdrawn + 1
- end
- return amtWithdrawn
- end
- function GetBalance(username)
- if bankAccounts[username] ~= nil then
- return bankAccounts[username]
- end
- return 0
- end
- function ValidateAmount(amount, mustBe)
- if type(amount) ~= "number" then
- return false, "Amount must be a number"
- end
- if mustBe == "neg" and amount >= 0 then
- return false, "Amount must be negative"
- end
- if mustBe == "pos" and amount <= 0 then
- return false, "Amount must be positive"
- end
- if amount ~= math.floor(amount) then
- return false, "Amount must be integer"
- end
- return true
- end
- function AddBalance(username, change, mustBe)
- local amountValid, notValidReason = ValidateAmount(change, mustBe)
- if amountValid == false then
- return nil, notValidReason
- end
- if bankAccounts[username] == nil then
- bankAccounts[username] = 0
- end
- if bankAccounts[username] + change < 0 then
- return nil, "Insufficient funds"
- end
- bankAccounts[username] = bankAccounts[username] + change
- Save("bankAccounts", bankAccounts)
- return bankAccounts[username]
- end
- function AddPendingTransaction(to, from, amount)
- local amountValid, notValidReason = ValidateAmount(amount, "pos")
- if amountValid == false then
- return nil, notValidReason
- end
- if type(to) ~= "string" then
- return nil, "'to' must be string"
- end
- if type(from) ~= "string" then
- return nil, "'from' must be string"
- end
- local transactionID = RandomString(16)
- pendingTransactions[transactionID] = {
- ["to"] = to,
- ["from"] = from,
- ["amount"] = amount,
- ["timestamp"] = os.date(),
- }
- Save("pendingTransactions", pendingTransactions)
- return transactionID
- end
- function CompletePendingTransaction(transactionID, allow)
- if pendingTransactions[transactionID] == nil then
- return false, "Transaction not found"
- end
- if type(allow) ~= "boolean" then
- return false, "'allow' is not boolean"
- end
- completedTransactions[transactionID] = {
- ["to"] = pendingTransactions[transactionID]["to"],
- ["from"] = pendingTransactions[transactionID]["from"],
- ["amount"] = pendingTransactions[transactionID]["amount"],
- ["timestamp"] = pendingTransactions[transactionID]["timestamp"],
- ["allowed"] = allow
- }
- pendingTransactions[transactionID] = nil
- end
- function GetTransactionStatus(transactionID)
- if pendingTransactions[transactionID] ~= nil then
- return "pending"
- end
- if completedTransactions[transactionID] ~= nil then
- if completedTransactions[transactionID]["allowed"] then
- return "allowed"
- else
- return "denied"
- end
- end
- return "notFound"
- end
- function GetPendingTo(to)
- local toRet = {}
- for k, v in pairs(pendingTransactions) do
- if v.to == to then
- table.insert(toRet, v)
- end
- end
- return toRet
- end
- function GetPendingFrom(to)
- local toRet = {}
- for k, v in pairs(pendingTransactions) do
- if v.from == from then
- table.insert(toRet, v)
- end
- end
- return toRet
- end
- function GetCompletedTo(to)
- local toRet = {}
- for k, v in pairs(completedTransactions) do
- if v.to == to then
- table.insert(toRet, v)
- end
- end
- return toRet
- end
- function GetCompletedFrom(to)
- local toRet = {}
- for k, v in pairs(completedTransactions) do
- if v.from == from then
- table.insert(toRet, v)
- end
- end
- return toRet
- end
- ----
- function WriteCenter(txt, line)
- monitor.setCursorPos(math.ceil((monWidth - string.len(txt)) / 2), line)
- monitor.write(txt)
- end
- function Button(txt, line)
- monitor.setTextColor(bgColor)
- monitor.setBackgroundColor(acColor)
- monitor.setCursorPos(1, line)
- monitor.clearLine()
- WriteCenter(txt, line)
- monitor.setTextColor(acColor)
- monitor.setBackgroundColor(bgColor)
- end
- function Session()
- monitor.setTextColor(acColor)
- monitor.setBackgroundColor(bgColor)
- monitor.clear()
- print("Waiting for player click to start session")
- WriteCenter("Welcome", 2)
- WriteCenter("Press the green", 7)
- WriteCenter("block on the", 8)
- WriteCenter("right to login.", 9)
- local playerClickEvent, username = os.pullEvent("playerClick")
- print("Starting session for " .. username)
- function HomeScreen()
- monitor.clear()
- WriteCenter("Welcome", 2)
- WriteCenter(username, 3)
- AddBalance(username, 0, true)--add to bankAccounts table
- WriteCenter("What would you like to do?", 7)
- Button("Check balance", 11)
- Button("Deposit", 13)
- Button("Withdraw", 15)
- Button("Log out", 17)
- local nextScreen = nil
- while nextScreen == nil do
- local touchEvent, monitorTouched, x, y = os.pullEvent("monitor_touch")
- if y == 11 then
- nextScreen = "checkBalance"
- elseif y == 13 then
- nextScreen = "deposit"
- elseif y == 15 then
- nextScreen = "withdraw"
- elseif y == 17 then
- nextScreen = "logOut"
- end
- end
- return nextScreen
- end
- function WriteExchangeRate(line)
- WriteCenter("1 " .. itemDisplayNameScreen, line)
- WriteCenter("is worth " .. CommaValue(bodCoinPerCoin) .. " BodCoins", line + 1)
- end
- function BackButton()
- Button("Back", 17)
- while true do
- local touchEvent, monitorTouched, x, y = os.pullEvent("monitor_touch")
- if y == 17 then
- break
- end
- end
- end
- while true do
- local nextScreen = HomeScreen()
- if nextScreen == "checkBalance" then
- monitor.clear()
- WriteCenter("Balance for", 2)
- WriteCenter(username, 3)
- WriteCenter(CommaValue(GetBalance(username)) .. " BodCoin", 5)
- WriteExchangeRate(7)
- BackButton()
- elseif nextScreen == "deposit" then
- function DepositScreen()
- while true do
- monitor.clear()
- WriteCenter("Please rename your", 2)
- WriteCenter(itemDisplayNameScreen .. "(s)", 3)
- WriteCenter("to '" .. coinDisplayName .. "' using the anvils.", 4)
- WriteCenter("Then insert them into the", 6)
- WriteCenter("shulker on the left.", 7)
- WriteCenter("Then, press 'Deposit'", 9)
- WriteCenter("and the items will be counted", 10)
- WriteExchangeRate(12)
- Button("Deposit", 15)
- Button("Back", 17)
- while true do
- local touchEvent, monitorTouched, x, y = os.pullEvent("monitor_touch")
- if y == 15 then
- break
- elseif y == 17 then
- return
- end
- end
- monitor.clear()
- local itemsAdded = AcceptCoins(username)
- WriteCenter(tostring(itemsAdded) .. " " .. itemDisplayNameScreen .. "(s)", 4)
- WriteCenter("were accepted.", 5)
- WriteCenter("You now have: ", 8)
- WriteCenter(CommaValue(GetBalance(username)) .. " BodCoin", 9)
- BackButton()
- end
- end
- DepositScreen()
- elseif nextScreen == "withdraw" then
- function WithdrawScreen()
- while true do
- monitor.clear()
- Button("Withdraw 1 " .. itemDisplayNameScreen, 15)
- Button("Back", 17)
- while true do
- local touchEvent, monitorTouched, x, y = os.pullEvent("monitor_touch")
- if y == 15 then
- break
- elseif y == 17 then
- return
- end
- end
- monitor.clear()
- local withdrawn = WithdrawCoins(username, 1)
- WriteCenter(tostring(withdrawn) .. " " .. itemDisplayNameScreen .. "(s)", 4)
- WriteCenter("were withdrawn.", 5)
- WriteCenter("You now have: ", 8)
- WriteCenter(CommaValue(GetBalance(username)) .. " BodCoin", 9)
- BackButton()
- end
- end
- WithdrawScreen()
- elseif nextScreen == "logOut" then
- monitor.clear()
- WriteCenter("Goodbye", 2)
- sleep(3)
- break
- end
- end
- end
- function UI()
- while true do
- Session()
- end
- end
- function Network()
- while true do
- sleep(0)
- function HandleIn()
- local id, msg = rednet.receive("BodCoin")
- if type(msg) ~= "table" then
- rednet.send(id, {
- ["status"] = "fail",
- ["msg"] = "Data must be in table format"
- }, "BodCoinResp")
- return
- end
- if type(msg["login"]) ~= "table" or msg["login"]["username"] == nil or passwords[msg["login"]["username"]] == nil or passwords[msg["login"]["username"]] ~= msg["login"]["password"] then
- rednet.send(id, {
- ["status"] = "fail",
- ["msg"] = "Invalid login"
- }, "BodCoinResp")
- return
- end
- if msg["action"] == "getBalance" then
- rednet.send(id, {
- ["status"] = "success",
- ["balance"] = GetBalance(msg["login"]["username"])
- }, "BodCoinResp")
- return
- end
- if msg["action"] == "checkAccountExists" then
- rednet.send(id, {
- ["status"] = "success",
- ["exists"] = bankAccounts[msg["username"]] ~= nil or passwords[msg["username"]] ~= nil
- }, "BodCoinResp")
- return
- end
- if msg["action"] == "send" then
- if type(msg["to"]) ~= "string" then
- rednet.send(id, {
- ["status"] = "fail",
- ["msg"] = "'to' must be string"
- }, "BodCoinResp")
- return
- end
- local amountValid, notValidReason = ValidateAmount(msg["amount"], "pos")
- if amountValid == false then
- rednet.send(id, {
- ["status"] = "fail",
- ["msg"] = notValidReason
- }, "BodCoinResp")
- return
- end
- local fromNewBal, fromBalChangeError = AddBalance(msg["login"]["username"], -msg["amount"], "neg")
- if fromNewBal == nil then
- rednet.send(id, {
- ["status"] = "fail",
- ["msg"] = fromBalChangeError
- }, "BodCoinResp")
- return
- end
- local toNewBal, toBalChangeError = AddBalance(msg["to"], msg["amount"], "pos")
- if toNewBal == nil then
- error(toBalChangeError)
- end
- rednet.send(id, {
- ["status"] = "success",
- ["exists"] = bankAccounts[msg["to"]] ~= nil or passwords[msg["to"]] ~= nil
- }, "BodCoinResp")
- return
- end
- if msg["action"] == "request" then
- if type(msg["from"]) ~= "string" then
- rednet.send(id, {
- ["status"] = "fail",
- ["msg"] = "'from' must be string"
- }, "BodCoinResp")
- return
- end
- local transactionID, failedReason = AddPendingTransaction(msg["login"]["username"], msg["from"], msg["amount"])
- if transactionID == nil then
- rednet.send(id, {
- ["status"] = "fail",
- ["msg"] = failedReason
- }, "BodCoinResp")
- return
- end
- rednet.send(id, {
- ["status"] = "success",
- ["requestID"] = transactionID
- }, "BodCoinResp")
- return
- end
- if msg["action"] == "getRequestStatus" then
- local transactionStatus, transactionStatusFailedMsg = GetTransactionStatus(msg["requestID"])
- if transactionStatus == nil then
- rednet.send(id, {
- ["status"] = "fail",
- ["msg"] = transactionStatusFailedMsg
- }, "BodCoinResp")
- return
- end
- rednet.send(id, {
- ["status"] = "success",
- ["requestStatus"] = transactionStatus
- }, "BodCoinResp")
- return
- end
- end
- HandleIn()
- end
- end
- parallel.waitForAny(UI, Network)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement