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) |