Add numbers over numberblocks up to 100
Floating number blocks are added based on 8x16 textures of the digits 0-9. These are placed above the closest top level block to the average position of the top level blocks, and automatically updated when the numberblock is changed. Signed-off-by: James Hogan <james@albanarts.com>master
1
init.lua
|
@ -1,2 +1,3 @@
|
|||
dofile(minetest.get_modpath("numberblocks") .. "/utils.lua")
|
||||
dofile(minetest.get_modpath("numberblocks") .. "/blocks.lua")
|
||||
dofile(minetest.get_modpath("numberblocks") .. "/numbers.lua")
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
-- shape of centred single digit numbers
|
||||
local node_box_single_centre = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-0.1875, -0.375, -0.0625, 0.1875, 0.375, 0.0625},
|
||||
},
|
||||
}
|
||||
-- shape of right justified single digit numbers
|
||||
local node_box_single_right = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{0.0625, -0.375, 0, 0.4375, 0.375, 0},
|
||||
},
|
||||
}
|
||||
-- shape of double digit numbers
|
||||
local node_box_double = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-0.4375, -0.375, 0, 0.4375, 0.375, 0},
|
||||
},
|
||||
}
|
||||
|
||||
for i = 1,9 do
|
||||
minetest.register_node("numberblocks:number_centre_"..tostring(i), {
|
||||
description = "Number "..tostring(i).." (centre)",
|
||||
tiles = {
|
||||
"numberblocks_blank.png",
|
||||
"numberblocks_blank.png",
|
||||
"numberblocks_blank.png",
|
||||
"numberblocks_blank.png",
|
||||
"numberblocks_blank.png^[combine:8x16:4,0=numberblocks_number_"..tostring(i)..".png^[transformFX",
|
||||
"numberblocks_blank.png^[combine:8x16:4,0=numberblocks_number_"..tostring(i)..".png",
|
||||
},
|
||||
groups = { cracky = 2, not_in_creative_inventory = 1 },
|
||||
drop = "",
|
||||
|
||||
drawtype = "nodebox",
|
||||
paramtype = "light",
|
||||
node_box = node_box_single_centre,
|
||||
})
|
||||
for j = 0,9 do
|
||||
minetest.register_node("numberblocks:number_"..tostring(i)..tostring(j), {
|
||||
description = "Number "..tostring(i)..tostring(j),
|
||||
tiles = {
|
||||
"numberblocks_blank.png",
|
||||
"numberblocks_blank.png",
|
||||
"numberblocks_blank.png",
|
||||
"numberblocks_blank.png",
|
||||
"numberblocks_blank.png^[combine:8x16:0,0=numberblocks_number_"..tostring(i)..".png:8,0=numberblocks_number_"..tostring(j)..".png^[transformFX",
|
||||
"numberblocks_blank.png^[combine:8x16:0,0=numberblocks_number_"..tostring(i)..".png:8,0=numberblocks_number_"..tostring(j)..".png",
|
||||
},
|
||||
groups = { cracky = 2, not_in_creative_inventory = 1 },
|
||||
drop = "",
|
||||
|
||||
drawtype = "nodebox",
|
||||
paramtype = "light",
|
||||
node_box = node_box_double,
|
||||
})
|
||||
end
|
||||
end
|
After Width: | Height: | Size: 101 B |
After Width: | Height: | Size: 124 B |
After Width: | Height: | Size: 104 B |
After Width: | Height: | Size: 145 B |
After Width: | Height: | Size: 146 B |
After Width: | Height: | Size: 131 B |
After Width: | Height: | Size: 145 B |
After Width: | Height: | Size: 145 B |
After Width: | Height: | Size: 121 B |
After Width: | Height: | Size: 125 B |
After Width: | Height: | Size: 133 B |
206
update.lua
|
@ -7,31 +7,41 @@ local adjacent_vectors = {
|
|||
{ x = 0, y = 0, z = 1 }
|
||||
}
|
||||
|
||||
NODE_NONE = 0
|
||||
NODE_BLOCK = 1
|
||||
NODE_NUMBER = 2
|
||||
|
||||
function nodes_test(nodes, pos)
|
||||
if not nodes[pos.y] then
|
||||
return false
|
||||
return NODE_NONE
|
||||
end
|
||||
if not nodes[pos.y][pos.x] then
|
||||
return false
|
||||
return NODE_NONE
|
||||
end
|
||||
if not nodes[pos.y][pos.x][pos.z] then
|
||||
return false
|
||||
return NODE_NONE
|
||||
end
|
||||
return true
|
||||
return nodes[pos.y][pos.x][pos.z]
|
||||
end
|
||||
|
||||
function nodes_set(nodes, pos)
|
||||
function nodes_set(nodes, pos, node_type)
|
||||
if not nodes[pos.y] then
|
||||
nodes[pos.y] = {}
|
||||
end
|
||||
if not nodes[pos.y][pos.x] then
|
||||
nodes[pos.y][pos.x] = {}
|
||||
end
|
||||
nodes[pos.y][pos.x][pos.z] = true
|
||||
nodes[pos.y][pos.x][pos.z] = node_type
|
||||
end
|
||||
|
||||
function is_number_block(node)
|
||||
return string.sub(node.name,1,string.len("numberblocks:block")) == "numberblocks:block"
|
||||
function get_node_type(node)
|
||||
if string.sub(node.name, 1, string.len("numberblocks:block")) == "numberblocks:block" then
|
||||
return NODE_BLOCK
|
||||
elseif string.sub(node.name, 1, string.len("numberblocks:number")) == "numberblocks:number" then
|
||||
return NODE_NUMBER
|
||||
else
|
||||
return NODE_NONE
|
||||
end
|
||||
end
|
||||
|
||||
function find_blocks(pos)
|
||||
|
@ -40,31 +50,42 @@ function find_blocks(pos)
|
|||
|
||||
-- Assume pointed_thing is a node
|
||||
local node = minetest.get_node(pos)
|
||||
if not is_number_block(node) then
|
||||
local node_type = get_node_type(node)
|
||||
local count = 0;
|
||||
local allcount = 1;
|
||||
if node_type == NODE_NONE then
|
||||
return nodes, 0
|
||||
elseif node_type == NODE_BLOCK then
|
||||
count = 1
|
||||
end
|
||||
nodes_set(nodes, pos)
|
||||
local count = 1;
|
||||
nodes_set(nodes, pos, node_type)
|
||||
|
||||
local unhandled = { pos }
|
||||
local unhandled = { { pos, node_type } }
|
||||
|
||||
-- start at the pointed node and expand out looking for more connected nodes
|
||||
-- have a list of unfinished nodes
|
||||
while #unhandled > 0 do
|
||||
local max = table.maxn(unhandled)
|
||||
pos = unhandled[max]
|
||||
pos = unhandled[max][1]
|
||||
node_type = unhandled[max][2]
|
||||
table.remove(unhandled, max)
|
||||
|
||||
-- Look in all directions from this node for more
|
||||
for i = 1, 6 do
|
||||
local pos2 = vector.add(pos, adjacent_vectors[i])
|
||||
if not nodes_test(nodes, pos2) then
|
||||
if nodes_test(nodes, pos2) == NODE_NONE then
|
||||
node = minetest.get_node(pos2)
|
||||
if is_number_block(node) then
|
||||
nodes_set(nodes, pos2)
|
||||
table.insert(unhandled, pos2)
|
||||
count = count + 1
|
||||
if count > 100 then
|
||||
local adj_node_type = get_node_type(node);
|
||||
if (node_type == NODE_BLOCK and adj_node_type == NODE_BLOCK) or
|
||||
(i == 3 and node_type == NODE_NUMBER and adj_node_type == NODE_BLOCK) or
|
||||
(i == 4 and node_type == NODE_BLOCK and adj_node_type == NODE_NUMBER) then
|
||||
nodes_set(nodes, pos2, adj_node_type)
|
||||
table.insert(unhandled, { pos2, adj_node_type })
|
||||
if adj_node_type == NODE_BLOCK then
|
||||
count = count + 1
|
||||
end
|
||||
allcount = allcount + 1
|
||||
if allcount > 100 then
|
||||
return nodes, count
|
||||
end
|
||||
end
|
||||
|
@ -75,55 +96,115 @@ function find_blocks(pos)
|
|||
return nodes, count
|
||||
end
|
||||
|
||||
-- Change the colour of blocks depending on the number of them
|
||||
function restyle_blocks(nodes, count)
|
||||
local i = 0
|
||||
for y,xs in orderedPairs(nodes) do
|
||||
for x,zs in orderedPairs(xs) do
|
||||
for z in orderedPairs(zs) do
|
||||
local pos = {x = x, y = y, z = z};
|
||||
local function numberblocks_add_number(pos, number)
|
||||
-- FIXME check space is unoccupied
|
||||
if number < 10 then
|
||||
minetest.set_node(pos, { name = "numberblocks:number_centre_"..tostring(number) })
|
||||
elseif number < 100 then
|
||||
minetest.set_node(pos, { name = "numberblocks:number_"..tostring(number) })
|
||||
else
|
||||
-- TODO
|
||||
end
|
||||
end
|
||||
|
||||
if count >= 10 and count < 100 then
|
||||
local tens = math.floor(count/10)*10
|
||||
if tens == 70 then
|
||||
local tens_in_70 = 10 + math.floor(i/10)*10
|
||||
if tens_in_70 == 10 then
|
||||
tens_in_70 = 71
|
||||
elseif tens_in_70 == 70 then
|
||||
tens_in_70 = 77
|
||||
-- Change the colour of blocks depending on the number of them
|
||||
local function numberblocks_restyle_blocks(nodes, count)
|
||||
-- find best place for number nodes
|
||||
local max_y = -31000
|
||||
local sum_pos = { x = 0, y = 0, z = 0 }
|
||||
local sum_count = 0
|
||||
|
||||
local left = count;
|
||||
local i = 0
|
||||
for y, xs in orderedPairs(nodes) do
|
||||
for x, zs in orderedPairs(xs) do
|
||||
for z, node_type in orderedPairs(zs) do
|
||||
local pos = {x = x, y = y, z = z};
|
||||
if node_type == NODE_NUMBER then
|
||||
minetest.remove_node(pos)
|
||||
elseif node_type == NODE_BLOCK then
|
||||
-- if new highest block, discard average XZ state
|
||||
if y > max_y then
|
||||
max_y = y
|
||||
sum_pos = { x = 0, y = 0, z = 0 }
|
||||
sum_count = 0
|
||||
end
|
||||
sum_pos = vector.add(sum_pos, pos)
|
||||
sum_count = sum_count + 1
|
||||
|
||||
if left >= 10 and left < 100 then
|
||||
local tens = math.floor(left/10)*10
|
||||
if tens == 70 then
|
||||
local tens_in_70 = 10 + math.floor(i/10)*10
|
||||
if tens_in_70 == 10 then
|
||||
tens_in_70 = 71
|
||||
elseif tens_in_70 == 70 then
|
||||
tens_in_70 = 77
|
||||
end
|
||||
minetest.set_node(pos, { name = "numberblocks:block_"..tostring(tens_in_70) })
|
||||
elseif tens == 90 then
|
||||
local thirties_in_90 = math.floor(i/30)
|
||||
minetest.set_node(pos, { name = "numberblocks:block_"..tostring(90 + thirties_in_90) })
|
||||
else
|
||||
minetest.set_node(pos, { name = "numberblocks:block_"..tostring(tens) })
|
||||
end
|
||||
minetest.set_node(pos, { name = "numberblocks:block_"..tostring(tens_in_70) })
|
||||
elseif tens == 90 then
|
||||
local thirties_in_90 = math.floor(i/30)
|
||||
minetest.set_node(pos, { name = "numberblocks:block_"..tostring(90 + thirties_in_90) })
|
||||
else
|
||||
minetest.set_node(pos, { name = "numberblocks:block_"..tostring(tens) })
|
||||
if i == tens - 1 then
|
||||
left = left - tens
|
||||
i = -1
|
||||
end
|
||||
elseif left == 7 then
|
||||
minetest.set_node(pos, { name = "numberblocks:block", param2 = i })
|
||||
elseif left == 9 then
|
||||
minetest.set_node(pos, { name = "numberblocks:block", param2 = 8 + math.floor(i/3) })
|
||||
elseif left < 9 then
|
||||
minetest.set_node(pos, { name = "numberblocks:block", param2 = left - 1 })
|
||||
end
|
||||
if i == tens - 1 then
|
||||
count = count - tens
|
||||
i = -1
|
||||
end
|
||||
elseif count == 7 then
|
||||
minetest.set_node(pos, { name = "numberblocks:block", param2 = i })
|
||||
elseif count == 9 then
|
||||
minetest.set_node(pos, { name = "numberblocks:block", param2 = 8 + math.floor(i/3) })
|
||||
elseif count < 9 then
|
||||
minetest.set_node(pos, { name = "numberblocks:block", param2 = count - 1 })
|
||||
i = i + 1
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if sum_count > 0 then
|
||||
-- find average XZ of max Y blocks
|
||||
sum_pos = vector.divide(sum_pos, sum_count)
|
||||
local best_pos
|
||||
local best_dist2 = -1
|
||||
-- find closest block at max_y
|
||||
for x, zs in orderedPairs(nodes[max_y]) do
|
||||
for z, node_type in orderedPairs(zs) do
|
||||
if node_type == NODE_BLOCK then
|
||||
local pos = {x = x, y = max_y, z = z};
|
||||
local disp = vector.subtract(pos, sum_pos)
|
||||
local dist2 = vector.dot(disp, disp)
|
||||
if best_dist2 < 0 or dist2 < best_dist2 then
|
||||
best_pos = pos
|
||||
best_dist2 = dist2
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
best_pos.y = best_pos.y + 1
|
||||
numberblocks_add_number(best_pos, count)
|
||||
end
|
||||
end
|
||||
|
||||
function numberblocks_block_on_place(itemstack, placer, pointed_thing)
|
||||
if pointed_thing.type == "node" then
|
||||
-- FIXME check if under is a number first and replace that
|
||||
local pos = pointed_thing.above
|
||||
local node = minetest.get_node(pos)
|
||||
local node_type = get_node_type(node)
|
||||
if node_type == NODE_NUMBER then
|
||||
minetest.remove_node(pos)
|
||||
end
|
||||
|
||||
local stack, success = minetest.item_place_node(itemstack, placer, pointed_thing, param2)
|
||||
|
||||
if success then
|
||||
local nodes, count = find_blocks(pointed_thing.above)
|
||||
local nodes, count = find_blocks(pos)
|
||||
|
||||
restyle_blocks(nodes, count)
|
||||
numberblocks_restyle_blocks(nodes, count)
|
||||
end
|
||||
|
||||
return stack, success
|
||||
|
@ -133,11 +214,22 @@ end
|
|||
|
||||
function numberblocks_block_after_dig_node(pos, oldnode, oldmetadata, digger)
|
||||
-- Look in each direction for a broken one
|
||||
local skips = {}
|
||||
local positions = {}
|
||||
for i = 1, 6 do
|
||||
local pos2 = vector.add(pos, adjacent_vectors[i])
|
||||
local nodes, count = find_blocks(pos2)
|
||||
if count > 0 then
|
||||
restyle_blocks(nodes, count)
|
||||
skips[i] = false;
|
||||
positions[i] = vector.add(pos, adjacent_vectors[i])
|
||||
end
|
||||
for i = 1, 6 do
|
||||
if skips[i] == false then
|
||||
local nodes, count = find_blocks(positions[i])
|
||||
numberblocks_restyle_blocks(nodes, count)
|
||||
-- Skip other adjacent nodes part of this numberblock
|
||||
for j = i+1, 6 do
|
||||
if nodes_test(nodes, positions[j]) ~= NODE_NONE then
|
||||
skips[j] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|