Initial commit.
236
mods/firefly_base/init.lua
Normal file
|
|
@ -0,0 +1,236 @@
|
|||
-- Enable Minetest forever.
|
||||
minetest = core
|
||||
|
||||
firefly = {
|
||||
-- Set to `true` to enable testing admin things without having to open a server.
|
||||
singleplayer_admin = true
|
||||
}
|
||||
local ns = firefly
|
||||
|
||||
function include(file)
|
||||
return dofile(minetest.get_modpath(minetest.get_current_modname()).."/"..file)
|
||||
end
|
||||
|
||||
function enum(cases)
|
||||
local out = {}
|
||||
local i = 0
|
||||
for _, x in ipairs(cases) do
|
||||
out[x] = i
|
||||
i = i +1
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
say = minetest.chat_send_all
|
||||
|
||||
function extend(dst, src)
|
||||
for k, v in pairs(src) do
|
||||
dst[k] = v
|
||||
end
|
||||
return dst
|
||||
end
|
||||
|
||||
Promise = {
|
||||
resolve = function(e, ...)
|
||||
if e.resolved then return end
|
||||
e.resolved = true
|
||||
if e._after then e._after(...) end
|
||||
end,
|
||||
after = function(e, fn)
|
||||
e._after = fn
|
||||
end
|
||||
}
|
||||
Promise.__index = Promise
|
||||
setmetatable(Promise, {
|
||||
__call = function(_, fn)
|
||||
local e = {resolved = false}
|
||||
setmetatable(e, Promise)
|
||||
fn(function(...) e:resolve(...) end)
|
||||
return e
|
||||
end
|
||||
})
|
||||
|
||||
EventTarget = {
|
||||
init = function()
|
||||
local e = {
|
||||
listeners = {}
|
||||
}
|
||||
return setmetatable(e, EventTarget)
|
||||
end,
|
||||
listen = function(e, channel, fn)
|
||||
if not e.listeners[channel] then e.listeners[channel] = {} end
|
||||
local l = e.listeners[channel]
|
||||
l[#l +1] = fn
|
||||
end,
|
||||
unlisten = function(e, channel, fn)
|
||||
if not e.listeners[channel] then return end
|
||||
local l = e.listeners[channel]
|
||||
local idx = table.indexof(l, fn)
|
||||
if idx < 0 then return end
|
||||
table.remove(l, idx)
|
||||
end,
|
||||
dispatch = function(e, channel, ...)
|
||||
local l = e.listeners[channel]
|
||||
if not l then return end
|
||||
for i = 1, #l do
|
||||
l[i](...)
|
||||
end
|
||||
end
|
||||
}
|
||||
EventTarget.__index = EventTarget
|
||||
setmetatable(EventTarget, {
|
||||
__call = function(_, ...) return EventTarget.init(...) end
|
||||
})
|
||||
|
||||
-- HACK: Lookup table for getting a rotation from a
|
||||
-- facedir (because Minetest doesn't have any way
|
||||
-- to get this information normally).
|
||||
local facedir_rotations = {
|
||||
-- +Y
|
||||
[0] = vector.new(0, 0, 0),
|
||||
[1] = vector.new(0, math.pi * 1.5, 0),
|
||||
[2] = vector.new(0, math.pi * 1.0, 0),
|
||||
[3] = vector.new(0, math.pi * 0.5, 0),
|
||||
-- +Z
|
||||
[4] = vector.new(math.pi * 1.5, 0, 0),
|
||||
[5] = vector.new(0, math.pi * 1.5, math.pi * 1.5),
|
||||
[6] = vector.new(math.pi * 0.5, math.pi * 1.0, 0),
|
||||
[7] = vector.new(0, math.pi * 0.5, math.pi * 0.5),
|
||||
-- -Z
|
||||
[8] = vector.new(math.pi * 0.5, 0, 0),
|
||||
[9] = vector.new(0, math.pi * 1.5, math.pi * 0.5),
|
||||
[10] = vector.new(math.pi * 1.5, math.pi * 1.0, 0),
|
||||
[11] = vector.new(0, math.pi * 0.5, math.pi * 1.5),
|
||||
-- +X
|
||||
[12] = vector.new(0, 0, math.pi * 0.5),
|
||||
[13] = vector.new(math.pi * 1.5, math.pi * 1.5, 0),
|
||||
[14] = vector.new(0, math.pi * 1.0, math.pi * 1.5),
|
||||
[15] = vector.new(math.pi * 0.5, math.pi * 0.5, 0),
|
||||
-- -X
|
||||
[16] = vector.new(0, 0, math.pi * 1.5),
|
||||
[17] = vector.new(math.pi * 0.5, math.pi * 1.5, 0),
|
||||
[18] = vector.new(0, math.pi * 1.0, math.pi * 0.5),
|
||||
[19] = vector.new(math.pi * 1.5, math.pi * 0.5, 0),
|
||||
-- -Y
|
||||
[20] = vector.new(0, 0, math.pi * 1.0),
|
||||
[21] = vector.new(0, math.pi * 0.5, math.pi * 1.0),
|
||||
[22] = vector.new(0, math.pi * 1.0, math.pi * 1.0),
|
||||
[23] = vector.new(0, math.pi * 1.5, math.pi * 1.0),
|
||||
}
|
||||
function ns.facedir_to_rotation(facedir)
|
||||
return facedir_rotations[facedir] or minetest.facedir_to_dir(facedir):dir_to_rotation()
|
||||
end
|
||||
|
||||
function ns.rotate_selectionbox(box, rot)
|
||||
local a = vector.new(box[1], box[2], box[3]):rotate(rot)
|
||||
local b = vector.new(box[4], box[5], box[6]):rotate(rot)
|
||||
return {
|
||||
a.x, a.y, a.z,
|
||||
b.x, b.y, b.z
|
||||
}
|
||||
end
|
||||
|
||||
function ns.register_item(name, def)
|
||||
local needs_alias
|
||||
if not name:find ":" then
|
||||
def._name = name
|
||||
name = "firefly:"..name
|
||||
needs_alias = true
|
||||
end
|
||||
|
||||
minetest.register_craftitem(":"..name, def)
|
||||
|
||||
if needs_alias then
|
||||
minetest.register_alias(def._name, name)
|
||||
end
|
||||
end
|
||||
|
||||
function ns.solid_color_frames(frames)
|
||||
local out = "[fill:1x"..#frames..":0,0:#000"
|
||||
for i, x in ipairs(frames) do
|
||||
out = out.."^[fill:1x3:0,"..(i -1)..":"..x
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
local digit_widths = {
|
||||
[0] = 7,
|
||||
6,
|
||||
7,
|
||||
7,
|
||||
7,
|
||||
7,
|
||||
7,
|
||||
7,
|
||||
7,
|
||||
7,
|
||||
}
|
||||
function ns.texture_from_number(num)
|
||||
local w = 0
|
||||
local digits = {}
|
||||
repeat
|
||||
w = w +1
|
||||
digits[w] = num %10
|
||||
num = math.floor(num /10)
|
||||
until num <= 0
|
||||
local width = 0
|
||||
local out = ""
|
||||
for i = w, 1, -1 do
|
||||
out = out..":"..width..",1=firefly_number_"..digits[i]..".png"
|
||||
width = width +digit_widths[digits[i]] +(i > 1 and 2 or 0)
|
||||
end
|
||||
return "[combine:"..width.."x16"..out, width
|
||||
end
|
||||
|
||||
function ns.read_file(path)
|
||||
local f = io.open(path)
|
||||
if not f then return false end
|
||||
local out = f:read("a")
|
||||
f:close()
|
||||
return out
|
||||
end
|
||||
|
||||
function ns.manhattan_distance(a, b)
|
||||
return math.abs(b.x -a.x) +math.abs(b.y -a.y) +math.abs(b.z -a.z)
|
||||
end
|
||||
|
||||
minetest.register_lbm {
|
||||
name = ":firefly:on_load",
|
||||
nodenames = {"group:call_on_load"},
|
||||
action = function(pos, node)
|
||||
minetest.registered_nodes[node.name].on_load(pos)
|
||||
end
|
||||
}
|
||||
|
||||
ns.timer = EventTarget()
|
||||
|
||||
local last_time = minetest.get_us_time()
|
||||
minetest.register_globalstep(function()
|
||||
local time = minetest.get_us_time()
|
||||
if time -last_time > 1000000 then
|
||||
ns.timer:dispatch("every_second")
|
||||
last_time = time
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_entity(":display", {
|
||||
initial_properties = {
|
||||
visual = "sprite",
|
||||
textures = {"blank.png"},
|
||||
pointable = false,
|
||||
static_save = false
|
||||
},
|
||||
on_activate = function(e)
|
||||
e.object:set_armor_groups{immortal = 1}
|
||||
end
|
||||
})
|
||||
|
||||
|
||||
if minetest.get_modpath("testtools") then
|
||||
minetest.override_item("testtools:param2tool", {
|
||||
pointabilities = {
|
||||
nodes = {["group:everything"] = true},
|
||||
objects = {["group:immortal"] = false}
|
||||
}
|
||||
})
|
||||
end
|
||||
1
mods/firefly_base/mod.conf
Normal file
|
|
@ -0,0 +1 @@
|
|||
name = firefly_base
|
||||
BIN
mods/firefly_base/textures/firefly_number_0.png
Normal file
|
After Width: | Height: | Size: 118 B |
BIN
mods/firefly_base/textures/firefly_number_1.png
Normal file
|
After Width: | Height: | Size: 121 B |
BIN
mods/firefly_base/textures/firefly_number_2.png
Normal file
|
After Width: | Height: | Size: 131 B |
BIN
mods/firefly_base/textures/firefly_number_3.png
Normal file
|
After Width: | Height: | Size: 129 B |
BIN
mods/firefly_base/textures/firefly_number_4.png
Normal file
|
After Width: | Height: | Size: 126 B |
BIN
mods/firefly_base/textures/firefly_number_5.png
Normal file
|
After Width: | Height: | Size: 130 B |
BIN
mods/firefly_base/textures/firefly_number_6.png
Normal file
|
After Width: | Height: | Size: 125 B |
BIN
mods/firefly_base/textures/firefly_number_7.png
Normal file
|
After Width: | Height: | Size: 125 B |
BIN
mods/firefly_base/textures/firefly_number_8.png
Normal file
|
After Width: | Height: | Size: 125 B |
BIN
mods/firefly_base/textures/firefly_number_9.png
Normal file
|
After Width: | Height: | Size: 126 B |