2022-05-17 06:49:56 +02:00
|
|
|
|
--[[
|
|
|
|
|
|
|
|
|
|
maps – Minetest mod to render very ugly HUD maps
|
|
|
|
|
Copyright © 2022 Nils Dagsson Moskopp (erlehmann)
|
|
|
|
|
|
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
|
|
|
it under the terms of the GNU Affero General Public License as
|
|
|
|
|
published by the Free Software Foundation, either version 3 of the
|
|
|
|
|
License, or (at your option) any later version.
|
|
|
|
|
|
|
|
|
|
Dieses Programm hat das Ziel, die Medienkompetenz der Leser zu
|
|
|
|
|
steigern. Gelegentlich packe ich sogar einen handfesten Buffer
|
|
|
|
|
Overflow oder eine Format String Vulnerability zwischen die anderen
|
|
|
|
|
Codezeilen und schreibe das auch nicht dran.
|
|
|
|
|
|
|
|
|
|
]]--
|
|
|
|
|
|
2022-05-19 03:19:25 +02:00
|
|
|
|
-- blit an icon into the image unless its rect overlaps pixels that
|
|
|
|
|
-- have any of the stop_colors, treating a nil pixel as transparent
|
|
|
|
|
function tga_encoder.image:blit_icon(icon, pos, stop_colors)
|
|
|
|
|
local x = pos.x
|
|
|
|
|
local z = pos.z
|
|
|
|
|
local overlap = false
|
|
|
|
|
for i_z = 1,#icon do
|
|
|
|
|
for i_x = 1,#icon[i_z] do
|
|
|
|
|
local color = self.pixels[z + i_z][x + i_x][1]
|
|
|
|
|
if stop_colors[color] then
|
|
|
|
|
overlap = true
|
|
|
|
|
break
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
if overlap then
|
|
|
|
|
break
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
if overlap then
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
for i_z = 1,#icon do
|
|
|
|
|
for i_x = 1,#icon[i_z] do
|
|
|
|
|
local color = icon[i_z][i_x][1]
|
|
|
|
|
if color then
|
|
|
|
|
self.pixels[z + i_z][x + i_x] = { color }
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2022-05-17 06:49:56 +02:00
|
|
|
|
maps = {}
|
|
|
|
|
maps.dots = {}
|
|
|
|
|
maps.maps = {}
|
|
|
|
|
maps.minp = {}
|
|
|
|
|
maps.maxp = {}
|
|
|
|
|
maps.work = {}
|
|
|
|
|
maps.sent = {}
|
|
|
|
|
maps.posx = {}
|
|
|
|
|
maps.posz = {}
|
|
|
|
|
|
2022-05-17 13:00:47 +02:00
|
|
|
|
local size = 80
|
|
|
|
|
|
2022-05-17 06:49:56 +02:00
|
|
|
|
local worldpath = minetest.get_worldpath()
|
|
|
|
|
local textures_dir = worldpath .. "/maps/"
|
|
|
|
|
minetest.mkdir(textures_dir)
|
|
|
|
|
|
|
|
|
|
maps.create_map = function(pos, player_name)
|
2022-05-17 13:00:47 +02:00
|
|
|
|
local minp = vector.multiply(vector.floor(vector.divide(pos, size)), size)
|
|
|
|
|
local maxp = vector.add(minp, vector.new(size - 1, size - 1, size - 1))
|
2022-05-17 06:49:56 +02:00
|
|
|
|
|
|
|
|
|
local prefix, _ = minetest.pos_to_string(maxp)
|
|
|
|
|
prefix, _ = prefix:gsub("%(", "")
|
|
|
|
|
prefix, _ = prefix:gsub("%)", "")
|
|
|
|
|
prefix, _ = prefix:gsub(",", "_")
|
|
|
|
|
local filename = prefix .. ".tga"
|
|
|
|
|
|
|
|
|
|
if maps.work[filename] then
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local player = minetest.get_player_by_name(player_name)
|
|
|
|
|
|
|
|
|
|
if maps.sent[filename] then
|
|
|
|
|
maps.minp[player_name] = minp
|
|
|
|
|
maps.maxp[player_name] = maxp
|
|
|
|
|
player:hud_change(
|
|
|
|
|
maps.maps[player_name],
|
|
|
|
|
"text",
|
|
|
|
|
filename
|
|
|
|
|
)
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
maps.work[filename] = true
|
|
|
|
|
|
|
|
|
|
player:hud_change(
|
|
|
|
|
maps.maps[player_name],
|
|
|
|
|
"text",
|
|
|
|
|
"blank.png"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
local emerge_callback = function(
|
|
|
|
|
blockpos,
|
|
|
|
|
action,
|
|
|
|
|
calls_remaining
|
|
|
|
|
)
|
|
|
|
|
if calls_remaining > 0 then
|
|
|
|
|
return
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local pixels = {}
|
|
|
|
|
local colormap = {
|
2022-05-17 17:15:04 +02:00
|
|
|
|
{ 195, 175, 140 }, -- background
|
|
|
|
|
{ 60, 35, 16 }, -- dark line
|
|
|
|
|
{ 210, 170, 130 }, -- liquid light
|
2022-05-17 20:31:14 +02:00
|
|
|
|
{ 135, 90, 40 }, -- liquid dark
|
|
|
|
|
{ 150, 105, 55 }, -- more liquid
|
|
|
|
|
{ 165, 120, 70 }, -- more liquid
|
|
|
|
|
{ 150, 105, 55 }, -- more liquid
|
2022-05-18 21:29:17 +02:00
|
|
|
|
{ 60, 35, 16 }, -- tree outline
|
|
|
|
|
{ 150, 105, 55 }, -- tree fill
|
2022-05-17 06:49:56 +02:00
|
|
|
|
}
|
2022-05-17 13:00:47 +02:00
|
|
|
|
for x = 1,size,1 do
|
|
|
|
|
for z = 1,size,1 do
|
2022-05-17 06:49:56 +02:00
|
|
|
|
local color = { 0 }
|
|
|
|
|
pixels[z] = pixels[z] or {}
|
|
|
|
|
pixels[z][x] = color
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2022-05-17 17:15:04 +02:00
|
|
|
|
local positions = minetest.find_nodes_in_area_under_air(
|
|
|
|
|
minp,
|
|
|
|
|
maxp,
|
|
|
|
|
"group:liquid"
|
|
|
|
|
)
|
|
|
|
|
for _, p in ipairs(positions) do
|
|
|
|
|
local z = p.z - minp.z + 1
|
|
|
|
|
local x = p.x - minp.x + 1
|
|
|
|
|
pixels[z][x] = { 2 }
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- draw coastline
|
|
|
|
|
for x = 1,size,1 do
|
|
|
|
|
for z = 1,size,1 do
|
2022-05-17 20:31:14 +02:00
|
|
|
|
if pixels[z][x][1] >= 2 then
|
|
|
|
|
pixels[z][x] = { 2 + ( z % 2 ) } -- stripes
|
|
|
|
|
if pixels[z][x][1] == 3 then
|
|
|
|
|
pixels[z][x] = { 3 + ( ( math.floor( x / 7 ) + math.floor( 1.3 * z * z ) ) % 4 ) }
|
|
|
|
|
end
|
2022-05-17 17:15:04 +02:00
|
|
|
|
if z > 1 and pixels[z-1][x][1] < 2 then
|
|
|
|
|
pixels[z-1][x] = { 1 }
|
2022-05-17 20:31:14 +02:00
|
|
|
|
pixels[z][x] = { 3 }
|
2022-05-17 17:15:04 +02:00
|
|
|
|
end
|
|
|
|
|
if z < size and pixels[z+1][x][1] < 2 then
|
|
|
|
|
pixels[z+1][x] = { 1 }
|
2022-05-17 20:31:14 +02:00
|
|
|
|
pixels[z][x] = { 3 }
|
2022-05-17 17:15:04 +02:00
|
|
|
|
end
|
|
|
|
|
if x > 1 and pixels[z][x-1][1] < 2 then
|
|
|
|
|
pixels[z][x-1] = { 1 }
|
2022-05-17 20:31:14 +02:00
|
|
|
|
pixels[z][x] = { 3 }
|
2022-05-17 17:15:04 +02:00
|
|
|
|
end
|
|
|
|
|
if x < size and pixels[z][x+1][1] < 2 then
|
|
|
|
|
pixels[z][x+1] = { 1 }
|
2022-05-17 20:31:14 +02:00
|
|
|
|
pixels[z][x] = { 3 }
|
2022-05-17 17:15:04 +02:00
|
|
|
|
end
|
|
|
|
|
end
|
2022-05-17 06:49:56 +02:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2022-05-19 03:19:25 +02:00
|
|
|
|
local image = tga_encoder.image(pixels)
|
|
|
|
|
|
2022-05-18 21:29:17 +02:00
|
|
|
|
local positions = minetest.find_nodes_in_area_under_air(
|
|
|
|
|
minp,
|
|
|
|
|
maxp,
|
|
|
|
|
{
|
|
|
|
|
"group:leaves",
|
|
|
|
|
"default:snow", -- snow-covered leaves
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
for _, p in ipairs(positions) do
|
|
|
|
|
local z = p.z - minp.z + 1
|
|
|
|
|
local x = p.x - minp.x + 1
|
|
|
|
|
local node = minetest.get_node({
|
|
|
|
|
x=p.x,
|
|
|
|
|
y=p.y - 4,
|
|
|
|
|
z=p.z,
|
|
|
|
|
})
|
|
|
|
|
local draw_tree = (
|
|
|
|
|
minetest.get_item_group(
|
|
|
|
|
node.name,
|
|
|
|
|
"tree"
|
|
|
|
|
) > 0 ) and (
|
2022-05-19 03:46:40 +02:00
|
|
|
|
z > 1 and
|
|
|
|
|
z < size - 7 and
|
|
|
|
|
x > 4 and
|
|
|
|
|
x < size - 4
|
2022-05-18 21:29:17 +02:00
|
|
|
|
)
|
|
|
|
|
if draw_tree then
|
|
|
|
|
local tree = {}
|
2022-05-19 03:19:25 +02:00
|
|
|
|
local _ = { nil } -- transparent
|
|
|
|
|
local O = { 7 } -- outline
|
|
|
|
|
local F = { 8 } -- filling
|
2022-05-18 21:29:17 +02:00
|
|
|
|
if nil ~= node.name:find("pine") then
|
|
|
|
|
tree = {
|
2022-05-19 03:46:40 +02:00
|
|
|
|
{ _, _, _, _, _, _, _ },
|
|
|
|
|
{ _, _, _, O, _, _, _ },
|
|
|
|
|
{ _, O, O, O, O, O, _ },
|
|
|
|
|
{ _, O, F, F, F, O, _ },
|
|
|
|
|
{ _, _, O, F, O, _, _ },
|
|
|
|
|
{ _, _, O, F, O, _, _ },
|
|
|
|
|
{ _, _, _, O, _, _, _ },
|
|
|
|
|
{ _, _, _, _, _, _, _ },
|
2022-05-18 21:29:17 +02:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
tree = {
|
2022-05-19 03:46:40 +02:00
|
|
|
|
{ _, _, _, _, _, _, _ },
|
|
|
|
|
{ _, _, _, O, _, _, _ },
|
|
|
|
|
{ _, _, _, O, _, _, _ },
|
|
|
|
|
{ _, _, O, O, O, _, _ },
|
|
|
|
|
{ _, O, F, F, F, O, _ },
|
|
|
|
|
{ _, O, F, F, F, O, _ },
|
|
|
|
|
{ _, _, O, O, O, _, _ },
|
|
|
|
|
{ _, _, _, _, _, _, _ },
|
2022-05-18 21:29:17 +02:00
|
|
|
|
}
|
|
|
|
|
end
|
2022-05-19 03:19:25 +02:00
|
|
|
|
image:blit_icon(
|
|
|
|
|
tree,
|
|
|
|
|
{
|
2022-05-19 03:46:40 +02:00
|
|
|
|
x = x - 4,
|
|
|
|
|
z = z - 1,
|
2022-05-19 03:19:25 +02:00
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
[3] = true,
|
|
|
|
|
[4] = true,
|
|
|
|
|
[5] = true,
|
|
|
|
|
[6] = true,
|
|
|
|
|
[7] = true,
|
|
|
|
|
[8] = true
|
|
|
|
|
}
|
|
|
|
|
)
|
2022-05-18 21:29:17 +02:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2022-05-19 03:35:26 +02:00
|
|
|
|
local positions = minetest.find_nodes_in_area_under_air(
|
|
|
|
|
minp,
|
|
|
|
|
maxp,
|
|
|
|
|
"group:grass"
|
|
|
|
|
)
|
|
|
|
|
for _, p in ipairs(positions) do
|
|
|
|
|
local z = p.z - minp.z + 1
|
|
|
|
|
local x = p.x - minp.x + 1
|
|
|
|
|
local draw_grass = (
|
|
|
|
|
z > 1 and
|
|
|
|
|
z < size - 4 and
|
|
|
|
|
x > 4 and
|
|
|
|
|
x < size - 4
|
|
|
|
|
)
|
|
|
|
|
if draw_grass then
|
|
|
|
|
local _ = { nil } -- transparent
|
|
|
|
|
local G = { 8 } -- line
|
|
|
|
|
local grass = {
|
|
|
|
|
{ _, _, _, _, _, _, _ },
|
|
|
|
|
{ _, G, _, G, _, G, _ },
|
|
|
|
|
{ _, G, _, G, _, G, _ },
|
|
|
|
|
{ _, _, _, G, _, _, _ },
|
|
|
|
|
{ _, _, _, _, _, _, _ },
|
|
|
|
|
}
|
|
|
|
|
image:blit_icon(
|
|
|
|
|
grass,
|
|
|
|
|
{
|
|
|
|
|
x = x - 5,
|
|
|
|
|
z = z - 1,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
[3] = true,
|
|
|
|
|
[4] = true,
|
|
|
|
|
[5] = true,
|
|
|
|
|
[6] = true,
|
|
|
|
|
[7] = true,
|
|
|
|
|
[8] = true
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2022-05-17 06:49:56 +02:00
|
|
|
|
local filepath = textures_dir .. filename
|
2022-05-19 03:19:25 +02:00
|
|
|
|
image:save(
|
2022-05-17 06:49:56 +02:00
|
|
|
|
filepath,
|
|
|
|
|
{ colormap=colormap }
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
minetest.dynamic_add_media(
|
|
|
|
|
filepath,
|
|
|
|
|
function()
|
|
|
|
|
local player =minetest.get_player_by_name(player_name)
|
|
|
|
|
player:hud_change(
|
|
|
|
|
maps.maps[player_name],
|
|
|
|
|
"text",
|
|
|
|
|
filename
|
|
|
|
|
)
|
|
|
|
|
maps.minp[player_name] = minp
|
|
|
|
|
maps.maxp[player_name] = maxp
|
|
|
|
|
maps.sent[filename] = true
|
|
|
|
|
maps.work[filename] = false
|
|
|
|
|
end
|
|
|
|
|
)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
minetest.emerge_area(
|
|
|
|
|
minp,
|
|
|
|
|
maxp,
|
|
|
|
|
emerge_callback
|
|
|
|
|
)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
minetest.register_on_joinplayer(
|
|
|
|
|
function(player)
|
|
|
|
|
local player_name = player:get_player_name()
|
|
|
|
|
local map_def = {
|
|
|
|
|
hud_elem_type = "image",
|
|
|
|
|
text = "blank.png",
|
|
|
|
|
position = { x = 0.15, y = 0.90 },
|
|
|
|
|
alignment = { x = 0, y = -1 },
|
|
|
|
|
offset = { x = 0, y = 0 },
|
|
|
|
|
scale = { x = 4, y = 4 }
|
|
|
|
|
}
|
|
|
|
|
local dot_def = table.copy(map_def)
|
2022-05-17 17:15:04 +02:00
|
|
|
|
dot_def.text = "maps_x.tga" -- "player.png^[resize:4x8"
|
2022-05-17 06:49:56 +02:00
|
|
|
|
maps.maps[player_name] = player:hud_add(map_def)
|
|
|
|
|
maps.dots[player_name] = player:hud_add(dot_def)
|
|
|
|
|
maps.minp[player_name] = { x=-32000, y=0, z=0 }
|
|
|
|
|
maps.maxp[player_name] = { x=-32000, y=0, z=0 }
|
|
|
|
|
end
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
local time_elapsed = 0
|
|
|
|
|
|
|
|
|
|
minetest.register_globalstep(
|
|
|
|
|
function(dtime)
|
|
|
|
|
time_elapsed = time_elapsed + dtime
|
|
|
|
|
if time_elapsed < ( 1 / 30 ) then
|
|
|
|
|
return -- fps limiter
|
|
|
|
|
end
|
|
|
|
|
local players = minetest.get_connected_players()
|
|
|
|
|
for _, player in pairs(players) do
|
|
|
|
|
local pos = vector.round(player:get_pos())
|
|
|
|
|
local player_name = player:get_player_name()
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
pos.x == maps.posx[player_name] and
|
|
|
|
|
pos.z == maps.posz[player_name]
|
|
|
|
|
) then
|
|
|
|
|
-- continue
|
|
|
|
|
else
|
|
|
|
|
local minp = maps.minp[player_name]
|
|
|
|
|
local maxp = maps.maxp[player_name]
|
|
|
|
|
|
|
|
|
|
if pos.x < minp.x then
|
|
|
|
|
maps.create_map(pos, player_name)
|
|
|
|
|
elseif pos.x > maxp.x then
|
|
|
|
|
maps.create_map(pos, player_name)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if pos.z < minp.z then
|
|
|
|
|
maps.create_map(pos, player_name)
|
|
|
|
|
elseif pos.z > maxp.z then
|
|
|
|
|
maps.create_map(pos, player_name)
|
|
|
|
|
end
|
|
|
|
|
|
2022-05-17 13:00:47 +02:00
|
|
|
|
local x = (pos.x - minp.x - (size/2)) * 4
|
2022-05-17 06:49:56 +02:00
|
|
|
|
local y = (minp.z - pos.z) * 4 - 2
|
|
|
|
|
player:hud_change(
|
|
|
|
|
maps.dots[player_name],
|
|
|
|
|
"offset",
|
|
|
|
|
{
|
|
|
|
|
x = x,
|
|
|
|
|
y = y,
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
maps.posx[player_name] = pos.x
|
|
|
|
|
maps.posz[player_name] = pos.z
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
)
|