Rework GPU (#58)
This commit is contained in:
parent
c1e6c4c711
commit
4763cb9805
595
gpu.lua
595
gpu.lua
@ -1,9 +1,10 @@
|
||||
local font = dofile(minetest.get_modpath("digistuff")..DIR_DELIM.."gpu-font.lua")
|
||||
local font = dofile(minetest.get_modpath("digistuff") .. "/gpu-font.lua")
|
||||
local MAX_BUFFERS = 8
|
||||
|
||||
local function explodebits(input, count)
|
||||
local output = {}
|
||||
if not count then count = 8 end
|
||||
for i=0,count-1,1 do
|
||||
count = count or 8
|
||||
for i = 0, count - 1 do
|
||||
output[i] = input % (2^(i + 1)) >= 2^i
|
||||
end
|
||||
return output
|
||||
@ -11,8 +12,8 @@ end
|
||||
|
||||
local function implodebits(input, count)
|
||||
local output = 0
|
||||
if not count then count = 8 end
|
||||
for i=0,count-1,1 do
|
||||
count = count or 8
|
||||
for i = 0, count - 1 do
|
||||
output = output + (input[i] and 2^i or 0)
|
||||
end
|
||||
return output
|
||||
@ -20,13 +21,13 @@ end
|
||||
|
||||
local packtable = {}
|
||||
local unpacktable = {}
|
||||
for i=0,25,1 do
|
||||
for i = 0, 25 do
|
||||
packtable[i] = string.char(i + 65)
|
||||
packtable[i + 26] = string.char(i + 97)
|
||||
unpacktable[string.char(i + 65)] = i
|
||||
unpacktable[string.char(i + 97)] = i + 26
|
||||
end
|
||||
for i=0,9,1 do
|
||||
for i = 0, 9 do
|
||||
packtable[i + 52] = tostring(i)
|
||||
unpacktable[tostring(i)] = i + 52
|
||||
end
|
||||
@ -37,13 +38,16 @@ unpacktable["/"] = 63
|
||||
|
||||
local function packpixel(pixel)
|
||||
pixel = tonumber(pixel, 16)
|
||||
if not pixel then return "AAAA" end
|
||||
if not pixel then
|
||||
return "AAAA"
|
||||
end
|
||||
|
||||
local bits = explodebits(pixel, 24)
|
||||
local block1 = {}
|
||||
local block2 = {}
|
||||
local block3 = {}
|
||||
local block4 = {}
|
||||
for i=0,5,1 do
|
||||
for i = 0, 5 do
|
||||
block1[i] = bits[i]
|
||||
block2[i] = bits[i + 6]
|
||||
block3[i] = bits[i + 12]
|
||||
@ -137,7 +141,7 @@ local function bitwiseblend(srcr,dstr,srcg,dstg,srcb,dstb,mode)
|
||||
local drbits = explodebits(dstr)
|
||||
local dgbits = explodebits(dstg)
|
||||
local dbbits = explodebits(dstb)
|
||||
for i=0,7,1 do
|
||||
for i = 0, 7 do
|
||||
if mode == "and" then
|
||||
drbits[i] = srbits[i] and drbits[i]
|
||||
dgbits[i] = sgbits[i] and dgbits[i]
|
||||
@ -168,7 +172,8 @@ local function bitwiseblend(srcr,dstr,srcg,dstg,srcb,dstb,mode)
|
||||
dbbits[i] = not (sbbits[i] or dbbits[i])
|
||||
end
|
||||
end
|
||||
return string.format("%02X%02X%02X",implodebits(drbits),implodebits(dgbits),implodebits(dbbits))
|
||||
return string.format("%02X%02X%02X",
|
||||
implodebits(drbits), implodebits(dgbits), implodebits(dbbits))
|
||||
end
|
||||
|
||||
local function blend(src, dst, mode, transparent)
|
||||
@ -179,335 +184,393 @@ local function blend(src,dst,mode,transparent)
|
||||
local dstg = tonumber(string.sub(dst, 3, 4), 16)
|
||||
local dstb = tonumber(string.sub(dst, 5, 6), 16)
|
||||
local op = "normal"
|
||||
if type(mode) == "string" then op = string.lower(mode) end
|
||||
if type(mode) == "string" then
|
||||
op = string.lower(mode)
|
||||
end
|
||||
if op == "normal" then
|
||||
return src
|
||||
|
||||
elseif op == "nop" then
|
||||
return dst
|
||||
|
||||
elseif op == "overlay" then
|
||||
return (string.upper(src) == string.upper(transparent)) and dst or src
|
||||
return string.upper(src) == string.upper(transparent) and dst or src
|
||||
|
||||
elseif op == "add" then
|
||||
local r = math.min(255, srcr + dstr)
|
||||
local g = math.min(255, srcg + dstg)
|
||||
local b = math.min(255, srcb + dstb)
|
||||
return string.format("%02X%02X%02X", r, g, b)
|
||||
|
||||
elseif op == "sub" then
|
||||
local r = math.max(0, dstr - srcr)
|
||||
local g = math.max(0, dstg - srcg)
|
||||
local b = math.max(0, dstb - srcb)
|
||||
return string.format("%02X%02X%02X", r, g, b)
|
||||
|
||||
elseif op == "isub" then
|
||||
local r = math.max(0, srcr - dstr)
|
||||
local g = math.max(0, srcg - dstg)
|
||||
local b = math.max(0, srcb - dstb)
|
||||
return string.format("%02X%02X%02X", r, g, b)
|
||||
|
||||
elseif op == "average" then
|
||||
local r = math.min(255, (srcr + dstr) / 2)
|
||||
local g = math.min(255, (srcg + dstg) / 2)
|
||||
local b = math.min(255, (srcb + dstb) / 2)
|
||||
return string.format("%02X%02X%02X", r, g, b)
|
||||
elseif op == "and" or op == "or" or op == "xor" or op == "xnor" or op == "not" or op == "nand" or op == "nor" then
|
||||
|
||||
elseif op == "and"
|
||||
or op == "or"
|
||||
or op == "xor"
|
||||
or op == "xnor"
|
||||
or op == "not"
|
||||
or op == "nand"
|
||||
or op == "nor"
|
||||
then
|
||||
return bitwiseblend(srcr, dstr, srcg, dstg, srcb, dstb, op)
|
||||
elseif op == "tohsv" or op == "rgbtohsv" then
|
||||
|
||||
elseif op == "tohsv"
|
||||
or op == "rgbtohsv"
|
||||
then
|
||||
return string.format("%02X%02X%02X", rgbtohsv(srcr, srcg, srcb))
|
||||
elseif op == "torgb" or op == "hsvtorgb" then
|
||||
|
||||
elseif op == "torgb"
|
||||
or op == "hsvtorgb"
|
||||
then
|
||||
return string.format("%02X%02X%02X",hsvtorgb(srcr, srcg, srcb))
|
||||
else
|
||||
end
|
||||
|
||||
return src
|
||||
end
|
||||
|
||||
local function validate_area(buffer, x1, y1, x2, y2)
|
||||
if not (buffer and buffer.xsize and buffer.ysize)
|
||||
or type(x1) ~= "number"
|
||||
or type(x2) ~= "number"
|
||||
or type(y1) ~= "number"
|
||||
or type(y2) ~= "number"
|
||||
then
|
||||
return
|
||||
end
|
||||
|
||||
x1 = math.max(1, math.min(buffer.xsize, math.floor(x1)))
|
||||
x2 = math.max(1, math.min(buffer.xsize, math.floor(x2)))
|
||||
y1 = math.max(1, math.min(buffer.ysize, math.floor(y1)))
|
||||
y2 = math.max(1, math.min(buffer.ysize, math.floor(y2)))
|
||||
if x1 > x2 then
|
||||
x1, x2 = x2, x1
|
||||
end
|
||||
if y1 > y2 then
|
||||
y1, y2 = y2, y1
|
||||
end
|
||||
return x1, y1, x2, y2
|
||||
end
|
||||
|
||||
local function validate_size(size)
|
||||
if type(size) ~= "number" then
|
||||
return 1
|
||||
end
|
||||
return math.max(1, math.min(64, math.floor(math.abs(size))))
|
||||
end
|
||||
|
||||
local function validate_color(fillcolor, fallback)
|
||||
fallback = fallback or "000000"
|
||||
if type(fillcolor) ~= "string"
|
||||
or string.len(fillcolor) > 7
|
||||
or string.len(fillcolor) < 6
|
||||
then
|
||||
fillcolor = fallback
|
||||
end
|
||||
if string.sub(fillcolor, 1, 1) == "#" then
|
||||
fillcolor = string.sub(fillcolor, 2, 7)
|
||||
end
|
||||
if not tonumber(fillcolor, 16) then
|
||||
fillcolor = fallback
|
||||
end
|
||||
return fillcolor
|
||||
end
|
||||
|
||||
local function validate_buffer_address(bufnum)
|
||||
if type(bufnum) ~= "number" then
|
||||
return
|
||||
end
|
||||
|
||||
bufnum = math.floor(math.abs(bufnum))
|
||||
return MAX_BUFFERS > bufnum and bufnum or nil
|
||||
end
|
||||
|
||||
local function read_buffer(meta, bufnum)
|
||||
local buffer = minetest.deserialize(meta:get_string("buffer" .. bufnum))
|
||||
return type(buffer) == "table" and buffer or nil
|
||||
end
|
||||
|
||||
local function write_buffer(meta, bufnum, buffer)
|
||||
meta:set_string("buffer" .. bufnum, minetest.serialize(buffer))
|
||||
end
|
||||
|
||||
local function runcommand(pos, meta, command)
|
||||
if type(command) ~= "table" then return end
|
||||
if type(command) ~= "table"
|
||||
or type(command.buffer) ~= "number"
|
||||
then
|
||||
return
|
||||
end
|
||||
|
||||
local bufnum = validate_buffer_address(command.buffer)
|
||||
if not bufnum then
|
||||
return
|
||||
end
|
||||
|
||||
local buffer
|
||||
if command.command ~= "createbuffer" then
|
||||
buffer = read_buffer(meta, bufnum)
|
||||
if not buffer then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local xsize, ysize, x1, x2, y1, y2
|
||||
local color, fillcolor, edgecolor
|
||||
if command.command == "createbuffer" then
|
||||
if type(command.buffer) ~= "number" or type(command.xsize) ~= "number" or type(command.ysize) ~= "number" then return end
|
||||
local bufnum = math.floor(command.buffer)
|
||||
if bufnum < 0 or bufnum > 7 then return end
|
||||
local xsize = math.min(64,math.floor(command.xsize))
|
||||
local ysize = math.min(64,math.floor(command.ysize))
|
||||
if xsize < 1 or ysize < 1 then return end
|
||||
local fillcolor = command.fill
|
||||
if type(fillcolor) ~= "string" or string.len(fillcolor) > 7 or string.len(fillcolor) < 6 then fillcolor = "000000" end
|
||||
if string.sub(fillcolor,1,1) == "#" then fillcolor = string.sub(fillcolor,2,7) end
|
||||
if not tonumber(fillcolor,16) then fillcolor = "000000" end
|
||||
local buffer = {}
|
||||
buffer.xsize = xsize
|
||||
buffer.ysize = ysize
|
||||
for y=1,ysize,1 do
|
||||
xsize = validate_size(command.xsize)
|
||||
ysize = validate_size(command.ysize)
|
||||
fillcolor = validate_color(command.fill)
|
||||
buffer = { xsize = xsize, ysize = ysize }
|
||||
for y = 1, ysize do
|
||||
buffer[y] = {}
|
||||
for x=1,xsize,1 do
|
||||
for x = 1, xsize do
|
||||
buffer[y][x] = fillcolor
|
||||
end
|
||||
end
|
||||
meta:set_string("buffer"..bufnum,minetest.serialize(buffer))
|
||||
write_buffer(meta, bufnum, buffer)
|
||||
elseif command.command == "send" then
|
||||
if type(command.buffer) ~= "number" or type(command.channel) ~= "string" then return end
|
||||
local bufnum = math.floor(command.buffer)
|
||||
if bufnum < 0 or bufnum > 7 then return end
|
||||
local buffer = meta:get_string("buffer"..bufnum)
|
||||
if string.len(buffer) == 0 then return end
|
||||
buffer = minetest.deserialize(buffer)
|
||||
if type(buffer) == "table" then
|
||||
digilines.receptor_send(pos,digilines.rules.default,command.channel,buffer)
|
||||
if type(command.channel) ~= "string" then
|
||||
return
|
||||
end
|
||||
|
||||
digilines.receptor_send(pos, digilines.rules.default,
|
||||
command.channel, buffer)
|
||||
|
||||
elseif command.command == "sendregion" then
|
||||
if type(command.buffer) ~= "number" or type(command.channel) ~= "string" then return end
|
||||
local bufnum = math.floor(command.buffer)
|
||||
if bufnum < 0 or bufnum > 7 then return end
|
||||
local buffer = meta:get_string("buffer"..bufnum)
|
||||
if string.len(buffer) == 0 then return end
|
||||
buffer = minetest.deserialize(buffer)
|
||||
if type(buffer) ~= "table" then return end
|
||||
if type(command.x1) ~= "number" or type(command.x2) ~= "number" or type(command.y1) ~= "number" or type(command.x2) ~= "number" then return end
|
||||
local x1 = math.min(64,math.floor(command.x1))
|
||||
local y1 = math.min(64,math.floor(command.y1))
|
||||
local x2 = math.min(64,math.floor(command.x2))
|
||||
local y2 = math.min(64,math.floor(command.y2))
|
||||
if x1 < 1 or y1 < 1 or x2 < 1 or y2 < 1 then return end
|
||||
x2 = math.min(x2,buffer.xsize)
|
||||
y2 = math.min(y2,buffer.ysize)
|
||||
if x1 > x2 or y1 > y2 then return end
|
||||
local tempbuf = {}
|
||||
for y=y1,y2,1 do
|
||||
local dsty = y-y1+1
|
||||
if type(command.channel) ~= "string" then
|
||||
return
|
||||
end
|
||||
|
||||
x1, y1, x2, y2 = validate_area(buffer,
|
||||
command.x1, command.y1, command.x2, command.y2)
|
||||
|
||||
if not x1 then
|
||||
return
|
||||
end
|
||||
|
||||
local tempbuf, dstx, dsty = {}
|
||||
for y = y1, y2 do
|
||||
dsty = y - y1 + 1
|
||||
tempbuf[dsty] = {}
|
||||
for x=x1,x2,1 do
|
||||
local dstx = x-x1+1
|
||||
for x = x1, x2 do
|
||||
dstx = x - x1 + 1
|
||||
tempbuf[dsty][dstx] = buffer[y][x]
|
||||
end
|
||||
end
|
||||
digilines.receptor_send(pos,digilines.rules.default,command.channel,tempbuf)
|
||||
digilines.receptor_send(pos, digilines.rules.default,
|
||||
command.channel, tempbuf)
|
||||
|
||||
elseif command.command == "drawrect" then
|
||||
if type(command.buffer) ~= "number" or type(command.x1) ~= "number" or type(command.y1) ~= "number" or type(command.x2) ~= "number" or type(command.y2) ~= "number" then return end
|
||||
local bufnum = math.floor(command.buffer)
|
||||
if bufnum < 0 or bufnum > 7 then return end
|
||||
local x1 = math.min(64,math.floor(command.x1))
|
||||
local y1 = math.min(64,math.floor(command.y1))
|
||||
local x2 = math.min(64,math.floor(command.x2))
|
||||
local y2 = math.min(64,math.floor(command.y2))
|
||||
if x1 < 1 or y1 < 1 or x2 < 1 or y2 < 1 then return end
|
||||
local buffer = meta:get_string("buffer"..bufnum)
|
||||
if string.len(buffer) == 0 then return end
|
||||
buffer = minetest.deserialize(buffer)
|
||||
if type(buffer) ~= "table" then return end
|
||||
x2 = math.min(x2,buffer.xsize)
|
||||
y2 = math.min(y2,buffer.ysize)
|
||||
if x1 > x2 or y1 > y2 then return end
|
||||
local fillcolor = command.fill
|
||||
if type(fillcolor) ~= "string" or string.len(fillcolor) > 7 or string.len(fillcolor) < 6 then fillcolor = "000000" end
|
||||
if string.sub(fillcolor,1,1) == "#" then fillcolor = string.sub(fillcolor,2,7) end
|
||||
if not tonumber(fillcolor,16) then fillcolor = "000000" end
|
||||
local edgecolor = command.edge
|
||||
if type(edgecolor) ~= "string" or string.len(edgecolor) > 7 or string.len(edgecolor) < 6 then edgecolor = fillcolor end
|
||||
if string.sub(edgecolor,1,1) == "#" then edgecolor = string.sub(edgecolor,2,7) end
|
||||
if not tonumber(edgecolor,16) then edgecolor = fillcolor end
|
||||
for y=y1,y2,1 do
|
||||
for x=x1,x2,1 do
|
||||
x1, y1, x2, y2 = validate_area(buffer,
|
||||
command.x1, command.y1, command.x2, command.y2)
|
||||
|
||||
if not x1 then
|
||||
return
|
||||
end
|
||||
|
||||
fillcolor = validate_color(command.fill)
|
||||
edgecolor = validate_color(command.edge, fillcolor)
|
||||
for y = y1, y2 do
|
||||
for x = x1, x2 do
|
||||
buffer[y][x] = fillcolor
|
||||
end
|
||||
end
|
||||
if fillcolor ~= edgecolor then
|
||||
for x=x1,x2,1 do
|
||||
for x = x1, x2 do
|
||||
buffer[y1][x] = edgecolor
|
||||
buffer[y2][x] = edgecolor
|
||||
end
|
||||
for y=y1,y2,1 do
|
||||
for y = y1, y2 do
|
||||
buffer[y][x1] = edgecolor
|
||||
buffer[y][x2] = edgecolor
|
||||
end
|
||||
end
|
||||
meta:set_string("buffer"..bufnum,minetest.serialize(buffer))
|
||||
write_buffer(meta, bufnum, buffer)
|
||||
elseif command.command == "drawline" then
|
||||
if type(command.buffer) ~= "number" or type(command.x1) ~= "number" or type(command.y1) ~= "number" or type(command.x2) ~= "number" or type(command.y2) ~= "number" then return end
|
||||
local bufnum = math.floor(command.buffer)
|
||||
if bufnum < 0 or bufnum > 7 then return end
|
||||
local x1 = math.min(64,math.floor(command.x1))
|
||||
local y1 = math.min(64,math.floor(command.y1))
|
||||
local x2 = math.min(64,math.floor(command.x2))
|
||||
local y2 = math.min(64,math.floor(command.y2))
|
||||
if x1 < 1 or y1 < 1 or x2 < 1 or y2 < 1 then return end
|
||||
local buffer = meta:get_string("buffer"..bufnum)
|
||||
if string.len(buffer) == 0 then return end
|
||||
buffer = minetest.deserialize(buffer)
|
||||
if type(buffer) ~= "table" then return end
|
||||
x2 = math.min(x2,buffer.xsize)
|
||||
y2 = math.min(y2,buffer.ysize)
|
||||
local color = command.color
|
||||
if type(color) ~= "string" or string.len(color) > 7 or string.len(color) < 6 then color = "000000" end
|
||||
if string.sub(color,1,1) == "#" then color = string.sub(color,2,7) end
|
||||
if not tonumber(color,16) then color = "000000" end
|
||||
x1, y1, x2, y2 = validate_area(buffer,
|
||||
command.x1, command.y1, command.x2, command.y2)
|
||||
|
||||
if not x1 then
|
||||
return
|
||||
end
|
||||
|
||||
color = validate_color(command.color)
|
||||
local p1 = vector.new(x1, y1, 0)
|
||||
local p2 = vector.new(x2, y2, 0)
|
||||
local length = vector.distance(p1,p2)
|
||||
local length = 1 + vector.distance(p1, p2)
|
||||
local dir = vector.direction(p1, p2)
|
||||
if length > 0 then
|
||||
local point
|
||||
-- not the most eficient process for horizontal, vertical
|
||||
-- or 45 degree lines
|
||||
for i = 0, length, 0.3 do
|
||||
local point = vector.add(p1,vector.multiply(dir,i))
|
||||
point = vector.add(p1, vector.multiply(dir, i))
|
||||
point = vector.floor(point)
|
||||
if command.antialias then
|
||||
buffer[point.y][point.x] = blend(buffer[point.y][point.x],color,"average")
|
||||
buffer[point.y][point.x] = blend(
|
||||
buffer[point.y][point.x], color, "average")
|
||||
else
|
||||
buffer[point.y][point.x] = color
|
||||
end
|
||||
end
|
||||
end
|
||||
meta:set_string("buffer"..bufnum,minetest.serialize(buffer))
|
||||
write_buffer(meta, bufnum, buffer)
|
||||
elseif command.command == "drawpoint" then
|
||||
if type(command.buffer) ~= "number" or type(command.x) ~= "number" or type(command.y) ~= "number" then return end
|
||||
local bufnum = math.floor(command.buffer)
|
||||
if bufnum < 0 or bufnum > 7 then return end
|
||||
local x = math.floor(command.x)
|
||||
local y = math.floor(command.y)
|
||||
if x < 1 or y < 1 then return end
|
||||
local buffer = meta:get_string("buffer"..bufnum)
|
||||
if string.len(buffer) == 0 then return end
|
||||
buffer = minetest.deserialize(buffer)
|
||||
if type(buffer) ~= "table" then return end
|
||||
if x > buffer.xsize or y > buffer.ysize then return end
|
||||
local color = command.color
|
||||
if type(color) ~= "string" or string.len(color) > 7 or string.len(color) < 6 then color = "000000" end
|
||||
if string.sub(color,1,1) == "#" then color = string.sub(color,2,7) end
|
||||
if not tonumber(color,16) then color = "000000" end
|
||||
buffer[y][x] = color
|
||||
meta:set_string("buffer"..bufnum,minetest.serialize(buffer))
|
||||
x1, y1 = validate_area(buffer, command.x, command.y, command.x, command.y)
|
||||
if not x1 then
|
||||
return
|
||||
end
|
||||
|
||||
buffer[y1][x1] = validate_color(command.color)
|
||||
write_buffer(meta, bufnum, buffer)
|
||||
elseif command.command == "copy" then
|
||||
if type(command.src) ~= "number" or type(command.dst) ~= "number" or type(command.srcx) ~= "number" or type(command.srcy) ~= "number" or type(command.dstx) ~= "number" or type(command.dsty) ~= "number" or type(command.xsize) ~= "number" or type(command.ysize) ~= "number" then return end
|
||||
local src = math.floor(command.src)
|
||||
if src < 0 or src > 7 then return end
|
||||
local dst = math.floor(command.dst)
|
||||
if dst < 0 or dst > 7 then return end
|
||||
local srcx = math.floor(command.srcx)
|
||||
local srcy = math.floor(command.srcy)
|
||||
local dstx = math.floor(command.dstx)
|
||||
local dsty = math.floor(command.dsty)
|
||||
local xsize = math.floor(command.xsize)
|
||||
local ysize = math.floor(command.ysize)
|
||||
if srcx < 1 or srcy < 1 or dstx < 1 or dsty < 1 or xsize < 1 or ysize < 1 then return end
|
||||
local sourcebuffer = meta:get_string("buffer"..src)
|
||||
local destbuffer = meta:get_string("buffer"..dst)
|
||||
if string.len(sourcebuffer) == 0 then return end
|
||||
sourcebuffer = minetest.deserialize(sourcebuffer)
|
||||
if type(sourcebuffer) ~= "table" then return end
|
||||
if string.len(destbuffer) == 0 then return end
|
||||
destbuffer = minetest.deserialize(destbuffer)
|
||||
if type(destbuffer) ~= "table" then return end
|
||||
if srcx + xsize-1 > sourcebuffer.xsize or srcy + ysize-1 > sourcebuffer.ysize then return end
|
||||
if dstx + xsize-1 > destbuffer.xsize or dsty + ysize-1 > destbuffer.ysize then return end
|
||||
local transparent = command.transparent
|
||||
if type(transparent) ~= "string" or string.len(transparent) > 7 or string.len(transparent) < 6 then transparent = "000000" end
|
||||
if string.sub(transparent,1,1) == "#" then transparent = string.sub(transparent,2,7) end
|
||||
if not tonumber(transparent,16) then transparent = "000000" end
|
||||
for y=0,ysize-1,1 do
|
||||
for x=0,xsize-1,1 do
|
||||
local srcpx = sourcebuffer[srcy+y][srcx+x]
|
||||
local destpx = destbuffer[dsty+y][dstx+x]
|
||||
destbuffer[dsty+y][dstx+x] = blend(srcpx,destpx,command.mode,transparent)
|
||||
if type(command.xsize) ~= "number"
|
||||
or type(command.ysize) ~= "number"
|
||||
then
|
||||
return
|
||||
end
|
||||
|
||||
x1, y1 = validate_area(buffer,
|
||||
command.srcx, command.srcy, command.srcx, command.srcy)
|
||||
|
||||
x2, y2 = validate_area(buffer,
|
||||
command.dstx, command.dsty, command.dstx, command.dsty)
|
||||
|
||||
if not (x1 and x2) then
|
||||
return
|
||||
end
|
||||
|
||||
local src = validate_buffer_address(command.src)
|
||||
local dst = validate_buffer_address(command.dst)
|
||||
if not (src and dst) then
|
||||
return
|
||||
end
|
||||
|
||||
local sourcebuffer = read_buffer(meta, src)
|
||||
local destbuffer = read_buffer(meta, dst)
|
||||
if not (sourcebuffer and destbuffer) then
|
||||
return
|
||||
end
|
||||
|
||||
-- clamp size to source and offset
|
||||
xsize = math.min(sourcebuffer.xsize - x1 + 1, validate_size(command.xsize))
|
||||
ysize = math.min(sourcebuffer.ysize - y1 + 1, validate_size(command.ysize))
|
||||
-- clamp size to destination and offset
|
||||
xsize = math.min(destbuffer.xsize - x2 + 1, xsize)
|
||||
ysize = math.min(destbuffer.ysize - y2 + 1, ysize)
|
||||
|
||||
local transparent = validate_color(command.transparent)
|
||||
local px1, px2
|
||||
for y = 0, ysize - 1 do
|
||||
for x = 0, xsize - 1 do
|
||||
px1 = sourcebuffer[y1 + y][x1 + x]
|
||||
px2 = destbuffer[y2 + y][x2 + x]
|
||||
destbuffer[y2 + y][x2 + x] = blend(
|
||||
px1, px2, command.mode, transparent)
|
||||
end
|
||||
end
|
||||
meta:set_string("buffer"..dst,minetest.serialize(destbuffer))
|
||||
write_buffer(meta, dst, destbuffer)
|
||||
elseif command.command == "load" then
|
||||
if type(command.buffer) ~= "number" or type(command.x) ~= "number" or type(command.y) ~= "number" or type(command.data) ~= "table" then return end
|
||||
local bufnum = math.floor(command.buffer)
|
||||
if bufnum < 0 or bufnum > 7 then return end
|
||||
local xstart = math.floor(command.x)
|
||||
local ystart = math.floor(command.y)
|
||||
if xstart < 1 or ystart < 1 then return end
|
||||
local buffer = meta:get_string("buffer"..bufnum)
|
||||
if string.len(buffer) == 0 then return end
|
||||
buffer = minetest.deserialize(buffer)
|
||||
if type(buffer) ~= "table" then return end
|
||||
if type(command.data[1]) ~= "table" then return end
|
||||
if #command.data[1] < 1 then return end
|
||||
local ysize = #command.data
|
||||
local xsize = #command.data[1]
|
||||
if xstart+xsize-1 > buffer.xsize or ystart+ysize-1 > buffer.ysize then return end
|
||||
for y=1,ysize,1 do
|
||||
x1, y1 = validate_area(buffer, command.x, command.y, command.x, command.y)
|
||||
if not x1
|
||||
or type(command.data) ~= "table"
|
||||
or type(command.data[1]) ~= "table"
|
||||
or #command.data[1] < 1
|
||||
then
|
||||
return
|
||||
end
|
||||
|
||||
ysize = math.min(buffer.ysize - y1 + 1, validate_size(#command.data))
|
||||
xsize = math.min(buffer.xsize - x1 + 1, validate_size(#command.data[1]))
|
||||
for y = 1, ysize do
|
||||
if type(command.data[y]) == "table" then
|
||||
for x=1,xsize,1 do
|
||||
local color = command.data[y][x]
|
||||
if type(color) == "string" then
|
||||
if string.len(color) == 7 then color = string.sub(color,2,7) end
|
||||
if tonumber(color,16) then
|
||||
buffer[ystart+y-1][xstart+x-1] = color
|
||||
for x = 1, xsize do
|
||||
-- slightly different behaviour from before refactor:
|
||||
-- illegal values are now set to '000000' instead of being skipped
|
||||
buffer[y1 + y - 1][x1 + x - 1] = validate_color(
|
||||
command.data[y][x])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
meta:set_string("buffer"..bufnum,minetest.serialize(buffer))
|
||||
write_buffer(meta, bufnum, buffer)
|
||||
elseif command.command == "text" then
|
||||
if type(command.buffer) ~= "number" or type(command.x) ~= "number" or type(command.y) ~= "number" or type(command.text) ~= "string" or string.len(command.text) < 1 then return end
|
||||
x1, y1 = validate_area(buffer, command.x, command.y, command.x, command.y)
|
||||
if not x1
|
||||
or x1 > buffer.xsize
|
||||
or y1 > buffer.ysize
|
||||
or type(command.text) ~= "string"
|
||||
or string.len(command.text) < 1
|
||||
then
|
||||
return
|
||||
end
|
||||
|
||||
command.text = string.sub(command.text, 1, 16)
|
||||
local bufnum = math.floor(command.buffer)
|
||||
if bufnum < 0 or bufnum > 7 then return end
|
||||
local x = math.floor(command.x)
|
||||
local y = math.floor(command.y)
|
||||
if x < 1 or y < 1 then return end
|
||||
local buffer = meta:get_string("buffer"..bufnum)
|
||||
if string.len(buffer) == 0 then return end
|
||||
buffer = minetest.deserialize(buffer)
|
||||
if type(buffer) ~= "table" then return end
|
||||
if x > buffer.xsize or y > buffer.ysize then return end
|
||||
local color = command.color
|
||||
if type(color) ~= "string" or string.len(color) > 7 or string.len(color) < 6 then color = "ff6600" end
|
||||
if string.sub(color,1,1) == "#" then color = string.sub(color,2,7) end
|
||||
if not tonumber(color,16) then color = "ff6600" end
|
||||
for i=1,string.len(command.text),1 do
|
||||
local char = font[string.byte(string.sub(command.text,i,i))]
|
||||
for chary=1,12,1 do
|
||||
for charx=1,5,1 do
|
||||
local startx = x + (i*6-6)
|
||||
if char[chary][charx] and y+chary-1 <= buffer.ysize and startx+charx-1 <= buffer.xsize then
|
||||
local dstpx = buffer[y+chary-1][startx+charx-1]
|
||||
buffer[y+chary-1][startx+charx-1] = blend(color,dstpx,command.mode,"")
|
||||
color = validate_color(command.color, "ff6600")
|
||||
local char, px
|
||||
for i = 1, string.len(command.text) do
|
||||
char = font[string.byte(string.sub(command.text, i, i))]
|
||||
for chary = 1, 12 do
|
||||
for charx = 1, 5 do
|
||||
x2 = x1 + (i * 6 - 6)
|
||||
if char[chary][charx] and y1 + chary - 1 <= buffer.ysize
|
||||
and x2 + charx - 1 <= buffer.xsize
|
||||
then
|
||||
px = buffer[y1 + chary - 1][x2 + charx - 1]
|
||||
buffer[y1 + chary - 1][x2 + charx - 1] = blend(
|
||||
color, px, command.mode, "")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
meta:set_string("buffer"..bufnum,minetest.serialize(buffer))
|
||||
write_buffer(meta, bufnum, buffer)
|
||||
elseif command.command == "sendpacked" then
|
||||
if type(command.buffer) ~= "number" or type(command.channel) ~= "string" then return end
|
||||
local bufnum = math.floor(command.buffer)
|
||||
if bufnum < 0 or bufnum > 7 then return end
|
||||
local buffer = meta:get_string("buffer"..bufnum)
|
||||
if string.len(buffer) == 0 then return end
|
||||
buffer = minetest.deserialize(buffer)
|
||||
if type(buffer) == "table" then
|
||||
local packeddata = ""
|
||||
for y=1,buffer.ysize,1 do
|
||||
for x=1,buffer.xsize,1 do
|
||||
packeddata = packeddata..packpixel(buffer[y][x])
|
||||
if type(command.channel) ~= "string" then
|
||||
return
|
||||
end
|
||||
local packedtable = {}
|
||||
for y = 1, buffer.ysize do
|
||||
for x = 1, buffer.xsize do
|
||||
table.insert(packedtable, packpixel(buffer[y][x]))
|
||||
end
|
||||
end
|
||||
digilines.receptor_send(pos,digilines.rules.default,command.channel,packeddata)
|
||||
end
|
||||
local packeddata = table.concat(packedtable, "")
|
||||
digilines.receptor_send(pos, digilines.rules.default,
|
||||
command.channel, packeddata)
|
||||
elseif command.command == "loadpacked" then
|
||||
if type(command.buffer) ~= "number" or type(command.data) ~= "string" then return end
|
||||
if type(command.x) ~= "number" or type(command.y) ~= "number" or type(command.xsize) ~= "number" or type(command.ysize) ~= "number" then return end
|
||||
command.x = math.floor(command.x)
|
||||
command.y = math.floor(command.y)
|
||||
command.xsize = math.floor(command.xsize)
|
||||
command.ysize = math.floor(command.ysize)
|
||||
if command.x < 1 or command.y < 1 or command.xsize < 1 or command.ysize < 1 then return end
|
||||
local bufnum = math.floor(command.buffer)
|
||||
if bufnum < 0 or bufnum > 7 then return end
|
||||
local buffer = meta:get_string("buffer"..bufnum)
|
||||
if string.len(buffer) == 0 then return end
|
||||
buffer = minetest.deserialize(buffer)
|
||||
if type(buffer) == "table" then
|
||||
if command.x + command.xsize - 1 > buffer.xsize then return end
|
||||
if command.y + command.ysize - 1 > buffer.ysize then return end
|
||||
for y=0,command.ysize-1,1 do
|
||||
local dsty = command.y+y
|
||||
for x=0,command.xsize-1,1 do
|
||||
local dstx = command.x+x
|
||||
local packidx = (y*command.xsize+x)*4+1
|
||||
local packeddata = string.sub(command.data,packidx,packidx+3)
|
||||
buffer[dsty][dstx] = unpackpixel(packeddata)
|
||||
x1, y1 = validate_area(buffer, command.x, command.y, command.x, command.y)
|
||||
if not x1
|
||||
or type(command.data) ~= "string"
|
||||
then
|
||||
return
|
||||
end
|
||||
|
||||
-- clamp size to buffer size
|
||||
xsize = math.min(buffer.xsize - x1 + 1, validate_size(command.xsize))
|
||||
ysize = math.min(buffer.ysize - y1 + 1, validate_size(command.ysize))
|
||||
local packidx, packeddata
|
||||
for y = 0, ysize - 1 do
|
||||
y2 = y1 + y
|
||||
for x = 0, xsize - 1 do
|
||||
x2 = x1 + x
|
||||
packidx = (y * xsize + x) * 4 + 1
|
||||
packeddata = string.sub(command.data, packidx, packidx + 3)
|
||||
buffer[y2][x2] = unpackpixel(packeddata)
|
||||
end
|
||||
end
|
||||
meta:set_string("buffer"..bufnum,minetest.serialize(buffer))
|
||||
end
|
||||
write_buffer(meta, bufnum, buffer)
|
||||
end
|
||||
end
|
||||
|
||||
@ -547,22 +610,36 @@ minetest.register_node("digistuff:gpu", {
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
on_receive_fields = function(pos, formname, fields, sender)
|
||||
-- Below link to lua_api.md says: not to check formname
|
||||
-- https://github.com/minetest/minetest/blob/2efd0996e61fe82a4922224fa8c039116281d345/doc/lua_api.md?plain=1#L9674
|
||||
if not fields.channel then
|
||||
return
|
||||
end
|
||||
|
||||
local name = sender:get_player_name()
|
||||
if minetest.is_protected(pos,name) and not minetest.check_player_privs(name,{protection_bypass=true}) then
|
||||
if minetest.is_protected(pos, name)
|
||||
and not minetest.check_player_privs(name, { protection_bypass = true })
|
||||
then
|
||||
minetest.record_protection_violation(pos, name)
|
||||
return
|
||||
end
|
||||
|
||||
local meta = minetest.get_meta(pos)
|
||||
if fields.channel then meta:set_string("channel",fields.channel) end
|
||||
meta:set_string("channel", fields.channel)
|
||||
end,
|
||||
digiline = {
|
||||
receptor = {},
|
||||
effector = {
|
||||
action = function(pos, node, channel, msg)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_string("channel") ~= channel or type(msg) ~= "table" then return end
|
||||
if meta:get_string("channel") ~= channel
|
||||
or type(msg) ~= "table"
|
||||
then
|
||||
return
|
||||
end
|
||||
|
||||
if type(msg[1]) == "table" then
|
||||
for i=1,32,1 do
|
||||
for i = 1, 32 do
|
||||
if type(msg[i]) == "table" then
|
||||
runcommand(pos, meta, msg[i])
|
||||
end
|
||||
@ -579,7 +656,11 @@ minetest.register_craft({
|
||||
output = "digistuff:gpu",
|
||||
recipe = {
|
||||
{ "", "default:steel_ingot", "" },
|
||||
{"digilines:wire_std_00000000","mesecons_luacontroller:luacontroller0000","digilines:wire_std_00000000"},
|
||||
{"dye:red","dye:green","dye:blue"},
|
||||
{
|
||||
"digilines:wire_std_00000000",
|
||||
"mesecons_luacontroller:luacontroller0000",
|
||||
"digilines:wire_std_00000000"
|
||||
},
|
||||
{ "dye:red", "dye:green", "dye:blue" }
|
||||
}
|
||||
})
|
||||
|
Loading…
x
Reference in New Issue
Block a user