xmaps/init.lua

384 lines
8.3 KiB
Lua
Raw Normal View History

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
)