SHOW:
|
|
- or go back to the newest paste.
| 1 | - | -- Minified CRC32 blob - MIT license - from here: https://raw.githubusercontent.com/davidm/lua-digest-crc32lua/master/lmod/digest/crc32lua.lua |
| 1 | + | -- converts a value between 0 and 127 to bits, least significant bits first |
| 2 | - | do |
| 2 | + | local function to_bits(charbyte) |
| 3 | - | local type=type;local require=require;local setmetatable=setmetatable;local a=bit.bxor;local b=bit.bnot;local c=bit.band;local d=bit.brshift;local e=0xEDB88320;local function f(g)local h={}local i=setmetatable({},h)function h:__index(j)local k=g(j)i[j]=k;return k end;return i end;local l=f(function(m)local n=m;for o=1,8 do local p=c(n,1)n=d(n,1)if p==1 then n=a(n,e)end end;return n end)local function q(r,n)n=b(n or 0)local s=d(n,8)local t=l[a(n%256,r)]return b(a(s,t))end;local function u(v,n)n=n or 0;for m=1,#v do n=q(v:byte(m),n)end;return n end;function crc32(v,n)if type(v)=='string'then return u(v,n)else return q(v,n)end end
|
| 3 | + | if charbyte > 127 then error "invalid character" end |
| 4 | local out = {}
| |
| 5 | for i = 0, 6 do | |
| 6 | - | local function get_byte(num, byte) |
| 6 | + | local bitmask = bit.blshift(1, i) |
| 7 | - | return bit.band(bit.brshift(num, byte * 8), 0xFF) |
| 7 | + | local bit = bit.brshift(bit.band(bitmask, charbyte), i) |
| 8 | table.insert(out, bit) | |
| 9 | end | |
| 10 | - | local function from_bytes(b) |
| 10 | + | return out |
| 11 | - | local n = 0 |
| 11 | + | |
| 12 | - | for ix, byte in pairs(b) do |
| 12 | + | |
| 13 | - | n = bit.bor(n, bit.blshift(byte, (ix - 1) * 8)) |
| 13 | + | local function from_bits(bit_table) |
| 14 | local int = 0 | |
| 15 | - | return n |
| 15 | + | for i = 0, 6 do |
| 16 | local index = i + 1 -- Lua... | |
| 17 | int = bit.bor(int, bit.blshift(bit_table[index], i)) | |
| 18 | - | local side = settings.get "bundlenet.side" or "back" |
| 18 | + | |
| 19 | return int | |
| 20 | - | local function send_raw(str) |
| 20 | + | |
| 21 | - | local i = 1 |
| 21 | + | |
| 22 | - | for i = 1, math.ceil(#str / 2) do |
| 22 | + | local rx_side = settings.get "rx_side" or "right" |
| 23 | - | local first = str:byte(i * 2 - 1) |
| 23 | + | local tx_side = settings.get "tx_side" or "left" |
| 24 | - | local second = str:byte(i * 2) or 0 |
| 24 | + | |
| 25 | - | local u16 = first * 256 + second |
| 25 | + | local function send(str) |
| 26 | - | rs.setBundledOutput(side, u16) |
| 26 | + | str = "\127" .. str |
| 27 | - | sleep(0.1) |
| 27 | + | for i = 1, #str do |
| 28 | local byte = str:byte(i) | |
| 29 | - | rs.setBundledOutput(side, 0) |
| 29 | + | for _, bit in ipairs(to_bits(byte)) do |
| 30 | rs.setOutput(tx_side, bit == 1) | |
| 31 | sleep(0.1) | |
| 32 | - | local function receive_raw(length) |
| 32 | + | |
| 33 | end | |
| 34 | - | local count = 0 |
| 34 | + | rs.setOutput(tx_side, false) |
| 35 | - | os.pullEvent "redstone" |
| 35 | + | |
| 36 | ||
| 37 | - | local u16 = rs.getBundledInput(side) |
| 37 | + | local function receive(char_callback) |
| 38 | - | local first = string.char(math.floor(u16 / 256)) |
| 38 | + | |
| 39 | - | if not length and first == "\0" then break |
| 39 | + | repeat |
| 40 | - | else |
| 40 | + | os.pullEvent "redstone" |
| 41 | - | count = count + 1 |
| 41 | + | until rs.getInput(rx_side) |
| 42 | - | str = str .. first |
| 42 | + | |
| 43 | - | if count == length then break end |
| 43 | + | local bits = {}
|
| 44 | - | local second = string.char(u16 % 256) |
| 44 | + | for i = 0, 6 do |
| 45 | - | if not length and second == "\0" then break |
| 45 | + | if rs.getInput(rx_side) then |
| 46 | table.insert(bits, 1) | |
| 47 | - | count = count + 1 |
| 47 | + | |
| 48 | - | str = str .. second |
| 48 | + | table.insert(bits, 0) |
| 49 | - | if count == length then break end |
| 49 | + | |
| 50 | sleep(0.1) | |
| 51 | end | |
| 52 | - | sleep(0.1) |
| 52 | + | local char = string.char(from_bits(bits)) |
| 53 | if char == "\0" then break end | |
| 54 | - | return str |
| 54 | + | if char ~= "\127" and char_callback then char_callback(char) end |
| 55 | str = str .. char | |
| 56 | end | |
| 57 | - | local function u32_to_string(u32) |
| 57 | + | return str:sub(2) |
| 58 | - | return string.char(get_byte(u32, 0), get_byte(u32, 1), get_byte(u32, 2), get_byte(u32, 3)) |
| 58 | + | |
| 59 | ||
| 60 | local w, h = term.getSize() | |
| 61 | - | local function string_to_u32(str) |
| 61 | + | local send_window = window.create(term.current(), 1, h, w, 1) |
| 62 | - | return from_bytes{str:byte(1), str:byte(2), str:byte(3), str:byte(4)}
|
| 62 | + | local message_window = window.create(term.current(), 1, 1, w, h - 1) |
| 63 | ||
| 64 | local function exec_in_window(w, f) | |
| 65 | - | local function send(data) |
| 65 | + | local x, y = term.getCursorPos() |
| 66 | - | local length = u32_to_string(#data) |
| 66 | + | local last = term.redirect(w) |
| 67 | - | local checksum = u32_to_string(crc32(data)) |
| 67 | + | f() |
| 68 | - | print("len", length, "checksum", checksum)
|
| 68 | + | term.redirect(last) |
| 69 | - | send_raw(length) |
| 69 | + | w.redraw() |
| 70 | - | send_raw(checksum) |
| 70 | + | term.setCursorPos(x, y) |
| 71 | - | send_raw(data) |
| 71 | + | |
| 72 | ||
| 73 | local function write_char(txt) | |
| 74 | - | local function receive() |
| 74 | + | exec_in_window(message_window, function() |
| 75 | - | local length = receive_raw(4) |
| 75 | + | write(txt) |
| 76 | - | --sleep(0.1) |
| 76 | + | end) |
| 77 | - | local checksum = receive_raw(4) |
| 77 | + | |
| 78 | - | print("len", length, "checksum", checksum, "l", string_to_u32(length), "c", string_to_u32(checksum))
|
| 78 | + | |
| 79 | - | --sleep(0.1) |
| 79 | + | local function sender() |
| 80 | - | local data = receive_raw(string_to_u32(length)) |
| 80 | + | term.redirect(send_window) |
| 81 | - | if crc32(data) ~= string_to_u32(checksum) then return false, "checksum mismatch", data end |
| 81 | + | term.setBackgroundColor(colors.lightGray) |
| 82 | - | return true, data |
| 82 | + | term.setTextColor(colors.white) |
| 83 | term.clear() | |
| 84 | while true do | |
| 85 | - | local option = ... |
| 85 | + | local msg = read() |
| 86 | send(msg) | |
| 87 | - | if option == "send" then |
| 87 | + | |
| 88 | - | write "Send: " |
| 88 | + | |
| 89 | - | local text = read() |
| 89 | + | |
| 90 | - | send(text) |
| 90 | + | local function receiver() |
| 91 | - | elseif option == "raw_receive" then |
| 91 | + | |
| 92 | - | print(receive_raw()) |
| 92 | + | receive(write_char) |
| 93 | - | elseif option == "receive" then |
| 93 | + | write_char "\n" |
| 94 | - | print(receive()) |
| 94 | + | |
| 95 | end | |
| 96 | ||
| 97 | - | return { send = send, receive = receive } |
| 97 | + | parallel.waitForAll(sender, receiver) |