Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Turtle Server Manager
- local PROTOCOL = "room_mgmt"
- -- Define your currency item here
- local CURRENCY_ITEM = "minecraft:gold_nugget"
- peripheral.find("modem", rednet.open)
- rednet.host(PROTOCOL, "server")
- local inputChest = peripheral.wrap("top")
- local vaultChest = peripheral.wrap("bottom")
- local db = { rooms = {}, users = {} }
- if fs.exists("database.json") then
- local file = fs.open("database.json", "r")
- db = textutils.unserializeJSON(file.readAll()) or { rooms = {}, users = {} }
- file.close()
- end
- local function saveDb()
- local file = fs.open("database.json", "w")
- file.write(textutils.serializeJSON(db))
- file.close()
- end
- local function updateRoomState(roomId)
- local room = db.rooms[roomId]
- local status = "Available"
- local overdue = false
- if room.state == "rented" then
- status = "Rented"
- if os.epoch("utc") > room.due then overdue = true end
- end
- if room.state == "sold" then status = "Sold" end
- rednet.broadcast({
- target = roomId,
- command = "update",
- status = status,
- owner = room.owner,
- isOpen = room.door_open or false,
- overdue = overdue
- }, PROTOCOL)
- end
- local function networkListener()
- while true do
- local sender, msg, prot = rednet.receive(PROTOCOL)
- if type(msg) == "table" then
- local now = os.epoch("utc")
- -- Ensure user exists in db
- if msg.user and not db.users[msg.user] then
- db.users[msg.user] = { balance = 0 }
- end
- if msg.type == "register" then
- local id = msg.info.id
- if not db.rooms[id] then
- db.rooms[id] = { info = msg.info, state = "available", owner = nil, due = 0, door_open = false, password = nil }
- else
- db.rooms[id].info = msg.info
- end
- saveDb()
- updateRoomState(id)
- elseif msg.type == "request_list" then
- local userBal = msg.user and db.users[msg.user] and db.users[msg.user].balance or 0
- rednet.send(sender, { type = "list_response", data = db.rooms, balance = userBal, time = now }, PROTOCOL)
- elseif msg.type == "deposit" then
- if not inputChest or not vaultChest then
- rednet.send(sender, { type = "error", msg = "Server chests missing!" }, PROTOCOL)
- else
- local vaultName = peripheral.getName(vaultChest)
- local totalDeposited = 0
- for slot, item in pairs(inputChest.list()) do
- if item.name == CURRENCY_ITEM then
- -- Push specific item amounts to vault
- local pushed = inputChest.pushItems(vaultName, slot, item.count)
- totalDeposited = totalDeposited + pushed
- end
- end
- if totalDeposited > 0 then
- db.users[msg.user].balance = db.users[msg.user].balance + totalDeposited
- saveDb()
- rednet.send(sender, { type = "success", msg = "Deposited " .. totalDeposited .. " " .. CURRENCY_ITEM }, PROTOCOL)
- else
- rednet.send(sender, { type = "error", msg = "No valid currency in Drop Box." }, PROTOCOL)
- end
- end
- elseif msg.type == "rent" or msg.type == "buy" then
- local room = db.rooms[msg.id]
- local price = (msg.type == "rent") and room.info.rent_price or room.info.sale_price
- if room and room.state == "available" then
- if db.users[msg.user].balance >= price then
- db.users[msg.user].balance = db.users[msg.user].balance - price
- room.state = (msg.type == "rent") and "rented" or "sold"
- room.owner = msg.user
- room.door_open = false
- room.password = nil
- room.due = (msg.type == "rent") and (now + room.info.rent_frequency) or 0
- saveDb()
- updateRoomState(msg.id)
- rednet.send(sender, { type = "success", msg = "Transaction successful!" }, PROTOCOL)
- else
- rednet.send(sender, { type = "error", msg = "Insufficient Bank Balance!" }, PROTOCOL)
- end
- end
- elseif msg.type == "cancel" or msg.type == "sell" then
- local room = db.rooms[msg.id]
- if room and room.owner == msg.user then
- if msg.type == "sell" and room.state == "sold" then
- db.users[msg.user].balance = db.users[msg.user].balance + math.floor(room.info.sale_price / 2)
- end
- room.state = "available"
- room.owner = nil
- room.door_open = false
- room.password = nil
- room.due = 0
- saveDb()
- updateRoomState(msg.id)
- rednet.send(sender, { type = "success", msg = "Room relinquished." }, PROTOCOL)
- end
- elseif msg.type == "set_password" then
- local room = db.rooms[msg.id]
- if room and room.owner == msg.user then
- room.password = msg.password
- saveDb()
- rednet.send(sender, { type = "success", msg = "Password updated!" }, PROTOCOL)
- end
- elseif msg.type == "toggle_door" then
- local room = db.rooms[msg.id]
- if room and (room.owner == msg.user or room.password == msg.password) then
- room.door_open = not room.door_open
- saveDb()
- updateRoomState(msg.id)
- if msg.user then rednet.send(sender, { type = "success", msg = "Door toggled." }, PROTOCOL) end
- else
- if msg.user then rednet.send(sender, { type = "error", msg = "Access Denied." }, PROTOCOL) end
- end
- end
- end
- end
- end
- local function timerLoop()
- while true do
- local now = os.epoch("utc")
- for id, room in pairs(db.rooms) do
- if room.state == "rented" and now >= room.due then
- -- Attempt auto-deduct
- if db.users[room.owner] and db.users[room.owner].balance >= room.info.rent_price then
- db.users[room.owner].balance = db.users[room.owner].balance - room.info.rent_price
- room.due = now + room.info.rent_frequency
- saveDb()
- updateRoomState(id)
- else
- -- Check eviction grace period
- if now >= (room.due + room.info.grace_period) then
- room.state = "available"
- room.owner = nil
- room.due = 0
- room.door_open = false
- room.password = nil
- saveDb()
- updateRoomState(id)
- else
- updateRoomState(id) -- Pushes overdue status update
- end
- end
- end
- end
- sleep(10)
- end
- end
- print("Room Bank Server Running.")
- parallel.waitForAny(networkListener, timerLoop)
Advertisement
Add Comment
Please, Sign In to add comment