osmarks

Labelnet

Feb 28th, 2019 (edited)
205
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 4.65 KB | None | 0 0
  1. -- The below code looks magic and kind of ridiculous, yes. It exists for good reason.
  2. -- https://github.com/SquidDev-CC/CC-Tweaked/blob/1c9110b9277bd7a2bf0b2ddd9d517656a72da906/src/main/java/dan200/computercraft/shared/util/StringUtil.java#L11-L31 is the code restricting the contents of labels.
  3. -- Basically, they can contain chars (I think in Extended ASCII for some reason, and inclusive) 32 to 126, 161 to 172, and 174 to 255. This gives us 187 (EDIT: 189) options to work with, thus base 187 (189).
  4.  
  5. -- BaseN encoding/decoding blob
  6. -- https://github.com/oploadk/base2base for computercraft
  7.  
  8. local a=string.format;local function b(c,d,e)local f,g,h={}for i=1,#c do g,h=i,c[i]*d;while true do h=(f[g]or 0)+h;f[g]=h%e;h=math.floor(h/e)if h==0 then break end;g=g+1 end end;return f end;local function j(k,l,m,n)local g,h;for i=1,#m do g,h=i,l*(m[i]or 0)while true do h=(k[g]or 0)+h;k[g]=h%n;h=math.floor(h/n)if h==0 then break end;g=g+1 end end end;local function o(self,p)local f,q={},#p;for i=1,q do f[i]=self.r_alpha_from[p:byte(q-i+1)]end;return f end;local function r(self,h)local f,q={},#h;for i=q,1,-1 do f[q-i+1]=self.alpha_to:byte(h[i]+1)end;return string.char(table.unpack(f))end;local function s(self,l)return self.power[l]or b(s(self,l-1),self.base_from,self.base_to)end;local function t(self,h)local f={}for i=1,#h do j(f,h[i],s(self,i-1),self.base_to)end;return f end;local function u(self,p)return r(self,t(self,o(self,p)))end;local function v(self,p)for i=1,#p do if not self.r_alpha_from[p:byte(i)]then return false end end;return true end;local w={__index={convert=u,validate=v},__call=function(self,p)return self:convert(p)end}function new_converter(x,y)local self={alpha_to=y,base_from=#x,base_to=#y}local z={}for i=1,#x do z[x:byte(i)]=i-1 end;self.r_alpha_from=z;self.power={[0]={1}}return setmetatable(self,w)end
  9.  
  10. local function byte_table_to_string(bytes)
  11.     local str = ""
  12.     for _, x in ipairs(bytes) do
  13.         str = str .. string.char(x)
  14.     end
  15.     return str
  16. end
  17.  
  18. local function get_byte(num, byte)
  19.     return bit.band(bit.brshift(num, byte * 8), 0xFF)
  20. end
  21.  
  22. local function from_bytes(b)
  23.     local n = 0
  24.     for ix, byte in pairs(b) do
  25.         n = bit.bor(n, bit.blshift(byte, (ix - 1) * 8))
  26.     end
  27.     return n
  28. end
  29.  
  30. local ascii = {}
  31. for i = 0, 255 do table.insert(ascii, i) end
  32. local label_charset = {}
  33. for i = 32, 126 do table.insert(label_charset, i) end
  34. for i = 161, 172 do table.insert(label_charset, i) end
  35. for i = 174, 255 do table.insert(label_charset, i) end
  36. label_charset = byte_table_to_string(label_charset)
  37. ascii = byte_table_to_string(ascii)
  38.  
  39. local from_label = new_converter(label_charset, ascii)
  40. local to_label = new_converter(ascii, label_charset)
  41.  
  42. local states = {
  43.     IDLE = 0,
  44.     TRANSMITTING = 1,
  45.     RECEIVING = 2,
  46.     RECEIVE_ERROR = 3
  47. }
  48.  
  49. local function receive_data(side)
  50.     local out = {}
  51.     repeat sleep(0.05) until rs.getBundledInput(side) == states.TRANSMITTING
  52.     rs.setBundledOutput(side, states.RECEIVING)
  53.     local last
  54.     local xseq = 1
  55.     repeat
  56.         local label = peripheral.call(side, "getLabel")
  57.         if label then
  58.             local received = from_label(label)
  59.             if received ~= last then
  60.                 local seq, rest = received:byte(1), received:sub(2)
  61.                 if seq ~= xseq then
  62.                     print("expected", xseq, "got", seq)
  63.                 end
  64.                 last = received
  65.                 xseq = xseq + 1
  66.                 table.insert(out, rest)
  67.             end
  68.         end
  69.         sleep(0.05)
  70.     until rs.getBundledInput(side) ~= states.TRANSMITTING
  71.     rs.setBundledOutput(side, states.IDLE)
  72.     return table.concat(out)
  73. end
  74.  
  75. local function send_data(side, data)
  76.     local packets = {}
  77.     local packet_index = 1
  78.     local remaining, chunk = data
  79.     while true do
  80.         chunk, remaining = remaining:sub(1, 29), remaining:sub(30)
  81.         local header = string.char(get_byte(packet_index, 0))
  82.         table.insert(packets, header .. chunk)
  83.         packet_index = packet_index + 1
  84.         if #remaining == 0 then break end
  85.     end
  86.     local label = os.getComputerLabel()
  87.     rs.setBundledOutput(side, states.TRANSMITTING)
  88.     repeat sleep(0.05) until rs.getBundledInput(side) == states.RECEIVING
  89.     for _, packet in ipairs(packets) do
  90.         os.setComputerLabel(to_label(packet))
  91.         sleep(0.05)
  92.     end
  93.     rs.setBundledOutput(side, states.IDLE)
  94.     sleep(0.1)
  95.     os.setComputerLabel(label)
  96. end
  97.  
  98. local other
  99. for _, name in pairs(peripheral.getNames()) do
  100.     for _, method in pairs(peripheral.getMethods(name)) do
  101.         if method == "getLabel" then
  102.             other = name
  103.             break
  104.         end
  105.     end
  106. end
  107.  
  108. local option = ...
  109.  
  110. if option == "send" then
  111.     write "Send: "
  112.     local text = read()
  113.     send_data(other, text)
  114. elseif option == "receive" then
  115.     print(receive_data(other))
  116. end
  117.  
  118. return { to_label = to_label, from_label = from_label, send_data = send_data, receive_data = receive_data }
Add Comment
Please, Sign In to add comment