From 5b4093d518d8415bbc64d844120233708bc66423 Mon Sep 17 00:00:00 2001 From: ubq323 Date: Sat, 7 Jan 2023 04:50:17 +0000 Subject: movement --- shop2.lua | 166 -------------------------------------------------------- shop2/disp.lua | 80 +++++++++++++++++++++++++++ shop2/main.lua | 163 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ shop2/stock.lua | 39 +++++++++++++ shop2m.lua | 80 --------------------------- 5 files changed, 282 insertions(+), 246 deletions(-) delete mode 100644 shop2.lua create mode 100644 shop2/disp.lua create mode 100644 shop2/main.lua create mode 100644 shop2/stock.lua delete mode 100644 shop2m.lua diff --git a/shop2.lua b/shop2.lua deleted file mode 100644 index 6c98d62..0000000 --- a/shop2.lua +++ /dev/null @@ -1,166 +0,0 @@ -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_topdisp() -end - -local function run_sidedisp() -end - -print(pcall(parallel.waitForAny,run_shop)) --- print("hi") --- peripheral.call("top","clear") --- peripheral.call("left","clear") diff --git a/shop2/disp.lua b/shop2/disp.lua new file mode 100644 index 0000000..5260cdc --- /dev/null +++ b/shop2/disp.lua @@ -0,0 +1,80 @@ +local ourname = "ac.kst" + +local function printseq(m) return function(q) + for _,v in ipairs(q) do + print(type(v),v) + if type(v) == "number" then + m.setTextColor(v) + elseif type(v) == "string" then + m.write(v) + elseif type(v) == "table" then + if #v == 2 then + -- position + m.setCursorPos(v[1],v[2]) + else + error("unknown format") + end + end + end +end end + +local function pad(s,n) + s=tostring(s) + local l = #s + local p = string.rep(" ",math.max(0,n-l)) + return p..s +end +local function centre(s,w) + s=tostring(s) + local l = #s + local p = math.floor(math.max(0,w-l)/2) + return string.rep(" ",p)..s +end + +local function disp_shopscreen(items) + -- i don't like how hardcoded all the spacing is in this + -- but i also don't feel like rewriting it yet. + local m = peripheral.wrap"left" + m.clear() + m.setTextScale(0.5) + -- Stock Price Adr. Name + -- xxxx xxxkst dmn Diamond + -- 123456789012345678901234567890123456789012345678901234567 + -- 0 1 2 3 4 5 + + -- local function fmt_row(m,y, stock,price,adr,name, colour) + local function fmt_row(m,y, idesc, + colour = colour or colors.cyan + printseq(m) { + {1,y}, colors.white, pad(stock,5), + {8,y}, colors.yellow, pad(price,3), colors.lightGray, "kst", + {16,y}, colour, adr, + {22,y}, colour, name, + } + end + + + printseq(m) { + {1,1}, colors.orange, "Apiaristics Consortium Store", + {1,2}, colors.lightGray, "Stock Price Adr. Name", + } + + -- sort alphabetically + -- todo: more intuitive sort, once more things are for sale + -- + for ix,i in ipairs() do + fmt_row(m,ix+2,i[6],i[2],i[1],i[4],i[5]) + end + + local w,h = m.getSize() + + printseq(m) { + {1,h-1}, colors.blue, centre("/pay @ac.kst ",w) + } + + + + +end + +disp_shopscreen() 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") diff --git a/shop2/stock.lua b/shop2/stock.lua new file mode 100644 index 0000000..ce76bf0 --- /dev/null +++ b/shop2/stock.lua @@ -0,0 +1,39 @@ + + +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 + diff --git a/shop2m.lua b/shop2m.lua deleted file mode 100644 index c8e2716..0000000 --- a/shop2m.lua +++ /dev/null @@ -1,80 +0,0 @@ -local ourname = "ac.kst" - -local ITEMS = { - {"dmn", 5, "minecraft:diamond", "Diamond", colors.cyan, 321}, - {"blz", 10, "minecraft:blaze_rod", "Blaze Rod", colors.orange, 27}, - {"ely", 40, "minecraft:elytra", "Elytra", colors.purple, 8}, -} - -local function printseq(m) return function(q) - for _,v in ipairs(q) do - print(type(v),v) - if type(v) == "number" then - m.setTextColor(v) - elseif type(v) == "string" then - m.write(v) - elseif type(v) == "table" then - if #v == 2 then - -- position - m.setCursorPos(v[1],v[2]) - else - error("unknown format") - end - end - end -end end - -local function pad(s,n) - s=tostring(s) - local l = #s - local p = string.rep(" ",math.max(0,n-l)) - return p..s -end -local function centre(s,w) - s=tostring(s) - local l = #s - local p = math.floor(math.max(0,w-l)/2) - return string.rep(" ",p)..s -end - -local function disp_shopscreen() - local m = peripheral.wrap"left" - m.clear() - m.setTextScale(0.5) - -- Stock Price Adr. Name - -- xxxx xxxkst dmn Diamond - -- 123456789012345678901234567890123456789012345678901234567 - -- 0 1 2 3 4 5 - - local function fmt_row(m,y, stock,price,adr,name, colour) - colour = colour or colors.cyan - printseq(m) { - {1,y}, colors.white, pad(stock,5), - {8,y}, colors.yellow, pad(price,3), colors.lightGray, "kst", - {16,y}, colour, adr, - {22,y}, colour, name, - } - end - - - printseq(m) { - {1,1}, colors.orange, "Apiaristics Consortium Store", - {1,2}, colors.lightGray, "Stock Price Adr. Name", - } - - for ix,i in ipairs(ITEMS) do - fmt_row(m,ix+2,i[6],i[2],i[1],i[4],i[5]) - end - - local w,h = m.getSize() - - printseq(m) { - {1,h-1}, colors.blue, centre("/pay @ac.kst ",w) - } - - - - -end - -disp_shopscreen() -- cgit v1.2.3