Advertisement
GravityCube

Untitled

May 22nd, 2019
396
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.84 KB | None | 0 0
  1. --[[
  2.  
  3. --*--*--*--*--*--*--*--*--*--*--*--*--*--*--
  4. --* Shop Program *--
  5. --* https://pastebin.com/XXXXXXXX *--
  6. --* by: GravityCube *--
  7. --*--*--*--*--*--*--*--*--*--*--*--*--*--*--
  8.  
  9.  
  10. Changelog:
  11. 1.0.0 First release. (DynamicChestShop fork https://pastebin.com/hQihjQ3b).
  12. 1.1.0 Added colors for the categories.
  13. 1.2.0 Changed currency to CLKeys
  14. 1.2.1 Issue fixed with non-stackeable items.
  15. 1.2.2 Bigger buy and qty buttons and change of color for buttons.
  16. 1.2.3 Remove function fixed.
  17. --]]
  18. os.pullEvent = os.pullEventRaw
  19. --------------------------------------
  20. --> APIs <--
  21. --------------------------------------
  22. os.loadAPI("gcapi")
  23. os.loadAPI("configAPI")
  24. os.loadAPI("tableAPI")
  25. os.loadAPI("windowAPI")
  26. --------------------------------------
  27. --> Config <--
  28. --------------------------------------
  29. local config = configAPI.open("config.cfg")
  30.  
  31. local mon = config:checkPeripheral("monitor", "Please enter the monitor name (enter 'search' for automatic detection): ", "monitor")
  32. local me = config:checkPeripheral("me_system", "Please enter the me cable name (enter 'search' for automatic detection): ", "appeng_me_tilecolorlesscable")
  33. local noteblock = config:checkPeripheral("noteblock", "Please enter noteblock name (enter 'search' for automatic detection): ", "music")
  34. local pim = config:checkPeripheral("pim", "Please enter pim name (enter 'search' for automatic detection): ", "pim")
  35. --------------------------------------
  36. --> CL KEYS <--
  37. --------------------------------------
  38. os.loadAPI("keySystem")
  39. keySystem.setup(pim, me)
  40. --------------------------------------
  41. --> Listed Items <--
  42. --------------------------------------
  43. local items_file = configAPI.open("items.list")
  44.  
  45. function checkMaxSizeItems()
  46. local items = items_file:get("items")
  47. for i, item in pairs(items) do
  48. if not item.max_size then
  49. local me_item = getItemFromME(item)
  50. if me_item then
  51. items[i].max_size = me_item.maxSize
  52. else
  53. print("Item " .. item.id .. ":" .. (item.dmg or 0) .. " not found in the me_system!")
  54. sleep(2)
  55. end
  56. end
  57. end
  58. items_file:put("items", items)
  59. end
  60.  
  61. function getItemFromME(item)
  62. local inventory = me.getAvailableItems()
  63. for k,v in pairs(inventory) do
  64. if v.id == tonumber(item.id) and v.dmg == (tonumber(item.dmg) or 0) then
  65. return inventory[k]
  66. end
  67. end
  68. return nil
  69. end
  70.  
  71. checkMaxSizeItems()
  72. --------------------------------------
  73. --> Table Instance <--
  74. --------------------------------------
  75. local category_colors = {}
  76. local tableInstance = tableAPI.new(mon, (items_file:get("items") or {}), {"name", "qty", "price", "category"})
  77. tableInstance.custom_colors_func.category = function(mon, txt)
  78. local color = category_colors[txt]
  79. if not color then
  80. local i = 0
  81. for k,v in pairs(category_colors) do i = i + 1 end
  82. color = 2^(i + 1)
  83. category_colors[txt] = color
  84. mon.setTextColor(color)
  85. else
  86. mon.setTextColor(color)
  87. end
  88. end
  89.  
  90. table.sort(tableInstance.data, function(a,b)
  91. if a.category == b.category then
  92. return a.name < b.name
  93. end
  94. return a.category < b.category
  95. end)
  96. tableInstance:draw()
  97.  
  98.  
  99.  
  100. --------------------------------------
  101. --> Sound Monitor <--
  102. --------------------------------------
  103. tableInstance.playSound = function(self)
  104. noteblock.playSound("random.wood_click",1,1)
  105. end
  106. --------------------------------------
  107. --> Item delivery <--
  108. --------------------------------------
  109. function getStock(item)
  110. local id = tonumber(item.id)
  111. local dmg = tonumber(item.dmg) or 0
  112. local stock = me.countOfItemType(id, dmg)
  113. return stock or 0
  114. end
  115.  
  116. function sendItems(item)
  117. local queue_qty = item.qty
  118. for r=1, math.floor(queue_qty/(item.max_size or 64))+1 do
  119. local move_qty = item.max_size or 64
  120. if queue_qty < move_qty then move_qty = queue_qty end
  121. queue_qty = queue_qty - me.extractItem({["id"] = tonumber(item.id), ["dmg"] = tonumber(item.dmg), ["qty"] = move_qty}, "up")
  122. end
  123. if delivered_qty == item.qty then
  124. return true
  125. end
  126. return false, delivered_qty
  127. end
  128. --------------------------------------
  129. --> Transaction Window <--
  130. --------------------------------------
  131. --[[
  132. --------------Close-
  133. - Name: item_name -
  134. - ID: id -
  135. - Qty: << < 1 > >> -
  136. - Price: $xxx -
  137. - Category: xxx -
  138. - -
  139. -Back-----------BUY-
  140. ]]--
  141.  
  142. local TransactionWindow = {
  143.  
  144. draw = function(self)
  145. self:clearButtonsMap()
  146.  
  147. local mon = self.mon
  148. local max_x, max_y = mon.getSize()
  149.  
  150. local item = self.item
  151.  
  152. local width = ( ( 40 > ( 6 + string.len(item.name) ) ) and 40 ) or ( 6 + string.len(item.name) )
  153.  
  154. local xi = gcapi.getCenter(max_x, width)
  155. local yi = gcapi.getCenter(max_y, 8)
  156.  
  157. self.window = windowAPI.newWindow(mon, xi, yi, width, 8)
  158. local window = self.window
  159.  
  160. window:setBackgroundColor(colors.white)
  161. window:clear()
  162.  
  163.  
  164. --** Borders
  165. window:setBackgroundColor(colors.cyan)
  166. for y=1, 8 do
  167. if y == 1 or y == 8 then
  168. window:setCursorPos(1,y)
  169. for x=1, width do
  170. window:write(" ")
  171. end
  172. end
  173. end
  174.  
  175. for y=1, 8 do
  176. window:setCursorPos(width,y)
  177. window:write(" ")
  178. end
  179.  
  180. for y=1, 8 do
  181. window:setCursorPos(1,y)
  182. window:write(" ")
  183. end
  184.  
  185. --**Close button
  186. self:newButton(" X ", width-3,1,1,1, function() return true end)
  187.  
  188. window:setBackgroundColor(colors.white)
  189. --**Item data
  190. window:setCursorPos(2,2)
  191. window:write("Name: " .. item.name)
  192. window:setCursorPos(2,3)
  193. window:write("ID: " .. item.id) if item.dmg then window:write(":" .. item.dmg) end
  194. window:setCursorPos(2,4)
  195. window:write("Qty: " .. item.qty .. " ")
  196.  
  197. --** << < Arrows > >>
  198. local cx, cy = window:getCursorPos()
  199. self:newButton(" < ", cx, cy, 3, 1, function() self:updateItemQty(-1) end)
  200. self:newButton(" > ", cx+4, cy, 3, 1, function() self:updateItemQty(1) end)
  201.  
  202. window:setBackgroundColor(colors.white)
  203. window:setCursorPos(2,5)
  204. window:write("Price: " .. keySystem.priceToKeys(item.price) .. " keys" .. " (Virtual price: " .. math.floor(item.price*10)/1000 .. ")")
  205. window:setCursorPos(2,6)
  206. window:write("Category: " .. item.category)
  207.  
  208. --** Back and Buy
  209. self:newButton("Back", 2,8,4,1, function() return true end)
  210. self:newButton(" Buy ", width-5,8,5,1, function()
  211. local stock = getStock(item)
  212. if stock < item.qty then
  213. self:displayMessage("There is no stock for this item", nil, colors.red)
  214. sleep(2)
  215. self:draw()
  216. return false
  217. end
  218.  
  219. local transaction_status, err = keySystem.withdraw(self.item.price, "Bought " .. item.id .. ":" .. (item.dmg or 0))
  220. if transaction_status then
  221. local text = "Thanks for your purchase!"
  222. self:displayMessage(text, nil, colors.lime)
  223. sendItems(item)
  224. sleep(2)
  225. return true
  226. else
  227. self:displayMessage(err, nil, colors.red)
  228. sleep(2)
  229. self:draw()
  230. return false
  231. end
  232. end)
  233.  
  234. end,
  235.  
  236. displayMessage = function(self, text, background_color, text_color)
  237. local background_color = background_color or colors.lightGray
  238. local text_color = text_color or colors.black
  239. local window = self.window
  240. local text = " " .. text .. " "
  241.  
  242. window:setBackgroundColor(background_color)
  243. window:setTextColor(text_color)
  244. window:setCursorPos(gcapi.getCenter(window.width+1, text), gcapi.getCenter(window.heigth+1))
  245. window:write(text)
  246. window:setTextColor(colors.black)
  247. end,
  248.  
  249. updateItemQty = function (self, diff)
  250. local item = self.item
  251. local org_qty = self.original_item["qty"]
  252. local new_qty = self.item["qty"] + org_qty*diff
  253. local stock = getStock(item)
  254. if new_qty > 0 and new_qty < 999 and stock >= new_qty then
  255. local pc = new_qty/self.item["qty"]
  256. item.price = item.price*pc
  257. item.qty = new_qty
  258. end
  259. self:draw()
  260. end,
  261. buttonListener = function (self)
  262. while true do
  263. local tEvent = {os.pullEvent()}
  264. if not self.window then
  265. return false
  266. end
  267. if tEvent[1] == "monitor_touch" then
  268. local x = tEvent[3]
  269. local y = tEvent[4]
  270.  
  271. local ix = self.window.init_x + 1
  272. local iy = self.window.init_y + 1
  273.  
  274. --if clic on the window
  275. if gcapi.numberBetween(x, ix, self.window.width+ix) and gcapi.numberBetween(y, iy, self.window.heigth+iy) then
  276. local buttonFunc = self.buttons_map[x][y]
  277. if buttonFunc then
  278. if buttonFunc() then
  279. return true
  280. end
  281. end
  282. else
  283. return false
  284. end
  285. end
  286. end
  287. end,
  288.  
  289. newButton = function(self, text, xi, yi, width, heigth, func)
  290. local drawButton = function(color)
  291. self.window:setBackgroundColor(color)
  292. local x_string = ""
  293. for x=xi, width+xi-1 do
  294. x_string = x_string .. " "
  295. end
  296. for y=yi, heigth+yi-1 do
  297. self.window:setCursorPos(xi, y)
  298. self.window:write(x_string)
  299. end
  300. self.window:setCursorPos(xi + gcapi.getCenter(width, text), yi + gcapi.getCenter(heigth))
  301. self.window:write(text)
  302. end
  303. drawButton(colors.cyan)
  304. for x=xi, width+xi-1 do
  305. for y=yi, heigth+yi-1 do
  306. self.buttons_map[x+self.window.init_x][y+self.window.init_y] = function()
  307. drawButton(colors.orange)
  308. sleep(0.15)
  309. drawButton(colors.cyan)
  310. if func then
  311. return func()
  312. end
  313. end
  314. end
  315. end
  316. end,
  317.  
  318. clearButtonsMap = function(self)
  319. local max_x, max_y = self.mon.getSize()
  320. for x=1, max_x do
  321. self.buttons_map[x] = {}
  322. end
  323. end,
  324. }
  325.  
  326. function createTransactionWindow(row_data)
  327. local max_x, max_y = mon.getSize()
  328.  
  329. local transactionWindow = {
  330. item = gcapi.deepCopy(row_data),
  331. original_item = row_data,
  332. buttons_map = {}
  333. }
  334. transactionWindow.mon = mon
  335. for x=1, max_x do
  336. transactionWindow.buttons_map[x] = {}
  337. end
  338. setmetatable(transactionWindow, {__index = TransactionWindow})
  339. return transactionWindow
  340. end
  341.  
  342.  
  343.  
  344. --------------------------------------
  345. --> Monitor <--
  346. --------------------------------------
  347. function printTable(new_data)
  348. tableInstance.data = new_data
  349. tableInstance:draw()
  350. end
  351.  
  352. function monitorListener()
  353. while true do
  354. local tEvent = {os.pullEvent()}
  355. local row_data, y = tableInstance:getRowOnEvent(tEvent)
  356. if row_data then
  357. tableInstance:highlight("name", row_data.name, true)
  358. tableInstance:draw()
  359.  
  360. local transactionWindow = createTransactionWindow(row_data)
  361. transactionWindow:draw()
  362. transactionWindow:buttonListener()
  363.  
  364. tableInstance:clearHighlights()
  365. tableInstance:draw()
  366. end
  367. end
  368. end
  369. --------------------------------------
  370. --> Terminal <--
  371. --------------------------------------
  372. function commandListener()
  373. textutils.slowPrint(".......", 6)
  374. while true do
  375.  
  376. verifyPassword("pass")
  377.  
  378. term.clear()
  379. term.setCursorPos(1,1)
  380. term.write("Available commands: ")
  381. term.setCursorPos(1,2)
  382. term.write("1. add <name> <id> <amount> <price> <category>")
  383. term.setCursorPos(1,3)
  384. term.write("2. remove <id>")
  385.  
  386. term.setCursorPos(1,5)
  387. term.write("Enter command: ")
  388. local input = read()
  389.  
  390. tInput = gcapi.split(input .. " ", " ")
  391.  
  392.  
  393. if tInput[1] == "add" then
  394. local name = tInput[2]
  395. local id = tInput[3]
  396. local qty = tonumber(tInput[4])
  397. local price = tonumber(tInput[5])
  398. local category = tInput[6]
  399.  
  400. if id and qty and price and category then
  401. local items = items_file:get("items") or {}
  402. local s = gcapi.split(id, ":")
  403. table.insert(items, {["id"] = s[1], ["dmg"] = s[2], ["name"] = name, ["price"] = price, ["qty"] = qty, ["category"] = category})
  404. printTable(items)
  405. items_file:put("items", items)
  406. print("Item " .. name .. " added!")
  407. else
  408. print("Wrong parameters!")
  409. end
  410. end
  411.  
  412. if tInput[1] == "remove" then
  413. local id0 = tInput[2]
  414. if id0 then
  415. local s = gcapi.split(id0, ":")
  416. local id = s[1]
  417. local dmg = s[2]
  418. local items = items_file:get("items") or {}
  419. local new_items = {}
  420. local was_deleted = false
  421. for _,row_data in pairs(items) do
  422. if row_data.id ~= id or row_data.dmg ~= dmg then
  423. table.insert(new_items, row_data)
  424. else
  425. was_deleted = true
  426. end
  427. end
  428. if was_deleted then
  429. printTable(new_items)
  430. items_file:put("items", new_items)
  431. print("Item (ID: " .. id ..") deleted!")
  432. else
  433. print("Item (ID: " .. id ..") not found!")
  434. end
  435. end
  436. end
  437.  
  438. if tInput[1] == "terminate" then
  439. return true
  440. end
  441. textutils.slowPrint("....", 4)
  442. end
  443. end
  444.  
  445. function verifyPassword(pass)
  446. while true do
  447. term.clear()
  448. term.setCursorPos(1,1)
  449. term.write("Password: ")
  450. local input = read("*")
  451. if input == pass then
  452. return true
  453. else
  454. term.setCursorPos(1,2)
  455. term.write("Incorrect password!")
  456. end
  457. end
  458. end
  459.  
  460. parallel.waitForAny(commandListener, monitorListener)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement