initial commit - Telemosaic by SaKeL - alpha

master
Juraj Vajda 2018-01-22 00:46:07 -05:00
commit 43d60e2bcc
20 changed files with 641 additions and 0 deletions

95
README.md Normal file
View File

@ -0,0 +1,95 @@
Telemosaic [telemosaic]
=======================
A Minetest mod for user-generated teleportation pads.
Version: 0.5.0
License:
Code: LGPL 2.1 (see included LICENSE file)
Textures: CC-BY-SA (see http://creativecommons.org/licenses/by-sa/4.0/)
Report bugs or request help on the forum topic.
Description
-----------
This is a mod for MineTest. It provides teleportation pads, called
"beacons". Unlike other teleportation mods, no menus or GUIs are used;
you set the destination with a simple "key" item. There is no
tooltip for the destination either, so signs are recommended.
Another difference is the limited default range of the beacons.
To increase the range, you need to place "extenders" around the beacon.
The extenders come in different colors, allowing the extenders to
form a pretty pattern; hence the name "telemosaic".
Current behavior
----------------
Beacons are created with 2 diamonds, 3 obsidian blocks, and a wooden
door: first row diamond, door, diamond; second row the obsidian blocks.
Right-clicking a beacon with a default mese crystal fragment remembers
the position in the fragment, which turns into a telemosaic key.
Right-clicking a second beacon with the key sets up a teleportation
route from the second beacon to the first beacon. To set up a return
path, right-click the second beacon with the fragment, and the first
beacon with the resulting key again.
The beacons do not need to be strictly paired this way: rings or
star-shaped networks are also possible. Each beacon has only a
single destination, but can itself be the destination of several
others.
Beacons will check that their destination is sane: the destination
still needs to be a beacon, and the two nodes above it should be
clear for walking / standing in. If your Minetest version supports
it, the beacon will emerge the area prior to checking and teleporting.
Emerging is merely a convenience, though.
Beacons have a maximum range of 20 nodes. If the destination is
too far away, the beacon will turn red and will not function.
To extend the range for a beacon, place "extenders" next to it,
within a 7x7 horizontal square centered on the beacon.
Extenders come in three tiers: tier 1 extends all affected beacons
by 5 nodes, tier 2 by 20 nodes, and tier 3 by 80 nodes. Placing
or digging extenders will update affected beacons.
Tier 1 extenders are crafted by placing an obsidian block, a wooden
door, and another obsidian block in a horizontal row. Tier 2 extenders
are crafted with an obsidian block in the middle, surrounded by a cross
of four tier 1 extenders. Tier 3 extenders are crafted with an obsidian
block surrounded by four tier 2 extenders.
Extenders can be colored with any of the dyes found in the dye mod.
Colored extenders work just like regular extenders, both for
teleporting and for recipes. To "uncolor" an extender, dye it grey.
Future plans
------------
* Particle and sound effects
* Protected beacons (will not teleport if protected)
Dependencies
------------
* default
* doors
* dye (optional)
Installation
------------
Unzip the archive, rename the folder to to `bewarethedark` and
place it in minetest/mods/
( Linux: If you have a linux system-wide installation place
it in ~/.minetest/mods/. )
( If you only want this to be used in a single world, place
the folder in worldmods/ in your worlddirectory. )
For further information or help see:
http://wiki.minetest.com/wiki/Installing_Mods

BIN
_material/nodes.xcf Normal file

Binary file not shown.

419
api.lua Normal file
View File

@ -0,0 +1,419 @@
local enable_particles = minetest.settings:get_bool("enable_particles")
telemosaic = {}
telemosaic.extender_ranges = {
-- not adding beacons here, since they don"t extend
["telemosaic:extender_one"] = 5,
["telemosaic:extender_two"] = 20,
["telemosaic:extender_three"] = 80
}
telemosaic.strengths = { "one", "two", "three" }
function telemosaic.effect_departure(pos)
minetest.sound_play("telemosaic_set", {
pos = pos,
max_hear_distance = 8,
gain = 1
})
if not enable_particles then return end
minetest.add_particlespawner({
amount = 100,
time = 0.25,
minpos = {x=pos.x, y=pos.y+0.3, z=pos.z},
maxpos = {x=pos.x, y=pos.y+2, z=pos.z},
minvel = {x = 1, y = -6, z = 1},
maxvel = {x = -1, y = -1, z = -1},
minacc = {x = 0, y = -2, z = 0},
maxacc = {x = 0, y = -6, z = 0},
minexptime = 0.1,
maxexptime = 1,
minsize = 0.5,
maxsize = 1.5,
texture = "telemosaic_particle_departure.png^[transform"..math.random(0,3),
glow = 15,
})
end
function telemosaic.effect_arrival(pos)
minetest.sound_play("telemosaic_teleport", {
pos = pos,
max_hear_distance = 8,
gain = 1
})
if not enable_particles then return end
minetest.add_particlespawner({
amount = 100,
time = 0.25,
minpos = {x=pos.x, y=pos.y+0.3, z=pos.z},
maxpos = {x=pos.x, y=pos.y+2, z=pos.z},
minvel = {x = -1, y = 1, z = -1},
maxvel = {x = 1, y = 6, z = 1},
minacc = {x = 0, y = -2, z = 0},
maxacc = {x = 0, y = -6, z = 0},
minexptime = 0.1,
maxexptime = 1,
minsize = 0.5,
maxsize = 1.5,
texture = "telemosaic_particle_arrival.png^[transform"..math.random(0,3),
glow = 15,
})
end
function telemosaic.get_formspec(pos, table)
local meta = minetest.get_meta(pos)
local arrivals_tbl = meta:get_string("arrivals_tbl")
local pos2_str = meta:get_string("dest_pos")
local pos2 = minetest.string_to_pos(pos2_str)
arrivals_tbl = minetest.deserialize(arrivals_tbl)
if not arrivals_tbl then arrivals_tbl = {} end
local range = table.range or 0
local bname = meta:get_string("bname")
if not bname or bname == "" then
bname = "beacon at: "..minetest.formspec_escape(minetest.pos_to_string(pos))
end
local textlist = ""
for ipos, ival in pairs(arrivals_tbl) do
textlist = textlist..minetest.formspec_escape(ipos)..": "..ival..","
end
local button_teleport = ""
local pos2_colorize = minetest.colorize("#ff0000", pos2_str)
if pos2 then
local meta2 = minetest.get_meta(pos2)
local bname2 = meta2:get_string("bname")
pos2_colorize = minetest.colorize("#00ff00", bname2)
button_teleport = "button_exit[0.1,7.5;2.4,1.5;teleport;Teleport Now]"
end
-- dynamic formspec
local formspec = "size[12,8.5]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
"label[0,0.5;beacon position: "..minetest.pos_to_string(pos).."]"..
"label[0,1;destinaton: "..pos2_colorize.."]"..
"label[0,1.5;range: "..range.." blocks]"..
"field[0.34,2.7;4,1;bname;beacon name:;"..bname.."]"..
button_teleport..
"button_exit[2.5,7.5;2.4,1.5;saveandclose;Save & Close]"..
"label[5,0;Arrivals from ( x | y | z ):]"..
"textlist[5,0.5;6.7,8;arrivals;"..textlist..";1;false]"
return formspec
end
minetest.register_on_player_receive_fields(function(player, formname, fields)
local mod_pos_pos2 = formname:split(":")
if fields.bname and mod_pos_pos2[1] == "telemosaic" then
local bname = fields.bname
local pos = minetest.string_to_pos(mod_pos_pos2[2])
local meta = minetest.get_meta(pos)
local pos2 = minetest.string_to_pos(mod_pos_pos2[3])
meta:set_string("bname", bname)
if pos2 then
local meta2 = minetest.get_meta(pos2)
local arrivals_tbl2 = meta2:get_string("arrivals_tbl")
arrivals_tbl2 = minetest.deserialize(arrivals_tbl2)
if not arrivals_tbl2 then arrivals_tbl2 = {} end
arrivals_tbl2[minetest.pos_to_string(pos)] = minetest.formspec_escape(bname)
meta2:set_string("arrivals_tbl", minetest.serialize(arrivals_tbl2))
end
if fields.teleport then
local range = meta:get_int("range")
if pos2 then
if math.floor(vector.distance(pos, pos2)) <= range then
pos2 = {x = pos2.x, y = pos2.y + 1, z = pos2.z}
-- attempt to emerge the target area before the player gets there
local vpos = vector.new(pos2)
minetest.get_voxel_manip():read_from_map(vpos, vpos)
if not minetest.get_node_or_nil(pos2) then
print("emerge area")
minetest.emerge_area(vector.subtract(vpos, 80), vector.add(vpos, 80))
end
minetest.after(5, function()
player:setpos(pos2)
telemosaic.effect_arrival(pos2)
telemosaic.effect_departure(pos)
end)
else
minetest.chat_send_player(player:get_player_name(), "Not enough power, destination is too far. Beacon needs "..math.floor(vector.distance(pos, pos2)) - range.." more power.")
end
end
end
end
end)
-- extenders
function telemosaic.extender_after_place(pos, placer, itemstack, pointed_thing)
local positions = minetest.find_nodes_in_area_under_air(
{x = pos.x - 3, y = pos.y, z = pos.z - 3},
{x = pos.x + 3, y = pos.y, z = pos.z + 3},
{"telemosaic:beacon_off", "telemosaic:beacon", "telemosaic:beacon_err"})
local meta = minetest.get_meta(pos)
local playername = placer:get_player_name()
local nodename = itemstack:get_name()
if not minetest.registered_nodes[nodename] then return end
local description = minetest.registered_nodes[nodename]["description"]
local power = telemosaic.extender_ranges[nodename]
for i, bpos in ipairs(positions) do
local bnode = minetest.get_node(bpos)
local bmeta = minetest.get_meta(bpos)
if not bnode then return end
local bnodename = bnode.name
if not minetest.registered_nodes[bnodename] then return end
local bdescription = minetest.registered_nodes[bnodename]["description"]
local bowner = bmeta:get_string("owner")
local brange = bmeta:get_int("range")
brange = brange + power
bmeta:set_int("range", brange)
telemosaic.set_status(bpos, placer)
bmeta:set_string("infotext", bdescription.."\nowner: "..bowner.."\nrange: "..brange.." blocks\nright-click to update info or with mese crystal fragment setup departure position")
end
meta:set_string("owner", playername)
meta:set_string("infotext", description.."\nowner: "..playername)
end
function telemosaic.extender_on_destruct(pos)
local node = minetest.get_node(pos)
if not node then return end
local meta = minetest.get_meta(pos)
local nodename = node.name
if not minetest.registered_nodes[nodename] then return end
local power = telemosaic.extender_ranges[nodename]
local positions = minetest.find_nodes_in_area_under_air(
{x = pos.x - 3, y = pos.y, z = pos.z - 3},
{x = pos.x + 3, y = pos.y, z = pos.z + 3},
{"telemosaic:beacon_off", "telemosaic:beacon", "telemosaic:beacon_err"})
for i, bpos in ipairs(positions) do
local bnode = minetest.get_node(bpos)
local bmeta = minetest.get_meta(bpos)
if not bmeta or not bnode then return end
local bnodename = bnode.name
if not minetest.registered_nodes[bnodename] then return end
local bdescription = minetest.registered_nodes[bnodename]["description"]
local bowner = bmeta:get_string("owner")
local brange = bmeta:get_int("range")
brange = brange - power
if brange < 0 then brange = 0 end
bmeta:set_int("range", brange)
telemosaic.set_status(bpos)
bmeta:set_string("infotext", bdescription.."\nowner: "..bowner.."\nrange: "..brange.." blocks\nright-click to update info or with mese crystal fragment setup departure position")
end
end
-- beacons
function telemosaic.get_range_from_extenders(be_pos)
local positions = minetest.find_nodes_in_area_under_air(
{x = be_pos.x - 3, y = be_pos.y, z = be_pos.z - 3},
{x = be_pos.x + 3, y = be_pos.y, z = be_pos.z + 3},
{"telemosaic:extender_one", "telemosaic:extender_two", "telemosaic:extender_three"})
local range = 0
for i, ex_pos in ipairs(positions) do
local inode = minetest.get_node(ex_pos)
if not inode then return end
range = range + telemosaic.extender_ranges[inode.name]
end
return range
end
function telemosaic.set_status(pos)
local meta = minetest.get_meta(pos)
if not meta then return end
local range = meta:get_int("range")
local pos2 = meta:get_string("dest_pos")
local state = meta:get_string("state")
local arrivals_tbl = meta:get_string("arrivals_tbl")
arrivals_tbl = minetest.deserialize(arrivals_tbl)
if not arrivals_tbl then arrivals_tbl = {} end
-- not enough energy (err)
if range <= 0 and
state ~= "err" then
minetest.swap_node(pos, { name = "telemosaic:beacon_err" })
meta:set_string("state", "err")
-- configured beacon (off)
elseif range > 0 and
pos2 == "not configured" and
state ~= "off" and
#arrivals_tbl == 0 then
minetest.swap_node(pos, { name = "telemosaic:beacon_off" })
meta:set_string("state", "off")
-- not configured beacon (on)
elseif range > 0 and
pos2 ~= "not configured" and
state ~= "on" then
minetest.swap_node(pos, { name = "telemosaic:beacon" })
meta:set_string("state", "on")
end
end
function telemosaic.beacon_after_place(pos, placer, itemstack, pointed_thing)
local meta = minetest.get_meta(pos)
local nodename = itemstack:get_name()
local playername = placer:get_player_name()
local range = telemosaic.get_range_from_extenders(pos)
if not minetest.registered_nodes[nodename] then return end
local bname = "beacon at: "..minetest.formspec_escape(minetest.pos_to_string(pos))
local description = minetest.registered_nodes[nodename]["description"]
meta:set_int("range", range)
meta:set_string("bname", bname)
meta:set_string("owner", playername)
meta:set_string("state", "off")
meta:set_string("dep_pos", "")
meta:set_string("dest_pos", "not configured")
meta:set_string("arrivals_tbl", "{}")
meta:set_string("infotext", description.."\nowner: "..playername.."\nrange: "..range.." blocks\nright-click to update info or with mese crystal fragment setup departure position")
telemosaic.set_status(pos)
end
function telemosaic.beacon_rightclick(pos, node, clicker, itemstack, pointed_thing)
local meta = minetest.get_meta(pos)
local meta_stack = itemstack:get_meta()
local ownername = meta:get_string("owner") or "unknown"
local clickername = clicker:get_player_name()
local nodename = node.name
local stackname = itemstack:get_name()
local range = telemosaic.get_range_from_extenders(pos)
local state = meta:get_string("state")
if not minetest.registered_nodes[nodename] then return end
local description = minetest.registered_nodes[nodename]["description"]
meta:set_int("range", range)
-- departure
if stackname == "default:mese_crystal_fragment" and itemstack:get_count() == 1 then
itemstack:replace("telemosaic:key")
meta_stack:set_string("dep_pos", minetest.pos_to_string(pos))
meta:set_string("infotext", description.."\nowner: "..ownername.."\nrange: "..range.." blocks\nstart pos: "..minetest.pos_to_string(pos).."\nright-click to update info")
-- destination
elseif stackname == "telemosaic:key" then
-- get deprature position from item
local pos_stack = meta_stack:get_string("dep_pos")
pos_stack = minetest.string_to_pos(pos_stack)
if math.floor(vector.distance(pos_stack, pos)) == 0 then
minetest.chat_send_player(clickername, "This is marked as your departure position, you have to mark your destination position now!")
return
elseif minetest.is_protected(pos, clickername) then
minetest.chat_send_player(clickername, "You cannot configure protected beacons!")
return
end
-- enough extenders / range
-- if math.floor(vector.distance(pos_stack, pos)) <= range then
minetest.swap_node(pos, { name = "telemosaic:beacon" })
meta:set_string("state", "on")
itemstack:replace("default:mese_crystal_fragment")
-- set arrival pos to departure pos node
local meta2 = minetest.get_meta(pos_stack)
local bname2 = meta2:get_string("bname")
local pos3 = meta2:get_string("dest_pos")
pos3 = minetest.string_to_pos(pos3)
if pos3 and math.floor(vector.distance(pos3, pos)) ~= 0 then
local meta3 = minetest.get_meta(pos3)
local arrivals_tbl3 = meta3:get_string("arrivals_tbl")
arrivals_tbl3 = minetest.deserialize(arrivals_tbl3)
if not arrivals_tbl3 then arrivals_tbl3 = {} end
arrivals_tbl3[minetest.pos_to_string(pos_stack)] = nil
meta3:set_string('arrivals_tbl', arrivals_tbl3)
telemosaic.set_status(pos3)
end
local arrivals_tbl = meta:get_string("arrivals_tbl")
arrivals_tbl = minetest.deserialize(arrivals_tbl)
if not arrivals_tbl then arrivals_tbl = {} end
arrivals_tbl[minetest.pos_to_string(pos_stack)] = bname2
arrivals_tbl = minetest.serialize(arrivals_tbl)
meta2:set_string("dest_pos", minetest.pos_to_string(pos))
meta:set_string("arrivals_tbl", arrivals_tbl)
telemosaic.set_status(pos_stack)
meta:set_string("infotext", description.."\nowner: "..ownername.."\nrange: "..range.." blocks\nend pos: "..minetest.pos_to_string(pos).."\nright-click to update info")
-- default place_node callback
elseif itemstack:get_definition().type == "node" then
itemstack = minetest.item_place_node(itemstack, clicker, pointed_thing)
else
-- mod : pos : pos2
-- - pos2 is from itemstack so not always set
local formspec = telemosaic.get_formspec(pos, {
range = range
})
local pos2 = meta:get_string("dest_pos")
minetest.show_formspec(clickername, "telemosaic:"..minetest.pos_to_string(pos)..":"..pos2, formspec)
meta:set_string("infotext", description.."\nowner: "..ownername.."\nrange: "..range.." blocks\nright-click to update info")
end
return itemstack
end
function telemosaic.beacon_on_destruct(pos)
local meta = minetest.get_meta(pos)
local pos2 = meta:get_string("dest_pos")
pos2 = minetest.string_to_pos(pos2)
local arrivals_tbl = meta:get_string("arrivals_tbl")
arrivals_tbl = minetest.deserialize(arrivals_tbl)
if not arrivals_tbl then arrivals_tbl = {} end
-- found destination position, will update the meta in destination
if pos2 then
local meta2 = minetest.get_meta(pos2)
local arrivals_tbl2 = meta2:get_string("arrivals_tbl")
arrivals_tbl2 = minetest.deserialize(arrivals_tbl2)
if not arrivals_tbl2 then arrivals_tbl2 = {} end
if arrivals_tbl2[minetest.pos_to_string(pos)] then
arrivals_tbl2[minetest.pos_to_string(pos)] = nil
arrivals_tbl2 = minetest.serialize(arrivals_tbl2)
meta2:set_string("arrivals_tbl", arrivals_tbl2)
end
meta2:set_string("dest_pos", "not configured")
telemosaic.set_status(pos2)
end
for k, v in pairs(arrivals_tbl) do
local ipos = minetest.string_to_pos(k)
local imeta = minetest.get_meta(ipos)
imeta:set_string("dest_pos", "not configured")
telemosaic.set_status(ipos)
end
end

37
crafting.lua Normal file
View File

@ -0,0 +1,37 @@
minetest.register_craft({
output = 'telemosaic:beacon_off',
recipe = {
{'default:diamond', 'doors:door_wood', 'default:diamond'},
{'default:obsidian','default:obsidian','default:obsidian'}
}
})
minetest.register_craft({
output = 'telemosaic:extender_one',
recipe = {
{"default:diamond","","default:diamond"},
{'default:obsidian','doors:door_wood','default:obsidian'}
}
})
minetest.register_craft({
output = 'telemosaic:extender_two',
recipe = {
{'', 'group:telemosaic_extender_one',''},
{'group:telemosaic_extender_one','default:obsidian','group:telemosaic_extender_one'},
{'', 'group:telemosaic_extender_one',''}
}
})
minetest.register_craft({
output = 'telemosaic:extender_three',
recipe = {
{'', 'group:telemosaic_extender_two',''},
{'group:telemosaic_extender_two','default:obsidian','group:telemosaic_extender_two'},
{'', 'group:telemosaic_extender_two',''}
}
})
-- how to recycle a key
minetest.register_craft({
type = 'shapeless',
recipe = {'telemosaic:key'},
output = 'default:mese_crystal_fragment'
})

2
depends.txt Normal file
View File

@ -0,0 +1,2 @@
default
doors

7
init.lua Normal file
View File

@ -0,0 +1,7 @@
MOD_NAME = minetest.get_current_modname()
dofile(minetest.get_modpath(MOD_NAME).."/api.lua")
dofile(minetest.get_modpath(MOD_NAME).."/nodes.lua")
dofile(minetest.get_modpath(MOD_NAME).."/crafting.lua")
print ("[Mod] Telemosaic Loaded.")

81
nodes.lua Normal file
View File

@ -0,0 +1,81 @@
-- extenders come in three strengths
for num, strength in ipairs(telemosaic.strengths) do
minetest.register_node("telemosaic:extender_"..strength, {
description = "Telemosaic extender, tier "..num..", extends beacon range by: "..telemosaic.extender_ranges["telemosaic:extender_"..strength].." blocks",
tiles = { "telemosaic_extender_"..strength..".png" },
is_ground_content = false,
groups = { cracky = 2, ["telemosaic_extender_"..strength] = 1 },
sounds = default.node_sound_stone_defaults(),
after_place_node = telemosaic.extender_after_place,
on_destruct = telemosaic.extender_on_destruct,
})
end
-- beacons
minetest.register_node("telemosaic:beacon_off", {
description = "Telemosaic beacon (off)",
tiles = {
"telemosaic_beacon_off.png",
"telemosaic_beacon_off.png",
"telemosaic_beacon_side.png",
"telemosaic_beacon_side.png",
"telemosaic_beacon_side.png",
"telemosaic_beacon_side.png",
},
is_ground_content = false,
groups = { cracky = 2 },
sounds = default.node_sound_stone_defaults(),
after_place_node = telemosaic.beacon_after_place,
on_rightclick = telemosaic.beacon_rightclick,
on_destruct = telemosaic.beacon_on_destruct,
on_receive_fields = telemosaic.on_receive_fields,
})
minetest.register_node("telemosaic:beacon", {
description = "Telemosaic beacon (on)",
tiles = {
"telemosaic_beacon_top.png",
"telemosaic_beacon_side.png",
"telemosaic_beacon_side.png",
"telemosaic_beacon_side.png",
"telemosaic_beacon_side.png",
"telemosaic_beacon_side.png",
},
is_ground_content = false,
groups = { cracky = 2 },
-- groups = { cracky = 2, not_in_creative_inventory = 1 },
drop = "telemosaic:beacon_off",
sounds = default.node_sound_stone_defaults(),
on_rightclick = telemosaic.beacon_rightclick,
on_destruct = telemosaic.beacon_on_destruct,
on_receive_fields = telemosaic.on_receive_fields,
-- on_punch = telemosaic.beacon_on_punch,
})
minetest.register_node("telemosaic:beacon_err", {
description = "Telemosaic beacon (err)",
tiles = {
"telemosaic_beacon_err.png",
"telemosaic_beacon_side.png",
"telemosaic_beacon_side.png",
"telemosaic_beacon_side.png",
"telemosaic_beacon_side.png",
"telemosaic_beacon_side.png",
},
is_ground_content = false,
groups = { cracky = 2 },
-- groups = { cracky = 2, not_in_creative_inventory = 1 },
drop = "telemosaic:beacon_off",
sounds = default.node_sound_stone_defaults(),
on_rightclick = telemosaic.beacon_rightclick,
on_destruct = telemosaic.beacon_on_destruct,
on_receive_fields = telemosaic.on_receive_fields,
})
-- telemosaic key
minetest.register_tool("telemosaic:key", {
description = "Telemosaic key",
inventory_image = "telemosaic_key.png",
stack_max = 1,
-- groups = { not_in_creative_inventory = 1 },
})

BIN
sounds/telemosaic_set.ogg Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 460 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 596 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 593 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 365 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 376 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 373 B

BIN
textures/telemosaic_key.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 322 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 B