Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local fName = "trades"
- local nameLength = 12
- local chestSide = "down"
- local expireDays = math.huge
- local mon = peripheral.find("monitor")
- mon.setBackgroundColor(colors.black)
- mon.clear()
- local pim = peripheral.find("pim")
- local chestInv = {}
- local deals = {}
- local saveData = {deals=deals,chestInv=chestInv}
- local buttons = {}
- local players = {}
- local curPl
- -- offer=Item,price=Item,owner=uuid,startDay=number,
- -- Item has display_name, dmg, max_dmg,qty, max_size, id
- if fs.exists(fName) then
- local f = fs.open(fName,"r")
- saveData = textutils.unserialize(f.readAll())
- deals = saveData.deals
- chestInv = saveData.chestInv
- f.close()
- end
- local function save()
- local f = fs.open(fName,"w")
- f.write(textutils.serialize(saveData))
- f.close()
- end
- local pInv = {}
- local invSlots
- local function loadInventory()
- pInv = {}
- invSlots = pim.getAllStacks()
- for i,k in pairs(invSlots) do
- local j=k.basic()
- if pInv[j.id] and pInv[j.id][j.dmg] then
- local t = pInv[j.id][j.dmg]
- table.insert(t.slots,i)
- t.qty = t.qty + j.qty
- else
- pInv[j.id] = pInv[j.id] or {}
- pInv[j.id][j.dmg] = j
- j.slots = {i}
- end
- end
- end
- local function writeItem(I,x,y)
- mon.setCursorPos(x,y)
- mon.write(string.format("%2d %s",math.floor(I.qty),(I.display_name..(" "):rep(nameLength)):sub(1,nameLength)))
- mon.setCursorPos(x,y+1)
- mon.write(string.format("%s%3d",string.rep(" ",nameLength),I.stored))
- end
- local function addButton(d,x,y,revs,name)
- mon.setCursorPos(x,y)
- mon.write(name)
- table.insert(buttons,{xmin=x,xmax=x+#name,y=y,deal=d,reversed=revs,name=name})
- end
- local function addButtons(d,x,y,revs)
- addButton(d,x,y,revs,"1")
- addButton(d,x+2,y,revs,"1/2")
- addButton(d,x+6,y,revs,"all")
- end
- local function hasItem(i,n)
- return pInv[i.id] and pInv[i.id][i.dmg] and pInv[i.id][i.dmg].qty >= n
- end
- local function amount(i)
- return pInv[i.id] and pInv[i.id][i.dmg] and pInv[i.id][i.dmg].qty or 0
- end
- local function drawDeal(d,x,y)
- local bc = colors.gray
- if d.owner == curPl.uuid then
- if d.offer.stored < d.offer.qty then
- bc = colors.red
- else
- bc = colors.blue
- end
- elseif hasItem(d.price,d.price.qty) then
- bc = colors.green
- end
- mon.setBackgroundColor(bc)
- writeItem(d.offer,x,y)
- mon.setCursorPos(x+nameLength+3,y)
- mon.write(" for ")
- mon.setCursorPos(x+nameLength+3,y+1)
- mon.write(" ")
- writeItem(d.price,x+nameLength+8,y)
- mon.setBackgroundColor(colors.orange)
- if d.owner == curPl.uuid then
- addButton(d,x,y+1,nil,"refill")
- addButton(d,x+7,y+1,nil,"delete")
- if d.price.stored > 0 then
- addButton(d,x+14,y+1,nil,"take")
- end
- else
- addButtons(d,x,y+1,false)
- if d.reversable then
- addButtons(d,x+nameLength+8,y+1,true)
- end
- end
- end
- local function updateMonitor()
- mon.setCursorPos(1,1)
- mon.setBackgroundColor(colors.black)
- mon.write("Player: "..curPl.name..string.rep(" ",nameLength))
- buttons = {}
- local dNum = 1
- local mx,my = mon.getSize()
- for j=3,my,3 do
- for i=1,mx - 2*nameLength-11 ,2*nameLength+12 do
- if deals[dNum] then
- drawDeal(deals[dNum],i,j)
- dNum = dNum + 1
- else
- mon.setBackgroundColor(colors.orange)
- addButton(nil,i,j,nil,"New Trade")
- return
- end
- end
- end
- end
- local function updatePlayer()
- if #players == 1 then
- curPl = players[1]
- loadInventory()
- else
- curPl = {name=""}
- pInv = {}
- end
- updateMonitor()
- end
- updatePlayer()
- local function copy(t)
- local r = {}
- for i,j in pairs(t) do
- if type(j) == "table" then
- r[i] = copy(j)
- else
- r[i] = j
- end
- end
- return r
- end
- local function store(I,n)
- local rem = n
- if hasItem(I,n) then
- local s = pInv[I.id][I.dmg].slots
- local si = #s
- local sc = 1
- while rem > 0 do
- local qty = invSlots[s[si]].basic().qty
- local k = chestInv[sc]
- while k and (k.id ~= I.id or k.dmg ~= I.dmg or k.max_size <= k.qty) do
- sc = sc + 1
- k = chestInv[sc]
- end
- local restSpace = k and k.max_size-k.qty or math.huge
- local put = pim.pushItem(chestSide,s[si],math.min(rem,qty,restSpace),sc)
- qty = qty - put
- rem = rem - put
- if k then
- k.qty = k.qty + put
- else
- chestInv[sc] = copy(I)
- end
- if qty == 0 then
- si = si - 1
- if si == 0 and rem > 0 then
- I.stored = I.stored+(n-rem)
- return false, n-rem
- end
- end
- end
- I.stored = I.stored+n
- return true,n
- end
- return false,0
- end
- local function giveOut(I,n)
- local rem = n
- local sc = #chestInv
- while rem > 0 do
- local k = chestInv[sc]
- while not k or k.id ~= I.id or k.dmg ~= I.dmg do
- sc = sc - 1
- if sc <= 0 then
- I.stored = I.stored-(n-rem)
- return false,n-rem
- end
- k = chestInv[sc]
- end
- local put = pim.pullItem(chestSide,sc,math.min(rem,chestInv[sc].qty))
- rem = rem - put
- if k then
- k.qty = k.qty - put
- if k.qty == 0 then
- chestInv[sc] = nil
- end
- end
- end
- I.stored = I.stored-n
- return true,n
- end
- while true do
- local e = {os.pullEvent()}
- if e[1] == "player_on" then
- table.insert(players,{name=e[2],uuid=e[3]})
- updatePlayer()
- elseif e[1] == "player_off" then
- for i,j in ipairs(players) do
- if j.uuid == e[3] then
- table.remove(players,i)
- break
- end
- end
- updatePlayer()
- elseif e[1] == "monitor_touch" then
- for i,j in ipairs(buttons) do
- if e[3] >= j.xmin and e[3] <= j.xmax and e[4] == j.y then
- if j.name == "New Trade" then
- local slots = pim.getAllStacks()
- if slots[4] and slots[6] then
- local ofr = slots[4].basic()
- local pri = slots[6].basic()
- ofr.stored = 0
- pri.stored = 0
- table.insert(deals,{offer=ofr,price=pri,owner=curPl.uuid,reversable=slots[5] and true or false,startDay=os.day()})
- save()
- updateMonitor()
- end
- elseif j.name == "delete" then
- for k,l in ipairs(deals) do
- if l == j.deal then
- giveOut(l.price,l.price.stored)
- giveOut(l.offer,l.offer.stored)
- table.remove(deals,k)
- save()
- mon.setBackgroundColor(colors.black)
- mon.clear()
- updateMonitor()
- break
- end
- end
- elseif j.name == "refill" then
- loadInventory()
- local item = j.deal.offer
- store(item,amount(item))
- save()
- updateMonitor()
- elseif j.name == "take" then
- loadInventory()
- local item = j.deal.price
- if item.stored > 0 then
- giveOut(item,item.stored)
- end
- save()
- updateMonitor()
- elseif j.name == "1" or j.name == "1/2" or j.name == "all" then
- loadInventory()
- local pri = j.deal.price
- local ofr = j.deal.offer
- if j.reversed then
- pri,ofr = ofr,pri
- end
- local times = 1
- if j.name == "1/2" then
- times = math.floor(amount(pri) / pri.qty / 2)
- elseif j.name == "all" then
- times = math.floor(amount(pri) / pri.qty)
- end
- local s,taken = store(pri,times * pri.qty)
- if s then
- local s2,given = giveOut(ofr,times * ofr.qty)
- if not s2 then --panic a little bit and try to undo
- loadInventory()
- store(ofr,times * ofr.qty)
- giveOut(pri,times * pri.qty)
- print("Failed to give "..ofr.display_name.. " to "..pim.getInventoryName())
- end
- else
- giveOut(pri,taken)
- end
- save()
- updateMonitor()
- else
- error("Invalid Button press")
- end
- end
- end
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment