diff --git a/.luacheckrc b/.luacheckrc new file mode 100644 index 0000000..2d38621 --- /dev/null +++ b/.luacheckrc @@ -0,0 +1,16 @@ +globals = { + "epidermis", + minetest = { + "dynamic_add_media" -- overridden + } +} + +read_globals = { + -- Minetest + "minetest", + "ItemStack", + "vector", + -- Mods + "modlib", + "moblib" +} \ No newline at end of file diff --git a/colorpicker_rgb_formspec.lua b/colorpicker_rgb_formspec.lua index 5656b52..e6d72ab 100644 --- a/colorpicker_rgb_formspec.lua +++ b/colorpicker_rgb_formspec.lua @@ -1,7 +1,8 @@ local function get_gradient_texture(component, color) local old_value = color[component] color[component] = 255 - local texture = ("epxw.png^[multiply:%s^[resize:256x1^[mask:epidermis_gradient_%s.png"):format(color:to_string(), component) + local texture = ("epxw.png^[multiply:%s^[resize:256x1^[mask:epidermis_gradient_%s.png") + :format(color:to_string(), component) color[component] = old_value return texture end @@ -27,7 +28,8 @@ function epidermis.show_colorpicker_formspec(player, color, callback) local component_short = component:sub(1, 1):lower() local y = 0.25 + index * 1.25 table.insert(fs, ("scrollbar[0.25,%f;8,0.5;horizontal;%s;%d]"):format(y, component_short, color[component_short])) - table.insert(fs, ("label[0.25,%f;%s]"):format(y + 0.75, minetest.colorize(("#%06X"):format(0xFF * 0x100 ^ (3 - index)), component:sub(1, 1)))) + table.insert(fs, ("label[0.25,%f;%s]") + :format(y + 0.75, minetest.colorize(("#%06X"):format(0xFF * 0x100 ^ (3 - index)), component:sub(1, 1)))) table.insert(fs, ("image[0.75,%f;6.5,0.5;%s]"):format(y + 0.5, get_gradient_texture(component_short, color))) table.insert(fs, ("field[7.25,%f;1,0.5;field_%s;;%s]"):format(y + 0.5, component_short, color[component_short])) table.insert(fs, ("field_close_on_enter[field_%s;false]"):format(component_short)) diff --git a/dynamic_add_media.lua b/dynamic_add_media.lua index 725b975..035b8ac 100644 --- a/dynamic_add_media.lua +++ b/dynamic_add_media.lua @@ -1,5 +1,7 @@ local media_paths = epidermis.media_paths --- TODO keep count of total added media, force-kick players after their RAM is too full, restart after server disk is too full +-- TODO keep count of total added media: +-- Force-kick players after their RAM is too full +-- Restart after server disk is too full function epidermis.dynamic_add_media(path, on_all_received, ephemeral) local filename = modlib.file.get_name(path) local existing_path = media_paths[filename] @@ -26,7 +28,8 @@ function epidermis.dynamic_add_media(path, on_all_received, ephemeral) for player in modlib.minetest.connected_players() do local name = player:get_player_name() if minetest.get_player_information(name).protocol_version < 39 then - minetest.kick_player(name, "Your Minetest client is outdated (< 5.3) and can't receive dynamic media. Rejoin to get the added media.") + minetest.kick_player(name, + "Your Minetest client is outdated (< 5.3) and can't receive dynamic media. Rejoin to get the added media.") else to_receive[name] = true end diff --git a/formspec.lua b/formspec.lua index c553d2e..8e3f163 100644 --- a/formspec.lua +++ b/formspec.lua @@ -27,7 +27,6 @@ function epidermis.show_formspec(player, formspec, handler) } id = id + 1 if id > 2^50 then id = 1 end - -- See https://github.com/minetest/minetest/issues/11907: Formspecs must not use exit buttons if there are to be following stages minetest.show_formspec(player_name, formspec_name, formspec) end diff --git a/help.lua b/help.lua index acee05f..e5db902 100644 --- a/help.lua +++ b/help.lua @@ -45,7 +45,13 @@ local help = { "Epidermis Spawner", "Spawns a paintable epidermis that copies your skin. Use your bare hands on the paintable:", "- Left-click (punch) to swap skins", - "- Right-click (interact) to open the control panel, which allows toggling backface culling, changing rotation, previewing the texture, playing the animation, picking a texture from and uploading to SkinDB" + "- Right-click (interact) to open the control panel, which allows " .. table.concat({ + "toggling backface culling", + "changing rotation", + "previewing the texture", + "playing the animation", + "picking a texture from and uploading to SkinDB" + }, ", ") .. "." ), item_( "epidermis:spawner_colorpicker", @@ -56,19 +62,23 @@ local help = { item_( "epidermis:undo_redo", "Undo / redo", - "Left-click to undo the last action, right-click to redo undone actions. Only a limited amount of actions can be undone / redone." + "Left-click to undo the last action, right-click to redo undone actions. " + .. "Only a limited amount of actions can be undone / redone." ), item_( "epidermis:eraser", "Eraser", - "Left-click to mark a pixel as transparent, right-click to restore opacity of the first transparent pixel above the pointed pixel." + "Left-click to mark a pixel as transparent, " + .. "right-click to restore opacity of the first transparent pixel above the pointed pixel." ), tags.b({ - "The painting tools below support right-clicking an epidermis or HSV color picker to choose a color. If nothing is pointed, you will be shown a RGB color picker.", + "The painting tools below support right-clicking an epidermis or HSV color picker to choose a color. ", + "If nothing is pointed, you will be shown a RGB color picker.", }), "\n", item_("epidermis:pen", "Pen", "Left-click to set a single pixel."), - item_("epidermis:filling_bucket", "Filling Bucket", "Left-click to fill pixels of (exactly) the same color on the texture."), + item_("epidermis:filling_bucket", "Filling Bucket", + "Left-click to fill pixels of (exactly) the same color on the texture."), item_("epidermis:line", "Line", "Drag to draw a line. The line is drawn on the texture, not the model."), item_( "epidermis:rectangle", diff --git a/paintable.lua b/paintable.lua index fc154e1..78f1ae1 100644 --- a/paintable.lua +++ b/paintable.lua @@ -279,7 +279,8 @@ function def:on_activate() local texture path, texture = epidermis.get_last_epidermis_path(self._.id) if path then - minetest.log("warning", ("Force-upgrading paintable #%d to texture %s due to staticdata loss"):format(self._.id, texture)) + minetest.log("warning", ("Force-upgrading paintable #%d to texture %s due to staticdata loss") + :format(self._.id, texture)) self:_set_texture(texture, true) -- related staticdata must be overwritten, as it relates to the old texture else minetest.log("warning", ("No texture for paintable #%d available, defaulting to character.png."):format(self._.id)) @@ -312,7 +313,8 @@ function def:_get_intersection_infos(mt_pos, mt_direction) local rotation_axis, rotation_angle = epidermis.vector_axis_angle(rotation) -- Instead of transforming all triangle vertices, we inversely transform the ray, which is a lot cheaper local inv_trans_dir = mlvec.rotate3((direction / scale):normalize(), rotation_axis, -rotation_angle) - local inv_trans_rel_pos = mlvec.rotate3(pos - mlvec.from_minetest(self.object:get_pos()), rotation_axis, -rotation_angle) + local inv_trans_rel_pos = mlvec.rotate3(pos - mlvec.from_minetest(self.object:get_pos()), + rotation_axis, -rotation_angle) for texid, tris in pairs(assert(models[properties.mesh]).triangle_sets) do for _, triangle in pairs(tris) do @@ -537,7 +539,9 @@ function def:_show_upload_formspec(player, message) local credit, completeness = context.credit, context.completeness local name, author = modlib.text.trim_spacing(fields.name or ""), modlib.text.trim_spacing(fields.author or "") if not (credit and completeness and name ~= "" and author ~= "") then - self:_show_upload_formspec(player, minetest.colorize(epidermis.colors.error:to_string(), "Please fill out the form!")) + self:_show_upload_formspec(player, + minetest.colorize(epidermis.colors.error:to_string(), + "Please fill out the form!")) return end epidermis.close_formspec(player) @@ -581,9 +585,9 @@ function def:_show_picker_formspec(player) results = epidermis.skins, index = #epidermis.skins } - local function show_formspec() + local function get_formspec() local skin = assert(context.results[context.index]) - epidermis.show_formspec(player, table.concat{ + return table.concat{ "size[8.5,5.25,false]", "real_coordinates[true]", "label[0.25,0.5;Pick a texture:]", @@ -603,21 +607,26 @@ function def:_show_picker_formspec(player) "label[3.5,1.75;Author: ", FSE(skin.author), "]"; "label[3.5,2.25;License: ", FSE(skin.license), "]"; "label[3.5,2.75;Uploaded: ", FSE(skin.uploaded), "]"; - "label[3.5,3.25;", FSE(context.message or (skin.deleted and minetest.colorize(epidermis.colors.error:to_string(), "This skin was deleted!")) or ""), "]"; - ("hypertext[4.75,4.45;2,0.7;_of;%d/%d]"):format(context.index, #context.results), -- HACK + "label[3.5,3.25;", FSE(context.message + or (skin.deleted and minetest.colorize(epidermis.colors.error:to_string(), "This skin was deleted!")) or ""), "]"; + ("hypertext[4.75,4.45;2,0.7;_of;%d/%d]") + :format(context.index, #context.results), -- HACK "image_button[6.75,4.5;0.5,0.5;", FSE(epidermis.textures.dice), ";random;]"; "tooltip[random;Random]", "image_button[7.25,4.5;0.5,0.5;", FSE(epidermis.textures.previous), ";previous;]"; "tooltip[previous;Previous]", "image_button[7.75,4.5;0.5,0.5;", FSE(epidermis.textures.next), ";next;]"; "tooltip[next;Next]", - }, function(fields) + } + end + local function show_formspec() + epidermis.show_formspec(player, get_formspec(), function(fields) if fields.set then - local skin = context.results[context.index] - if skin.deleted then + local selected_skin = context.results[context.index] + if selected_skin.deleted then epidermis.send_notification(player, "The selected skin was deleted!") else - self:_set_texture(skin.texture, true) + self:_set_texture(selected_skin.texture, true) end return end diff --git a/tools.lua b/tools.lua index ddcb7db..32d5d69 100644 --- a/tools.lua +++ b/tools.lua @@ -48,7 +48,9 @@ minetest.register_craftitem("epidermis:spawner_colorpicker", { -- HACK assuming a node size of exactly one local face_pos = vector.divide(vector.add(pointed_thing.above, pointed_thing.under), 2) local direction = vector.direction(pointed_thing.under, pointed_thing.above) - local object = minetest.add_entity(vector.add(face_pos, vector.multiply(direction, colorpicker_thickness/2)), colorpicker_name) + local object = minetest.add_entity( + vector.add(face_pos, vector.multiply(direction, colorpicker_thickness/2)), + colorpicker_name) if not object then send_notification(user, "Can't spawn colorpicker!", "error") return @@ -68,7 +70,9 @@ local function set_item_color(itemstack, colorspec) -- Bright background: Choose a dark foreground color foreground = "#000000" end - itemstack:get_meta():set_string("description", minetest.get_background_escape_sequence(colorstring) .. minetest.colorize(foreground, itemstack:get_definition().description)) + itemstack:get_meta():set_string("description", + minetest.get_background_escape_sequence(colorstring) + .. minetest.colorize(foreground, itemstack:get_definition().description)) end local function get_entity(user, pointed_thing, allow_any) @@ -181,7 +185,7 @@ end) minetest.register_tool("epidermis:eraser", { description = "Eraser", inventory_image = "epidermis_eraser.png", - on_secondary_use = function(_itemstack, user, pointed_thing) + on_secondary_use = function(_, user, pointed_thing) local paintable = get_entity(user, pointed_thing) if not paintable then return @@ -201,7 +205,7 @@ minetest.register_tool("epidermis:eraser", { paintable:_update_texture() end end, - on_use = function(_itemstack, user, pointed_thing) + on_use = function(_, user, pointed_thing) local paintable = get_entity(user, pointed_thing) if not paintable then return @@ -219,7 +223,7 @@ minetest.register_tool("epidermis:eraser", { }) local function undo_redo_use_func(logname) - return function(_itemstack, user, pointed_thing) + return function(_, user, pointed_thing) local paintable = get_entity(user, pointed_thing) if not paintable then return @@ -244,9 +248,9 @@ register_color_tool("epidermis:filling_bucket", { inventory_image = "epidermis_filling_paint.png", inventory_overlay = "epidermis_filling_bucket.png", }, function(entity, pixelcoord, color) - local index = entity:_get_pixel_index(unpack(pixelcoord)) - local replace_color = entity:_get_color(index) - local to_fill = {[index] = replace_color} + local start_index = entity:_get_pixel_index(unpack(pixelcoord)) + local replace_color = entity:_get_color(start_index) + local to_fill = {[start_index] = replace_color} local additions local width, height = entity._.width, entity._.height local function fill(index) @@ -310,9 +314,14 @@ minetest.register_globalstep(function() local def = wielded_item:get_definition() local range = def.range or 4 local eye_pos = moblib.get_eye_pos(player) - local raycast = minetest.raycast(eye_pos, vector.add(eye_pos, vector.multiply(player:get_look_dir(), range)), true, def.liquids_pointable) + local raycast = minetest.raycast(eye_pos, + vector.add(eye_pos, vector.multiply(player:get_look_dir(), range)), + true, def.liquids_pointable) local pointed_thing = raycast() - if pointed_thing.type == "object" and pointed_thing.ref:is_player() and pointed_thing.ref:get_player_name() == name then + if pointed_thing.type == "object" + and pointed_thing.ref:is_player() + and pointed_thing.ref:get_player_name() == name + then -- Skip player pointed_thing = raycast(pointed_thing) end @@ -364,7 +373,8 @@ register_color_tool("epidermis:rectangle", { local max = modlib.vector.combine(pixelcoord_start, pixelcoord_end, math.max) local dim = max - min local preview = "^[combine:" .. entity._.width .. "x" .. entity._.height - .. ":" .. min[1] .."," .. min[2] .. "=epxw.png\\^[multiply\\:" .. color:to_string() .. "\\^[resize\\:" .. (dim[1] + 1) .. "x" .. (dim[2] + 1) + .. ":" .. min[1] .."," .. min[2] .. "=epxw.png\\^[multiply\\:" .. color:to_string() + .. "\\^[resize\\:" .. (dim[1] + 1) .. "x" .. (dim[2] + 1) entity:_update_texture(preview) end, pixels = function(pixelcoord_end) @@ -392,22 +402,23 @@ register_color_tool("epidermis:line", { entity = entity, -- A pixel preview is sufficient here as the line may at most have max(width, height) pixels pixels = function(pixelcoord_end) - local pixelcoord_start = pixelcoord_start + -- This might be copied & swapped. We don't want this to affect the upvalue, so we localize it. + local pixelcoord_start_copy = pixelcoord_start -- Uses Bresenham's line algorithm - local diff = modlib.vector.subtract(pixelcoord_end, pixelcoord_start) + local diff = modlib.vector.subtract(pixelcoord_end, pixelcoord_start_copy) if diff:norm() == 0 then -- Early return: We would divide by zero when obtaining the slope otherwise - local idx = entity:_get_pixel_index(unpack(pixelcoord_start)) + local idx = entity:_get_pixel_index(unpack(pixelcoord_start_copy)) return {[idx] = entity:_get_color(idx)}, color_argb end local swapped if math.abs(diff[2]) > math.abs(diff[1]) then swapped = true - pixelcoord_start = {pixelcoord_start[2], pixelcoord_start[1]} + pixelcoord_start_copy = {pixelcoord_start_copy[2], pixelcoord_start_copy[1]} pixelcoord_end = {pixelcoord_end[2], pixelcoord_end[1]} end local actions = {} - local min = pixelcoord_start + local min = pixelcoord_start_copy local max = pixelcoord_end if min[1] > max[1] then min, max = max, min