summaryrefslogtreecommitdiff
path: root/shop2/main.lua
diff options
context:
space:
mode:
Diffstat (limited to 'shop2/main.lua')
-rw-r--r--shop2/main.lua163
1 files changed, 163 insertions, 0 deletions
diff --git a/shop2/main.lua b/shop2/main.lua
new file mode 100644
index 0000000..e79872c
--- /dev/null
+++ b/shop2/main.lua
@@ -0,0 +1,163 @@
+local key=assert(settings.get"krist.pkey","please set private key")
+local pp = require"cc.pretty".pretty_print
+
+-- ac.kst
+local OURNAME = "ac"
+local ITEMS = {}
+local function i(adr,itname,hname,price)
+ ITEMS[adr]={itname=itname,hname=hname,price=price,adr=adr}
+end
+i("dmn","minecraft:diamond","Diamond",5)
+i("blz","minecraft:blaze_rod","Blaze Rod",10)
+i("ely","minecraft:elytra","Elytra",200)
+i=nil
+
+
+local sres =textutils.unserializeJSON( http.post("https://krist.dev/ws/start","privatekey="..key).readAll())
+assert(sres.ok,"not ok")
+
+local ws = assert(http.websocket(sres.url))
+local nextid = 0
+local our_addr = "???"
+
+local function sendws(t)
+ t.id = nextid
+ nextid = nextid + 1
+ return ws.send(textutils.serializeJSON(t))
+end
+
+sendws{type="me"}
+
+local function parsemeta(m)
+ local out = {}
+ for s in string.gmatch(m..";","(.-);") do
+ local k,v = s:match"^(.-)=(.-)$"
+ if k==nil then
+ out.recipient = s
+ else
+ out[k]=v
+ end
+ end
+ return out
+end
+
+local chest
+for _,name in ipairs(peripheral.getNames()) do
+ if name:match("chest") then chest = peripheral.wrap(name) break end
+end
+assert(chest,"couldn't find chest")
+-- might not work if there are multiple modems but why would you do that
+local localname = peripheral.find("modem").getNameLocal()
+
+local function take_stock()
+ -- if you do this in parallel, you avoid having to wait 1 tick for each
+ -- slot of the chest. which is probably good.
+ local out = {}
+ local fns = {}
+ for i=1,chest.size() do
+ fns[i] = function() out[i] = chest.getItemDetail(i) end
+ end
+ parallel.waitForAll(unpack(fns))
+ return out
+end
+
+local function item_desc_matches(idesc,itemdetail)
+ -- idesc is an entry from ITEMS
+ -- itemdetail is something returned from getItemDetail on the chest
+ -- if you were wondering
+ return idesc.itname == itemdetail.name
+end
+
+local function stock_amt(stockinfo,idesc)
+ local total = 0
+ for ix,itm in pairs(stockinfo) do
+ if item_desc_matches(idesc,itm) then
+ total = total + itm.count
+ end
+ end
+ return total
+end
+
+local function give(stockinfo,idesc,amt)
+ amt = amt or 1
+ -- assumes that we have at least amt in stock already
+ -- actually no, might as well double check this anyway
+ assert(stock_amt(stockinfo,idesc) >= amt)
+ assert(amt>0)
+ -- make sure current turtle inv slot is empty
+ assert(turtle.getItemCount() == 0)
+
+ for slotidx,idtl in pairs(stockinfo) do
+ if item_desc_matches(idesc,idtl) then
+ local a = math.min(amt,idtl.count)
+ chest.pushItems(localname, slotidx, a, 1)
+ turtle.drop(a)
+ amt = amt - a
+ if amt <= 0 then break end
+ end
+ end
+end
+
+local function proctrans(tr)
+ if tr.to ~= our_addr then return end
+ if tr.type ~= "transfer" then return end
+ if tr.sent_name ~= OURNAME then return end
+ local meta = parsemeta(tr.metadata)
+ local function tell(msg) if meta.username then chatbox.tell(meta.username,msg) end end
+ local function refund() if meta['return'] then sendws { type="make_transaction", to=meta['return'], amount=tr.value } end end
+
+ local mtn = tr.sent_metaname
+ local idesc = ITEMS[mtn]
+ if not idesc then
+ -- some other metaname that has nothing to do with us
+ -- presumably some other service @ac.kst. so just ignore it
+ tell("(debug) i didn't recognise that metaname so no transaction occurs")
+ return
+ end
+
+ local remainder = tr.value % idesc.price
+ if remainder ~= 0 then
+ tell("i can only give you a whole number of items. make sure the amount you gave me is a multiple of "..idesc.price)
+ refund()
+ else
+ local si = take_stock()
+ local in_stock = stock_amt(si,idesc)
+ if in_stock == 0 then
+ tell("we are out of stock! please yell at ubq323 about this")
+ refund()
+ else
+ local to_give = math.floor(tr.value / idesc.price)
+ if to_give > in_stock then
+ tell("i don't have that many items in stock, sorry")
+ refund()
+ else
+ give(si,idesc,to_give)
+ tell("thank you!!! :3")
+ end
+ end
+ end
+end
+
+local function run_shop()
+ print("RUNSHOP")
+ while true do
+ msgtxt = assert(ws.receive(),"ws error")
+ print(msgtxt)
+ msg = textutils.unserializeJSON(msgtxt)
+ if msg.type == "response" and msg.responding_to_type == "me" then
+ our_addr = msg.address.address
+ end
+ if msg.type == "event" and msg.event == "transaction" then
+ print("proctransing...")
+ proctrans(msg.transaction)
+ end
+ end
+end
+
+local function run_sidedisp()
+end
+
+print(pcall(parallel.waitForAny,run_shop))
+-- print("hi")
+-- peripheral.call("top","clear")
+-- peripheral.call("left","clear")