Advertisement
codingbutter

P2P Beta

Jan 26th, 2022
58
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.31 KB | None | 0 0
  1. local class = (function()
  2. local class = function(classDef, parentClass)
  3. -- So we dont forget that these two methods will get overwritten
  4. if classDef.super or classDef.new then
  5. error("super and new can not exist within class defenitions", 2)
  6. end
  7. -- We need access to the parent classes methods methods
  8. if parentClass then
  9. setmetatable(classDef, {
  10. __index = parentClass
  11. })
  12. -- Allow access to uneffected parent class methods
  13. classDef.super = parentClass
  14. end
  15. -- Need to create Individual Class instances
  16. function classDef:new(...)
  17. local new = {}
  18. setmetatable(new, {
  19. __index = self
  20. })
  21. -- When a class has a constructor it must be called when creating an instance
  22. if new.constructor then
  23. new:constructor(...)
  24. end
  25. return new
  26. end
  27. -- Expose the modified class definition which includes :new and .super
  28. return classDef
  29. end
  30. return class
  31.  
  32. end)()
  33. local json = (function()
  34. --
  35. -- json.lua
  36. --
  37. -- Copyright (c) 2020 rxi
  38. --
  39. -- Permission is hereby granted, free of charge, to any person obtaining a copy of
  40. -- this software and associated documentation files (the "Software"), to deal in
  41. -- the Software without restriction, including without limitation the rights to
  42. -- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
  43. -- of the Software, and to permit persons to whom the Software is furnished to do
  44. -- so, subject to the following conditions:
  45. --
  46. -- The above copyright notice and this permission notice shall be included in all
  47. -- copies or substantial portions of the Software.
  48. --
  49. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  50. -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  51. -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  52. -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  53. -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  54. -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  55. -- SOFTWARE.
  56. --
  57. local json = {
  58. _version = "0.1.2"
  59. }
  60.  
  61. -------------------------------------------------------------------------------
  62. -- Encode
  63. -------------------------------------------------------------------------------
  64.  
  65. local encode
  66.  
  67. local escape_char_map = {
  68. ["\\"] = "\\",
  69. ["\""] = "\"",
  70. ["\b"] = "b",
  71. ["\f"] = "f",
  72. ["\n"] = "n",
  73. ["\r"] = "r",
  74. ["\t"] = "t"
  75. }
  76.  
  77. local escape_char_map_inv = {
  78. ["/"] = "/"
  79. }
  80. for k, v in pairs(escape_char_map) do
  81. escape_char_map_inv[v] = k
  82. end
  83.  
  84. local function escape_char(c)
  85. return "\\" .. (escape_char_map[c] or string.format("u%04x", c:byte()))
  86. end
  87.  
  88. local function encode_nil(val)
  89. return "null"
  90. end
  91.  
  92. local function encode_table(val, stack)
  93. local res = {}
  94. stack = stack or {}
  95.  
  96. -- Circular reference?
  97. if stack[val] then
  98. error("circular reference")
  99. end
  100.  
  101. stack[val] = true
  102.  
  103. if rawget(val, 1) ~= nil or next(val) == nil then
  104. -- Treat as array -- check keys are valid and it is not sparse
  105. local n = 0
  106. for k in pairs(val) do
  107. if type(k) ~= "number" then
  108. error("invalid table: mixed or invalid key types")
  109. end
  110. n = n + 1
  111. end
  112. if n ~= #val then
  113. error("invalid table: sparse array")
  114. end
  115. -- Encode
  116. for i, v in ipairs(val) do
  117. table.insert(res, encode(v, stack))
  118. end
  119. stack[val] = nil
  120. return "[" .. table.concat(res, ",") .. "]"
  121.  
  122. else
  123. -- Treat as an object
  124. for k, v in pairs(val) do
  125. if type(k) ~= "string" then
  126. error("invalid table: mixed or invalid key types")
  127. end
  128. table.insert(res, encode(k, stack) .. ":" .. encode(v, stack))
  129. end
  130. stack[val] = nil
  131. return "{" .. table.concat(res, ",") .. "}"
  132. end
  133. end
  134.  
  135. local function encode_string(val)
  136. return '"' .. val:gsub('[%z\1-\31\\"]', escape_char) .. '"'
  137. end
  138.  
  139. local function encode_number(val)
  140. -- Check for NaN, -inf and inf
  141. if val ~= val or val <= -math.huge or val >= math.huge then
  142. error("unexpected number value '" .. tostring(val) .. "'")
  143. end
  144. return string.format("%.14g", val)
  145. end
  146.  
  147. local type_func_map = {
  148. ["nil"] = encode_nil,
  149. ["table"] = encode_table,
  150. ["string"] = encode_string,
  151. ["number"] = encode_number,
  152. ["boolean"] = tostring
  153. }
  154.  
  155. encode = function(val, stack)
  156. local t = type(val)
  157. local f = type_func_map[t]
  158. if f then
  159. return f(val, stack)
  160. end
  161. error("unexpected type '" .. t .. "'")
  162. end
  163.  
  164. function json.encode(val)
  165. return (encode(val))
  166. end
  167.  
  168. -------------------------------------------------------------------------------
  169. -- Decode
  170. -------------------------------------------------------------------------------
  171.  
  172. local parse
  173.  
  174. local function create_set(...)
  175. local res = {}
  176. for i = 1, select("#", ...) do
  177. res[select(i, ...)] = true
  178. end
  179. return res
  180. end
  181.  
  182. local space_chars = create_set(" ", "\t", "\r", "\n")
  183. local delim_chars = create_set(" ", "\t", "\r", "\n", "]", "}", ",")
  184. local escape_chars = create_set("\\", "/", '"', "b", "f", "n", "r", "t", "u")
  185. local literals = create_set("true", "false", "null")
  186.  
  187. local literal_map = {
  188. ["true"] = true,
  189. ["false"] = false,
  190. ["null"] = nil
  191. }
  192.  
  193. local function next_char(str, idx, set, negate)
  194. for i = idx, #str do
  195. if set[str:sub(i, i)] ~= negate then
  196. return i
  197. end
  198. end
  199. return #str + 1
  200. end
  201.  
  202. local function decode_error(str, idx, msg)
  203. local line_count = 1
  204. local col_count = 1
  205. for i = 1, idx - 1 do
  206. col_count = col_count + 1
  207. if str:sub(i, i) == "\n" then
  208. line_count = line_count + 1
  209. col_count = 1
  210. end
  211. end
  212. error(string.format("%s at line %d col %d", msg, line_count, col_count))
  213. end
  214.  
  215. local function codepoint_to_utf8(n)
  216. -- http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=iws-appendixa
  217. local f = math.floor
  218. if n <= 0x7f then
  219. return string.char(n)
  220. elseif n <= 0x7ff then
  221. return string.char(f(n / 64) + 192, n % 64 + 128)
  222. elseif n <= 0xffff then
  223. return string.char(f(n / 4096) + 224, f(n % 4096 / 64) + 128, n % 64 + 128)
  224. elseif n <= 0x10ffff then
  225. return string.char(f(n / 262144) + 240, f(n % 262144 / 4096) + 128, f(n % 4096 / 64) + 128, n % 64 + 128)
  226. end
  227. error(string.format("invalid unicode codepoint '%x'", n))
  228. end
  229.  
  230. local function parse_unicode_escape(s)
  231. local n1 = tonumber(s:sub(1, 4), 16)
  232. local n2 = tonumber(s:sub(7, 10), 16)
  233. -- Surrogate pair?
  234. if n2 then
  235. return codepoint_to_utf8((n1 - 0xd800) * 0x400 + (n2 - 0xdc00) + 0x10000)
  236. else
  237. return codepoint_to_utf8(n1)
  238. end
  239. end
  240.  
  241. local function parse_string(str, i)
  242. local res = ""
  243. local j = i + 1
  244. local k = j
  245.  
  246. while j <= #str do
  247. local x = str:byte(j)
  248.  
  249. if x < 32 then
  250. decode_error(str, j, "control character in string")
  251.  
  252. elseif x == 92 then -- `\`: Escape
  253. res = res .. str:sub(k, j - 1)
  254. j = j + 1
  255. local c = str:sub(j, j)
  256. if c == "u" then
  257. local hex = str:match("^[dD][89aAbB]%x%x\\u%x%x%x%x", j + 1) or str:match("^%x%x%x%x", j + 1) or
  258. decode_error(str, j - 1, "invalid unicode escape in string")
  259. res = res .. parse_unicode_escape(hex)
  260. j = j + #hex
  261. else
  262. if not escape_chars[c] then
  263. decode_error(str, j - 1, "invalid escape char '" .. c .. "' in string")
  264. end
  265. res = res .. escape_char_map_inv[c]
  266. end
  267. k = j + 1
  268.  
  269. elseif x == 34 then -- `"`: End of string
  270. res = res .. str:sub(k, j - 1)
  271. return res, j + 1
  272. end
  273.  
  274. j = j + 1
  275. end
  276.  
  277. decode_error(str, i, "expected closing quote for string")
  278. end
  279.  
  280. local function parse_number(str, i)
  281. local x = next_char(str, i, delim_chars)
  282. local s = str:sub(i, x - 1)
  283. local n = tonumber(s)
  284. if not n then
  285. decode_error(str, i, "invalid number '" .. s .. "'")
  286. end
  287. return n, x
  288. end
  289.  
  290. local function parse_literal(str, i)
  291. local x = next_char(str, i, delim_chars)
  292. local word = str:sub(i, x - 1)
  293. if not literals[word] then
  294. decode_error(str, i, "invalid literal '" .. word .. "'")
  295. end
  296. return literal_map[word], x
  297. end
  298.  
  299. local function parse_array(str, i)
  300. local res = {}
  301. local n = 1
  302. i = i + 1
  303. while 1 do
  304. local x
  305. i = next_char(str, i, space_chars, true)
  306. -- Empty / end of array?
  307. if str:sub(i, i) == "]" then
  308. i = i + 1
  309. break
  310. end
  311. -- Read token
  312. x, i = parse(str, i)
  313. res[n] = x
  314. n = n + 1
  315. -- Next token
  316. i = next_char(str, i, space_chars, true)
  317. local chr = str:sub(i, i)
  318. i = i + 1
  319. if chr == "]" then
  320. break
  321. end
  322. if chr ~= "," then
  323. decode_error(str, i, "expected ']' or ','")
  324. end
  325. end
  326. return res, i
  327. end
  328.  
  329. local function parse_object(str, i)
  330. local res = {}
  331. i = i + 1
  332. while 1 do
  333. local key, val
  334. i = next_char(str, i, space_chars, true)
  335. -- Empty / end of object?
  336. if str:sub(i, i) == "}" then
  337. i = i + 1
  338. break
  339. end
  340. -- Read key
  341. if str:sub(i, i) ~= '"' then
  342. decode_error(str, i, "expected string for key")
  343. end
  344. key, i = parse(str, i)
  345. -- Read ':' delimiter
  346. i = next_char(str, i, space_chars, true)
  347. if str:sub(i, i) ~= ":" then
  348. decode_error(str, i, "expected ':' after key")
  349. end
  350. i = next_char(str, i + 1, space_chars, true)
  351. -- Read value
  352. val, i = parse(str, i)
  353. -- Set
  354. res[key] = val
  355. -- Next token
  356. i = next_char(str, i, space_chars, true)
  357. local chr = str:sub(i, i)
  358. i = i + 1
  359. if chr == "}" then
  360. break
  361. end
  362. if chr ~= "," then
  363. decode_error(str, i, "expected '}' or ','")
  364. end
  365. end
  366. return res, i
  367. end
  368.  
  369. local char_func_map = {
  370. ['"'] = parse_string,
  371. ["0"] = parse_number,
  372. ["1"] = parse_number,
  373. ["2"] = parse_number,
  374. ["3"] = parse_number,
  375. ["4"] = parse_number,
  376. ["5"] = parse_number,
  377. ["6"] = parse_number,
  378. ["7"] = parse_number,
  379. ["8"] = parse_number,
  380. ["9"] = parse_number,
  381. ["-"] = parse_number,
  382. ["t"] = parse_literal,
  383. ["f"] = parse_literal,
  384. ["n"] = parse_literal,
  385. ["["] = parse_array,
  386. ["{"] = parse_object
  387. }
  388.  
  389. parse = function(str, idx)
  390. local chr = str:sub(idx, idx)
  391. local f = char_func_map[chr]
  392. if f then
  393. return f(str, idx)
  394. end
  395. decode_error(str, idx, "unexpected character '" .. chr .. "'")
  396. end
  397.  
  398. function json.decode(str)
  399. if type(str) ~= "string" then
  400. error("expected argument of type string, got " .. type(str))
  401. end
  402. local res, idx = parse(str, next_char(str, 1, space_chars, true))
  403. idx = next_char(str, idx, space_chars, true)
  404. if idx <= #str then
  405. decode_error(str, idx, "trailing garbage")
  406. end
  407. return res
  408. end
  409.  
  410. return json
  411. end)()
  412.  
  413. local PEER_LOBBY = "http://beastcraft.codingbutter.com:8888/"
  414. local WS_SERVER = "ws://beastcraft.codingbutter.com:3028"
  415. local P2P = class({
  416. dispatch = {
  417. connected = function()
  418. end
  419. },
  420. constructor = function(self, computerusername)
  421. self.username = computerusername or os.getComputerID()
  422. self.peers = {}
  423. self.ws, self.err = http.websocket(WS_SERVER)
  424. if self.ws then
  425. self.connected = true
  426. end
  427. end,
  428. attachEventLoop = function(self, eventLoop)
  429. parallel.waitForAll(function()
  430. while self.connected do
  431. local msg = self.ws.receive()
  432. self:parseMessage(msg)
  433. end
  434. end, function()
  435. local timeId = os.startTimer(60)
  436. while self.connected == true do
  437. local timer = os.pullEvent("timer")
  438. if timer[2] == timeId and self.id and self.lobby and self.room then
  439. self:joinRoom(self.lobby, self.room, self.password)
  440. timeId = os.startTimer(60)
  441. end
  442. end
  443. end, eventLoop)
  444. end,
  445. captureRecieved = function(self)
  446.  
  447. end,
  448. parseMessage = function(self, msg)
  449. local event = json.decode(msg)
  450. local eventMsg = event.event
  451. local payload = event.payload
  452. if eventMsg == "peerId" then
  453. self.id = payload
  454. self:joinRoom()
  455. self:send("peer_added", {
  456. message = "Hello"
  457. }, self.peers)
  458. self.dispatch["connected"]()
  459. else
  460. if eventMsg == "peer_added" then
  461. self:joinRoom()
  462. end
  463. local peer = event.peer
  464. if self.dispatch[eventMsg] then
  465. self.dispatch[eventMsg](payload, peer)
  466. end
  467. end
  468. end,
  469. send = function(self, event, payload, peerIds)
  470. local peers = peerIds or self.peers
  471. if type(peers) ~= "table" then
  472. peers = {peerIds}
  473. end
  474. self.ws.send(json.encode({
  475. event = event,
  476. peer = {
  477. peerid = self.id,
  478. username = self.username
  479. },
  480. payload = payload,
  481. peers = peers
  482. }))
  483. end,
  484. on = function(self, eventusername, func)
  485. self.dispatch[eventusername] = func
  486. end,
  487. getPeers = function(self)
  488. return self.peers
  489. end,
  490. getRooms = function(lobby)
  491. local request = http.get(PEER_LOBBY .. lobby)
  492. return json.decode(request.readAll())
  493. end,
  494. joinRoom = function(self)
  495. local requestUrl = PEER_LOBBY .. self.lobby .. "/" .. self.room .. "/" .. self.id .. "/" .. self.username
  496. if password then
  497. requestUrl = requestUrl .. "?password=" .. password
  498. end
  499. local response = json.decode(http.get(requestUrl).readAll())
  500.  
  501. self.peers = response.error and {} or response
  502.  
  503. end,
  504. connect = function(self, lobby, room, password)
  505. self.lobby = lobby
  506. self.room = room
  507. self.password = password
  508. self:send("connect", {
  509. username = self.username
  510. })
  511.  
  512. end,
  513. close = function(self)
  514. self.connected = false
  515. self.ws.close()
  516. end
  517. })
  518. return P2P
  519.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement