From d88a0595f7d083c7820569e17be0b281ffd9eb27 Mon Sep 17 00:00:00 2001 From: cheapie Date: Mon, 27 Apr 2020 13:35:21 -0500 Subject: Add true-color version --- README | 16 ++-- depends.txt | 0 init.lua | 274 ++++++++++++++++++++++++++++++++++++++++++------------------ mod.conf | 2 + 4 files changed, 203 insertions(+), 89 deletions(-) delete mode 100644 depends.txt create mode 100644 mod.conf diff --git a/README b/README index 1b042a0..df7488e 100644 --- a/README +++ b/README @@ -4,21 +4,17 @@ License: ---Code: WTFPL ---Textures: "white" image by VanessaE (WTFPL), "palette" image is from here: https://commons.wikimedia.org/wiki/File:256colour.png -Depends: mesecons_lightstone, digilines -(neither is in depends.txt since the order doesn't matter) +Depends: digilines +(should load without it but won't be real useful) Instructions: -* Grab one from the creative inventory, or craft one: - nothing green lightstone nothing - red lightstone luacontroller blue lightstone - nothing digiline nothing - * Place the thing * Right-click and set a channel * Send a digilines message to it on that channel with the color you want (choices listed below) -Colors available: Any 6-digit hex color, such as "FF0000", "#c0ffee", "123456"... (will be set to the nearest color available) +Colors available for 256-color version: Any 6-digit hex color, such as "FF0000", "#c0ffee", "123456"... (will be set to the nearest color available) +Colors available for true-color version: Any 6-digit hex color, all values are supported Group addressing mode: @@ -36,8 +32,8 @@ blue yellow send this: -{{"red","green"}, -{"blue","yellow"}} +{{"FF0000","00FF00"}, +{"0000FF","FFFF00"}} Note that if you are using group addressing mode, if there is an already-configured RGB lightstone node directly above the one you are setting up, punching the one you are setting up (or right-clicking and selecting the Auto-Fill option) will attempt to auto-fill it (incrementing the Y address) from the one above. diff --git a/depends.txt b/depends.txt deleted file mode 100644 index e69de29..0000000 diff --git a/init.lua b/init.lua index 0151c3a..36714da 100644 --- a/init.lua +++ b/init.lua @@ -8,7 +8,7 @@ else end end -function rgblightstone.autofill(pos, player) +function rgblightstone.autofill(pos,player) local name = player:get_player_name() if minetest.is_protected(pos, name) and not minetest.check_player_privs(name, { protection_bypass = true }) then minetest.record_protection_violation(pos, name) @@ -37,12 +37,123 @@ function rgblightstone.autofill(pos, player) end end +function rgblightstone.handle_digilines(pos,node,channel,msg,truecolor) + local meta = minetest.get_meta(pos) + local setchan = meta:get_string("channel") + if channel ~= setchan then + return + end + + local addrx = tonumber(meta:get_string("addrx")) + local addry = tonumber(meta:get_string("addry")) + + if type(msg) == "table" then + if not (addrx and addry and type(msg[addry]) == "table" and msg[addry][addrx]) then + return + end + msg = msg[addry][addrx] + end + + --Validation starts here + if type(msg) ~= "string" then + return + end + msg = string.upper(msg) + --Drop a leading # if present (e.g. "#FF55AA") + if string.sub(msg,1,1) == "#" then + msg = string.sub(msg,2) + end + --Check length + if string.len(msg) ~= 6 then + return + end + --Make sure there aren't any invalid chars + local acceptable_chars = {["0"]=true,["1"]=true,["2"]=true,["3"]=true,["4"]=true,["5"]=true,["6"]=true,["7"]=true,["8"]=true,["9"]=true,["A"]=true,["B"]=true,["C"]=true,["D"]=true,["E"]=true,["F"]=true} + for i = 1,6,1 do + if not acceptable_chars[string.sub(msg,i,i)] then + return + else + end + end + --Should be a valid hex color by this point + + meta:set_string("color",msg) + + --Split into three colors + local r = tonumber(string.sub(msg,1,2),16) + local g = tonumber(string.sub(msg,3,4),16) + local b = tonumber(string.sub(msg,5,6),16) + + --Convert RGB to HSV... or at least V, for the light + local v = math.max(r,g,b) + v = math.floor(v/255*14) + v = math.max(0,math.min(14,v)) + + if truecolor then + node.name = "rgblightstone:rgblightstone_truecolor_"..v + minetest.swap_node(pos,node) + rgblightstone.update_entity(pos) + else + --Round to nearest available values and convert to a pixel count in the palette + r = math.floor(r/32) + g = math.floor(g/32) + b = math.floor(b/64) --Blue has one fewer bit + + local paletteidx = 32*g+4*r+b + + --Set the color + node.name = "rgblightstone:rgblightstone_"..v + node.param2 = paletteidx + minetest.swap_node(pos,node) + end +end + +function rgblightstone.handle_fields(pos,formname,fields,sender) + local name = sender:get_player_name() + 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.autofill then + rgblightstone.autofill(pos,sender) + else + if fields.channel then + meta:set_string("channel", fields.channel) + meta:set_string("infotext","") + end + if fields.addrx then meta:set_string("addrx",fields.addrx) end + if fields.addry then meta:set_string("addry",fields.addry) end + end +end + +function rgblightstone.update_entity(pos) + local objs = minetest.get_objects_inside_radius(pos,0.5) + for _,obj in ipairs(objs) do + if obj:get_luaentity() and obj:get_luaentity().name == "rgblightstone:entity" then + obj:remove() + end + end + local obj = minetest.add_entity(pos,"rgblightstone:entity") + local tex = "rgblightstone_white.png^[colorize:#"..minetest.get_meta(pos):get_string("color")..":255" + obj:set_properties({textures = {tex,tex,tex,tex,tex,tex}}) +end + +minetest.register_entity("rgblightstone:entity",{ + hp_max = 1, + physical = false, + collisionbox = {0,0,0,0,0,0}, + visual_size = {x=1,y=1}, + visual = "cube", + static_save = false, +}) + for i=0,14,1 do minetest.register_node("rgblightstone:rgblightstone_"..i, { tiles = {"rgblightstone_white.png"}, palette = "rgblightstone_palette.png", groups = i == 0 and {cracky = 2,} or {cracky = 2,not_in_creative_inventory = 1,}, - description = i == 0 and "RGB Lightstone" or "RGB Lightstone (lit state - you hacker you!)", + description = i == 0 and "256-Color RGB Lightstone" or "256-Color RGB Lightstone (lit state - you hacker you!)", paramtype2 = "color", light_source = i, drop = "rgblightstone:rgblightstone_0", @@ -52,27 +163,70 @@ for i=0,14,1 do meta:set_string("infotext","Not configured! Right-click to set up manually, or punch to auto-fill from the node above.") meta:set_string("color","000000") end, - on_punch = function(pos, node, player, pointed_thing) + on_punch = function(pos,node,player,pointed_thing) rgblightstone.autofill(pos,player) end, - on_receive_fields = function(pos, formname, fields, sender) - local name = sender:get_player_name() - 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 + on_receive_fields = rgblightstone.handle_fields, + light_source = 0, + digiline = { + wire = { + rules = { + {x = 1,y = 0,z = 0}, + {x = -1,y = 0,z = 0}, + {x = 0,y = 0,z = 1}, + {x = 0,y = 0,z = -1}, + {x = 0,y = 1,z = 0}, + {x = 0,y = -1,z = 0}, + }, + }, + receptor = {}, + effector = { + action = function(pos,node,channel,msg) + rgblightstone.handle_digilines(pos,node,channel,msg,false) + end + } + } + }) + + minetest.register_node("rgblightstone:rgblightstone_truecolor_"..i, { + tiles = {"rgblightstone_white.png^[colorize:#000000:255"}, + groups = i == 0 and {cracky = 2,} or {cracky = 2,not_in_creative_inventory = 1,}, + description = i == 0 and "True-Color RGB Lightstone" or "True-Color RGB Lightstone (lit state - you hacker you!)", + light_source = i, + drop = "rgblightstone:rgblightstone_truecolor_0", + on_construct = function(pos) local meta = minetest.get_meta(pos) - if fields.autofill then - rgblightstone.autofill(pos,sender) - else - if fields.channel then - meta:set_string("channel", fields.channel) - meta:set_string("infotext","") + meta:set_string("formspec", "size[8,5;]field[1,1;6,2;channel;Channel;${channel}]field[1,2;2,2;addrx;X Address;${addrx}]field[5,2;2,2;addry;Y Address;${addry}]button_exit[2.25,3;3,1;submit;Save]button_exit[2.25,4;3,1;autofill;Auto-Fill From Node Above]label[3,2;Leave address blank\nfor individual mode]") + meta:set_string("infotext","Not configured! Right-click to set up manually, or punch to auto-fill from the node above.") + meta:set_string("color","000000") + rgblightstone.update_entity(pos) + end, + on_punch = function(pos,node,player,pointed_thing) + rgblightstone.autofill(pos,player) + end, + after_destruct = function(pos) + local objs = minetest.get_objects_inside_radius(pos,0.5) + for _,obj in ipairs(objs) do + if obj:get_luaentity() and obj:get_luaentity().name == "rgblightstone:entity" then + obj:remove() end - if fields.addrx then meta:set_string("addrx",fields.addrx) end - if fields.addry then meta:set_string("addry",fields.addry) end end end, + paramtype = "light", + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = {{-0.45,-0.45,-0.45,0.45,0.45,0.45}} + }, + collision_box = { + type = "fixed", + fixed = {{-0.5,-0.5,-0.5,0.5,0.5,0.5}} + }, + selection_box = { + type = "fixed", + fixed = {{-0.5,-0.5,-0.5,0.5,0.5,0.5}} + }, + on_receive_fields = rgblightstone.handle_fields, light_source = 0, digiline = { wire = { @@ -87,81 +241,43 @@ for i=0,14,1 do }, receptor = {}, effector = { - action = function(pos, node, channel, msg) - local meta = minetest.get_meta(pos) - local setchan = meta:get_string("channel") - if channel ~= setchan then - return - end - - local addrx = tonumber(meta:get_string("addrx")) - local addry = tonumber(meta:get_string("addry")) - - if type(msg) == "table" then - if not (addrx and addry and type(msg[addry]) == "table" and msg[addry][addrx]) then - return - end - msg = msg[addry][addrx] - end - - --Validation starts here - if type(msg) ~= "string" then - return - end - msg = string.upper(msg) - --Drop a leading # if present (e.g. "#FF55AA") - if string.sub(msg,1,1) == "#" then - msg = string.sub(msg,2) - end - --Check length - if string.len(msg) ~= 6 then - return - end - --Make sure there aren't any invalid chars - local acceptable_chars = {["0"]=true,["1"]=true,["2"]=true,["3"]=true,["4"]=true,["5"]=true,["6"]=true,["7"]=true,["8"]=true,["9"]=true,["A"]=true,["B"]=true,["C"]=true,["D"]=true,["E"]=true,["F"]=true} - for i = 1,6,1 do - if not acceptable_chars[string.sub(msg,i,i)] then - return - else - end - end - --Should be a valid hex color by this point - - --Split into three colors - local r = tonumber(string.sub(msg,1,2),16) - local g = tonumber(string.sub(msg,3,4),16) - local b = tonumber(string.sub(msg,5,6),16) - - --Convert RGB to HSV... or at least V, for the light - local v = math.max(r,g,b) - v = math.floor(v/255*14) - v = math.max(0,math.min(14,v)) - - --Round to nearest available values and convert to a pixel count in the palette - r = math.floor(r/32) - g = math.floor(g/32) - b = math.floor(b/64) --Blue has one fewer bit - - local paletteidx = 32*g+4*r+b - - --Set the color - node.name = "rgblightstone:rgblightstone_"..v - node.param2 = paletteidx - minetest.swap_node(pos,node) + action = function(pos,node,channel,msg) + rgblightstone.handle_digilines(pos,node,channel,msg,true) end } } }) end +local tclist = {} +for i=0,14,1 do table.insert(tclist,"rgblightstone:rgblightstone_truecolor_"..i) end + +minetest.register_lbm({ + name = "rgblightstone:restore_entities", + label = "Restore true-color rgblightstone entities", + nodenames = tclist, + run_at_every_load = true, + action = rgblightstone.update_entity, +}) + minetest.register_alias("rgblightstone:rgblightstone","rgblightstone:rgblightstone_0") +minetest.register_alias("rgblightstone:rgblightstone_truecolor","rgblightstone:rgblightstone_truecolor_0") minetest.register_craft({ - output = "rgblightstone:rgblightstone", + output = "rgblightstone:rgblightstone_0", recipe = { {"","mesecons_lightstone:lightstone_green_off",""}, {"mesecons_lightstone:lightstone_red_off","mesecons_luacontroller:luacontroller0000","mesecons_lightstone:lightstone_blue_off"}, {"","digilines:wire_std_00000000",""} } }) + +minetest.register_craft({ + output = "rgblightstone:rgblightstone_truecolor_0", + recipe = { + {"","rgblightstone:rgblightstone_0",""}, + {"rgblightstone:rgblightstone_0","mesecons_luacontroller:luacontroller0000","rgblightstone:rgblightstone_0"}, + {"","digilines:wire_std_00000000",""} + } +}) diff --git a/mod.conf b/mod.conf new file mode 100644 index 0000000..59518e8 --- /dev/null +++ b/mod.conf @@ -0,0 +1,2 @@ +name = rgblightstone +description = RGB Lightstone -- cgit v1.2.3