Init
|
@ -23,8 +23,8 @@ minetest.register_alias("mapgen_sandstone", "default:sandstone")
|
||||||
minetest.register_alias("mapgen_tree", "default:tree")
|
minetest.register_alias("mapgen_tree", "default:tree")
|
||||||
minetest.register_alias("mapgen_leaves", "default:leaves")
|
minetest.register_alias("mapgen_leaves", "default:leaves")
|
||||||
minetest.register_alias("mapgen_apple", "default:apple")
|
minetest.register_alias("mapgen_apple", "default:apple")
|
||||||
minetest.register_alias("mapgen_jungletree", "default:jungletree")
|
minetest.register_alias("mapgen_jungletree", "default:jungle_tree")
|
||||||
minetest.register_alias("mapgen_jungleleaves", "default:jungleleaves")
|
minetest.register_alias("mapgen_jungleleaves", "default:jungle_leaves")
|
||||||
minetest.register_alias("mapgen_junglegrass", "default:junglegrass")
|
minetest.register_alias("mapgen_junglegrass", "default:junglegrass")
|
||||||
minetest.register_alias("mapgen_pine_tree", "default:pine_tree")
|
minetest.register_alias("mapgen_pine_tree", "default:pine_tree")
|
||||||
minetest.register_alias("mapgen_pine_needles", "default:pine_needles")
|
minetest.register_alias("mapgen_pine_needles", "default:pine_needles")
|
||||||
|
|
Before Width: | Height: | Size: 916 B After Width: | Height: | Size: 586 B |
Before Width: | Height: | Size: 214 B After Width: | Height: | Size: 206 B |
Before Width: | Height: | Size: 830 B After Width: | Height: | Size: 540 B |
|
@ -542,16 +542,18 @@ minetest.register_alias("trees:wood_conifer", "default:pine_wood")
|
||||||
minetest.register_alias("trees:sapling_conifer", "default:pine_sapling")
|
minetest.register_alias("trees:sapling_conifer", "default:pine_sapling")
|
||||||
minetest.register_alias("trees:leaves_conifer", "default:pine_needles")
|
minetest.register_alias("trees:leaves_conifer", "default:pine_needles")
|
||||||
|
|
||||||
minetest.register_alias("trees:tree_palm", "default:jungletree")
|
minetest.register_alias("trees:tree_palm", "default:jungle_tree")
|
||||||
minetest.register_alias("trees:leaves_palm", "default:jungleleaves")
|
minetest.register_alias("default:jungleleaves", "default:jungle_leaves")
|
||||||
minetest.register_alias("trees:sapling_palm", "default:junglesapling")
|
minetest.register_alias("default:junglewood", "default:jungle_wood")
|
||||||
minetest.register_alias("trees:wood_palm", "default:junglewood")
|
minetest.register_alias("trees:leaves_palm", "default:jungle_leaves")
|
||||||
|
minetest.register_alias("trees:sapling_palm", "default:jungle_sapling")
|
||||||
|
minetest.register_alias("trees:wood_palm", "default:jungle_wood")
|
||||||
|
|
||||||
minetest.register_alias("trees:tree_mangrove", "default:aspen_tree")
|
minetest.register_alias("trees:tree_mangrove", "default:aspen_tree")
|
||||||
minetest.register_alias("trees:leaves_mangrove", "default:aspen_leaves")
|
minetest.register_alias("trees:leaves_mangrove", "default:aspen_leaves")
|
||||||
minetest.register_alias("trees:sapling_mangrove", "default:aspen_sapling")
|
minetest.register_alias("trees:sapling_mangrove", "default:aspen_sapling")
|
||||||
minetest.register_alias("trees:wood_mangrove", "default:aspen_wood")
|
minetest.register_alias("trees:wood_mangrove", "default:aspen_wood")
|
||||||
|
|
||||||
minetest.register_alias("trees:leaves_red", "default:jungleleaves")
|
minetest.register_alias("trees:leaves_red", "default:jungle_leaves")
|
||||||
minetest.register_alias("trees:leaves_yellow", "default:jungleleaves")
|
minetest.register_alias("trees:leaves_yellow", "default:jungle_leaves")
|
||||||
minetest.register_alias("trees:leaves_green", "default:jungleleaves")
|
minetest.register_alias("trees:leaves_green", "default:jungle_leaves")
|
||||||
|
|
|
@ -0,0 +1,299 @@
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
-- Fishing - Mossmanikin's version - Bobber 0.1.0
|
||||||
|
-- License (code & textures): WTFPL
|
||||||
|
-- Contains code from: fishing (original), mobs, throwing
|
||||||
|
-- Supports: animal_clownfish, animal_fish_blue_white, animal_rat, mobs
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
-- 0.0625 (= 1 pixel on 16x16 texture)
|
||||||
|
-- 0.125
|
||||||
|
-- 0.1875
|
||||||
|
-- 0.25
|
||||||
|
-- 0.3125
|
||||||
|
-- 0.375
|
||||||
|
-- 0.4375
|
||||||
|
-- 0.5 (= 8 pixels on 16x16 texture)
|
||||||
|
-- 0.5625 (= 9 pixels on 16x16 texture)
|
||||||
|
-- 0.625
|
||||||
|
-- 0.6875
|
||||||
|
-- 0.75
|
||||||
|
-- 0.8125
|
||||||
|
-- 0.875
|
||||||
|
-- 0.9375
|
||||||
|
-- 1.0 (= 16 pixels on 16x16 texture)
|
||||||
|
|
||||||
|
minetest.register_node("fishing:bobber_box", {
|
||||||
|
drawtype = "nodebox",
|
||||||
|
node_box = {
|
||||||
|
type = "fixed",
|
||||||
|
fixed = {
|
||||||
|
-- { left , bottom , front , right , top , back }
|
||||||
|
{-0.0625, -0.6875, -0.0625, 0.0625, -0.5625, 0.0625},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tiles = {"fishing_bobber.png"},
|
||||||
|
groups = {not_in_creative_inventory=1},
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("fishing:bobber_box_ready", {
|
||||||
|
drawtype = "nodebox",
|
||||||
|
node_box = {
|
||||||
|
type = "fixed",
|
||||||
|
fixed = {
|
||||||
|
-- { left , bottom , front , right , top , back }
|
||||||
|
{-0.0625, -0.6875, -0.0625, 0.0625, -0.5625, 0.0625},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tiles = {"fishing_bobber_ready.png"},
|
||||||
|
groups = {not_in_creative_inventory=1},
|
||||||
|
})
|
||||||
|
|
||||||
|
local FISHING_BOBBER_ENTITY={
|
||||||
|
hp_max = 605,
|
||||||
|
water_damage = 1,
|
||||||
|
physical = true,
|
||||||
|
timer = 0,
|
||||||
|
env_damage_timer = 0,
|
||||||
|
visual = "wielditem",
|
||||||
|
visual_size = {x=0.5, y=0.5, z=0.5},
|
||||||
|
textures = {"fishing:bobber_box"},
|
||||||
|
-- { left , bottom , front , right , top , back }
|
||||||
|
collisionbox = {-0.125 , -0.5625, -0.125 , 0.125 , -0.3125, 0.125 },
|
||||||
|
view_range = 7,
|
||||||
|
-- DESTROY BOBBER WHEN PUNCHING IT
|
||||||
|
on_punch = function (self, puncher, time_from_last_punch, tool_capabilities, dir)
|
||||||
|
local player = puncher:get_player_name()
|
||||||
|
if MESSAGES == true then
|
||||||
|
--minetest.chat_send_all("Your fish escaped.")
|
||||||
|
minetest.chat_send_player(player, "Your fish escaped.", false)
|
||||||
|
end
|
||||||
|
minetest.sound_play("fishing_bobber1", {
|
||||||
|
pos = self.object:getpos(),
|
||||||
|
gain = 0.5,
|
||||||
|
})
|
||||||
|
self.object:remove()
|
||||||
|
end,
|
||||||
|
-- WHEN RIGHTCLICKING THE BOBBER THE FOLLOWING HAPPENS (CLICK AT THE RIGHT TIME WHILE HOLDING A FISHING POLE)
|
||||||
|
on_rightclick = function (self, clicker)
|
||||||
|
local item = clicker:get_wielded_item()
|
||||||
|
local player = clicker:get_player_name()
|
||||||
|
if item:get_name() == "fishing:pole" then
|
||||||
|
local inv = clicker:get_inventory()
|
||||||
|
local room_fish = inv:room_for_item("main", {name="fishing:fish_raw", count=1, wear=0, metadata=""})
|
||||||
|
if self.object:get_hp() <= 300 then
|
||||||
|
if math.random(1, 100) < FISH_CHANCE then
|
||||||
|
local chance = math.random(1, 84)
|
||||||
|
if chance <= 60 then
|
||||||
|
if room_fish then
|
||||||
|
inv:add_item("main", {name="fishing:fish_raw", count=1, wear=0, metadata=""})
|
||||||
|
if MESSAGES == true then
|
||||||
|
--minetest.chat_send_all("You caught a Fish.")
|
||||||
|
minetest.chat_send_player(player, "You caught a Fish.", false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif chance <= 70 then
|
||||||
|
if minetest.get_modpath("animal_clownfish") ~= nil then
|
||||||
|
if inv:room_for_item("main", {name="animal_clownfish:clownfish", count=1, wear=0, metadata=""}) then
|
||||||
|
inv:add_item("main", {name="animal_clownfish:clownfish", count=1, wear=0, metadata=""})
|
||||||
|
if MESSAGES == true then
|
||||||
|
--minetest.chat_send_all("You caught a Clownfish.")
|
||||||
|
minetest.chat_send_player(player, "You caught a Clownfish.", false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if room_fish then
|
||||||
|
inv:add_item("main", {name="fishing:fish_raw", count=1, wear=0, metadata=""})
|
||||||
|
if MESSAGES == true then
|
||||||
|
--minetest.chat_send_all("You caught a Fish.")
|
||||||
|
minetest.chat_send_player(player, "You caught a Fish.", false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif chance <= 80 then
|
||||||
|
if minetest.get_modpath("animal_fish_blue_white") ~= nil then
|
||||||
|
if inv:room_for_item("main", {name="animal_fish_blue_white:fish_blue_white", count=1, wear=0, metadata=""}) then
|
||||||
|
inv:add_item("main", {name="animal_fish_blue_white:fish_blue_white", count=1, wear=0, metadata=""})
|
||||||
|
if MESSAGES == true then
|
||||||
|
--minetest.chat_send_all("You caught a Blue white fish.")
|
||||||
|
minetest.chat_send_player(player, "You caught a Blue white fish.", false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if room_fish then
|
||||||
|
inv:add_item("main", {name="fishing:fish_raw", count=1, wear=0, metadata=""})
|
||||||
|
if MESSAGES == true then
|
||||||
|
--minetest.chat_send_all("You caught a Fish.")
|
||||||
|
minetest.chat_send_player(player, "You caught a Fish.", false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif chance == 81 then
|
||||||
|
if inv:room_for_item("main", {name="default:stick", count=1, wear=0, metadata=""}) then
|
||||||
|
inv:add_item("main", {name="default:stick", count=1, wear=0, metadata=""})
|
||||||
|
if MESSAGES == true then
|
||||||
|
--minetest.chat_send_all("You caught a Stick.")
|
||||||
|
minetest.chat_send_player(player, "You caught a Stick.", false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif chance == 82 then
|
||||||
|
if minetest.get_modpath("mobs") ~= nil then
|
||||||
|
if inv:room_for_item("main", {name="mobs:rat", count=1, wear=0, metadata=""}) then
|
||||||
|
inv:add_item("main", {name="mobs:rat", count=1, wear=0, metadata=""})
|
||||||
|
if MESSAGES == true then
|
||||||
|
--minetest.chat_send_all("You caught a Rat.")
|
||||||
|
minetest.chat_send_player(player, "You caught a Rat.", false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif minetest.get_modpath("animal_rat") ~= nil then
|
||||||
|
if inv:room_for_item("main", {name="animal_rat:rat", count=1, wear=0, metadata=""}) then
|
||||||
|
inv:add_item("main", {name="animal_rat:rat", count=1, wear=0, metadata=""})
|
||||||
|
if MESSAGES == true then
|
||||||
|
--minetest.chat_send_all("You caught a Rat.")
|
||||||
|
minetest.chat_send_player(player, "You caught a Rat.", false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if inv:room_for_item("main", {name="rat", count=1, wear=0, metadata=""}) then
|
||||||
|
inv:add_item("main", {name="rat", count=1, wear=0, metadata=""})
|
||||||
|
if MESSAGES == true then
|
||||||
|
--minetest.chat_send_all("You caught a Rat.")
|
||||||
|
minetest.chat_send_player(player, "You caught a Rat.", false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif chance == 83 then
|
||||||
|
if minetest.get_modpath("flowers_plus") ~= nil then
|
||||||
|
if inv:room_for_item("main", {name="flowers:seaweed", count=1, wear=0, metadata=""}) then
|
||||||
|
inv:add_item("main", {name="flowers:seaweed", count=1, wear=0, metadata=""})
|
||||||
|
if MESSAGES == true then
|
||||||
|
--minetest.chat_send_all("You caught a Clownfish.")
|
||||||
|
minetest.chat_send_player(player, "You caught some Seaweed.", false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if room_fish then
|
||||||
|
inv:add_item("main", {name="fishing:fish_raw", count=1, wear=0, metadata=""})
|
||||||
|
if MESSAGES == true then
|
||||||
|
--minetest.chat_send_all("You caught a Fish.")
|
||||||
|
minetest.chat_send_player(player, "You caught a Fish.", false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif chance == 84 then
|
||||||
|
if minetest.get_modpath("seaplants") ~= nil then
|
||||||
|
if inv:room_for_item("main", {name="seaplants:leavysnackgreen", count=1, wear=0, metadata=""}) then
|
||||||
|
inv:add_item("main", {name="seaplants:leavysnackgreen", count=1, wear=0, metadata=""})
|
||||||
|
if MESSAGES == true then
|
||||||
|
--minetest.chat_send_all("You caught a Clownfish.")
|
||||||
|
minetest.chat_send_player(player, "You caught a Leavy Snack.", false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if room_fish then
|
||||||
|
inv:add_item("main", {name="fishing:fish_raw", count=1, wear=0, metadata=""})
|
||||||
|
if MESSAGES == true then
|
||||||
|
--minetest.chat_send_all("You caught a Fish.")
|
||||||
|
minetest.chat_send_player(player, "You caught a Fish.", false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if MESSAGES == true then
|
||||||
|
--minetest.chat_send_all("Your fish escaped.")
|
||||||
|
minetest.chat_send_player(player, "Your fish escaped.", false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if MESSAGES == true then
|
||||||
|
--minetest.chat_send_all("Your fish escaped.")
|
||||||
|
minetest.chat_send_player(player, "Your fish escaped.", false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if MESSAGES == true then
|
||||||
|
--minetest.chat_send_all("Your fish escaped.")
|
||||||
|
minetest.chat_send_player(player, "Your fish escaped.", false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
minetest.sound_play("fishing_bobber1", {
|
||||||
|
pos = self.object:getpos(),
|
||||||
|
gain = 0.5,
|
||||||
|
})
|
||||||
|
self.object:remove()
|
||||||
|
end,
|
||||||
|
-- AS SOON AS THE BOBBER IS PLACED IT WILL ACT LIKE
|
||||||
|
on_step = function(self, dtime)
|
||||||
|
local pos = self.object:getpos()
|
||||||
|
if BOBBER_CHECK_RADIUS > 0 then
|
||||||
|
local objs = minetest.env:get_objects_inside_radius({x=pos.x,y=pos.y,z=pos.z}, BOBBER_CHECK_RADIUS)
|
||||||
|
for k, obj in pairs(objs) do
|
||||||
|
if obj:get_luaentity() ~= nil then
|
||||||
|
if obj:get_luaentity().name == "fishing:bobber_entity" then
|
||||||
|
if obj:get_luaentity() ~= self then
|
||||||
|
self.object:remove()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if math.random(1, 4) == 1 then
|
||||||
|
self.object:setyaw(self.object:getyaw()+((math.random(0,360)-180)/180*math.pi))
|
||||||
|
end
|
||||||
|
for _,player in pairs(minetest.get_connected_players()) do
|
||||||
|
local s = self.object:getpos()
|
||||||
|
local p = player:getpos()
|
||||||
|
local dist = ((p.x-s.x)^2 + (p.y-s.y)^2 + (p.z-s.z)^2)^0.5
|
||||||
|
if dist > self.view_range then
|
||||||
|
minetest.sound_play("fishing_bobber1", {
|
||||||
|
pos = self.object:getpos(),
|
||||||
|
gain = 0.5,
|
||||||
|
})
|
||||||
|
self.object:remove()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local do_env_damage = function(self)
|
||||||
|
self.object:set_hp(self.object:get_hp()-self.water_damage)
|
||||||
|
--local pos = self.object:getpos()
|
||||||
|
if self.object:get_hp() == 600 then
|
||||||
|
self.object:moveto({x=pos.x,y=pos.y-0.03125,z=pos.z})
|
||||||
|
elseif self.object:get_hp() == 595 then
|
||||||
|
self.object:moveto({x=pos.x,y=pos.y+0.03125,z=pos.z})
|
||||||
|
elseif self.object:get_hp() == 590 then
|
||||||
|
self.object:moveto({x=pos.x,y=pos.y+0.03125,z=pos.z})
|
||||||
|
elseif self.object:get_hp() == 585 then
|
||||||
|
self.object:moveto({x=pos.x,y=pos.y-0.03125,z=pos.z})
|
||||||
|
self.object:set_hp(self.object:get_hp()-(math.random(1, 200)))
|
||||||
|
elseif self.object:get_hp() == 300 then
|
||||||
|
minetest.sound_play("fishing_bobber1", {
|
||||||
|
pos = self.object:getpos(),
|
||||||
|
gain = 0.5,
|
||||||
|
})
|
||||||
|
if BOBBER_COLOR_CHANGE == true then
|
||||||
|
self.object:set_properties({
|
||||||
|
textures = {"fishing:bobber_box_ready"},
|
||||||
|
})
|
||||||
|
end
|
||||||
|
self.object:moveto({x=pos.x,y=pos.y-0.0625,z=pos.z})
|
||||||
|
elseif self.object:get_hp() == 295 then
|
||||||
|
self.object:moveto({x=pos.x,y=pos.y+0.0625,z=pos.z})
|
||||||
|
elseif self.object:get_hp() == 290 then
|
||||||
|
self.object:moveto({x=pos.x,y=pos.y+0.0625,z=pos.z})
|
||||||
|
elseif self.object:get_hp() == 285 then
|
||||||
|
self.object:moveto({x=pos.x,y=pos.y-0.0625,z=pos.z})
|
||||||
|
elseif self.object:get_hp() < 284 then
|
||||||
|
self.object:moveto({x=pos.x+(0.001*(math.random(-8, 8))),y=pos.y,z=pos.z+(0.001*(math.random(-8, 8)))})
|
||||||
|
elseif self.object:get_hp() == 0 then
|
||||||
|
minetest.sound_play("fishing_bobber1", {
|
||||||
|
pos = self.object:getpos(),
|
||||||
|
gain = 0.5,
|
||||||
|
})
|
||||||
|
self.object:remove()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
do_env_damage(self)
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
|
minetest.register_entity("fishing:bobber_entity", FISHING_BOBBER_ENTITY)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
-- Fishing - Mossmanikin's version - Recipes 0.0.5
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
-- original by wulfsdad (http://forum.minetest.net/viewtopic.php?id=4375)
|
||||||
|
-- this version by Mossmanikin
|
||||||
|
-- License (code & textures): WTFPL
|
||||||
|
-- Contains code from: animal_clownfish, animal_fish_blue_white, fishing (original), stoneage
|
||||||
|
-- Looked at code from:
|
||||||
|
-- Dependencies: default, farming
|
||||||
|
-- Supports: animal_clownfish, animal_fish_blue_white, animal_rat, mobs
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
-- Fishing Pole
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
-- mc style
|
||||||
|
minetest.register_craft({
|
||||||
|
output = "fishing:pole",
|
||||||
|
recipe = {
|
||||||
|
{"", "", "default:stick" },
|
||||||
|
{"", "default:stick", "farming:string"},
|
||||||
|
{"default:stick", "", "farming:string"},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craft({
|
||||||
|
output = "fishing:pole",
|
||||||
|
recipe = {
|
||||||
|
{"", "", "default:stick" },
|
||||||
|
{"", "default:stick", "moreblocks:rope"},
|
||||||
|
{"default:stick", "", "moreblocks:rope"},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craft({
|
||||||
|
output = "fishing:pole",
|
||||||
|
recipe = {
|
||||||
|
{"", "", "default:stick" },
|
||||||
|
{"", "default:stick", "ropes:rope" },
|
||||||
|
{"default:stick", "", "ropes:rope" },
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
-- Fish
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
minetest.register_craft({
|
||||||
|
type = "cooking",
|
||||||
|
output = "fishing:fish",
|
||||||
|
recipe = "fishing:fish_raw",
|
||||||
|
cooktime = 2,
|
||||||
|
})
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
-- Sushi
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
minetest.register_craft({
|
||||||
|
type = "shapeless",
|
||||||
|
output = "fishing:sushi",
|
||||||
|
recipe = {"fishing:fish_raw","flowers:seaweed"},
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craft({
|
||||||
|
type = "shapeless",
|
||||||
|
output = "fishing:sushi",
|
||||||
|
recipe = {"fishing:fish_raw","seaplants:leavysnackgreen"},
|
||||||
|
})
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
default
|
||||||
|
farming
|
|
@ -0,0 +1,30 @@
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
-- Fish
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
minetest.register_craftitem("fishing:fish_raw", {
|
||||||
|
description = "Fish",
|
||||||
|
groups = {},
|
||||||
|
inventory_image = "fishing_fish.png",
|
||||||
|
on_use = minetest.item_eat(2),
|
||||||
|
})
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
-- Roasted Fish
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
minetest.register_craftitem("fishing:fish", {
|
||||||
|
description = "Roasted Fish",
|
||||||
|
groups = {},
|
||||||
|
inventory_image = "fishing_fish_cooked.png",
|
||||||
|
on_use = minetest.item_eat(4),
|
||||||
|
})
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
-- Sushi
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
minetest.register_craftitem("fishing:sushi", {
|
||||||
|
description = "Sushi (Hoso Maki)",
|
||||||
|
groups = {},
|
||||||
|
inventory_image = "fishing_sushi.png",
|
||||||
|
on_use = minetest.item_eat(8),
|
||||||
|
})
|
||||||
|
|
|
@ -0,0 +1,309 @@
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
local title = "Fishing - Mossmanikin's version"
|
||||||
|
local version = "0.1.2-LGN"
|
||||||
|
local mname = "fishing"
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
-- original by wulfsdad (http://forum.minetest.net/viewtopic.php?id=4375)
|
||||||
|
-- this version by Mossmanikin
|
||||||
|
-- License (code & textures): WTFPL (exception below)
|
||||||
|
-- except for: "fishing_fish_cooked.png" contributed by Tirifto,
|
||||||
|
-- released into public domain under CC0.
|
||||||
|
-- Contains code from: animal_clownfish, animal_fish_blue_white, fishing (original), stoneage
|
||||||
|
-- Looked at code from: default, farming
|
||||||
|
-- Dependencies: default
|
||||||
|
-- Supports: animal_clownfish, animal_fish_blue_white, animal_rat, mobs
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-- todo: item wear done
|
||||||
|
-- automatic re-baiting option done
|
||||||
|
-- different types of fish, sort of
|
||||||
|
-- add sound done
|
||||||
|
-- bobber done
|
||||||
|
-- change rainworms filling inv & make 'em disappear done
|
||||||
|
|
||||||
|
-- placable fishing rod for decoration done
|
||||||
|
-- make bobber move slowly while fish on hook done
|
||||||
|
-- catch bigger fish with smaller
|
||||||
|
-- change color of bobber when fish on hook done
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
dofile(minetest.get_modpath("fishing").."/settings.txt")
|
||||||
|
dofile(minetest.get_modpath("fishing").."/bobber.lua")
|
||||||
|
dofile(minetest.get_modpath("fishing").."/crafting.lua")
|
||||||
|
dofile(minetest.get_modpath("fishing").."/fishes.lua")
|
||||||
|
dofile(minetest.get_modpath("fishing").."/worm.lua")
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
-- Fishing Pole
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local function rod_wear(itemstack, user, pointed_thing, uses)
|
||||||
|
itemstack:add_wear(65535/(uses-1))
|
||||||
|
return itemstack
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_tool("fishing:pole", {
|
||||||
|
|
||||||
|
description = "Fishing Pole",
|
||||||
|
groups = {},
|
||||||
|
inventory_image = "fishing_pole.png",
|
||||||
|
wield_image = "fishing_pole.png^[transformFXR270",
|
||||||
|
stack_max = 1,
|
||||||
|
liquids_pointable = true,
|
||||||
|
on_use = function (itemstack, user, pointed_thing)
|
||||||
|
if pointed_thing and pointed_thing.under then
|
||||||
|
local pt = pointed_thing
|
||||||
|
local node = minetest.env:get_node(pt.under)
|
||||||
|
if string.find(node.name, "default:water") then
|
||||||
|
local player = user:get_player_name()
|
||||||
|
local inv = user:get_inventory()
|
||||||
|
if inv:get_stack("main", user:get_wield_index()+1):get_name() == "fishing:bait_worm" then
|
||||||
|
inv:remove_item("main", "fishing:bait_worm")
|
||||||
|
minetest.sound_play("fishing_bobber2", {
|
||||||
|
pos = pt.under,
|
||||||
|
gain = 0.5,
|
||||||
|
})
|
||||||
|
minetest.env:add_entity({interval = 1,x=pt.under.x, y=pt.under.y+1, z=pt.under.z}, "fishing:bobber_entity")
|
||||||
|
|
||||||
|
if WEAR_OUT == true then
|
||||||
|
return rod_wear(itemstack, user, pointed_thing, 30)
|
||||||
|
else
|
||||||
|
return {name="fishing:pole", count=1, wear=0, metadata=""}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end,
|
||||||
|
on_place = function(itemstack, placer, pointed_thing)
|
||||||
|
local pt = pointed_thing
|
||||||
|
if minetest.get_node(pt.under).name~="default:water_source" and minetest.get_node(pt.under).name~="default:water_flowing" then
|
||||||
|
local wear = itemstack:get_wear()
|
||||||
|
local direction = minetest.dir_to_facedir(placer:get_look_dir())
|
||||||
|
local meta1 = minetest.env:get_meta({x=pt.under.x, y=pt.under.y , z=pt.under.z})
|
||||||
|
local meta2 = minetest.env:get_meta({x=pt.under.x, y=pt.under.y+1, z=pt.under.z})
|
||||||
|
minetest.set_node({x=pt.under.x, y=pt.under.y+1, z=pt.under.z}, {name="fishing:pole_deco", param2=direction})
|
||||||
|
meta1:set_int("wear", wear)
|
||||||
|
meta2:set_int("wear", wear)
|
||||||
|
itemstack:take_item()
|
||||||
|
end
|
||||||
|
return itemstack
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
if SIMPLE_DECO_FISHING_POLE == true then
|
||||||
|
minetest.register_node("fishing:pole_deco", {
|
||||||
|
description = "Fishing Pole",
|
||||||
|
drawtype = "nodebox",
|
||||||
|
paramtype = "light",
|
||||||
|
paramtype2 = "facedir",
|
||||||
|
tiles = {
|
||||||
|
"fishing_pole_top.png", "fishing_pole_bottom.png", "fishing_pole.png", "fishing_pole.png^[transformFX", "fishing_pole_front.png", "fishing_pole_back.png",
|
||||||
|
},
|
||||||
|
groups = {
|
||||||
|
snappy=3,
|
||||||
|
flammable=2,
|
||||||
|
not_in_creative_inventory=1
|
||||||
|
},
|
||||||
|
node_box = {
|
||||||
|
type = "fixed",
|
||||||
|
fixed = {
|
||||||
|
{-0.5/3, -1.5/3, -1.5/3, 0.5/3, -0.5/3, -0.5/3},{-0.5/3, -0.5/3, -0.5/3, 0.5/3, 0.5/3, 0.5/3},{-0.5/3, 0.5/3, 0.5/3, 0.5/3, 1.5/3, 1.5/3},{-0.5/3, -1.5/3, 0.5/3, 0.5/3, 0.5/3, 1.5/3},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
selection_box = {
|
||||||
|
type = "fixed",
|
||||||
|
fixed = {
|
||||||
|
{-0.5/3, -1.5/3, -1.5/3, 0.5/3, -0.5/3, -0.5/3},{-0.5/3, -0.5/3, -0.5/3, 0.5/3, 0.5/3, 0.5/3},{-0.5/3, 0.5/3, 0.5/3, 0.5/3, 1.5/3, 1.5/3},{-0.5/3, -1.5/3, 0.5/3, 0.5/3, 0.5/3, 1.5/3},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
sounds = default.node_sound_wood_defaults(),
|
||||||
|
on_dig = function(pos, node, digger)
|
||||||
|
if digger:is_player() and digger:get_inventory() then
|
||||||
|
local meta = minetest.env:get_meta(pos)
|
||||||
|
local wear_out = meta:get_int("wear")
|
||||||
|
digger:get_inventory():add_item("main", {name="fishing:pole", count=1, wear=wear_out, metadata=""})
|
||||||
|
end
|
||||||
|
minetest.remove_node(pos)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
else
|
||||||
|
minetest.register_node("fishing:pole_deco", {
|
||||||
|
description = "Fishing Pole",
|
||||||
|
inventory_image = "fishing_pole.png",
|
||||||
|
wield_image = "fishing_pole.png^[transformFXR270",
|
||||||
|
drawtype = "nodebox",
|
||||||
|
paramtype = "light",
|
||||||
|
paramtype2 = "facedir",
|
||||||
|
tiles = {
|
||||||
|
"fishing_pole_top.png",
|
||||||
|
"fishing_pole_bottom.png",
|
||||||
|
"fishing_pole_deco.png", -- right
|
||||||
|
"fishing_pole_deco.png^[transformFX", -- left
|
||||||
|
"fishing_pole_back.png",
|
||||||
|
"fishing_pole_front.png"
|
||||||
|
},
|
||||||
|
node_box = {
|
||||||
|
type = "fixed",
|
||||||
|
-- { left , bottom , front , right , top , back }
|
||||||
|
fixed = {
|
||||||
|
{-1/32 , -1/16 , 14/16 , 1/32 , 6/16 , 15/16},
|
||||||
|
{-1/32 , -3/16 , 13/16 , 1/32 , -1/16 , 14/16},
|
||||||
|
{-1/32 , -4/16 , 12/16 , 1/32 , -3/16 , 13/16},
|
||||||
|
{-1/32 , -5/16 , 11/16 , 1/32 , -4/16 , 12/16},
|
||||||
|
{-1/32 , -6/16 , 9/16 , 1/32 , -5/16 , 11/16},
|
||||||
|
{-1/32 , -5/16 , 9/16 , 1/32 , -4/16 , 10/16},
|
||||||
|
-- stick
|
||||||
|
{-1/32 , 6/16 , 12/16 , 1/32 , 7/16 , 15/16}, -- top
|
||||||
|
{-1/32 , 5/16 , 11/16 , 1/32 , 7/16 , 12/16},
|
||||||
|
{-1/32 , 5/16 , 10/16 , 1/32 , 6/16 , 11/16},
|
||||||
|
{-1/32 , 4/16 , 9/16 , 1/32 , 6/16 , 10/16},
|
||||||
|
{-1/32 , 3/16 , 8/16 , 1/32 , 5/16 , 9/16},
|
||||||
|
{-1/32 , 2/16 , 7/16 , 1/32 , 4/16 , 8/16},
|
||||||
|
{-1/32 , 1/16 , 6/16 , 1/32 , 3/16 , 7/16},
|
||||||
|
{-1/32 , 0 , 5/16 , 1/32 , 2/16 , 6/16},
|
||||||
|
{-1/32 , -2/16 , 4/16 , 1/32 , 1/16 , 5/16},
|
||||||
|
{-1/32 , -3/16 , 3/16 , 1/32 , 0 , 4/16},
|
||||||
|
{-1/32 , -5/16 , 2/16 , 1/32 , -1/16 , 3/16},
|
||||||
|
{-1/32 , -7/16 , 1/16 , 1/32 , -3/16 , 2/16},
|
||||||
|
{-1/32 , -1/2 , 0 , 1/32 , -5/16 , 1/16}, -- bottom
|
||||||
|
}
|
||||||
|
},
|
||||||
|
selection_box = {
|
||||||
|
type = "fixed",
|
||||||
|
fixed = {
|
||||||
|
{-1/16 , -1/2 , 0 , 1/16 , 1/2 , 1 },
|
||||||
|
}
|
||||||
|
},
|
||||||
|
groups = {
|
||||||
|
snappy=3,
|
||||||
|
flammable=2,
|
||||||
|
not_in_creative_inventory=1
|
||||||
|
},
|
||||||
|
sounds = default.node_sound_wood_defaults(),
|
||||||
|
on_dig = function(pos, node, digger)
|
||||||
|
if digger:is_player() and digger:get_inventory() then
|
||||||
|
local meta = minetest.env:get_meta(pos)
|
||||||
|
local wear_out = meta:get_int("wear")
|
||||||
|
digger:get_inventory():add_item("main", {name="fishing:pole", count=1, wear=wear_out, metadata=""})
|
||||||
|
end
|
||||||
|
minetest.remove_node(pos)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
end
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
-- GETTING WORMS
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
-- get worms from digging in dirt:
|
||||||
|
if NEW_WORM_SOURCE == false then
|
||||||
|
|
||||||
|
minetest.register_node(":default:dirt", {
|
||||||
|
description = "Dirt",
|
||||||
|
tiles = {"default_dirt.png"},
|
||||||
|
is_ground_content = true,
|
||||||
|
groups = {crumbly=3},
|
||||||
|
sounds = default.node_sound_dirt_defaults(),
|
||||||
|
after_dig_node = function (pos, oldnode, oldmetadata, digger)
|
||||||
|
if math.random(1, 100) < WORM_CHANCE then
|
||||||
|
local tool_in_use = digger:get_wielded_item():get_name()
|
||||||
|
if tool_in_use == "" or tool_in_use == "default:dirt" then
|
||||||
|
minetest.env:add_entity({x = pos.x, y = pos.y+0.4, z = pos.z}, "fishing:bait_worm_entity")
|
||||||
|
--local inv = digger:get_inventory()
|
||||||
|
--if inv:room_for_item("main", {name="fishing:bait_worm", count=1, wear=0, metadata=""}) then
|
||||||
|
--inv:add_item("main", {name="fishing:bait_worm", count=1, wear=0, metadata=""})
|
||||||
|
--end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
else
|
||||||
|
-- get worms from digging with hoes:
|
||||||
|
|
||||||
|
-- turns nodes with group soil=1 into soil
|
||||||
|
local function hoe_on_use(itemstack, user, pointed_thing, uses)
|
||||||
|
local pt = pointed_thing
|
||||||
|
-- check if pointing at a node
|
||||||
|
if not pt then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if pt.type ~= "node" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local under = minetest.get_node(pt.under)
|
||||||
|
local p = {x=pt.under.x, y=pt.under.y+1, z=pt.under.z}
|
||||||
|
local above = minetest.get_node(p)
|
||||||
|
|
||||||
|
-- return if any of the nodes is not registered
|
||||||
|
if not minetest.registered_nodes[under.name] then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if not minetest.registered_nodes[above.name] then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- check if the node above the pointed thing is air
|
||||||
|
if above.name ~= "air" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- check if pointing at dirt
|
||||||
|
if minetest.get_item_group(under.name, "soil") ~= 1 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- turn the node into soil, play sound, get worm and wear out item
|
||||||
|
minetest.set_node(pt.under, {name="farming:soil"})
|
||||||
|
minetest.sound_play("default_dig_crumbly", {
|
||||||
|
pos = pt.under,
|
||||||
|
gain = 0.5,
|
||||||
|
})
|
||||||
|
--local inv = user:get_inventory()
|
||||||
|
if math.random(1, 100) < WORM_CHANCE then
|
||||||
|
minetest.env:add_entity({x=pt.under.x, y=pt.under.y+0.4, z=pt.under.z}, "fishing:bait_worm_entity")
|
||||||
|
--if inv:room_for_item("main", {name="fishing:bait_worm", count=1, wear=0, metadata=""}) then
|
||||||
|
--inv:add_item("main", {name="fishing:bait_worm", count=1, wear=0, metadata=""})
|
||||||
|
--end
|
||||||
|
end
|
||||||
|
itemstack:add_wear(65535/(uses-1))
|
||||||
|
return itemstack
|
||||||
|
end
|
||||||
|
|
||||||
|
-- didn't change the hoes, just here because hoe_on_use is local
|
||||||
|
minetest.register_tool(":farming:hoe_wood", {
|
||||||
|
description = "Wooden Hoe",
|
||||||
|
inventory_image = "farming_tool_woodhoe.png",
|
||||||
|
on_use = function(itemstack, user, pointed_thing)
|
||||||
|
return hoe_on_use(itemstack, user, pointed_thing, 30)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
minetest.register_tool(":farming:hoe_stone", {
|
||||||
|
description = "Stone Hoe",
|
||||||
|
inventory_image = "farming_tool_stonehoe.png",
|
||||||
|
on_use = function(itemstack, user, pointed_thing)
|
||||||
|
return hoe_on_use(itemstack, user, pointed_thing, 90)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
minetest.register_tool(":farming:hoe_steel", {
|
||||||
|
description = "Steel Hoe",
|
||||||
|
inventory_image = "farming_tool_steelhoe.png",
|
||||||
|
on_use = function(itemstack, user, pointed_thing)
|
||||||
|
return hoe_on_use(itemstack, user, pointed_thing, 200)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
minetest.register_tool(":farming:hoe_bronze", {
|
||||||
|
description = "Bronze Hoe",
|
||||||
|
inventory_image = "farming_tool_bronzehoe.png",
|
||||||
|
on_use = function(itemstack, user, pointed_thing)
|
||||||
|
return hoe_on_use(itemstack, user, pointed_thing, 220)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
end
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
print("[Mod] "..title.." ["..version.."] ["..mname.."] Loaded...")
|
||||||
|
-----------------------------------------------------------------------------------------------
|
|
@ -0,0 +1,8 @@
|
||||||
|
MESSAGES = true
|
||||||
|
FISH_CHANCE = 70
|
||||||
|
NEW_WORM_SOURCE = false
|
||||||
|
WORM_CHANCE = 60
|
||||||
|
WEAR_OUT = true
|
||||||
|
BOBBER_CHECK_RADIUS = 5
|
||||||
|
BOBBER_COLOR_CHANGE = true
|
||||||
|
SIMPLE_DECO_FISHING_POLE = true
|
|
@ -0,0 +1,4 @@
|
||||||
|
These sounds are used for the Mod for Minetest; Fishing - Mossmanikin's version.
|
||||||
|
The included sounds are http://creativecommons.org/licenses/by-nc-sa/3.0/
|
||||||
|
|
||||||
|
--"fishing_bobber1" & "fishing_bobber2" sampled from "01260 water swimming splashing 1.wav", Attribution Noncommercial License, Robinhood76, http://www.freesound.org/people/Robinhood76/sounds/79657/
|
After Width: | Height: | Size: 217 B |
After Width: | Height: | Size: 295 B |
After Width: | Height: | Size: 238 B |
After Width: | Height: | Size: 222 B |
After Width: | Height: | Size: 196 B |
After Width: | Height: | Size: 209 B |
After Width: | Height: | Size: 206 B |
After Width: | Height: | Size: 142 B |
After Width: | Height: | Size: 181 B |
After Width: | Height: | Size: 354 B |
After Width: | Height: | Size: 180 B |
After Width: | Height: | Size: 151 B |
After Width: | Height: | Size: 303 B |
After Width: | Height: | Size: 142 B |
After Width: | Height: | Size: 590 B |
After Width: | Height: | Size: 203 B |
After Width: | Height: | Size: 269 B |
|
@ -0,0 +1,118 @@
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
-- Fishing - Mossmanikin's version - Worm 0.0.2
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
-- License (code & textures): WTFPL
|
||||||
|
-- Contains code from: fishing (original), mobs
|
||||||
|
-- Looked at code from: my_mobs
|
||||||
|
-- Dependencies: default
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
-- WORM ITEM
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
minetest.register_craftitem("fishing:bait_worm", {
|
||||||
|
description = "Worm",
|
||||||
|
groups = { fishing_bait=1 },
|
||||||
|
inventory_image = "fishing_worm.png",
|
||||||
|
on_use = minetest.item_eat(1),
|
||||||
|
on_place = function(itemstack, placer, pointed_thing)
|
||||||
|
local pt = pointed_thing
|
||||||
|
minetest.env:add_entity({x=pt.under.x, y=pt.under.y+0.6, z=pt.under.z}, "fishing:bait_worm_entity")
|
||||||
|
itemstack:take_item()
|
||||||
|
return itemstack
|
||||||
|
end,
|
||||||
|
on_drop = function(itemstack, dropper, pos)
|
||||||
|
minetest.env:add_entity({x = pos.x, y = pos.y, z = pos.z}, "fishing:bait_worm_entity")
|
||||||
|
itemstack:take_item()
|
||||||
|
return itemstack
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
-- WORM MOB
|
||||||
|
-----------------------------------------------------------------------------------------------
|
||||||
|
minetest.register_entity("fishing:bait_worm_entity", {
|
||||||
|
hp_max = 300,
|
||||||
|
damage_over_time = 1,
|
||||||
|
collisionbox = {-3/16, -3/16, -3/16, 3/16, 3/16, 3/16},
|
||||||
|
visual = "sprite",
|
||||||
|
visual_size = {x=1/2, y=1/2},
|
||||||
|
textures = { "fishing_worm.png", "fishing_worm.png"},
|
||||||
|
view_range = 32,
|
||||||
|
-- Don't punch this poor creature...
|
||||||
|
on_punch = function(self, puncher)
|
||||||
|
self.object:remove()
|
||||||
|
end,
|
||||||
|
-- ...softly take it into your hand.
|
||||||
|
on_rightclick = function(self, clicker)
|
||||||
|
if clicker:is_player() and clicker:get_inventory() then
|
||||||
|
clicker:get_inventory():add_item("main", "fishing:bait_worm")
|
||||||
|
self.object:remove()
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
-- AI :D
|
||||||
|
on_step = function(self, dtime)
|
||||||
|
local pos = self.object:getpos()
|
||||||
|
local n = minetest.env:get_node({x=pos.x,y=pos.y-0.3,z=pos.z})
|
||||||
|
-- despawn when no player in range
|
||||||
|
for _,player in pairs(minetest.get_connected_players()) do
|
||||||
|
local s = self.object:getpos()
|
||||||
|
local p = player:getpos()
|
||||||
|
local dist = ((p.x-s.x)^2 + (p.y-s.y)^2 + (p.z-s.z)^2)^0.5
|
||||||
|
if dist > self.view_range then
|
||||||
|
self.object:remove()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- move in world
|
||||||
|
local look_whats_up = function(self)
|
||||||
|
self.object:set_hp(self.object:get_hp()-self.damage_over_time) -- creature is getting older
|
||||||
|
if n.name == "air" then -- fall when in air
|
||||||
|
self.object:moveto({x=pos.x,y=pos.y-0.5,z=pos.z})
|
||||||
|
self.object:set_hp(self.object:get_hp()-75)
|
||||||
|
|
||||||
|
--if n.name == "snappy" then -- fall when leaves or similar
|
||||||
|
elseif minetest.get_item_group(n.name, "snappy") ~= 0 then
|
||||||
|
self.object:moveto({x=pos.x+(0.001*(math.random(-32, 32))),y=pos.y-(0.001*(math.random(0, 64))),z=pos.z+(0.001*(math.random(-32, 32)))})
|
||||||
|
|
||||||
|
|
||||||
|
elseif string.find(n.name, "default:water") then -- sink when in water
|
||||||
|
self.object:moveto({x=pos.x,y=pos.y-0.25,z=pos.z})
|
||||||
|
self.object:set_hp(self.object:get_hp()-37)
|
||||||
|
|
||||||
|
elseif minetest.get_item_group(n.name, "soil") ~= 0 then
|
||||||
|
if minetest.get_item_group(minetest.env:get_node({x=pos.x,y=pos.y-0.1,z=pos.z}).name, "soil") == 0 and self.object:get_hp() > 200 then
|
||||||
|
self.object:set_hp(199)
|
||||||
|
elseif self.object:get_hp() > 200 then -- leave dirt to see whats going on
|
||||||
|
self.object:moveto({x=pos.x+(0.001*(math.random(-2, 2))),y=pos.y+0.003,z=pos.z+(0.001*(math.random(-2, 2)))})
|
||||||
|
elseif self.object:get_hp() < 199 then -- no rain here, let's get outa here
|
||||||
|
self.object:moveto({x=pos.x+(0.001*(math.random(-2, 2))),y=pos.y-0.001,z=pos.z+(0.001*(math.random(-2, 2)))})
|
||||||
|
elseif self.object:get_hp() == 0 then
|
||||||
|
self.object:remove()
|
||||||
|
end
|
||||||
|
else -- check if there's dirt anywhere (not finished)
|
||||||
|
local check_group = minetest.get_item_group
|
||||||
|
local goal_01 = check_group(minetest.env:get_node({x = pos.x + 1, y = pos.y-0.4, z = pos.z }).name, "soil")
|
||||||
|
local goal_02 = check_group(minetest.env:get_node({x = pos.x, y = pos.y-0.4, z = pos.z + 1}).name, "soil")
|
||||||
|
local goal_03 = check_group(minetest.env:get_node({x = pos.x - 1, y = pos.y-0.4, z = pos.z }).name, "soil")
|
||||||
|
local goal_04 = check_group(minetest.env:get_node({x = pos.x, y = pos.y-0.4, z = pos.z - 1}).name, "soil")
|
||||||
|
|
||||||
|
local goal_1a = check_group(minetest.env:get_node({x = pos.x + 1, y = pos.y+0.6, z = pos.z }).name, "soil")
|
||||||
|
local goal_2a = check_group(minetest.env:get_node({x = pos.x, y = pos.y+0.6, z = pos.z + 1}).name, "soil")
|
||||||
|
local goal_3a = check_group(minetest.env:get_node({x = pos.x - 1, y = pos.y+0.6, z = pos.z }).name, "soil")
|
||||||
|
local goal_4a = check_group(minetest.env:get_node({x = pos.x, y = pos.y+0.6, z = pos.z - 1}).name, "soil")
|
||||||
|
-- if there's dirt nearby, go there
|
||||||
|
if goal_01 ~= 0 or goal_1a ~= 0 then
|
||||||
|
self.object:moveto({x=pos.x+0.002,y=pos.y,z=pos.z+(0.001*(math.random(-2, 2)))})
|
||||||
|
elseif goal_02 ~= 0 or goal_2a ~= 0 then
|
||||||
|
self.object:moveto({x=pos.x+(0.001*(math.random(-2, 2))),y=pos.y,z=pos.z+0.002})
|
||||||
|
elseif goal_03 ~= 0 or goal_3a ~= 0 then
|
||||||
|
self.object:moveto({x=pos.x-0.002,y=pos.y,z=pos.z+(0.001*(math.random(-2, 2)))})
|
||||||
|
elseif goal_04 ~= 0 or goal_4a ~= 0 then
|
||||||
|
self.object:moveto({x=pos.x+(0.001*(math.random(-2, 2))),y=pos.y,z=pos.z-0.002})
|
||||||
|
else -- I'm lost, no dirt
|
||||||
|
self.object:moveto({x=pos.x+(0.001*(math.random(-8, 8))),y=pos.y,z=pos.z+(0.001*(math.random(-8, 8)))})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
look_whats_up(self)
|
||||||
|
end,
|
||||||
|
})
|
|
@ -0,0 +1,2 @@
|
||||||
|
*~
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "src/LuaIRC"]
|
||||||
|
path = irc
|
||||||
|
url = https://github.com/ShadowNinja/LuaIRC.git
|
|
@ -0,0 +1,14 @@
|
||||||
|
|
||||||
|
allow_defined_top = true
|
||||||
|
|
||||||
|
read_globals = {
|
||||||
|
"minetest",
|
||||||
|
}
|
||||||
|
|
||||||
|
exclude_files = {
|
||||||
|
"irc/*",
|
||||||
|
}
|
||||||
|
|
||||||
|
globals = {
|
||||||
|
"irc",
|
||||||
|
}
|
|
@ -0,0 +1,90 @@
|
||||||
|
IRC Mod API
|
||||||
|
===========
|
||||||
|
|
||||||
|
This file documents the Minetest IRC mod API.
|
||||||
|
|
||||||
|
Basics
|
||||||
|
------
|
||||||
|
|
||||||
|
In order to allow your mod to interface with this mod, you must add `irc`
|
||||||
|
to your mod's `depends.txt` file.
|
||||||
|
|
||||||
|
|
||||||
|
Reference
|
||||||
|
---------
|
||||||
|
|
||||||
|
irc.say([name,] message)
|
||||||
|
Sends <message> to either the channel (if <name> is nil or not specified),
|
||||||
|
or to the given user (if <name> is specified).
|
||||||
|
Example:
|
||||||
|
irc.say("Hello, Channel!")
|
||||||
|
irc.say("john1234", "How are you?")
|
||||||
|
|
||||||
|
irc.register_bot_command(name, cmdDef)
|
||||||
|
Registers a new bot command named <name>.
|
||||||
|
When an user sends a private message to the bot with the command name, the
|
||||||
|
command's function is called.
|
||||||
|
Here's the format of a command definition (<cmdDef>):
|
||||||
|
cmdDef = {
|
||||||
|
params = "<param1> ...", -- A description of the command's parameters
|
||||||
|
description = "My command", -- A description of what the command does. (one-liner)
|
||||||
|
func = function(user, args)
|
||||||
|
-- This function gets called when the command is invoked.
|
||||||
|
-- <user> is a user table for the user that ran the command.
|
||||||
|
-- (See the LuaIRC documentation for details.)
|
||||||
|
-- It contains fields such as 'nick' and 'ident'
|
||||||
|
-- <args> is a string of arguments to the command (may be "")
|
||||||
|
-- This function should return boolean success and a message.
|
||||||
|
end,
|
||||||
|
};
|
||||||
|
Example:
|
||||||
|
irc.register_bot_command("hello", {
|
||||||
|
params = "",
|
||||||
|
description = "Greet user",
|
||||||
|
func = function(user, param)
|
||||||
|
return true, "Hello!"
|
||||||
|
end,
|
||||||
|
});
|
||||||
|
|
||||||
|
irc.joined_players[name]
|
||||||
|
This table holds the players who are currently on the channel (may be less
|
||||||
|
than the players in the game). It is modified by the /part and /join chat
|
||||||
|
commands.
|
||||||
|
Example:
|
||||||
|
if irc.joined_players["joe"] then
|
||||||
|
-- Joe is talking on IRC
|
||||||
|
end
|
||||||
|
|
||||||
|
irc.register_hook(name, func)
|
||||||
|
Registers a function to be called when an event happens. <name> is the name
|
||||||
|
of the event, and <func> is the function to be called. See HOOKS below
|
||||||
|
for more information
|
||||||
|
Example:
|
||||||
|
irc.register_hook("OnSend", function(line)
|
||||||
|
print("SEND: "..line)
|
||||||
|
end)
|
||||||
|
|
||||||
|
This mod also supplies some utility functions:
|
||||||
|
|
||||||
|
string.expandvars(string, vars)
|
||||||
|
Expands all occurrences of the pattern "$(varname)" with the value of
|
||||||
|
'varname' in the <vars> table. Variable names not found on the table
|
||||||
|
are left verbatim in the string.
|
||||||
|
Example:
|
||||||
|
local tpl = "$(foo) $(bar) $(baz)"
|
||||||
|
local s = tpl:expandvars({foo=1, bar="Hello"})
|
||||||
|
assert(s == "1 Hello $(baz)")
|
||||||
|
|
||||||
|
In addition, all the configuration options decribed in `README.txt` are
|
||||||
|
available to other mods, though they should be considered read-only. Do
|
||||||
|
not modify these settings at runtime or you might crash the server!
|
||||||
|
|
||||||
|
|
||||||
|
Hooks
|
||||||
|
-----
|
||||||
|
|
||||||
|
The `irc.register_hook` function can register functions to be called
|
||||||
|
when some events happen. The events supported are the same as the LuaIRC
|
||||||
|
ones with a few added (mostly for internal use).
|
||||||
|
See src/LuaIRC/doc/irc.luadoc for more information.
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
Copyright (c) 2013, Diego Martinez (kaeza)
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
- Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
- Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
|
@ -0,0 +1,181 @@
|
||||||
|
|
||||||
|
IRC Mod for Minetest
|
||||||
|
====================
|
||||||
|
|
||||||
|
Introduction
|
||||||
|
------------
|
||||||
|
|
||||||
|
This mod is just a glue between IRC and Minetest. It provides two-way
|
||||||
|
communication between the in-game chat, and an arbitrary IRC channel.
|
||||||
|
|
||||||
|
The forum topic is [here][forum].
|
||||||
|
|
||||||
|
[forum]: https://forum.minetest.net/viewtopic.php?f=11&t=3905
|
||||||
|
|
||||||
|
|
||||||
|
Installing
|
||||||
|
----------
|
||||||
|
|
||||||
|
Quick one line install for Linux:
|
||||||
|
|
||||||
|
cd <Mods directory> && git clone --recursive https://github.com/minetest-mods/irc.git
|
||||||
|
|
||||||
|
Please change `<Mods directory>` to fit your installation of Minetest.
|
||||||
|
For more information, see [the wiki][wiki].
|
||||||
|
|
||||||
|
The IRC mod's git repository uses submodules, therefore you will have to run
|
||||||
|
`git submodule init` when first installing the mod (unless you used
|
||||||
|
`--recursive` as above), and `git submodule update` every time that a submodule
|
||||||
|
is updated. These steps can be combined into `git submodule update --init`.
|
||||||
|
|
||||||
|
You'll need to install LuaSocket. You can do so with your package manager on
|
||||||
|
many distributions, for example:
|
||||||
|
|
||||||
|
# # On Arch Linux:
|
||||||
|
# pacman -S lua51-socket
|
||||||
|
# # On Debian/Ubuntu:
|
||||||
|
# # Debian/Ubuntu's LuaSocket packages are broken, so use LuaRocks.
|
||||||
|
# apt-get install luarocks
|
||||||
|
# luarocks install luasocket
|
||||||
|
|
||||||
|
You will also need to add IRC to your trusted mods if you haven't disabled mod
|
||||||
|
security. Here's an example configuration line:
|
||||||
|
|
||||||
|
secure.trusted_mods = irc
|
||||||
|
|
||||||
|
[wiki]: https://wiki.minetest.net/Installing_mods
|
||||||
|
|
||||||
|
|
||||||
|
Settings
|
||||||
|
--------
|
||||||
|
|
||||||
|
All settings are changed in `minetest.conf`. If any of these settings
|
||||||
|
are not set, the default value is used.
|
||||||
|
|
||||||
|
* `irc.server` (string):
|
||||||
|
The address of the IRC server to connect to.
|
||||||
|
|
||||||
|
* `irc.channel` (string):
|
||||||
|
The IRC channel to join.
|
||||||
|
|
||||||
|
* `irc.interval` (number, default 2.0):
|
||||||
|
This prevents the server from flooding. It should be at
|
||||||
|
least 2.0 but can be higher. After four messages this much
|
||||||
|
time must pass between folowing messages.
|
||||||
|
|
||||||
|
* `irc.nick` (string):
|
||||||
|
Nickname the server uses when it connects to IRC.
|
||||||
|
|
||||||
|
* `irc.password` (string, default nil):
|
||||||
|
Password to use when connecting to the server.
|
||||||
|
|
||||||
|
* `irc.NSPass` (string, default nil):
|
||||||
|
NickServ password. Don't set this if you use SASL authentication.
|
||||||
|
|
||||||
|
* `irc.sasl.pass` (string, default nil):
|
||||||
|
SASL password, same as nickserv password.
|
||||||
|
You should use this instead of NickServ authentication
|
||||||
|
if the server supports it.
|
||||||
|
|
||||||
|
* `irc.sasl.user` (string, default `irc.nick`):
|
||||||
|
The SASL username. This should normaly be set to your
|
||||||
|
NickServ account name.
|
||||||
|
|
||||||
|
* `irc.debug` (boolean, default false):
|
||||||
|
Whether to output debug information.
|
||||||
|
|
||||||
|
* `irc.disable_auto_connect` (boolean, default false):
|
||||||
|
If false, the bot is connected by default. If true, a player with
|
||||||
|
the 'irc_admin' privilege has to use the `/irc_connect` command to
|
||||||
|
connect to the server.
|
||||||
|
|
||||||
|
* `irc.disable_auto_join` (boolean, default false):
|
||||||
|
If false, players join the channel automatically upon entering the
|
||||||
|
game. If true, each user must manually use the `/join` command to
|
||||||
|
join the channel. In any case, the players may use the `/part`
|
||||||
|
command to opt-out of being in the channel.
|
||||||
|
|
||||||
|
* `irc.send_join_part` (boolean, default true):
|
||||||
|
Determines whether to send player join and part messages to the channel.
|
||||||
|
|
||||||
|
|
||||||
|
Usage
|
||||||
|
-----
|
||||||
|
|
||||||
|
Once the game is connected to the IRC channel, chatting in-game will send
|
||||||
|
messages to the channel, and will be visible by anyone. Also, messages sent
|
||||||
|
to the channel will be visible in-game.
|
||||||
|
|
||||||
|
Messages that begin with `[off]` from in-game or IRC are not sent to the
|
||||||
|
other side.
|
||||||
|
|
||||||
|
This mod also adds a few chat commands:
|
||||||
|
|
||||||
|
* `/irc_msg <nick> <message>`:
|
||||||
|
Send a private message to a IRC user.
|
||||||
|
|
||||||
|
* `/join`:
|
||||||
|
Join the IRC chat.
|
||||||
|
|
||||||
|
* `/part`:
|
||||||
|
Part the IRC chat.
|
||||||
|
|
||||||
|
* `/irc_connect`:
|
||||||
|
Connect the bot manually to the IRC network.
|
||||||
|
|
||||||
|
* `/irc_disconnect`:
|
||||||
|
Disconnect the bot manually from the IRC network (this does not
|
||||||
|
shutdown the game).
|
||||||
|
|
||||||
|
* `/irc_reconnect`:
|
||||||
|
Equivalent to `/irc_disconnect` followed by `/irc_connect`.
|
||||||
|
|
||||||
|
You can also send private messages from IRC to in-game players
|
||||||
|
by sending a private message to the bot (set with the `irc.nick`
|
||||||
|
option above), in the following format:
|
||||||
|
|
||||||
|
@playername message
|
||||||
|
|
||||||
|
For example, if there's a player named `mtuser`, you can send him/her
|
||||||
|
a private message from IRC with:
|
||||||
|
|
||||||
|
/msg server_nick @mtuser Hello!
|
||||||
|
|
||||||
|
The bot also supports some basic commands, which are invoked by saying
|
||||||
|
the bot name followed by either a colon or a comma and the command, or
|
||||||
|
sending a private message to it. For example: `ServerBot: help whereis`.
|
||||||
|
|
||||||
|
* `help [<command>]`:
|
||||||
|
Prints help about a command, or a list of supported commands if no
|
||||||
|
command is given.
|
||||||
|
|
||||||
|
* `uptime`:
|
||||||
|
Prints the server's running time.
|
||||||
|
|
||||||
|
* `whereis <player>`:
|
||||||
|
Prints the coordinates of the given player.
|
||||||
|
|
||||||
|
* `players`:
|
||||||
|
Lists players currently in the server.
|
||||||
|
|
||||||
|
|
||||||
|
Thanks
|
||||||
|
------
|
||||||
|
|
||||||
|
I'd like to thank the users who supported this mod both on the Minetest
|
||||||
|
Forums and on the `#minetest` channel. In no particular order:
|
||||||
|
|
||||||
|
0gb.us, ShadowNinja, Shaun/kizeren, RAPHAEL, DARGON, Calinou, Exio,
|
||||||
|
vortexlabs/mrtux, marveidemanis, marktraceur, jmf/john\_minetest,
|
||||||
|
sdzen/Muadtralk, VanessaE, PilzAdam, sfan5, celeron55, KikaRz,
|
||||||
|
OldCoder, RealBadAngel, and all the people who commented in the
|
||||||
|
forum topic. Thanks to you all!
|
||||||
|
|
||||||
|
|
||||||
|
License
|
||||||
|
-------
|
||||||
|
|
||||||
|
See `LICENSE.txt` for details.
|
||||||
|
|
||||||
|
The files in the `irc` directory are part of the LuaIRC project.
|
||||||
|
See `irc/LICENSE.txt` for details.
|
|
@ -0,0 +1,175 @@
|
||||||
|
|
||||||
|
irc.bot_commands = {}
|
||||||
|
|
||||||
|
-- From RFC1459:
|
||||||
|
-- "Because of IRC’s scandanavian origin, the characters {}| are
|
||||||
|
-- considered to be the lower case equivalents of the characters
|
||||||
|
-- []\, respectively."
|
||||||
|
local irctolower = { ["["]="{", ["\\"]="|", ["]"]="}" }
|
||||||
|
|
||||||
|
local function irclower(s)
|
||||||
|
return (s:lower():gsub("[%[%]\\]", irctolower))
|
||||||
|
end
|
||||||
|
|
||||||
|
local function nickequals(nick1, nick2)
|
||||||
|
return irclower(nick1) == irclower(nick2)
|
||||||
|
end
|
||||||
|
|
||||||
|
function irc.check_botcmd(msg)
|
||||||
|
local prefix = irc.config.command_prefix
|
||||||
|
local nick = irc.conn.nick
|
||||||
|
local text = msg.args[2]
|
||||||
|
local nickpart = text:sub(1, #nick)
|
||||||
|
local suffix = text:sub(#nick+1, #nick+2)
|
||||||
|
|
||||||
|
-- First check for a nick prefix
|
||||||
|
if nickequals(nickpart, nick)
|
||||||
|
and (suffix == ": " or suffix == ", ") then
|
||||||
|
irc.bot_command(msg, text:sub(#nick + 3))
|
||||||
|
return true
|
||||||
|
-- Then check for the configured prefix
|
||||||
|
elseif prefix and text:sub(1, #prefix):lower() == prefix:lower() then
|
||||||
|
irc.bot_command(msg, text:sub(#prefix + 1))
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function irc.bot_command(msg, text)
|
||||||
|
-- Remove leading whitespace
|
||||||
|
text = text:match("^%s*(.*)")
|
||||||
|
if text:sub(1, 1) == "@" then
|
||||||
|
local _, _, player_to, message = text:find("^.([^%s]+)%s(.+)$")
|
||||||
|
if not player_to then
|
||||||
|
return
|
||||||
|
elseif not minetest.get_player_by_name(player_to) then
|
||||||
|
irc.reply("User '"..player_to.."' is not in the game.")
|
||||||
|
return
|
||||||
|
elseif not irc.joined_players[player_to] then
|
||||||
|
irc.reply("User '"..player_to.."' is not using IRC.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
minetest.chat_send_player(player_to,
|
||||||
|
"PM from "..msg.user.nick.."@IRC: "..message, false)
|
||||||
|
irc.reply("Message sent!")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local pos = text:find(" ", 1, true)
|
||||||
|
local cmd, args
|
||||||
|
if pos then
|
||||||
|
cmd = text:sub(1, pos - 1)
|
||||||
|
args = text:sub(pos + 1)
|
||||||
|
else
|
||||||
|
cmd = text
|
||||||
|
args = ""
|
||||||
|
end
|
||||||
|
|
||||||
|
if not irc.bot_commands[cmd] then
|
||||||
|
irc.reply("Unknown command '"..cmd.."'. Try 'help'."
|
||||||
|
.." Or use @playername <message> to send a private message")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local _, message = irc.bot_commands[cmd].func(msg.user, args)
|
||||||
|
if message then
|
||||||
|
irc.reply(message)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function irc.register_bot_command(name, def)
|
||||||
|
if (not def.func) or (type(def.func) ~= "function") then
|
||||||
|
error("Erroneous bot command definition. def.func missing.", 2)
|
||||||
|
elseif name:sub(1, 1) == "@" then
|
||||||
|
error("Erroneous bot command name. Command name begins with '@'.", 2)
|
||||||
|
end
|
||||||
|
irc.bot_commands[name] = def
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
irc.register_bot_command("help", {
|
||||||
|
params = "<command>",
|
||||||
|
description = "Get help about a command",
|
||||||
|
func = function(_, args)
|
||||||
|
if args == "" then
|
||||||
|
local cmdlist = { }
|
||||||
|
for name in pairs(irc.bot_commands) do
|
||||||
|
cmdlist[#cmdlist+1] = name
|
||||||
|
end
|
||||||
|
return true, "Available commands: "..table.concat(cmdlist, ", ")
|
||||||
|
.." -- Use 'help <command name>' to get"
|
||||||
|
.." help about a specific command."
|
||||||
|
end
|
||||||
|
|
||||||
|
local cmd = irc.bot_commands[args]
|
||||||
|
if not cmd then
|
||||||
|
return false, "Unknown command '"..args.."'."
|
||||||
|
end
|
||||||
|
|
||||||
|
return true, ("Usage: %s%s %s -- %s"):format(
|
||||||
|
irc.config.command_prefix or "",
|
||||||
|
args,
|
||||||
|
cmd.params or "<no parameters>",
|
||||||
|
cmd.description or "<no description>")
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
irc.register_bot_command("list", {
|
||||||
|
params = "",
|
||||||
|
description = "List available commands.",
|
||||||
|
func = function()
|
||||||
|
return false, "The `list` command has been merged into `help`."
|
||||||
|
.." Use `help` with no arguments to get a list."
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
irc.register_bot_command("whereis", {
|
||||||
|
params = "<player>",
|
||||||
|
description = "Tell the location of <player>",
|
||||||
|
func = function(_, args)
|
||||||
|
if args == "" then
|
||||||
|
return false, "Player name required."
|
||||||
|
end
|
||||||
|
local player = minetest.get_player_by_name(args)
|
||||||
|
if not player then
|
||||||
|
return false, "There is no player named '"..args.."'"
|
||||||
|
end
|
||||||
|
local fmt = "Player %s is at (%.2f,%.2f,%.2f)"
|
||||||
|
local pos = player:getpos()
|
||||||
|
return true, fmt:format(args, pos.x, pos.y, pos.z)
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
local starttime = os.time()
|
||||||
|
irc.register_bot_command("uptime", {
|
||||||
|
description = "Tell how much time the server has been up",
|
||||||
|
func = function()
|
||||||
|
local cur_time = os.time()
|
||||||
|
local diff = os.difftime(cur_time, starttime)
|
||||||
|
local fmt = "Server has been running for %d:%02d:%02d"
|
||||||
|
return true, fmt:format(
|
||||||
|
math.floor(diff / 60 / 60),
|
||||||
|
math.floor(diff / 60) % 60,
|
||||||
|
math.floor(diff) % 60
|
||||||
|
)
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
irc.register_bot_command("players", {
|
||||||
|
description = "List the players on the server",
|
||||||
|
func = function()
|
||||||
|
local players = minetest.get_connected_players()
|
||||||
|
local names = {}
|
||||||
|
for _, player in pairs(players) do
|
||||||
|
table.insert(names, player:get_player_name())
|
||||||
|
end
|
||||||
|
return true, "Connected players: "
|
||||||
|
..table.concat(names, ", ")
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
-- This file is licensed under the terms of the BSD 2-clause license.
|
||||||
|
-- See LICENSE.txt for details.
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_on_joinplayer(function(player)
|
||||||
|
local name = player:get_player_name()
|
||||||
|
if irc.connected and irc.config.send_join_part then
|
||||||
|
irc.say("*** "..name.." joined the game")
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_on_leaveplayer(function(player, timed_out)
|
||||||
|
local name = player:get_player_name()
|
||||||
|
if irc.connected and irc.config.send_join_part then
|
||||||
|
irc.say("*** "..name.." left the game"..
|
||||||
|
(timed_out and " (Timed out)" or ""))
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_on_chat_message(function(name, message)
|
||||||
|
if not irc.connected
|
||||||
|
or message:sub(1, 1) == "/"
|
||||||
|
or message:sub(1, 5) == "[off]"
|
||||||
|
or not irc.joined_players[name]
|
||||||
|
or (not minetest.check_player_privs(name, {shout=true})) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local nl = message:find("\n", 1, true)
|
||||||
|
if nl then
|
||||||
|
message = message:sub(1, nl - 1)
|
||||||
|
end
|
||||||
|
irc.say(irc.playerMessage(name, core.strip_colors(message)))
|
||||||
|
end)
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_on_shutdown(function()
|
||||||
|
irc.disconnect("Game shutting down.")
|
||||||
|
end)
|
||||||
|
|
|
@ -0,0 +1,134 @@
|
||||||
|
-- This file is licensed under the terms of the BSD 2-clause license.
|
||||||
|
-- See LICENSE.txt for details.
|
||||||
|
|
||||||
|
-- Note: This file does NOT conatin every chat command, only general ones.
|
||||||
|
-- Feature-specific commands (like /join) are in their own files.
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_chatcommand("irc_msg", {
|
||||||
|
params = "<name> <message>",
|
||||||
|
description = "Send a private message to an IRC user",
|
||||||
|
privs = {shout=true},
|
||||||
|
func = function(name, param)
|
||||||
|
if not irc.connected then
|
||||||
|
return false, "Not connected to IRC. Use /irc_connect to connect."
|
||||||
|
end
|
||||||
|
local found, _, toname, message = param:find("^([^%s]+)%s(.+)")
|
||||||
|
if not found then
|
||||||
|
return false, "Invalid usage, see /help irc_msg."
|
||||||
|
end
|
||||||
|
local toname_l = toname:lower()
|
||||||
|
local validNick = false
|
||||||
|
local hint = "They have to be in the channel"
|
||||||
|
for nick in pairs(irc.conn.channels[irc.config.channel].users) do
|
||||||
|
if nick:lower() == toname_l then
|
||||||
|
validNick = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if toname_l:find("serv$") or toname_l:find("bot$") then
|
||||||
|
hint = "it looks like a bot or service"
|
||||||
|
validNick = false
|
||||||
|
end
|
||||||
|
if not validNick then
|
||||||
|
return false, "You can not message that user. ("..hint..")"
|
||||||
|
end
|
||||||
|
irc.say(toname, irc.playerMessage(name, message))
|
||||||
|
return true, "Message sent!"
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_chatcommand("irc_names", {
|
||||||
|
params = "",
|
||||||
|
description = "List the users in IRC.",
|
||||||
|
func = function()
|
||||||
|
if not irc.connected then
|
||||||
|
return false, "Not connected to IRC. Use /irc_connect to connect."
|
||||||
|
end
|
||||||
|
local users = { }
|
||||||
|
for nick in pairs(irc.conn.channels[irc.config.channel].users) do
|
||||||
|
table.insert(users, nick)
|
||||||
|
end
|
||||||
|
return true, "Users in IRC: "..table.concat(users, ", ")
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_chatcommand("irc_connect", {
|
||||||
|
description = "Connect to the IRC server.",
|
||||||
|
privs = {irc_admin=true},
|
||||||
|
func = function(name)
|
||||||
|
if irc.connected then
|
||||||
|
return false, "You are already connected to IRC."
|
||||||
|
end
|
||||||
|
minetest.chat_send_player(name, "IRC: Connecting...")
|
||||||
|
irc.connect()
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_chatcommand("irc_disconnect", {
|
||||||
|
params = "[message]",
|
||||||
|
description = "Disconnect from the IRC server.",
|
||||||
|
privs = {irc_admin=true},
|
||||||
|
func = function(name, param)
|
||||||
|
if not irc.connected then
|
||||||
|
return false, "Not connected to IRC. Use /irc_connect to connect."
|
||||||
|
end
|
||||||
|
if param == "" then
|
||||||
|
param = "Manual disconnect by "..name
|
||||||
|
end
|
||||||
|
irc.disconnect(param)
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_chatcommand("irc_reconnect", {
|
||||||
|
description = "Reconnect to the IRC server.",
|
||||||
|
privs = {irc_admin=true},
|
||||||
|
func = function(name)
|
||||||
|
if not irc.connected then
|
||||||
|
return false, "Not connected to IRC. Use /irc_connect to connect."
|
||||||
|
end
|
||||||
|
minetest.chat_send_player(name, "IRC: Reconnecting...")
|
||||||
|
irc.disconnect("Reconnecting...")
|
||||||
|
irc.connect()
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_chatcommand("irc_quote", {
|
||||||
|
params = "<command>",
|
||||||
|
description = "Send a raw command to the IRC server.",
|
||||||
|
privs = {irc_admin=true},
|
||||||
|
func = function(name, param)
|
||||||
|
if not irc.connected then
|
||||||
|
return false, "Not connected to IRC. Use /irc_connect to connect."
|
||||||
|
end
|
||||||
|
irc.queue(param)
|
||||||
|
minetest.chat_send_player(name, "Command sent!")
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
local oldme = minetest.chatcommands["me"].func
|
||||||
|
-- luacheck: ignore
|
||||||
|
minetest.chatcommands["me"].func = function(name, param, ...)
|
||||||
|
irc.say(("* %s %s"):format(name, param))
|
||||||
|
return oldme(name, param, ...)
|
||||||
|
end
|
||||||
|
|
||||||
|
if irc.config.send_kicks and minetest.chatcommands["kick"] then
|
||||||
|
local oldkick = minetest.chatcommands["kick"].func
|
||||||
|
-- luacheck: ignore
|
||||||
|
minetest.chatcommands["kick"].func = function(name, param, ...)
|
||||||
|
local plname, reason = param:match("^(%S+)%s*(.*)$")
|
||||||
|
if not plname then
|
||||||
|
return false, "Usage: /kick player [reason]"
|
||||||
|
end
|
||||||
|
irc.say(("*** Kicked %s.%s"):format(name,
|
||||||
|
reason~="" and " Reason: "..reason or ""))
|
||||||
|
return oldkick(name, param, ...)
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,56 @@
|
||||||
|
-- This file is licensed under the terms of the BSD 2-clause license.
|
||||||
|
-- See LICENSE.txt for details.
|
||||||
|
|
||||||
|
|
||||||
|
irc.config = {}
|
||||||
|
|
||||||
|
local function setting(stype, name, default, required)
|
||||||
|
local value
|
||||||
|
if stype == "bool" then
|
||||||
|
value = minetest.setting_getbool("irc."..name)
|
||||||
|
elseif stype == "string" then
|
||||||
|
value = minetest.setting_get("irc."..name)
|
||||||
|
elseif stype == "number" then
|
||||||
|
value = tonumber(minetest.setting_get("irc."..name))
|
||||||
|
end
|
||||||
|
if value == nil then
|
||||||
|
if required then
|
||||||
|
error("Required configuration option irc."..
|
||||||
|
name.." missing.")
|
||||||
|
end
|
||||||
|
value = default
|
||||||
|
end
|
||||||
|
irc.config[name] = value
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------
|
||||||
|
-- BASIC USER SETTINGS --
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
setting("string", "nick", nil, true) -- Nickname
|
||||||
|
setting("string", "server", nil, true) -- Server address to connect to
|
||||||
|
setting("number", "port", 6667) -- Server port to connect to
|
||||||
|
setting("string", "NSPass") -- NickServ password
|
||||||
|
setting("string", "sasl.user", irc.config.nick) -- SASL username
|
||||||
|
setting("string", "username", "Minetest") -- Username/ident
|
||||||
|
setting("string", "realname", "Minetest") -- Real name/GECOS
|
||||||
|
setting("string", "sasl.pass") -- SASL password
|
||||||
|
setting("string", "channel", nil, true) -- Channel to join
|
||||||
|
setting("string", "key") -- Key for the channel
|
||||||
|
setting("bool", "send_join_part", true) -- Whether to send player join and part messages to the channel
|
||||||
|
setting("bool", "send_kicks", false) -- Whether to send player kicked messages to the channel
|
||||||
|
|
||||||
|
-----------------------
|
||||||
|
-- ADVANCED SETTINGS --
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
setting("string", "password") -- Server password
|
||||||
|
setting("bool", "secure", false) -- Enable a TLS connection, requires LuaSEC
|
||||||
|
setting("number", "timeout", 60) -- Underlying socket timeout in seconds.
|
||||||
|
setting("number", "reconnect", 600) -- Time between reconnection attempts, in seconds.
|
||||||
|
setting("string", "command_prefix") -- Prefix to use for bot commands
|
||||||
|
setting("bool", "debug", false) -- Enable debug output
|
||||||
|
setting("bool", "enable_player_part", true) -- Whether to enable players joining and parting the channel
|
||||||
|
setting("bool", "auto_join", true) -- Whether to automatically show players in the channel when they join
|
||||||
|
setting("bool", "auto_connect", true) -- Whether to automatically connect to the server on mod load
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
This mod is just a glue between IRC and Minetest.
|
||||||
|
|
||||||
|
It provides two-way communication between the
|
||||||
|
in-game chat, and an arbitrary IRC channel.
|
|
@ -0,0 +1,258 @@
|
||||||
|
-- This file is licensed under the terms of the BSD 2-clause license.
|
||||||
|
-- See LICENSE.txt for details.
|
||||||
|
|
||||||
|
local ie = ...
|
||||||
|
|
||||||
|
-- MIME is part of LuaSocket
|
||||||
|
local b64e = ie.require("mime").b64
|
||||||
|
|
||||||
|
irc.hooks = {}
|
||||||
|
irc.registered_hooks = {}
|
||||||
|
|
||||||
|
|
||||||
|
local stripped_chars = "[\2\31]"
|
||||||
|
|
||||||
|
local function normalize(text)
|
||||||
|
-- Strip colors
|
||||||
|
text = text:gsub("\3[0-9][0-9,]*", "")
|
||||||
|
|
||||||
|
return text:gsub(stripped_chars, "")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function irc.doHook(conn)
|
||||||
|
for name, hook in pairs(irc.registered_hooks) do
|
||||||
|
for _, func in pairs(hook) do
|
||||||
|
conn:hook(name, func)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function irc.register_hook(name, func)
|
||||||
|
irc.registered_hooks[name] = irc.registered_hooks[name] or {}
|
||||||
|
table.insert(irc.registered_hooks[name], func)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function irc.hooks.raw(line)
|
||||||
|
if irc.config.debug then
|
||||||
|
print("RECV: "..line)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function irc.hooks.send(line)
|
||||||
|
if irc.config.debug then
|
||||||
|
print("SEND: "..line)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function irc.hooks.chat(msg)
|
||||||
|
local channel, text = msg.args[1], msg.args[2]
|
||||||
|
if text:sub(1, 1) == string.char(1) then
|
||||||
|
irc.conn:invoke("OnCTCP", msg)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if channel == irc.conn.nick then
|
||||||
|
irc.last_from = msg.user.nick
|
||||||
|
irc.conn:invoke("PrivateMessage", msg)
|
||||||
|
else
|
||||||
|
irc.last_from = channel
|
||||||
|
irc.conn:invoke("OnChannelChat", msg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function get_core_version()
|
||||||
|
local status = minetest.get_server_status()
|
||||||
|
local start_pos = select(2, status:find("version=", 1, true))
|
||||||
|
local end_pos = status:find(",", start_pos, true)
|
||||||
|
return status:sub(start_pos + 1, end_pos - 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function irc.hooks.ctcp(msg)
|
||||||
|
local text = msg.args[2]:sub(2, -2) -- Remove ^C
|
||||||
|
local args = text:split(' ')
|
||||||
|
local command = args[1]:upper()
|
||||||
|
|
||||||
|
local function reply(s)
|
||||||
|
irc.queue(irc.msgs.notice(msg.user.nick,
|
||||||
|
("\1%s %s\1"):format(command, s)))
|
||||||
|
end
|
||||||
|
|
||||||
|
if command == "ACTION" and msg.args[1] == irc.config.channel then
|
||||||
|
local action = text:sub(8, -1)
|
||||||
|
irc.sendLocal(("* %s@IRC %s"):format(msg.user.nick, action))
|
||||||
|
elseif command == "VERSION" then
|
||||||
|
reply(("Minetest version %s, IRC mod version %s.")
|
||||||
|
:format(get_core_version(), irc.version))
|
||||||
|
elseif command == "PING" then
|
||||||
|
reply(args[2])
|
||||||
|
elseif command == "TIME" then
|
||||||
|
reply(os.date())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function irc.hooks.channelChat(msg)
|
||||||
|
local text = normalize(msg.args[2])
|
||||||
|
|
||||||
|
irc.check_botcmd(msg)
|
||||||
|
|
||||||
|
-- Don't let a user impersonate someone else by using the nick "IRC"
|
||||||
|
local fake = msg.user.nick:lower():match("^[il|]rc$")
|
||||||
|
if fake then
|
||||||
|
irc.sendLocal("<"..msg.user.nick.."@IRC> "..text)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Support multiple servers in a channel better by converting:
|
||||||
|
-- "<server@IRC> <player> message" into "<player@server> message"
|
||||||
|
-- "<server@IRC> *** player joined/left the game" into "*** player joined/left server"
|
||||||
|
-- and "<server@IRC> * player orders a pizza" into "* player@server orders a pizza"
|
||||||
|
local foundchat, _, chatnick, chatmessage =
|
||||||
|
text:find("^<([^>]+)> (.*)$")
|
||||||
|
local foundjoin, _, joinnick =
|
||||||
|
text:find("^%*%*%* ([^%s]+) joined the game$")
|
||||||
|
local foundleave, _, leavenick =
|
||||||
|
text:find("^%*%*%* ([^%s]+) left the game$")
|
||||||
|
local foundaction, _, actionnick, actionmessage =
|
||||||
|
text:find("^%* ([^%s]+) (.*)$")
|
||||||
|
|
||||||
|
if text:sub(1, 5) == "[off]" then
|
||||||
|
return
|
||||||
|
elseif foundchat then
|
||||||
|
irc.sendLocal(("<%s@%s> %s")
|
||||||
|
:format(chatnick, msg.user.nick, chatmessage))
|
||||||
|
elseif foundjoin then
|
||||||
|
irc.sendLocal(("*** %s joined %s")
|
||||||
|
:format(joinnick, msg.user.nick))
|
||||||
|
elseif foundleave then
|
||||||
|
irc.sendLocal(("*** %s left %s")
|
||||||
|
:format(leavenick, msg.user.nick))
|
||||||
|
elseif foundaction then
|
||||||
|
irc.sendLocal(("* %s@%s %s")
|
||||||
|
:format(actionnick, msg.user.nick, actionmessage))
|
||||||
|
else
|
||||||
|
irc.sendLocal(("<%s@IRC> %s"):format(msg.user.nick, text))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function irc.hooks.pm(msg)
|
||||||
|
-- Trim prefix if it is found
|
||||||
|
local text = msg.args[2]
|
||||||
|
local prefix = irc.config.command_prefix
|
||||||
|
if prefix and text:sub(1, #prefix) == prefix then
|
||||||
|
text = text:sub(#prefix + 1)
|
||||||
|
end
|
||||||
|
irc.bot_command(msg, text)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function irc.hooks.kick(channel, target, prefix, reason)
|
||||||
|
if target == irc.conn.nick then
|
||||||
|
minetest.chat_send_all("IRC: kicked from "..channel.." by "..prefix.nick..".")
|
||||||
|
irc.disconnect("Kicked")
|
||||||
|
else
|
||||||
|
irc.sendLocal(("-!- %s was kicked from %s by %s [%s]")
|
||||||
|
:format(target, channel, prefix.nick, reason))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function irc.hooks.notice(user, target, message)
|
||||||
|
if user.nick and target == irc.config.channel then
|
||||||
|
irc.sendLocal("-"..user.nick.."@IRC- "..message)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function irc.hooks.mode(user, target, modes, ...)
|
||||||
|
local by = ""
|
||||||
|
if user.nick then
|
||||||
|
by = " by "..user.nick
|
||||||
|
end
|
||||||
|
local options = ""
|
||||||
|
if select("#", ...) > 0 then
|
||||||
|
options = " "
|
||||||
|
end
|
||||||
|
options = options .. table.concat({...}, " ")
|
||||||
|
minetest.chat_send_all(("-!- mode/%s [%s%s]%s")
|
||||||
|
:format(target, modes, options, by))
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function irc.hooks.nick(user, newNick)
|
||||||
|
irc.sendLocal(("-!- %s is now known as %s")
|
||||||
|
:format(user.nick, newNick))
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function irc.hooks.join(user, channel)
|
||||||
|
irc.sendLocal(("-!- %s joined %s")
|
||||||
|
:format(user.nick, channel))
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function irc.hooks.part(user, channel, reason)
|
||||||
|
reason = reason or ""
|
||||||
|
irc.sendLocal(("-!- %s has left %s [%s]")
|
||||||
|
:format(user.nick, channel, reason))
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function irc.hooks.quit(user, reason)
|
||||||
|
irc.sendLocal(("-!- %s has quit [%s]")
|
||||||
|
:format(user.nick, reason))
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function irc.hooks.disconnect(_, isError)
|
||||||
|
irc.connected = false
|
||||||
|
if isError then
|
||||||
|
minetest.log("error", "IRC: Error: Disconnected, reconnecting in one minute.")
|
||||||
|
minetest.chat_send_all("IRC: Error: Disconnected, reconnecting in one minute.")
|
||||||
|
minetest.after(60, irc.connect, irc)
|
||||||
|
else
|
||||||
|
minetest.log("action", "IRC: Disconnected.")
|
||||||
|
minetest.chat_send_all("IRC: Disconnected.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function irc.hooks.preregister(conn)
|
||||||
|
if not (irc.config["sasl.user"] and irc.config["sasl.pass"]) then return end
|
||||||
|
local authString = b64e(
|
||||||
|
("%s\x00%s\x00%s"):format(
|
||||||
|
irc.config["sasl.user"],
|
||||||
|
irc.config["sasl.user"],
|
||||||
|
irc.config["sasl.pass"])
|
||||||
|
)
|
||||||
|
conn:send("CAP REQ sasl")
|
||||||
|
conn:send("AUTHENTICATE PLAIN")
|
||||||
|
conn:send("AUTHENTICATE "..authString)
|
||||||
|
conn:send("CAP END")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
irc.register_hook("PreRegister", irc.hooks.preregister)
|
||||||
|
irc.register_hook("OnRaw", irc.hooks.raw)
|
||||||
|
irc.register_hook("OnSend", irc.hooks.send)
|
||||||
|
irc.register_hook("DoPrivmsg", irc.hooks.chat)
|
||||||
|
irc.register_hook("OnPart", irc.hooks.part)
|
||||||
|
irc.register_hook("OnKick", irc.hooks.kick)
|
||||||
|
irc.register_hook("OnJoin", irc.hooks.join)
|
||||||
|
irc.register_hook("OnQuit", irc.hooks.quit)
|
||||||
|
irc.register_hook("NickChange", irc.hooks.nick)
|
||||||
|
irc.register_hook("OnCTCP", irc.hooks.ctcp)
|
||||||
|
irc.register_hook("PrivateMessage", irc.hooks.pm)
|
||||||
|
irc.register_hook("OnNotice", irc.hooks.notice)
|
||||||
|
irc.register_hook("OnChannelChat", irc.hooks.channelChat)
|
||||||
|
irc.register_hook("OnModeChange", irc.hooks.mode)
|
||||||
|
irc.register_hook("OnDisconnect", irc.hooks.disconnect)
|
||||||
|
|
|
@ -0,0 +1,218 @@
|
||||||
|
-- This file is licensed under the terms of the BSD 2-clause license.
|
||||||
|
-- See LICENSE.txt for details.
|
||||||
|
|
||||||
|
local modpath = minetest.get_modpath(minetest.get_current_modname())
|
||||||
|
|
||||||
|
-- Handle mod security if needed
|
||||||
|
local ie, req_ie = _G, minetest.request_insecure_environment
|
||||||
|
if req_ie then ie = req_ie() end
|
||||||
|
if not ie then
|
||||||
|
error("The IRC mod requires access to insecure functions in order "..
|
||||||
|
"to work. Please add the irc mod to your secure.trusted_mods "..
|
||||||
|
"setting or disable the irc mod.")
|
||||||
|
end
|
||||||
|
|
||||||
|
ie.package.path =
|
||||||
|
-- To find LuaIRC's init.lua
|
||||||
|
modpath.."/?/init.lua;"
|
||||||
|
-- For LuaIRC to find its files
|
||||||
|
..modpath.."/?.lua;"
|
||||||
|
..ie.package.path
|
||||||
|
|
||||||
|
-- The build of Lua that Minetest comes with only looks for libraries under
|
||||||
|
-- /usr/local/share and /usr/local/lib but LuaSocket is often installed under
|
||||||
|
-- /usr/share and /usr/lib.
|
||||||
|
if not rawget(_G, "jit") and package.config:sub(1, 1) == "/" then
|
||||||
|
ie.package.path = ie.package.path..
|
||||||
|
";/usr/share/lua/5.1/?.lua"..
|
||||||
|
";/usr/share/lua/5.1/?/init.lua"
|
||||||
|
ie.package.cpath = ie.package.cpath..
|
||||||
|
";/usr/lib/lua/5.1/?.so"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Temporarily set require so that LuaIRC can access it
|
||||||
|
local old_require = require
|
||||||
|
require = ie.require
|
||||||
|
|
||||||
|
-- Silence warnings about `module` in `ltn12`.
|
||||||
|
local old_module = rawget(_G, "module")
|
||||||
|
rawset(_G, "module", ie.module)
|
||||||
|
|
||||||
|
local lib = ie.require("irc")
|
||||||
|
|
||||||
|
irc = {
|
||||||
|
version = "0.2.0",
|
||||||
|
connected = false,
|
||||||
|
cur_time = 0,
|
||||||
|
message_buffer = {},
|
||||||
|
recent_message_count = 0,
|
||||||
|
joined_players = {},
|
||||||
|
modpath = modpath,
|
||||||
|
lib = lib,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Compatibility
|
||||||
|
rawset(_G, "mt_irc", irc)
|
||||||
|
|
||||||
|
local getinfo = debug.getinfo
|
||||||
|
local warned = { }
|
||||||
|
|
||||||
|
local function warn_deprecated(k)
|
||||||
|
local info = getinfo(3)
|
||||||
|
local loc = info.source..":"..info.currentline
|
||||||
|
if warned[loc] then return end
|
||||||
|
warned[loc] = true
|
||||||
|
print("COLON: "..tostring(k))
|
||||||
|
minetest.log("warning", "Deprecated use of colon notation when calling"
|
||||||
|
.." method `"..tostring(k).."` at "..loc)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- This is a hack.
|
||||||
|
setmetatable(irc, {
|
||||||
|
__newindex = function(t, k, v)
|
||||||
|
if type(v) == "function" then
|
||||||
|
local f = v
|
||||||
|
v = function(me, ...)
|
||||||
|
if rawequal(me, t) then
|
||||||
|
warn_deprecated(k)
|
||||||
|
return f(...)
|
||||||
|
else
|
||||||
|
return f(me, ...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
rawset(t, k, v)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
dofile(modpath.."/config.lua")
|
||||||
|
dofile(modpath.."/messages.lua")
|
||||||
|
loadfile(modpath.."/hooks.lua")(ie)
|
||||||
|
dofile(modpath.."/callback.lua")
|
||||||
|
dofile(modpath.."/chatcmds.lua")
|
||||||
|
dofile(modpath.."/botcmds.lua")
|
||||||
|
|
||||||
|
-- Restore old (safe) functions
|
||||||
|
require = old_require
|
||||||
|
rawset(_G, "module", old_module)
|
||||||
|
|
||||||
|
if irc.config.enable_player_part then
|
||||||
|
dofile(modpath.."/player_part.lua")
|
||||||
|
else
|
||||||
|
setmetatable(irc.joined_players, {__index = function() return true end})
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_privilege("irc_admin", {
|
||||||
|
description = "Allow IRC administrative tasks to be performed.",
|
||||||
|
give_to_singleplayer = true
|
||||||
|
})
|
||||||
|
|
||||||
|
local stepnum = 0
|
||||||
|
|
||||||
|
minetest.register_globalstep(function(dtime) return irc.step(dtime) end)
|
||||||
|
|
||||||
|
function irc.step()
|
||||||
|
if stepnum == 3 then
|
||||||
|
if irc.config.auto_connect then
|
||||||
|
irc.connect()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
stepnum = stepnum + 1
|
||||||
|
|
||||||
|
if not irc.connected then return end
|
||||||
|
|
||||||
|
-- Hooks will manage incoming messages and errors
|
||||||
|
local good, err = xpcall(function() irc.conn:think() end, debug.traceback)
|
||||||
|
if not good then
|
||||||
|
print(err)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function irc.connect()
|
||||||
|
if irc.connected then
|
||||||
|
minetest.log("error", "IRC: Ignoring attempt to connect when already connected.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
irc.conn = irc.lib.new({
|
||||||
|
nick = irc.config.nick,
|
||||||
|
username = irc.config.username,
|
||||||
|
realname = irc.config.realname,
|
||||||
|
})
|
||||||
|
irc.doHook(irc.conn)
|
||||||
|
|
||||||
|
-- We need to swap the `require` function again since
|
||||||
|
-- LuaIRC `require`s `ssl` if `irc.secure` is true.
|
||||||
|
old_require = require
|
||||||
|
require = ie.require
|
||||||
|
|
||||||
|
local good, message = pcall(function()
|
||||||
|
irc.conn:connect({
|
||||||
|
host = irc.config.server,
|
||||||
|
port = irc.config.port,
|
||||||
|
password = irc.config.password,
|
||||||
|
timeout = irc.config.timeout,
|
||||||
|
reconnect = irc.config.reconnect,
|
||||||
|
secure = irc.config.secure
|
||||||
|
})
|
||||||
|
end)
|
||||||
|
|
||||||
|
require = old_require
|
||||||
|
|
||||||
|
if not good then
|
||||||
|
minetest.log("error", ("IRC: Connection error: %s: %s -- Reconnecting in %d seconds...")
|
||||||
|
:format(irc.config.server, message, irc.config.reconnect))
|
||||||
|
minetest.after(irc.config.reconnect, function() irc.connect() end)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if irc.config.NSPass then
|
||||||
|
irc.conn:queue(irc.msgs.privmsg(
|
||||||
|
"NickServ", "IDENTIFY "..irc.config.NSPass))
|
||||||
|
end
|
||||||
|
|
||||||
|
irc.conn:join(irc.config.channel, irc.config.key)
|
||||||
|
irc.connected = true
|
||||||
|
minetest.log("action", "IRC: Connected!")
|
||||||
|
minetest.chat_send_all("IRC: Connected!")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function irc.disconnect(message)
|
||||||
|
if irc.connected then
|
||||||
|
--The OnDisconnect hook will clear irc.connected and print a disconnect message
|
||||||
|
irc.conn:disconnect(message)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function irc.say(to, message)
|
||||||
|
if not message then
|
||||||
|
message = to
|
||||||
|
to = irc.config.channel
|
||||||
|
end
|
||||||
|
to = to or irc.config.channel
|
||||||
|
|
||||||
|
irc.queue(irc.msgs.privmsg(to, message))
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function irc.reply(message)
|
||||||
|
if not irc.last_from then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
message = message:gsub("[\r\n%z]", " \\n ")
|
||||||
|
irc.say(irc.last_from, message)
|
||||||
|
end
|
||||||
|
|
||||||
|
function irc.send(msg)
|
||||||
|
if not irc.connected then return end
|
||||||
|
irc.conn:send(msg)
|
||||||
|
end
|
||||||
|
|
||||||
|
function irc.queue(msg)
|
||||||
|
if not irc.connected then return end
|
||||||
|
irc.conn:queue(msg)
|
||||||
|
end
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
--[[
|
||||||
|
Lua IRC library
|
||||||
|
|
||||||
|
Copyright (c) 2010 Jakob Ovrum
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person
|
||||||
|
obtaining a copy of this software and associated documentation
|
||||||
|
files (the "Software"), to deal in the Software without
|
||||||
|
restriction, including without limitation the rights to use,
|
||||||
|
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following
|
||||||
|
conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
OTHER DEALINGS IN THE SOFTWARE.]]
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
[![Build Status](https://travis-ci.org/JakobOvrum/LuaIRC.svg?branch=master)](https://travis-ci.org/JakobOvrum/LuaIRC)
|
||||||
|
LuaIRC
|
||||||
|
============
|
||||||
|
|
||||||
|
IRC client library for Lua.
|
||||||
|
|
||||||
|
Dependencies
|
||||||
|
-------------
|
||||||
|
|
||||||
|
* [LuaSocket](http://w3.impa.br/~diego/software/luasocket/)
|
||||||
|
|
||||||
|
**Only required if you want to make use of the TLS support**
|
||||||
|
|
||||||
|
* [LuaSec](http://www.inf.puc-rio.br/~brunoos/luasec/)
|
||||||
|
|
||||||
|
Documentation
|
||||||
|
-------------
|
||||||
|
Documentation can be automatically generated by passing irc.luadoc (in doc/) to [LuaDoc](http://luadoc.luaforge.net/), or pre-generated documentation can be found in the 'gh-pages' branch, which can also be browsed [online](http://jakobovrum.github.com/LuaIRC/doc/modules/irc.html).
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
local msgs = require("irc.messages")
|
||||||
|
|
||||||
|
local meta = {}
|
||||||
|
|
||||||
|
function meta:send(msg, ...)
|
||||||
|
if type(msg) == "table" then
|
||||||
|
msg = msg:toRFC1459()
|
||||||
|
else
|
||||||
|
if select("#", ...) > 0 then
|
||||||
|
msg = msg:format(...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self:invoke("OnSend", msg)
|
||||||
|
|
||||||
|
local bytes, err = self.socket:send(msg .. "\r\n")
|
||||||
|
|
||||||
|
if not bytes and err ~= "timeout" and err ~= "wantwrite" then
|
||||||
|
self:invoke("OnDisconnect", err, true)
|
||||||
|
self:shutdown()
|
||||||
|
error(err, errlevel)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function meta:queue(msg)
|
||||||
|
table.insert(self.messageQueue, msg)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function verify(str, errLevel)
|
||||||
|
if str:find("^:") or str:find("%s%z") then
|
||||||
|
error(("malformed parameter '%s' to irc command"):format(str), errLevel)
|
||||||
|
end
|
||||||
|
|
||||||
|
return str
|
||||||
|
end
|
||||||
|
|
||||||
|
function meta:sendChat(target, msg)
|
||||||
|
-- Split the message into segments if it includes newlines.
|
||||||
|
for line in msg:gmatch("([^\r\n]+)") do
|
||||||
|
self:queue(msgs.privmsg(verify(target, 3), line))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function meta:sendNotice(target, msg)
|
||||||
|
-- Split the message into segments if it includes newlines.
|
||||||
|
for line in msg:gmatch("([^\r\n]+)") do
|
||||||
|
self:queue(msgs.notice(verify(target, 3), line))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function meta:join(channel, key)
|
||||||
|
self:queue(msgs.join(
|
||||||
|
verify(channel, 3),
|
||||||
|
key and verify(key, 3) or nil))
|
||||||
|
end
|
||||||
|
|
||||||
|
function meta:part(channel, reason)
|
||||||
|
channel = verify(channel, 3)
|
||||||
|
self:queue(msgs.part(channel, reason))
|
||||||
|
if self.track_users then
|
||||||
|
self.channels[channel] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function meta:trackUsers(b)
|
||||||
|
self.track_users = b
|
||||||
|
if not b then
|
||||||
|
for k,v in pairs(self.channels) do
|
||||||
|
self.channels[k] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function meta:setMode(t)
|
||||||
|
local target = t.target or self.nick
|
||||||
|
local mode = ""
|
||||||
|
local add, rem = t.add, t.remove
|
||||||
|
|
||||||
|
assert(add or rem, "table contains neither 'add' nor 'remove'")
|
||||||
|
|
||||||
|
if add then
|
||||||
|
mode = table.concat{"+", verify(add, 3)}
|
||||||
|
end
|
||||||
|
|
||||||
|
if rem then
|
||||||
|
mode = table.concat{mode, "-", verify(rem, 3)}
|
||||||
|
end
|
||||||
|
|
||||||
|
self:queue(msgs.mode(verify(target, 3), mode))
|
||||||
|
end
|
||||||
|
|
||||||
|
return meta
|
||||||
|
|
|
@ -0,0 +1,198 @@
|
||||||
|
--- LuaIRC is a low-level IRC library for Lua.
|
||||||
|
-- All functions raise Lua exceptions on error.
|
||||||
|
--
|
||||||
|
-- Use <code>new</code> to create a new Connection object.<br/>
|
||||||
|
-- Example:<br/><br/>
|
||||||
|
--<code>
|
||||||
|
--require "irc"<br/>
|
||||||
|
--local sleep = require "socket".sleep<br/>
|
||||||
|
--<br/>
|
||||||
|
--local s = irc.new{nick = "example"}<br/>
|
||||||
|
--<br/>
|
||||||
|
--s:hook("OnChat", function(user, channel, message)<br/>
|
||||||
|
-- print(("[%s] %s: %s"):format(channel, user.nick, message))<br/>
|
||||||
|
--end)<br/>
|
||||||
|
--<br/>
|
||||||
|
--s:connect("irc.example.net")<br/>
|
||||||
|
--s:join("#example")<br/>
|
||||||
|
--<br/>
|
||||||
|
--while true do<br/>
|
||||||
|
-- s:think()<br/>
|
||||||
|
-- sleep(0.5)<br/>
|
||||||
|
--end<br/>
|
||||||
|
--</code>
|
||||||
|
|
||||||
|
module "irc"
|
||||||
|
|
||||||
|
--- Create a new Connection object. Use <code>irc:connect</code> to connect to a server.
|
||||||
|
-- @param user Table with fields <code>nick</code>, <code>username</code> and <code>realname</code>.
|
||||||
|
-- The <code>nick</code> field is required.
|
||||||
|
--
|
||||||
|
-- @return Returns a new Connection object.
|
||||||
|
-- @see Connection
|
||||||
|
function new(user)
|
||||||
|
|
||||||
|
--- Hook a function to an event.
|
||||||
|
-- @param name Name of event.
|
||||||
|
-- @param id Unique tag.
|
||||||
|
-- @param f Callback function. [defaults to <code>id</code>]
|
||||||
|
-- @see Hooks
|
||||||
|
function irc:hook(name, id, f)
|
||||||
|
|
||||||
|
--- Remove previous hooked callback.
|
||||||
|
-- @param name Name of event.
|
||||||
|
-- @param id Unique tag.
|
||||||
|
function irc:unhook(name, id)
|
||||||
|
|
||||||
|
--- Connect <code>irc</code> to an IRC server.
|
||||||
|
-- @param host Host address.
|
||||||
|
-- @param port Server port. [default 6667]
|
||||||
|
function irc:connect(host, port)
|
||||||
|
|
||||||
|
-- @param table Table of connection details
|
||||||
|
-- @see ConnectOptions
|
||||||
|
function irc:connect(table)
|
||||||
|
|
||||||
|
--- Disconnect <code>irc</code> from the server.
|
||||||
|
-- @param message Quit message.
|
||||||
|
function irc:disconnect(message)
|
||||||
|
|
||||||
|
--- Handle incoming data for <code>irc</code>, and invoke previously hooked callbacks based on new server input.
|
||||||
|
-- You should call this in some kind of main loop, or at least often enough to not time out.
|
||||||
|
function irc:think()
|
||||||
|
|
||||||
|
--- Look up user info.
|
||||||
|
-- @param nick Nick of user to query.
|
||||||
|
-- @return Table with fields <code>userinfo</code>, <code>node</code>, <code>channels</code> and <code>account</code>.
|
||||||
|
function irc:whois(nick)
|
||||||
|
|
||||||
|
--- Look up topic.
|
||||||
|
-- Use this to invoke the hooks OnTopic and OnTopicInfo at any time.
|
||||||
|
-- @param channel Channel to query.
|
||||||
|
function irc:topic(channel)
|
||||||
|
|
||||||
|
--- Send a IRC message to the server.
|
||||||
|
-- @param msg Message or raw line to send, excluding newline characters.
|
||||||
|
-- @param ... Format parameters for <code>msg</code>, with <code>string.format</code> semantics. [optional]
|
||||||
|
function irc:send(msg, ...)
|
||||||
|
|
||||||
|
--- Queue Message to be sent to the server.
|
||||||
|
-- @param msg Message to be sent.
|
||||||
|
function irc:queue(msg)
|
||||||
|
|
||||||
|
--- Send a message to a channel or user.
|
||||||
|
-- @param target Nick or channel to send to.
|
||||||
|
-- @param message Message text.
|
||||||
|
function irc:sendChat(target, message)
|
||||||
|
|
||||||
|
--- Send a notice to a channel or user.
|
||||||
|
-- @param target Nick or channel to send to.
|
||||||
|
-- @param message Notice text.
|
||||||
|
function irc:sendNotice(target, message)
|
||||||
|
|
||||||
|
--- Join a channel.
|
||||||
|
-- @param channel Channel to join.
|
||||||
|
-- @param key Channel key. [optional]
|
||||||
|
function irc:join(channel, key)
|
||||||
|
|
||||||
|
--- Leave a channel.
|
||||||
|
-- @param channel Channel to leave.
|
||||||
|
function irc:part(channel)
|
||||||
|
|
||||||
|
--- Turn user information tracking on or off. User tracking is enabled by default.
|
||||||
|
-- @param b Boolean whether or not to track user information.
|
||||||
|
function irc:trackUsers(b)
|
||||||
|
|
||||||
|
--- Add/remove modes for a channel or nick.
|
||||||
|
-- @param t Table with fields <code>target, nick, add</code> and/or <code>rem</code>. <code>target</code> or <code>nick</code>
|
||||||
|
-- specifies the user or channel to add/remove modes. <code>add</code> is a list of modes to add to the user or channel.
|
||||||
|
-- <code>rem</code> is a list of modes to remove from the user or channel.
|
||||||
|
-- @usage Example which sets +m (moderated) for #channel: <br/>
|
||||||
|
-- <code>irc:setMode{target = "#channel", add = "m"}</code>
|
||||||
|
function irc:setMode(t)
|
||||||
|
|
||||||
|
--internal
|
||||||
|
function irc:invoke(name, ...)
|
||||||
|
function irc:handle(msg)
|
||||||
|
function irc:shutdown()
|
||||||
|
|
||||||
|
--- Table with connection information.
|
||||||
|
-- @name ConnectOptions
|
||||||
|
-- @class table
|
||||||
|
-- @field host Server host name.
|
||||||
|
-- @field port Server port. [defaults to <code>6667</code>]
|
||||||
|
-- @field timeout Connect timeout. [defaults to <code>30</code>]
|
||||||
|
-- @field password Server password.
|
||||||
|
-- @field secure Boolean to enable TLS connection, pass a params table (described, [luasec]) to control
|
||||||
|
-- [luasec]: http://www.inf.puc-rio.br/~brunoos/luasec/reference.html
|
||||||
|
|
||||||
|
--- Class representing a connection.
|
||||||
|
-- @name Connection
|
||||||
|
-- @class table
|
||||||
|
-- @field authed Boolean indicating whether the connection has completed registration.
|
||||||
|
-- @field connected Whether the connection is currently connected.
|
||||||
|
-- @field motd The server's message of the day. Can be nil.
|
||||||
|
-- @field nick The current nickname.
|
||||||
|
-- @field realname The real name sent to the server.
|
||||||
|
-- @field username The username/ident sent to the server.
|
||||||
|
-- @field socket Raw socket used by the library.
|
||||||
|
-- @field supports What the server claims to support in it's ISUPPORT message.
|
||||||
|
|
||||||
|
--- Class representing an IRC message.
|
||||||
|
-- @name Message
|
||||||
|
-- @class table
|
||||||
|
-- @field args A list of the command arguments
|
||||||
|
-- @field command The IRC command
|
||||||
|
-- @field prefix The prefix of the message
|
||||||
|
-- @field raw A raw IRC line for this message
|
||||||
|
-- @field tags A table of IRCv3 tags
|
||||||
|
-- @field user A User object describing the sender of the message
|
||||||
|
-- Fields may be missing.
|
||||||
|
-- Messages have the following methods:
|
||||||
|
-- <ul>
|
||||||
|
-- <li><code>toRFC1459()</code> - Returns the message serialized in RFC 1459 format.</li>
|
||||||
|
-- </ul>
|
||||||
|
|
||||||
|
--- List of hooks you can use with irc:hook.
|
||||||
|
-- The parameter list describes the parameters passed to the callback function.
|
||||||
|
-- <ul>
|
||||||
|
-- <li><code>PreRegister()</code> - Usefull for requesting capabilities.</li>
|
||||||
|
-- <li><code>OnRaw(line)</code> - Any non false/nil return value assumes line handled and will not be further processed.</li>
|
||||||
|
-- <li><code>OnSend(line)</code></li>
|
||||||
|
-- <li><code>OnDisconnect(message, errorOccurred)</code></li>
|
||||||
|
-- <li><code>OnChat(user, channel, message)</code></li>
|
||||||
|
-- <li><code>OnNotice(user, channel, message)</code></li>
|
||||||
|
-- <li><code>OnJoin(user, channel)</code>*</li>
|
||||||
|
-- <li><code>OnPart(user, channel)</code>*</li>
|
||||||
|
-- <li><code>OnQuit(user, message)</code></li>
|
||||||
|
-- <li><code>NickChange(user, newnick, channel)</code>*†</li>
|
||||||
|
-- <li><code>NameList(channel, names)</code></li>
|
||||||
|
-- <li><code>OnTopic(channel, topic)</code></li>
|
||||||
|
-- <li><code>OnTopicInfo(channel, creator, timeCreated)</code></li>
|
||||||
|
-- <li><code>OnKick(channel, nick, kicker, reason)</code>* (kicker is a <code>user</code> table)</li>
|
||||||
|
-- <li><code>OnUserMode(modes)</code></li>
|
||||||
|
-- <li><code>OnChannelMode(user, channel, modes)</code></li>
|
||||||
|
-- <li><code>OnModeChange(user, target, modes, ...)</code>* ('...' contains mode options such as banmasks)</li>
|
||||||
|
-- <li><code>OnCapabilityList(caps)</code></li>
|
||||||
|
-- <li><code>OnCapabilityAvailable(cap, value)</code> Called only when a capability becomes available or changes.</li>
|
||||||
|
-- <li><code>OnCapabilitySet(cap, enabled)</code>*</li>
|
||||||
|
-- <li><code>DoX(msg)</code>* - 'X' is any IRC command or numeric with the first letter capitalized (eg, DoPing and Do001)</li>
|
||||||
|
-- </ul>
|
||||||
|
-- * Event also invoked for yourself.
|
||||||
|
-- † Channel passed only when user tracking is enabled
|
||||||
|
-- @name Hooks
|
||||||
|
-- @class table
|
||||||
|
|
||||||
|
--- Table with information about a user.
|
||||||
|
-- <ul>
|
||||||
|
-- <li><code>server</code> - Server name.</li>
|
||||||
|
-- <li><code>nick</code> - User nickname.</li>
|
||||||
|
-- <li><code>username</code> - User username.</li>
|
||||||
|
-- <li><code>host</code> - User hostname.</li>
|
||||||
|
-- <li><code>realname</code> - User real name.</li>
|
||||||
|
-- <li><code>access</code> - User access, available in channel-oriented callbacks. A table containing boolean fields for each access mode that the server supports. Eg: 'o', and 'v'.</li>
|
||||||
|
-- </ul>
|
||||||
|
-- Fields may be missing. To fill them in, enable user tracking and use irc:whois.
|
||||||
|
-- @name User
|
||||||
|
-- @class table
|
||||||
|
|
|
@ -0,0 +1,277 @@
|
||||||
|
local util = require("irc.util")
|
||||||
|
local msgs = require("irc.messages")
|
||||||
|
local Message = msgs.Message
|
||||||
|
|
||||||
|
local handlers = {}
|
||||||
|
|
||||||
|
handlers["PING"] = function(conn, msg)
|
||||||
|
conn:send(Message({command="PONG", args=msg.args}))
|
||||||
|
end
|
||||||
|
|
||||||
|
local function requestWanted(conn, wanted)
|
||||||
|
local args = {}
|
||||||
|
for cap, value in pairs(wanted) do
|
||||||
|
if type(value) == "string" then
|
||||||
|
cap = cap .. "=" .. value
|
||||||
|
end
|
||||||
|
if not conn.capabilities[cap] then
|
||||||
|
table.insert(args, cap)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
conn:queue(Message({
|
||||||
|
command = "CAP",
|
||||||
|
args = {"REQ", table.concat(args, " ")}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
handlers["CAP"] = function(conn, msg)
|
||||||
|
local cmd = msg.args[2]
|
||||||
|
if not cmd then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if cmd == "LS" then
|
||||||
|
local list = msg.args[3]
|
||||||
|
local last = false
|
||||||
|
if list == "*" then
|
||||||
|
list = msg.args[4]
|
||||||
|
else
|
||||||
|
last = true
|
||||||
|
end
|
||||||
|
local avail = conn.availableCapabilities
|
||||||
|
local wanted = conn.wantedCapabilities
|
||||||
|
for item in list:gmatch("(%S+)") do
|
||||||
|
local eq = item:find("=", 1, true)
|
||||||
|
local k, v
|
||||||
|
if eq then
|
||||||
|
k, v = item:sub(1, eq - 1), item:sub(eq + 1)
|
||||||
|
else
|
||||||
|
k, v = item, true
|
||||||
|
end
|
||||||
|
if not avail[k] or avail[k] ~= v then
|
||||||
|
wanted[k] = conn:invoke("OnCapabilityAvailable", k, v)
|
||||||
|
end
|
||||||
|
avail[k] = v
|
||||||
|
end
|
||||||
|
if last then
|
||||||
|
if next(wanted) then
|
||||||
|
requestWanted(conn, wanted)
|
||||||
|
end
|
||||||
|
conn:invoke("OnCapabilityList", conn.availableCapabilities)
|
||||||
|
end
|
||||||
|
elseif cmd == "ACK" then
|
||||||
|
for item in msg.args[3]:gmatch("(%S+)") do
|
||||||
|
local enabled = (item:sub(1, 1) ~= "-")
|
||||||
|
local name = enabled and item or item:sub(2)
|
||||||
|
conn:invoke("OnCapabilitySet", name, enabled)
|
||||||
|
conn.capabilities[name] = enabled
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
handlers["001"] = function(conn, msg)
|
||||||
|
conn.authed = true
|
||||||
|
conn.nick = msg.args[1]
|
||||||
|
end
|
||||||
|
|
||||||
|
handlers["PRIVMSG"] = function(conn, msg)
|
||||||
|
conn:invoke("OnChat", msg.user, msg.args[1], msg.args[2])
|
||||||
|
end
|
||||||
|
|
||||||
|
handlers["NOTICE"] = function(conn, msg)
|
||||||
|
conn:invoke("OnNotice", msg.user, msg.args[1], msg.args[2])
|
||||||
|
end
|
||||||
|
|
||||||
|
handlers["JOIN"] = function(conn, msg)
|
||||||
|
local channel = msg.args[1]
|
||||||
|
if conn.track_users then
|
||||||
|
if msg.user.nick == conn.nick then
|
||||||
|
conn.channels[channel] = {users = {}}
|
||||||
|
else
|
||||||
|
conn.channels[channel].users[msg.user.nick] = msg.user
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
conn:invoke("OnJoin", msg.user, msg.args[1])
|
||||||
|
end
|
||||||
|
|
||||||
|
handlers["PART"] = function(conn, msg)
|
||||||
|
local channel = msg.args[1]
|
||||||
|
if conn.track_users then
|
||||||
|
if msg.user.nick == conn.nick then
|
||||||
|
conn.channels[channel] = nil
|
||||||
|
else
|
||||||
|
conn.channels[channel].users[msg.user.nick] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
conn:invoke("OnPart", msg.user, msg.args[1], msg.args[2])
|
||||||
|
end
|
||||||
|
|
||||||
|
handlers["QUIT"] = function(conn, msg)
|
||||||
|
if conn.track_users then
|
||||||
|
for chanName, chan in pairs(conn.channels) do
|
||||||
|
chan.users[msg.user.nick] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
conn:invoke("OnQuit", msg.user, msg.args[1], msg.args[2])
|
||||||
|
end
|
||||||
|
|
||||||
|
handlers["NICK"] = function(conn, msg)
|
||||||
|
local newNick = msg.args[1]
|
||||||
|
if conn.track_users then
|
||||||
|
for chanName, chan in pairs(conn.channels) do
|
||||||
|
local users = chan.users
|
||||||
|
local oldinfo = users[msg.user.nick]
|
||||||
|
if oldinfo then
|
||||||
|
users[newNick] = oldinfo
|
||||||
|
users[msg.user.nick] = nil
|
||||||
|
conn:invoke("NickChange", msg.user, newNick, chanName)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
conn:invoke("NickChange", msg.user, newNick)
|
||||||
|
end
|
||||||
|
if msg.user.nick == conn.nick then
|
||||||
|
conn.nick = newNick
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function needNewNick(conn, msg)
|
||||||
|
local newnick = conn.nickGenerator(msg.args[2])
|
||||||
|
conn:queue(irc.msgs.nick(newnick))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ERR_ERRONEUSNICKNAME (Misspelt but remains for historical reasons)
|
||||||
|
handlers["432"] = needNewNick
|
||||||
|
|
||||||
|
-- ERR_NICKNAMEINUSE
|
||||||
|
handlers["433"] = needNewNick
|
||||||
|
|
||||||
|
-- ERR_UNAVAILRESOURCE
|
||||||
|
handlers["437"] = function(conn, msg)
|
||||||
|
if not conn.authed then
|
||||||
|
needNewNick(conn, msg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- RPL_ISUPPORT
|
||||||
|
handlers["005"] = function(conn, msg)
|
||||||
|
local arglen = #msg.args
|
||||||
|
-- Skip first and last parameters (nick and info)
|
||||||
|
for i = 2, arglen - 1 do
|
||||||
|
local item = msg.args[i]
|
||||||
|
local pos = item:find("=")
|
||||||
|
if pos then
|
||||||
|
conn.supports[item:sub(1, pos - 1)] = item:sub(pos + 1)
|
||||||
|
else
|
||||||
|
conn.supports[item] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- RPL_MOTDSTART
|
||||||
|
handlers["375"] = function(conn, msg)
|
||||||
|
conn.motd = ""
|
||||||
|
end
|
||||||
|
|
||||||
|
-- RPL_MOTD
|
||||||
|
handlers["372"] = function(conn, msg)
|
||||||
|
-- MOTD lines have a "- " prefix, strip it.
|
||||||
|
conn.motd = conn.motd .. msg.args[2]:sub(3) .. '\n'
|
||||||
|
end
|
||||||
|
|
||||||
|
-- NAMES list
|
||||||
|
handlers["353"] = function(conn, msg)
|
||||||
|
local chanType = msg.args[2]
|
||||||
|
local channel = msg.args[3]
|
||||||
|
local names = msg.args[4]
|
||||||
|
if conn.track_users then
|
||||||
|
conn.channels[channel] = conn.channels[channel] or {users = {}, type = chanType}
|
||||||
|
|
||||||
|
local users = conn.channels[channel].users
|
||||||
|
for nick in names:gmatch("(%S+)") do
|
||||||
|
local access, name = util.parseNick(conn, nick)
|
||||||
|
users[name] = {access = access}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- End of NAMES list
|
||||||
|
handlers["366"] = function(conn, msg)
|
||||||
|
if conn.track_users then
|
||||||
|
conn:invoke("NameList", msg.args[2], msg.args[3])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- No topic
|
||||||
|
handlers["331"] = function(conn, msg)
|
||||||
|
conn:invoke("OnTopic", msg.args[2], nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
handlers["TOPIC"] = function(conn, msg)
|
||||||
|
conn:invoke("OnTopic", msg.args[1], msg.args[2])
|
||||||
|
end
|
||||||
|
|
||||||
|
handlers["332"] = function(conn, msg)
|
||||||
|
conn:invoke("OnTopic", msg.args[2], msg.args[3])
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Topic creation info
|
||||||
|
handlers["333"] = function(conn, msg)
|
||||||
|
conn:invoke("OnTopicInfo", msg.args[2], msg.args[3], tonumber(msg.args[4]))
|
||||||
|
end
|
||||||
|
|
||||||
|
handlers["KICK"] = function(conn, msg)
|
||||||
|
conn:invoke("OnKick", msg.args[1], msg.args[2], msg.user, msg.args[3])
|
||||||
|
end
|
||||||
|
|
||||||
|
-- RPL_UMODEIS
|
||||||
|
-- To answer a query about a client's own mode, RPL_UMODEIS is sent back
|
||||||
|
handlers["221"] = function(conn, msg)
|
||||||
|
conn:invoke("OnUserMode", msg.args[2])
|
||||||
|
end
|
||||||
|
|
||||||
|
-- RPL_CHANNELMODEIS
|
||||||
|
-- The result from common irc servers differs from that defined by the rfc
|
||||||
|
handlers["324"] = function(conn, msg)
|
||||||
|
conn:invoke("OnChannelMode", msg.args[2], msg.args[3])
|
||||||
|
end
|
||||||
|
|
||||||
|
handlers["MODE"] = function(conn, msg)
|
||||||
|
local target = msg.args[1]
|
||||||
|
local modes = msg.args[2]
|
||||||
|
local optList = {}
|
||||||
|
for i = 3, #msg.args do
|
||||||
|
table.insert(optList, msg.args[i])
|
||||||
|
end
|
||||||
|
if conn.track_users and target ~= conn.nick then
|
||||||
|
local add = true
|
||||||
|
local argNum = 1
|
||||||
|
util.updatePrefixModes(conn)
|
||||||
|
for c in modes:gmatch(".") do
|
||||||
|
if c == "+" then add = true
|
||||||
|
elseif c == "-" then add = false
|
||||||
|
elseif conn.modeprefix[c] then
|
||||||
|
local nick = optList[argNum]
|
||||||
|
argNum = argNum + 1
|
||||||
|
local user = conn.channels[target].users[nick]
|
||||||
|
user.access = user.access or {}
|
||||||
|
local access = user.access
|
||||||
|
access[c] = add
|
||||||
|
if c == "o" then access.op = add
|
||||||
|
elseif c == "v" then access.voice = add
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
conn:invoke("OnModeChange", msg.user, target, modes, unpack(optList))
|
||||||
|
end
|
||||||
|
|
||||||
|
handlers["ERROR"] = function(conn, msg)
|
||||||
|
conn:invoke("OnDisconnect", msg.args[1], true)
|
||||||
|
conn:shutdown()
|
||||||
|
error(msg.args[1], 3)
|
||||||
|
end
|
||||||
|
|
||||||
|
return handlers
|
||||||
|
|
|
@ -0,0 +1,257 @@
|
||||||
|
local socket = require("socket")
|
||||||
|
local util = require("irc.util")
|
||||||
|
local handlers = require("irc.handlers")
|
||||||
|
local msgs = require("irc.messages")
|
||||||
|
local Message = msgs.Message
|
||||||
|
|
||||||
|
local meta = {}
|
||||||
|
meta.__index = meta
|
||||||
|
|
||||||
|
|
||||||
|
for k, v in pairs(require("irc.asyncoperations")) do
|
||||||
|
meta[k] = v
|
||||||
|
end
|
||||||
|
|
||||||
|
local meta_preconnect = {}
|
||||||
|
function meta_preconnect.__index(o, k)
|
||||||
|
local v = rawget(meta_preconnect, k)
|
||||||
|
|
||||||
|
if v == nil and meta[k] ~= nil then
|
||||||
|
error(("field '%s' is not accessible before connecting"):format(k), 2)
|
||||||
|
end
|
||||||
|
return v
|
||||||
|
end
|
||||||
|
|
||||||
|
meta.connected = true
|
||||||
|
meta_preconnect.connected = false
|
||||||
|
|
||||||
|
function new(data)
|
||||||
|
local o = {
|
||||||
|
nick = assert(data.nick, "Field 'nick' is required");
|
||||||
|
username = data.username or "lua";
|
||||||
|
realname = data.realname or "Lua owns";
|
||||||
|
nickGenerator = data.nickGenerator or util.defaultNickGenerator;
|
||||||
|
hooks = {};
|
||||||
|
track_users = true;
|
||||||
|
supports = {};
|
||||||
|
messageQueue = {};
|
||||||
|
lastThought = 0;
|
||||||
|
recentMessages = 0;
|
||||||
|
availableCapabilities = {};
|
||||||
|
wantedCapabilities = {};
|
||||||
|
capabilities = {};
|
||||||
|
}
|
||||||
|
assert(util.checkNick(o.nick), "Erroneous nickname passed to irc.new")
|
||||||
|
return setmetatable(o, meta_preconnect)
|
||||||
|
end
|
||||||
|
|
||||||
|
function meta:hook(name, id, f)
|
||||||
|
f = f or id
|
||||||
|
self.hooks[name] = self.hooks[name] or {}
|
||||||
|
self.hooks[name][id] = f
|
||||||
|
return id or f
|
||||||
|
end
|
||||||
|
meta_preconnect.hook = meta.hook
|
||||||
|
|
||||||
|
|
||||||
|
function meta:unhook(name, id)
|
||||||
|
local hooks = self.hooks[name]
|
||||||
|
|
||||||
|
assert(hooks, "no hooks exist for this event")
|
||||||
|
assert(hooks[id], "hook ID not found")
|
||||||
|
|
||||||
|
hooks[id] = nil
|
||||||
|
end
|
||||||
|
meta_preconnect.unhook = meta.unhook
|
||||||
|
|
||||||
|
function meta:invoke(name, ...)
|
||||||
|
local hooks = self.hooks[name]
|
||||||
|
if hooks then
|
||||||
|
for id, f in pairs(hooks) do
|
||||||
|
local ret = f(...)
|
||||||
|
if ret then
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function meta_preconnect:connect(_host, _port)
|
||||||
|
local host, port, password, secure, timeout
|
||||||
|
|
||||||
|
if type(_host) == "table" then
|
||||||
|
host = _host.host
|
||||||
|
port = _host.port
|
||||||
|
timeout = _host.timeout
|
||||||
|
password = _host.password
|
||||||
|
secure = _host.secure
|
||||||
|
else
|
||||||
|
host = _host
|
||||||
|
port = _port
|
||||||
|
end
|
||||||
|
|
||||||
|
host = host or error("host name required to connect", 2)
|
||||||
|
port = port or 6667
|
||||||
|
|
||||||
|
local s = socket.tcp()
|
||||||
|
|
||||||
|
s:settimeout(timeout or 30)
|
||||||
|
assert(s:connect(host, port))
|
||||||
|
|
||||||
|
if secure then
|
||||||
|
local work, ssl = pcall(require, "ssl")
|
||||||
|
if not work then
|
||||||
|
error("LuaSec required for secure connections", 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
local params
|
||||||
|
if type(secure) == "table" then
|
||||||
|
params = secure
|
||||||
|
else
|
||||||
|
params = {mode = "client", protocol = "tlsv1"}
|
||||||
|
end
|
||||||
|
|
||||||
|
s = ssl.wrap(s, params)
|
||||||
|
local success, errmsg = s:dohandshake()
|
||||||
|
if not success then
|
||||||
|
error(("could not make secure connection: %s"):format(errmsg), 2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
self.socket = s
|
||||||
|
setmetatable(self, meta)
|
||||||
|
|
||||||
|
self:invoke("PreRegister", self)
|
||||||
|
|
||||||
|
if password then
|
||||||
|
self:queue(Message({command="PASS", args={password}}))
|
||||||
|
end
|
||||||
|
|
||||||
|
self:queue(msgs.nick(self.nick))
|
||||||
|
self:queue(Message({command="USER", args={self.username, "0", "*", self.realname}}))
|
||||||
|
|
||||||
|
self.channels = {}
|
||||||
|
|
||||||
|
s:settimeout(0)
|
||||||
|
|
||||||
|
repeat
|
||||||
|
self:think()
|
||||||
|
socket.sleep(0.1)
|
||||||
|
until self.authed
|
||||||
|
end
|
||||||
|
|
||||||
|
function meta:disconnect(message)
|
||||||
|
message = message or "Bye!"
|
||||||
|
|
||||||
|
self:invoke("OnDisconnect", message, false)
|
||||||
|
self:send(msgs.quit(message))
|
||||||
|
|
||||||
|
self:shutdown()
|
||||||
|
end
|
||||||
|
|
||||||
|
function meta:shutdown()
|
||||||
|
self.socket:close()
|
||||||
|
setmetatable(self, meta_preconnect)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function getline(self, errlevel)
|
||||||
|
local line, err = self.socket:receive("*l")
|
||||||
|
|
||||||
|
if not line and err ~= "timeout" and err ~= "wantread" then
|
||||||
|
self:invoke("OnDisconnect", err, true)
|
||||||
|
self:shutdown()
|
||||||
|
error(err, errlevel)
|
||||||
|
end
|
||||||
|
|
||||||
|
return line
|
||||||
|
end
|
||||||
|
|
||||||
|
function meta:think()
|
||||||
|
while true do
|
||||||
|
local line = getline(self, 3)
|
||||||
|
if line and #line > 0 then
|
||||||
|
if not self:invoke("OnRaw", line) then
|
||||||
|
self:handle(Message({raw=line}))
|
||||||
|
end
|
||||||
|
else
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Handle outgoing message queue
|
||||||
|
local diff = socket.gettime() - self.lastThought
|
||||||
|
self.recentMessages = self.recentMessages - (diff * 2)
|
||||||
|
if self.recentMessages < 0 then
|
||||||
|
self.recentMessages = 0
|
||||||
|
end
|
||||||
|
for i = 1, #self.messageQueue do
|
||||||
|
if self.recentMessages > 4 then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
self:send(table.remove(self.messageQueue, 1))
|
||||||
|
self.recentMessages = self.recentMessages + 1
|
||||||
|
end
|
||||||
|
self.lastThought = socket.gettime()
|
||||||
|
end
|
||||||
|
|
||||||
|
function meta:handle(msg)
|
||||||
|
local handler = handlers[msg.command]
|
||||||
|
if handler then
|
||||||
|
handler(self, msg)
|
||||||
|
end
|
||||||
|
self:invoke("Do" .. util.capitalize(msg.command), msg)
|
||||||
|
end
|
||||||
|
|
||||||
|
local whoisHandlers = {
|
||||||
|
["311"] = "userinfo";
|
||||||
|
["312"] = "node";
|
||||||
|
["319"] = "channels";
|
||||||
|
["330"] = "account"; -- Freenode
|
||||||
|
["307"] = "registered"; -- Unreal
|
||||||
|
}
|
||||||
|
|
||||||
|
function meta:whois(nick)
|
||||||
|
self:send(msgs.whois(nick))
|
||||||
|
|
||||||
|
local result = {}
|
||||||
|
|
||||||
|
while true do
|
||||||
|
local line = getline(self, 3)
|
||||||
|
if line then
|
||||||
|
local msg = Message({raw=line})
|
||||||
|
|
||||||
|
local handler = whoisHandlers[msg.command]
|
||||||
|
if handler then
|
||||||
|
result[handler] = msg.args
|
||||||
|
elseif msg.command == "318" then
|
||||||
|
break
|
||||||
|
else
|
||||||
|
self:handle(msg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if result.account then
|
||||||
|
result.account = result.account[3]
|
||||||
|
elseif result.registered then
|
||||||
|
result.account = result.registered[2]
|
||||||
|
end
|
||||||
|
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
function meta:topic(channel)
|
||||||
|
self:queue(msgs.topic(channel))
|
||||||
|
end
|
||||||
|
|
||||||
|
return {
|
||||||
|
new = new;
|
||||||
|
|
||||||
|
Message = Message;
|
||||||
|
msgs = msgs;
|
||||||
|
|
||||||
|
color = util.color;
|
||||||
|
bold = util.bold;
|
||||||
|
underline = util.underline;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,207 @@
|
||||||
|
|
||||||
|
-- Module table
|
||||||
|
local m = {}
|
||||||
|
|
||||||
|
local msg_meta = {}
|
||||||
|
msg_meta.__index = msg_meta
|
||||||
|
|
||||||
|
local function Message(opts)
|
||||||
|
opts = opts or {}
|
||||||
|
setmetatable(opts, msg_meta)
|
||||||
|
if opts.raw then
|
||||||
|
opts:fromRFC1459(opts.raw)
|
||||||
|
end
|
||||||
|
return opts
|
||||||
|
end
|
||||||
|
|
||||||
|
m.Message = Message
|
||||||
|
|
||||||
|
local tag_escapes = {
|
||||||
|
[";"] = "\\:",
|
||||||
|
[" "] = "\\s",
|
||||||
|
["\0"] = "\\0",
|
||||||
|
["\\"] = "\\\\",
|
||||||
|
["\r"] = "\\r",
|
||||||
|
["\n"] = "\\n",
|
||||||
|
}
|
||||||
|
|
||||||
|
local tag_unescapes = {}
|
||||||
|
for x, y in pairs(tag_escapes) do tag_unescapes[y] = x end
|
||||||
|
|
||||||
|
function msg_meta:toRFC1459()
|
||||||
|
local s = ""
|
||||||
|
|
||||||
|
if self.tags then
|
||||||
|
s = s.."@"
|
||||||
|
for key, value in pairs(self.tags) do
|
||||||
|
s = s..key
|
||||||
|
if value ~= true then
|
||||||
|
value = value:gsub("[; %z\\\r\n]", tag_escapes)
|
||||||
|
s = s.."="..value
|
||||||
|
end
|
||||||
|
s = s..";"
|
||||||
|
end
|
||||||
|
-- Strip trailing semicolon
|
||||||
|
s = s:sub(1, -2)
|
||||||
|
s = s.." "
|
||||||
|
end
|
||||||
|
|
||||||
|
s = s..self.command
|
||||||
|
|
||||||
|
local argnum = #self.args
|
||||||
|
for i = 1, argnum do
|
||||||
|
local arg = self.args[i]
|
||||||
|
local startsWithColon = (arg:sub(1, 1) == ":")
|
||||||
|
local hasSpace = arg:find(" ")
|
||||||
|
if i == argnum and (hasSpace or startsWithColon) then
|
||||||
|
s = s.." :"
|
||||||
|
else
|
||||||
|
assert(not hasSpace and not startsWithColon,
|
||||||
|
"Message arguments can not be "
|
||||||
|
.."serialized to RFC1459 format")
|
||||||
|
s = s.." "
|
||||||
|
end
|
||||||
|
s = s..arg
|
||||||
|
end
|
||||||
|
|
||||||
|
return s
|
||||||
|
end
|
||||||
|
|
||||||
|
local function parsePrefix(prefix)
|
||||||
|
local user = {}
|
||||||
|
user.nick, user.username, user.host = prefix:match("^(.+)!(.+)@(.+)$")
|
||||||
|
if not user.nick and prefix:find(".", 1, true) then
|
||||||
|
user.server = prefix
|
||||||
|
end
|
||||||
|
return user
|
||||||
|
end
|
||||||
|
|
||||||
|
function msg_meta:fromRFC1459(line)
|
||||||
|
-- IRCv3 tags
|
||||||
|
if line:sub(1, 1) == "@" then
|
||||||
|
self.tags = {}
|
||||||
|
local space = line:find(" ", 1, true)
|
||||||
|
-- For each semicolon-delimited section from after
|
||||||
|
-- the @ character to before the space character.
|
||||||
|
for tag in line:sub(2, space - 1):gmatch("([^;]+)") do
|
||||||
|
local eq = tag:find("=", 1, true)
|
||||||
|
if eq then
|
||||||
|
self.tags[tag:sub(1, eq - 1)] =
|
||||||
|
tag:sub(eq + 1):gsub("\\([:s0\\rn])", tag_unescapes)
|
||||||
|
else
|
||||||
|
self.tags[tag] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
line = line:sub(space + 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
if line:sub(1, 1) == ":" then
|
||||||
|
local space = line:find(" ", 1, true)
|
||||||
|
self.prefix = line:sub(2, space - 1)
|
||||||
|
self.user = parsePrefix(self.prefix)
|
||||||
|
line = line:sub(space + 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
local pos
|
||||||
|
self.command, pos = line:match("(%S+)()")
|
||||||
|
line = line:sub(pos)
|
||||||
|
|
||||||
|
self.args = self.args or {}
|
||||||
|
for pos, param in line:gmatch("()(%S+)") do
|
||||||
|
if param:sub(1, 1) == ":" then
|
||||||
|
param = line:sub(pos + 1)
|
||||||
|
table.insert(self.args, param)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
table.insert(self.args, param)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function m.privmsg(to, text)
|
||||||
|
return Message({command="PRIVMSG", args={to, text}})
|
||||||
|
end
|
||||||
|
|
||||||
|
function m.notice(to, text)
|
||||||
|
return Message({command="NOTICE", args={to, text}})
|
||||||
|
end
|
||||||
|
|
||||||
|
function m.action(to, text)
|
||||||
|
return Message({command="PRIVMSG", args={to, ("\x01ACTION %s\x01"):format(text)}})
|
||||||
|
end
|
||||||
|
|
||||||
|
function m.ctcp(command, to, args)
|
||||||
|
s = "\x01"..command
|
||||||
|
if args then
|
||||||
|
s = ' '..args
|
||||||
|
end
|
||||||
|
s = s..'\x01'
|
||||||
|
return Message({command="PRIVMSG", args={to, s}})
|
||||||
|
end
|
||||||
|
|
||||||
|
function m.kick(channel, target, reason)
|
||||||
|
return Message({command="KICK", args={channel, target, reason}})
|
||||||
|
end
|
||||||
|
|
||||||
|
function m.join(channel, key)
|
||||||
|
return Message({command="JOIN", args={channel, key}})
|
||||||
|
end
|
||||||
|
|
||||||
|
function m.part(channel, reason)
|
||||||
|
return Message({command="PART", args={channel, reason}})
|
||||||
|
end
|
||||||
|
|
||||||
|
function m.quit(reason)
|
||||||
|
return Message({command="QUIT", args={reason}})
|
||||||
|
end
|
||||||
|
|
||||||
|
function m.kill(target, reason)
|
||||||
|
return Message({command="KILL", args={target, reason}})
|
||||||
|
end
|
||||||
|
|
||||||
|
function m.kline(time, mask, reason, operreason)
|
||||||
|
local args = nil
|
||||||
|
if time then
|
||||||
|
args = {time, mask, reason..'|'..operreason}
|
||||||
|
else
|
||||||
|
args = {mask, reason..'|'..operreason}
|
||||||
|
end
|
||||||
|
return Message({command="KLINE", args=args})
|
||||||
|
end
|
||||||
|
|
||||||
|
function m.whois(nick, server)
|
||||||
|
local args = nil
|
||||||
|
if server then
|
||||||
|
args = {server, nick}
|
||||||
|
else
|
||||||
|
args = {nick}
|
||||||
|
end
|
||||||
|
return Message({command="WHOIS", args=args})
|
||||||
|
end
|
||||||
|
|
||||||
|
function m.topic(channel, text)
|
||||||
|
return Message({command="TOPIC", args={channel, text}})
|
||||||
|
end
|
||||||
|
|
||||||
|
function m.invite(channel, target)
|
||||||
|
return Message({command="INVITE", args={channel, target}})
|
||||||
|
end
|
||||||
|
|
||||||
|
function m.nick(nick)
|
||||||
|
return Message({command="NICK", args={nick}})
|
||||||
|
end
|
||||||
|
|
||||||
|
function m.mode(target, modes)
|
||||||
|
-- We have to split the modes parameter because the mode string and
|
||||||
|
-- each parameter are seperate arguments (The first command is incorrect)
|
||||||
|
-- MODE foo :+ov Nick1 Nick2
|
||||||
|
-- MODE foo +ov Nick1 Nick2
|
||||||
|
local mt = util.split(modes)
|
||||||
|
return Message({command="MODE", args={target, unpack(mt)}})
|
||||||
|
end
|
||||||
|
|
||||||
|
function m.cap(cmd, ...)
|
||||||
|
return Message({command="CAP", args={cmd, ...}})
|
||||||
|
end
|
||||||
|
|
||||||
|
return m
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if [ "$TRAVIS_REPO_SLUG" == "JakobOvrum/LuaIRC" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_BRANCH" == "master" ]; then
|
||||||
|
|
||||||
|
echo -e "Generating luadoc...\n"
|
||||||
|
|
||||||
|
git config --global user.email "travis@travis-ci.org"
|
||||||
|
git config --global user.name "travis-ci"
|
||||||
|
git clone --quiet --branch=gh-pages https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG} gh-pages > /dev/null
|
||||||
|
|
||||||
|
cd gh-pages
|
||||||
|
git rm -rf ./doc
|
||||||
|
sh ./generate.sh
|
||||||
|
git add -f ./doc
|
||||||
|
git commit -m "Lastest documentation on successful travis build $TRAVIS_BUILD_NUMBER auto-pushed to gh-pages"
|
||||||
|
git push -fq origin gh-pages > /dev/null
|
||||||
|
|
||||||
|
echo -e "Published luadoc to gh-pages.\n"
|
||||||
|
fi
|
|
@ -0,0 +1,52 @@
|
||||||
|
local select = require("socket").select
|
||||||
|
|
||||||
|
local m = {}
|
||||||
|
local set = {}
|
||||||
|
set.__index = set
|
||||||
|
|
||||||
|
function m.new(t)
|
||||||
|
t.connections = {}
|
||||||
|
t.sockets = {}
|
||||||
|
return setmetatable(t, set)
|
||||||
|
end
|
||||||
|
|
||||||
|
function set:add(connection)
|
||||||
|
local socket = connection.socket
|
||||||
|
insert(self.sockets, socket)
|
||||||
|
|
||||||
|
self.connections[socket] = connection
|
||||||
|
insert(self.connections, connection)
|
||||||
|
end
|
||||||
|
|
||||||
|
function set:remove(connection)
|
||||||
|
local socket = connection.socket
|
||||||
|
self.connections[socket] = nil
|
||||||
|
for k, s in ipairs(self.sockets) do
|
||||||
|
if socket == s then
|
||||||
|
remove(self.sockets, k)
|
||||||
|
remove(self.connections, k)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function set:select()
|
||||||
|
local read, write, err = select(self.sockets, nil, self.timeout)
|
||||||
|
|
||||||
|
if read then
|
||||||
|
for k, socket in ipairs(read) do
|
||||||
|
read[k] = self.connections[socket]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return read, err
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Select - but if it times out, it returns all connections.
|
||||||
|
function set:poll()
|
||||||
|
local read, err = self:select()
|
||||||
|
return err == "timeout" and self.connections or read
|
||||||
|
end
|
||||||
|
|
||||||
|
return m
|
||||||
|
|
|
@ -0,0 +1,120 @@
|
||||||
|
|
||||||
|
-- Module table
|
||||||
|
local m = {}
|
||||||
|
|
||||||
|
function m.updatePrefixModes(conn)
|
||||||
|
if conn.prefixmode and conn.modeprefix then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
conn.prefixmode = {}
|
||||||
|
conn.modeprefix = {}
|
||||||
|
if conn.supports.PREFIX then
|
||||||
|
local modes, prefixes = conn.supports.PREFIX:match("%(([^%)]*)%)(.*)")
|
||||||
|
for i = 1, #modes do
|
||||||
|
conn.prefixmode[prefixes:sub(i, i)] = modes:sub(i, i)
|
||||||
|
conn.modeprefix[ modes:sub(i, i)] = prefixes:sub(i, i)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
conn.prefixmode['@'] = 'o'
|
||||||
|
conn.prefixmode['+'] = 'v'
|
||||||
|
conn.modeprefix['o'] = '@'
|
||||||
|
conn.modeprefix['v'] = '+'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function m.parseNick(conn, nick)
|
||||||
|
local access = {}
|
||||||
|
m.updatePrefixModes(conn)
|
||||||
|
local namestart = 1
|
||||||
|
for i = 1, #nick - 1 do
|
||||||
|
local c = nick:sub(i, i)
|
||||||
|
if conn.prefixmode[c] then
|
||||||
|
access[conn.prefixmode[c]] = true
|
||||||
|
else
|
||||||
|
namestart = i
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
access.op = access.o
|
||||||
|
access.voice = access.v
|
||||||
|
local name = nick:sub(namestart)
|
||||||
|
return access, name
|
||||||
|
end
|
||||||
|
|
||||||
|
-- mIRC markup scheme (de-facto standard)
|
||||||
|
m.color = {
|
||||||
|
black = 1,
|
||||||
|
blue = 2,
|
||||||
|
green = 3,
|
||||||
|
red = 4,
|
||||||
|
lightred = 5,
|
||||||
|
purple = 6,
|
||||||
|
brown = 7,
|
||||||
|
yellow = 8,
|
||||||
|
lightgreen = 9,
|
||||||
|
navy = 10,
|
||||||
|
cyan = 11,
|
||||||
|
lightblue = 12,
|
||||||
|
violet = 13,
|
||||||
|
gray = 14,
|
||||||
|
lightgray = 15,
|
||||||
|
white = 16
|
||||||
|
}
|
||||||
|
|
||||||
|
local colByte = string.char(3)
|
||||||
|
setmetatable(m.color, {__call = function(_, text, colornum)
|
||||||
|
colornum = (type(colornum) == "string" and
|
||||||
|
assert(color[colornum], "Invalid color '"..colornum.."'") or
|
||||||
|
colornum)
|
||||||
|
return table.concat{colByte, tostring(colornum), text, colByte}
|
||||||
|
end})
|
||||||
|
|
||||||
|
local boldByte = string.char(2)
|
||||||
|
function m.bold(text)
|
||||||
|
return boldByte..text..boldByte
|
||||||
|
end
|
||||||
|
|
||||||
|
local underlineByte = string.char(31)
|
||||||
|
function m.underline(text)
|
||||||
|
return underlineByte..text..underlineByte
|
||||||
|
end
|
||||||
|
|
||||||
|
function m.checkNick(nick)
|
||||||
|
return nick:find("^[a-zA-Z_%-%[|%]%^{|}`][a-zA-Z0-9_%-%[|%]%^{|}`]*$") ~= nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function m.defaultNickGenerator(nick)
|
||||||
|
-- LuaBot -> LuaCot -> LuaCou -> ...
|
||||||
|
-- We change a random character rather than appending to the
|
||||||
|
-- nickname as otherwise the new nick could exceed the ircd's
|
||||||
|
-- maximum nickname length.
|
||||||
|
local randindex = math.random(1, #nick)
|
||||||
|
local randchar = string.sub(nick, randindex, randindex)
|
||||||
|
local b = string.byte(randchar)
|
||||||
|
b = b + 1
|
||||||
|
if b < 65 or b > 125 then
|
||||||
|
b = 65
|
||||||
|
end
|
||||||
|
-- Get the halves before and after the changed character
|
||||||
|
local first = string.sub(nick, 1, randindex - 1)
|
||||||
|
local last = string.sub(nick, randindex + 1, #nick)
|
||||||
|
nick = first .. string.char(b) .. last -- Insert the new charachter
|
||||||
|
return nick
|
||||||
|
end
|
||||||
|
|
||||||
|
function m.capitalize(text)
|
||||||
|
-- Converts first character to upercase and the rest to lowercase.
|
||||||
|
-- "PING" -> "Ping" | "hello" -> "Hello" | "123" -> "123"
|
||||||
|
return text:sub(1, 1):upper()..text:sub(2):lower()
|
||||||
|
end
|
||||||
|
|
||||||
|
function m.split(str, sep)
|
||||||
|
local t = {}
|
||||||
|
for s in str:gmatch("%S+") do
|
||||||
|
table.insert(t, s)
|
||||||
|
end
|
||||||
|
return t
|
||||||
|
end
|
||||||
|
|
||||||
|
return m
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
-- This file is licensed under the terms of the BSD 2-clause license.
|
||||||
|
-- See LICENSE.txt for details.
|
||||||
|
|
||||||
|
irc.msgs = irc.lib.msgs
|
||||||
|
|
||||||
|
function irc.logChat(message)
|
||||||
|
minetest.log("action", "IRC CHAT: "..message)
|
||||||
|
end
|
||||||
|
|
||||||
|
function irc.sendLocal(message)
|
||||||
|
minetest.chat_send_all(message)
|
||||||
|
irc.logChat(message)
|
||||||
|
end
|
||||||
|
|
||||||
|
function irc.playerMessage(name, message)
|
||||||
|
return ("<%s> %s"):format(name, message)
|
||||||
|
end
|
|
@ -0,0 +1 @@
|
||||||
|
name = irc
|
|
@ -0,0 +1,69 @@
|
||||||
|
-- This file is licensed under the terms of the BSD 2-clause license.
|
||||||
|
-- See LICENSE.txt for details.
|
||||||
|
|
||||||
|
|
||||||
|
function irc.player_part(name)
|
||||||
|
if not irc.joined_players[name] then
|
||||||
|
return false, "You are not in the channel"
|
||||||
|
end
|
||||||
|
irc.joined_players[name] = nil
|
||||||
|
return true, "You left the channel"
|
||||||
|
end
|
||||||
|
|
||||||
|
function irc.player_join(name)
|
||||||
|
if irc.joined_players[name] then
|
||||||
|
return false, "You are already in the channel"
|
||||||
|
end
|
||||||
|
irc.joined_players[name] = true
|
||||||
|
return true, "You joined the channel"
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_chatcommand("join", {
|
||||||
|
description = "Join the IRC channel",
|
||||||
|
privs = {shout=true},
|
||||||
|
func = function(name)
|
||||||
|
return irc.player_join(name)
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_chatcommand("part", {
|
||||||
|
description = "Part the IRC channel",
|
||||||
|
privs = {shout=true},
|
||||||
|
func = function(name)
|
||||||
|
return irc.player_part(name)
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_chatcommand("who", {
|
||||||
|
description = "Tell who is currently on the channel",
|
||||||
|
privs = {},
|
||||||
|
func = function()
|
||||||
|
local out, n = { }, 0
|
||||||
|
for plname in pairs(irc.joined_players) do
|
||||||
|
n = n + 1
|
||||||
|
out[n] = plname
|
||||||
|
end
|
||||||
|
table.sort(out)
|
||||||
|
return true, "Players in channel: "..table.concat(out, ", ")
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_on_joinplayer(function(player)
|
||||||
|
local name = player:get_player_name()
|
||||||
|
irc.joined_players[name] = irc.config.auto_join
|
||||||
|
end)
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_on_leaveplayer(function(player)
|
||||||
|
local name = player:get_player_name()
|
||||||
|
irc.joined_players[name] = nil
|
||||||
|
end)
|
||||||
|
|
||||||
|
function irc.sendLocal(message)
|
||||||
|
for name, _ in pairs(irc.joined_players) do
|
||||||
|
minetest.chat_send_player(name, message)
|
||||||
|
end
|
||||||
|
irc.logChat(message)
|
||||||
|
end
|
|
@ -0,0 +1,75 @@
|
||||||
|
|
||||||
|
[Basic]
|
||||||
|
|
||||||
|
# Whether to automatically connect to the server on mod load.
|
||||||
|
# If false, you must use /irc_connect to connect.
|
||||||
|
irc.auto_connect (Auto-connect on load) bool true
|
||||||
|
|
||||||
|
# Nickname for the bot. May only contain characters A-Z, 0-9
|
||||||
|
# '{', '}', '[', ']', '|', '^', '-', or '_'.
|
||||||
|
irc.nick (Bot nickname) string Minetest
|
||||||
|
|
||||||
|
# Server to connect to.
|
||||||
|
irc.server (IRC server) string irc.freenode.net
|
||||||
|
|
||||||
|
# Server port.
|
||||||
|
# The standard IRC protocol port is 6667 for regular servers,
|
||||||
|
# or 6697 for SSL-enabled servers.
|
||||||
|
# If unsure, leave at 6667.
|
||||||
|
irc.port (IRC server port) int 6667 1 65535
|
||||||
|
|
||||||
|
# Channel the bot joins after connecting.
|
||||||
|
irc.channel (Channel to join) string ##mt-irc-mod
|
||||||
|
|
||||||
|
[Authentication]
|
||||||
|
|
||||||
|
# Password for authenticating to NickServ.
|
||||||
|
# Leave empty to not authenticate with NickServ.
|
||||||
|
irc.NSPass (NickServ password) string
|
||||||
|
|
||||||
|
# IRC server password.
|
||||||
|
# Leave empty for no password.
|
||||||
|
irc.password (Server password) string
|
||||||
|
|
||||||
|
# Password for joining the channel.
|
||||||
|
# Leave empty if your channel is not protected.
|
||||||
|
irc.key (Channel key) string
|
||||||
|
|
||||||
|
# Enable TLS connection.
|
||||||
|
# Requires LuaSEC <https://github.com/brunoos/luasec>.
|
||||||
|
irc.secure (Use TLS) bool false
|
||||||
|
|
||||||
|
# Username for SASL authentication.
|
||||||
|
# Leave empty to use the nickname.
|
||||||
|
irc.sasl.user (SASL username) string
|
||||||
|
|
||||||
|
# Password for SASL authentication.
|
||||||
|
# Leave empty to not authenticate via SASL.
|
||||||
|
irc.sasl.pass (SASL password) string
|
||||||
|
|
||||||
|
[Advanced]
|
||||||
|
|
||||||
|
# Enable this to make the bot send messages when players join
|
||||||
|
# or leave the game server.
|
||||||
|
irc.send_join_part (Send join and part messages) bool true
|
||||||
|
|
||||||
|
# Enable this to make the bot send messages when players are kicked.
|
||||||
|
irc.send_kicks (Send kick messages) bool false
|
||||||
|
|
||||||
|
# Underlying socket timeout in seconds.
|
||||||
|
irc.timeout (Timeout) int 60 1
|
||||||
|
|
||||||
|
# Time between reconnection attempts, in seconds.
|
||||||
|
irc.reconnect (Reconnect delay) int 600 1
|
||||||
|
|
||||||
|
# Prefix to use for bot commands.
|
||||||
|
irc.command_prefix (Command prefix) string
|
||||||
|
|
||||||
|
# Enable debug output.
|
||||||
|
irc.debug (Debug mode) bool false
|
||||||
|
|
||||||
|
# Whether to enable players joining and parting the channel.
|
||||||
|
irc.enable_player_part (Allow player join/part) bool true
|
||||||
|
|
||||||
|
# Whether to automatically show players in the channel when they join.
|
||||||
|
irc.auto_join (Auto join players) bool true
|
|
@ -0,0 +1,26 @@
|
||||||
|
minetest.register_chatcommand("pointing", {
|
||||||
|
description = "Print what you're pointing at",
|
||||||
|
func = function(name)
|
||||||
|
local player = minetest.get_player_by_name(name)
|
||||||
|
local pos = vector.round(player:getpos())
|
||||||
|
if player then
|
||||||
|
if minetest.settings:get_bool("enable_damage") then
|
||||||
|
player:set_hp(0)
|
||||||
|
lightning.strike(pos)
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
for _, callback in pairs(core.registered_on_respawnplayers) do
|
||||||
|
if callback(player) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- There doesn't seem to be a way to get a default spawn pos from the lua API
|
||||||
|
return false, "No static_spawnpoint defined"
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- Show error message if used when not logged in, eg: from IRC mod
|
||||||
|
return false, "You need to be online to be killed!"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
})
|
|
@ -0,0 +1,224 @@
|
||||||
|
--Poudlard by Perlipop , code from moreblcoks/stairs+ by Calinou
|
||||||
|
--Alliases compatibility ======= RENOMMAGE POUDLARD ==========
|
||||||
|
-- Compatibility aliases de moreblocks/stairsplus vers poudlard pour les items de chaque fonction et
|
||||||
|
-- pour poudstone + poudwood
|
||||||
|
|
||||||
|
minetest.register_alias("moreblocks:poudwood", "poudlard:poudwood")
|
||||||
|
minetest.register_alias("default:poudstone", "poudlard:poudstone")
|
||||||
|
minetest.register_alias("poudwood", "poudlard:poudwood")
|
||||||
|
minetest.register_alias("poudstone", "poudlard:poudstone")
|
||||||
|
minetest.register_alias("redblock", "poudlard:redblock")
|
||||||
|
minetest.register_alias("blackblock", "poudlard:blackblock")
|
||||||
|
|
||||||
|
|
||||||
|
--RENAMING MOREBLOCKS ET STAIRS+ VERS POUDLARD
|
||||||
|
|
||||||
|
|
||||||
|
local function register_poudlard_alias(modname, origname, newname)
|
||||||
|
minetest.register_alias(modname.. ":slab_" ..origname, "poudlard:slab_" ..newname)
|
||||||
|
minetest.register_alias(modname.. ":slab_" ..origname.. "_inverted", "poudlard:slab_" ..newname.. "_inverted")
|
||||||
|
minetest.register_alias(modname.. ":slab_" ..origname.. "_wall", "poudlard:slab_" ..newname.. "_wall")
|
||||||
|
minetest.register_alias(modname.. ":slab_" ..origname.. "_quarter", "poudlard:slab_" ..newname.. "_quarter")
|
||||||
|
minetest.register_alias(modname.. ":slab_" ..origname.. "_quarter_inverted", "poudlard:slab_" ..newname.. "_quarter_inverted")
|
||||||
|
minetest.register_alias(modname.. ":slab_" ..origname.. "_quarter_wall", "poudlard:slab_" ..newname.. "_quarter_wall")
|
||||||
|
minetest.register_alias(modname.. ":slab_" ..origname.. "_three_quarter", "poudlard:slab_" ..newname.. "_three_quarter")
|
||||||
|
minetest.register_alias(modname.. ":slab_" ..origname.. "_three_quarter_inverted", "poudlard:slab_" ..newname.. "_three_quarter_inverted")
|
||||||
|
minetest.register_alias(modname.. ":slab_" ..origname.. "_three_quarter_wall", "poudlard:slab_" ..newname.. "_three_quarter_wall")
|
||||||
|
minetest.register_alias(modname.. ":stair_" ..origname, "poudlard:stair_" ..newname)
|
||||||
|
minetest.register_alias(modname.. ":stair_" ..origname.. "_inverted", "poudlard:stair_" ..newname.. "_inverted")
|
||||||
|
minetest.register_alias(modname.. ":stair_" ..origname.. "_wall", "poudlard:stair_" ..newname.. "_wall")
|
||||||
|
minetest.register_alias(modname.. ":stair_" ..origname.. "_wall_half", "poudlard:stair_" ..newname.. "_wall_half")
|
||||||
|
minetest.register_alias(modname.. ":stair_" ..origname.. "_wall_half_inverted", "poudlard:stair_" ..newname.. "_wall_half_inverted")
|
||||||
|
minetest.register_alias(modname.. ":stair_" ..origname.. "_half", "poudlard:stair_" ..newname.. "_half")
|
||||||
|
minetest.register_alias(modname.. ":stair_" ..origname.. "_half_inverted", "poudlard:stair_" ..newname.. "_half_inverted")
|
||||||
|
minetest.register_alias(modname.. ":stair_" ..origname.. "_right_half", "poudlard:stair_" ..newname.. "_right_half")
|
||||||
|
minetest.register_alias(modname.. ":stair_" ..origname.. "_right_half_inverted", "poudlard:stair_" ..newname.. "_right_half_inverted")
|
||||||
|
minetest.register_alias(modname.. ":stair_" ..origname.. "_wall_half", "poudlard:stair_" ..newname.. "_wall_half")
|
||||||
|
minetest.register_alias(modname.. ":stair_" ..origname.. "_wall_half_inverted", "poudlard:stair_" ..newname.. "_wall_half_inverted")
|
||||||
|
minetest.register_alias(modname.. ":stair_" ..origname.. "_inner", "poudlard:stair_" ..newname.. "_inner")
|
||||||
|
minetest.register_alias(modname.. ":stair_" ..origname.. "_inner_inverted", "poudlard:stair_" ..newname.. "_inner_inverted")
|
||||||
|
minetest.register_alias(modname.. ":stair_" ..origname.. "_outer", "poudlard:stair_" ..newname.. "_outer")
|
||||||
|
minetest.register_alias(modname.. ":stair_" ..origname.. "_outer_inverted", "poudlard:stair_" ..newname.. "_outer_inverted")
|
||||||
|
minetest.register_alias(modname.. ":panel_" ..origname.. "_bottom", "poudlard:panel_" ..newname.. "_bottom")
|
||||||
|
minetest.register_alias(modname.. ":panel_" ..origname.. "_top", "poudlard:panel_" ..newname.. "_top")
|
||||||
|
minetest.register_alias(modname.. ":panel_" ..origname.. "_vertical", "poudlard:panel_" ..newname.. "_vertical")
|
||||||
|
minetest.register_alias(modname.. ":micro_" ..origname.. "_bottom", "poudlard:micro_" ..newname.. "_bottom")
|
||||||
|
minetest.register_alias(modname.. ":micro_" ..origname.. "_top", "poudlard:micro_" ..newname.. "_top")
|
||||||
|
end
|
||||||
|
register_poudlard_alias("stairsplus", "poudwood","poudwood")
|
||||||
|
register_poudlard_alias("stairsplus", "poudstone","poudstone")
|
||||||
|
register_poudlard_alias("stairsplus", "redblock","redblock")
|
||||||
|
register_poudlard_alias("stairsplus", "blackblock","blackblock")
|
||||||
|
register_poudlard_alias("stairsplus", "stone", "stone")
|
||||||
|
register_poudlard_alias("stairsplus", "wood", "wood")
|
||||||
|
register_poudlard_alias("stairsplus", "cobble", "cobble")
|
||||||
|
register_poudlard_alias("stairsplus", "brick", "brick")
|
||||||
|
register_poudlard_alias("stairsplus", "sandstone", "sandstone")
|
||||||
|
register_poudlard_alias("stairsplus", "glass", "glass")
|
||||||
|
register_poudlard_alias("stairsplus", "tree", "tree")
|
||||||
|
register_poudlard_alias("stairsplus", "jungletree", "jungletree")
|
||||||
|
register_poudlard_alias("stairsplus", "desert_stone", "desert_stone")
|
||||||
|
register_poudlard_alias("stairsplus", "steelblock", "steelblock")
|
||||||
|
register_poudlard_alias("stairsplus", "mossycobble", "mossycobble")
|
||||||
|
|
||||||
|
register_poudlard_alias("moreblocks", "poudwood","poudwood")
|
||||||
|
register_poudlard_alias("moreblocks", "poudstone","poudstone")
|
||||||
|
register_poudlard_alias("moreblocks", "redblock","redblock")
|
||||||
|
register_poudlard_alias("moreblocks", "blackblock","blackblock")
|
||||||
|
register_poudlard_alias("moreblocks", "plankstone", "plankstone")
|
||||||
|
register_poudlard_alias("moreblocks", "coalstone", "coalstone")
|
||||||
|
register_poudlard_alias("moreblocks", "junglewood", "junglewood")
|
||||||
|
register_poudlard_alias("moreblocks", "stonebrick", "stonebrick")
|
||||||
|
register_poudlard_alias("moreblocks", "circlestonebrick", "circlestonebricks")
|
||||||
|
register_poudlard_alias("moreblocks", "ironstone", "ironstone")
|
||||||
|
register_poudlard_alias("moreblocks", "coalglass", "coalglass")
|
||||||
|
register_poudlard_alias("moreblocks", "ironglass", "ironglass")
|
||||||
|
register_poudlard_alias("moreblocks", "glowglass", "glowglass")
|
||||||
|
register_poudlard_alias("moreblocks", "superglowglass", "superglowglass")
|
||||||
|
register_poudlard_alias("moreblocks", "coalchecker", "coalchecker")
|
||||||
|
register_poudlard_alias("moreblocks", "ironchecker", "ironchecker")
|
||||||
|
register_poudlard_alias("moreblocks", "cactuschecker", "cactuschecker")
|
||||||
|
register_poudlard_alias("moreblocks", "ironstonebrick", "ironstonebricks")
|
||||||
|
register_poudlard_alias("moreblocks", "stonesquare", "stone_tile")
|
||||||
|
register_poudlard_alias("moreblocks", "splitstonesquare", "split_stone_tile")
|
||||||
|
register_poudlard_alias("moreblocks", "woodtile", "wood_tile")
|
||||||
|
register_poudlard_alias("moreblocks", "woodtile_centered", "wood_tile_centered")
|
||||||
|
register_poudlard_alias("moreblocks", "woodtile_full", "wood_tile_full")
|
||||||
|
|
||||||
|
--
|
||||||
|
|
||||||
|
minetest.register_alias("moreblocks:stone_bricks", "default:stonebrick")
|
||||||
|
minetest.register_alias("moreblocks:stonebrick", "default:stonebrick")
|
||||||
|
|
||||||
|
minetest.register_alias("stonebrick", "default:stonebrick")
|
||||||
|
minetest.register_alias("stonebricks", "default:stonebrick")
|
||||||
|
minetest.register_alias("stone_brick", "default:stonebrick")
|
||||||
|
minetest.register_alias("stone_bricks", "default:stonebrick")
|
||||||
|
|
||||||
|
minetest.register_alias("stonesquare", "poudlard:stone_tile")
|
||||||
|
minetest.register_alias("moreblocks:stonesquare", "poudlard:stone_tile")
|
||||||
|
|
||||||
|
minetest.register_alias("stonesquares", "poudlard:stone_tile")
|
||||||
|
minetest.register_alias("stone_square", "poudlard:stone_tile")
|
||||||
|
minetest.register_alias("stone_squares", "poudlard:stone_tile")
|
||||||
|
|
||||||
|
minetest.register_alias("splitstonesquare", "poudlard:split_stone_tile")
|
||||||
|
minetest.register_alias("moreblocks:splitstonesquare", "poudlard:split_stone_tile")
|
||||||
|
minetest.register_alias("splitstonesquares", "poudlard:split_stone_tile")
|
||||||
|
minetest.register_alias("split_stone_square", "poudlard:split_stone_tile")
|
||||||
|
minetest.register_alias("split_stone_squares", "poudlard:split_stone_tile")
|
||||||
|
minetest.register_alias("split_stonesquare", "poudlard:split_stone_tile")
|
||||||
|
minetest.register_alias("split_stonesquares", "poudlard:split_stone_tile")
|
||||||
|
|
||||||
|
minetest.register_alias("moreblocks:circlestonebrick", "poudlard:circlestonebricks")
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_alias("coalstone", "poudlard:coalstone")
|
||||||
|
minetest.register_alias("ironstone", "poudlard:ironstonebricks")
|
||||||
|
minetest.register_alias("coalglass", "poudlard:coalglass")
|
||||||
|
minetest.register_alias("ironglass", "poudlard:ironglass")
|
||||||
|
minetest.register_alias("superglowglass", "poudlard:superglowglass")
|
||||||
|
minetest.register_alias("plankstone", "poudlard:plankstone")
|
||||||
|
minetest.register_alias("cactuschecker", "poudlard:cactuschecker")
|
||||||
|
minetest.register_alias("coalchecker", "poudlard:coalchecker")
|
||||||
|
minetest.register_alias("ironchecker", "poudlard:ironchecker")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_alias("moreblocks:junglewood","poudlard:junglewood")
|
||||||
|
|
||||||
|
minetest.register_alias("moreblocks:circle_stone_bricks","poudlard:circlestonebricks")
|
||||||
|
|
||||||
|
minetest.register_alias("moreblocks:plankstone","poudlard:plankstone")
|
||||||
|
|
||||||
|
minetest.register_alias("moreblocks:ironglass","poudlard:ironglass")
|
||||||
|
|
||||||
|
minetest.register_alias("moreblocks:coalglass","poudlard:coalglass")
|
||||||
|
|
||||||
|
minetest.register_alias("moreblocks:cleanglass","poudlard:cleanglass")
|
||||||
|
|
||||||
|
minetest.register_alias("moreblocks:cactuschecker","poudlard:cactuschecker")
|
||||||
|
|
||||||
|
minetest.register_alias("moreblocks:emptybookshelf","poudlard:emptybookshelf")
|
||||||
|
|
||||||
|
minetest.register_alias("moreblocks:coalstone","poudlard:coalstone")
|
||||||
|
|
||||||
|
minetest.register_alias("moreblocks:ironstone","poudlard:ironstone")
|
||||||
|
|
||||||
|
minetest.register_alias("moreblocks:ironstonebrick","poudlard:ironstonebricks")
|
||||||
|
|
||||||
|
minetest.register_alias("moreblocks:coalchecker","poudlard:coalchecker")
|
||||||
|
|
||||||
|
minetest.register_alias("moreblocks:ironchecker","poudlard:ironchecker")
|
||||||
|
|
||||||
|
minetest.register_alias("moreblocks:trapstone","poudlard:trapstone")
|
||||||
|
|
||||||
|
minetest.register_alias("moreblocks:trapglass","poudlard:trapglass")
|
||||||
|
|
||||||
|
minetest.register_alias("moreblocks:fence_junglewood","poudlard:fence_junglewood")
|
||||||
|
|
||||||
|
minetest.register_alias("moreblocks:horizontaltree","poudlard:horizontaltree")
|
||||||
|
|
||||||
|
minetest.register_alias("moreblocks:allfacestree","poudlard:allfacestree")
|
||||||
|
|
||||||
|
minetest.register_alias("moreblocks:superglowglass","poudlard:superglowglass")
|
||||||
|
|
||||||
|
minetest.register_alias("moreblocks:rope","poudlard:rope")
|
||||||
|
|
||||||
|
minetest.register_alias("moreblocks:wood_tile","poudlard:wood_tile")
|
||||||
|
|
||||||
|
minetest.register_alias("moreblocks:wood_tile_full","poudlard:wood_tile_full")
|
||||||
|
|
||||||
|
minetest.register_alias("moreblocks:wood_tile_center","poudlard:wood_tile_center")
|
||||||
|
|
||||||
|
-- Items
|
||||||
|
|
||||||
|
minetest.register_alias("moreblocks:sweeper","poudlard:sweeper")
|
||||||
|
minetest.register_alias("moreblocks:junglestick","poudlard:junglestick")
|
||||||
|
|
||||||
|
-- Additional default aliases
|
||||||
|
|
||||||
|
minetest.register_alias("woodpick", "default:pick_wood")
|
||||||
|
minetest.register_alias("woodenpick", "default:pick_wood")
|
||||||
|
minetest.register_alias("stonepick", "default:pick_stone")
|
||||||
|
minetest.register_alias("steelpick", "default:pick_steel")
|
||||||
|
minetest.register_alias("ironpick", "default:pick_steel")
|
||||||
|
minetest.register_alias("mesepick", "default:pick_mese")
|
||||||
|
|
||||||
|
minetest.register_alias("woodaxe", "default:axe_wood")
|
||||||
|
minetest.register_alias("woodenaxe", "default:axe_wood")
|
||||||
|
minetest.register_alias("stoneaxe", "default:axe_stone")
|
||||||
|
minetest.register_alias("steelaxe", "default:axe_steel")
|
||||||
|
minetest.register_alias("ironaxe", "default:axe_steel")
|
||||||
|
|
||||||
|
minetest.register_alias("woodshovel", "default:shovel_wood")
|
||||||
|
minetest.register_alias("woodenshovel", "default:shovel_wood")
|
||||||
|
minetest.register_alias("stoneshovel", "default:shovel_stone")
|
||||||
|
minetest.register_alias("steelshovel", "default:shovel_steel")
|
||||||
|
minetest.register_alias("ironshovel", "default:shovel_steel")
|
||||||
|
|
||||||
|
minetest.register_alias("woodsword", "default:sword_wood")
|
||||||
|
minetest.register_alias("woodensword", "default:sword_wood")
|
||||||
|
minetest.register_alias("stonesword", "default:sword_stone")
|
||||||
|
minetest.register_alias("steelsword", "default:sword_steel")
|
||||||
|
minetest.register_alias("ironsword", "default:sword_steel")
|
||||||
|
|
||||||
|
minetest.register_alias("grass", "default:dirt_with_grass")
|
||||||
|
minetest.register_alias("grassblock", "default:dirt_with_grass")
|
||||||
|
minetest.register_alias("grass_block", "default:dirt_with_grass")
|
||||||
|
|
||||||
|
minetest.register_alias("grassfootsteps", "default:dirt_with_grass_footsteps")
|
||||||
|
minetest.register_alias("grass_footsteps", "default:dirt_with_grass_footsteps")
|
||||||
|
|
||||||
|
minetest.register_alias("stick", "default:stick")
|
||||||
|
minetest.register_alias("sign", "default:sign_wall")
|
||||||
|
minetest.register_alias("fence", "default:fence_wood")
|
||||||
|
minetest.register_alias("coal", "default:coal_lump")
|
||||||
|
minetest.register_alias("iron", "default:iron_lump")
|
||||||
|
minetest.register_alias("clay", "default:clay_lump")
|
||||||
|
minetest.register_alias("steel", "default:steel_ingot")
|
||||||
|
minetest.register_alias("steel_block", "default:steelblock")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
default
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,194 @@
|
||||||
|
|
||||||
|
#
|
||||||
|
# Language: Español
|
||||||
|
# Author: Diego Martínez <lkaezadl3@gmail.com>
|
||||||
|
#
|
||||||
|
|
||||||
|
### kitchen_cabinet.lua ###
|
||||||
|
Kitchen Cabinet = Gabinete de Cocina
|
||||||
|
## 1: Player name, 2: position
|
||||||
|
%s moves stuff in kitchen cabinet at %s = %s mueve cosas en gabinete de cocina en %s
|
||||||
|
%s moves stuff to kitchen cabinet at %s = %s mueve cosas al gabinete de cocina en %s
|
||||||
|
%s takes stuff from kitchen cabinet at %s = %s toma cosas del gabinete de cocina en %s
|
||||||
|
Half-height Kitchen Cabinet (on ceiling) = Gabinete de cocina de media altura (en techo)
|
||||||
|
Under-sink cabinet = Gabinete con Lavabo
|
||||||
|
Kitchen Cabinet with sink = Gabinete de cocina con lavabo
|
||||||
|
|
||||||
|
### door_models.lua ###
|
||||||
|
Mahogany Closet Door = Puerta de Armario de Caoba
|
||||||
|
Oak Closet Door = Puerta de Armario de Roble
|
||||||
|
Fancy Wood/Glass Door = Puerta de Madera y Cristal de Lujo
|
||||||
|
Glass Office Door = Puerta de Oficina de Cristal
|
||||||
|
Glass and Wood, Mahogany-colored = Cristal y Madera, color Caoba
|
||||||
|
Glass and Wood, Oak-colored = Cristal y Madera, color Roble
|
||||||
|
Glass and Wood, White = Cristal y Madera, color Blanco
|
||||||
|
Plain Wooden Door = Puerta Simple de Madera
|
||||||
|
left = izquierda
|
||||||
|
right = derecha
|
||||||
|
## 1: Side the doors opens to
|
||||||
|
(Top Half, %s-opening) = (Parte Superior, abre a la %s)
|
||||||
|
(%s-opening) = (abre a la %s)
|
||||||
|
|
||||||
|
### door_nodes.lua ###
|
||||||
|
Not enough vertical space to place a door! = ¡No hay suficiente espacio vertical para colocar una puerta!
|
||||||
|
|
||||||
|
### crafts.lua ###
|
||||||
|
Brass Ingot = Lingote de Latón
|
||||||
|
Bucket of white paint = Cubo de Pintura Blanca
|
||||||
|
Legs for Small Utility table = Patas de Mesa Utilitaria Pequeña
|
||||||
|
Plastic sheet = Lámina de Plástico
|
||||||
|
Silicon lump = Terrón de Silicio
|
||||||
|
Simple Integrated Circuit = Circuito Integrado Simple
|
||||||
|
Small Wooden Drawer = Cajón Pequeño de Madera
|
||||||
|
Terracotta Roof Tile = Teja de Terracota
|
||||||
|
Titanium Dioxide = Dióxido de Titanio
|
||||||
|
Uncooked Terracotta Base = Base de Terracota sin Cocer
|
||||||
|
Unprocessed Plastic base = Base de Plástico sin Procesar
|
||||||
|
|
||||||
|
### fences.lua ###
|
||||||
|
Barbed Wire Fence = Cerca de Alambre de Púas
|
||||||
|
Barbed Wire Fence Gate = Portón de Cerca de Alambre de Púas
|
||||||
|
Brass Fence/railing = Cerca/Barandilla de Latón
|
||||||
|
Brass Fence/railing with sign = Cerca/Barandilla de Latón con Letrero
|
||||||
|
Chainlink Fence = Cerca de Cadenas
|
||||||
|
Chainlink Fence Gate = Portón de Cerca de Cadenas
|
||||||
|
Chainlink Fence Gate (open) = Portón de Cerca de Cadenas (Abierto)
|
||||||
|
Unpainted Picket Fence = Cerca de Piquete sin pintar
|
||||||
|
Unpainted Picket Fence Gate = Portón de Cerca de Piquete sin pintar
|
||||||
|
White Picket Fence = Cerca de Piquete blanca
|
||||||
|
White Picket Fence Gate = Portón de Cerca de Piquete blanca
|
||||||
|
Wooden Privacy Fence = Cerca privada de madera
|
||||||
|
Wrought Iron Fence/railing = Cerca/Barandilla de Hierro Forjado
|
||||||
|
Wrought Iron Fence/railing with sign = Cerca/Barandilla de Hierro Forjado con Letrero
|
||||||
|
want to simply place the wielded item like usual. = solo se desea colocar el objeto empuñado normalmente.
|
||||||
|
|
||||||
|
### furniture_medieval.lua ###
|
||||||
|
Bars = Barras
|
||||||
|
Binding Bars = Barras de Unión
|
||||||
|
Chains = Cadenas
|
||||||
|
Wall Torch = Antorcha de Pared
|
||||||
|
|
||||||
|
### furniture_bathroom.lua ###
|
||||||
|
Toilet = Inodoro
|
||||||
|
Sink = Lavabo
|
||||||
|
Taps = Grifo
|
||||||
|
Shower Tray = Piso de Ducha
|
||||||
|
Shower Head = Ducha
|
||||||
|
|
||||||
|
### init.lua ###
|
||||||
|
Loaded! = ¡Cargado!
|
||||||
|
Asphalt Shingles = Tejas de Asfalto
|
||||||
|
Black Plastic Flower Pot = Florero de Plástico Negro
|
||||||
|
Brass Pole = Poste de Latón
|
||||||
|
Brass Table Legs = Patas de Mesa de Latón
|
||||||
|
red = rojas
|
||||||
|
green = verdes
|
||||||
|
blue = azules
|
||||||
|
white = blancas
|
||||||
|
pink = rosas
|
||||||
|
violet = violetas
|
||||||
|
## 1: Color name
|
||||||
|
Curtains (%s) = Cortinas (%s)
|
||||||
|
Drop-Ceiling Tile = Cielorraso
|
||||||
|
Glass Skylight = Claraboya de Cristal
|
||||||
|
Glass Table (Small, Round) = Mesa de Cristal (Pequeña, Redonda)
|
||||||
|
Glass Table (Small, Square) = Mesa de Cristal (Pequeña, Cuadrada)
|
||||||
|
Green Plastic Flower Pot = Florero de Plástico Negro
|
||||||
|
Large Area Rug = Manta Grande
|
||||||
|
Large Glass Table Piece = Pieza de Mesa de Cristal Grande
|
||||||
|
Large Stereo Speaker = Altavoz de Estéreo Grande
|
||||||
|
Legs for Utility Table = Patas de Mesa Utilitaria
|
||||||
|
Projection Screen Material = Material de Pantalla de Proyección
|
||||||
|
Small Surround Speaker = Pequeño Altavoz Envolvente
|
||||||
|
Small Throw Rug = Manta Pequeña
|
||||||
|
Stereo Receiver = Receptor Estéreo
|
||||||
|
Terracotta Flower Pot = Florero de Terracota
|
||||||
|
Terracotta Roofing = Tejado de Terracota
|
||||||
|
Textured Ceiling Paint = Pintura Texturada para Techo
|
||||||
|
Utility Table = Mesa Utilitaria
|
||||||
|
Utility table mk2 = Mesa Utilitaria mk2
|
||||||
|
Wooden Shutter (Black) = Obturador de Madera (Negro)
|
||||||
|
Wooden Shutter (Dark Grey) = Obturador de Madera (Gris Oscuro)
|
||||||
|
Wooden Shutter (Forest Green) = Obturador de Madera (Verde Bosque)
|
||||||
|
Wooden Shutter (Grey) = Obturador de Madera (Gris)
|
||||||
|
Wooden Shutter (Light Blue) = Obturador de Madera (Azul Claro)
|
||||||
|
Wooden Shutter (Purple) = Obturador de Madera (Púrpura)
|
||||||
|
Wooden Shutter (Red) = Obturador de Madera (Rojo)
|
||||||
|
Wooden Shutter (Unpainted Mahogany) = Obturador de Madera (Caoba sin Pintar)
|
||||||
|
Wooden Shutter (Unpainted Oak) = Obturador de Madera (Roble sin Pintar)
|
||||||
|
Wooden Shutter (White) = Obturador de Madera (Blanco)
|
||||||
|
Wooden Shutter (Yellow) = Obturador de Madera (Amarillo)
|
||||||
|
Wooden Tabletop piece = Pieza de Mesa de Madera
|
||||||
|
Wooden Tabletop (Small, Round) = Pieza de Mesa de Madera (Pequeña, Redonda)
|
||||||
|
Wooden Tabletop (Small, Square) = Pieza de Mesa de Madera (Pequeña, Cuadrada)
|
||||||
|
Wood Shingles = Tejas de Madera
|
||||||
|
Wrought Iron Pole = Poste de Hierro Forjado
|
||||||
|
someone = alguien
|
||||||
|
## 1: Player name
|
||||||
|
Sorry, %s owns that spot. = Lo siento, %s es dueño de ése lugar.
|
||||||
|
|
||||||
|
### lighting.lua ###
|
||||||
|
White Glowlight (small cube) = Luz Blanca (cubo pequeño)
|
||||||
|
White Glowlight (small cube, on ceiling) = Luz Blanca (cubo pequeño, en techo)
|
||||||
|
White Glowlight (thick) = Luz Blanca (Gruesa)
|
||||||
|
White Glowlight (thick, on wall) = Luz Blanca (Gruesa, en pared)
|
||||||
|
White Glowlight (thin) = Luz Blanca (Fina)
|
||||||
|
White Glowlight (thin, on wall) = Luz Blanca (Fina, en pared)
|
||||||
|
Yellow Glowlight (small cube) = Luz Amarilla (cubo pequeño)
|
||||||
|
Yellow Glowlight (small cube, on ceiling) = Luz Amarilla (cubo pequeño, en techo)
|
||||||
|
Yellow Glowlight (thick) = Luz Amarilla (Gruesa)
|
||||||
|
Yellow Glowlight (thick, on wall) = Luz Amarilla (Gruesa, en pared)
|
||||||
|
Yellow Glowlight (thin) = Luz Amarilla (Fina)
|
||||||
|
Yellow Glowlight (thin, on wall) = Luz Amarilla (Fina, en pared)
|
||||||
|
|
||||||
|
### locked.lua ###
|
||||||
|
## 1: Item description, 2: Owner name
|
||||||
|
%s (owned by %s) = %s (propiedad de %s)
|
||||||
|
## 1: Player name, 2: Item description, 3: Owner name, 4: Position
|
||||||
|
%s tried to access a %s belonging to %s at %s = %s ha intentado acceder un(a) %s propiedad de %s en %s
|
||||||
|
## 1: Item description
|
||||||
|
%s (Locked) = %s (Cerrado)
|
||||||
|
Locked Cabinet = Gabinete Cerrado
|
||||||
|
Locked Nightstand = Mesa de Noche Cerrada
|
||||||
|
Locked Fridge = Refri Cerrado
|
||||||
|
Locked Oven = Estufa Cerrada
|
||||||
|
|
||||||
|
### nightstands.lua ###
|
||||||
|
Mahogany Nightstand with One Drawer = Mesa de Noche de Caoba, un Cajón
|
||||||
|
Mahogany Nightstand with Two Drawers = Mesa de Noche de Caoba, dos Cajones
|
||||||
|
Oak Nightstand with One Drawer = Mesa de Noche de Roble, un Cajón
|
||||||
|
Oak Nightstand with Two Drawers = Mesa de Noche de Roble, dos Cajones
|
||||||
|
## 1: Player name, 2: position
|
||||||
|
%s moves stuff in nightstand at %s = %s mueve cosas en mesa de noche en %s
|
||||||
|
%s moves stuff to nightstand at %s = %s mueve cosas hacia mesa de noche en %s
|
||||||
|
%s takes stuff from nightstand at %s = %s mueve cosas desde mesa de noche en %s
|
||||||
|
One-drawer Nightstand = Mesa de Noche de un Cajón
|
||||||
|
Two-drawer Nightstand = Mesa de Noche de dos Cajones
|
||||||
|
|
||||||
|
### oven.lua ###
|
||||||
|
Oven = Estufa
|
||||||
|
## 1: Item name
|
||||||
|
Could not insert '%s' = No se pudo insertar '%s'
|
||||||
|
## 1: Percentage
|
||||||
|
Oven active: %d%% = Estufa activa: %d%%
|
||||||
|
Oven out of fuel = Estufa sin combustible
|
||||||
|
Oven is empty = Estufavacía
|
||||||
|
|
||||||
|
### refrigerator.lua ###
|
||||||
|
Refrigerator = Refrigerador
|
||||||
|
## 1: Player name, 2: position
|
||||||
|
%s moves stuff in refrigerator at %s = %s mueve cosas en refrigerador en %s
|
||||||
|
%s moves stuff to refrigerator at %s = %s mueve cosas hacia refrigerador en %s
|
||||||
|
%s takes stuff from refrigerator at %s = %s mueve cosas desde refrigerador en %s
|
||||||
|
Not enough vertical space to place a refrigerator! = ¡No hay suficiente espacio vertical para colocar un refrigerador!
|
||||||
|
|
||||||
|
### television.lua ###
|
||||||
|
Small CRT Television = Pequeña Televisión CRT
|
||||||
|
|
||||||
|
### signs_lib.lua ###
|
||||||
|
%s wrote "%s" to sign at %s = %s ha escrito "%s" en el letrero en %s
|
||||||
|
Reading cached character database. = Leyendo base de datos de catacteres.
|
||||||
|
Font seems to have changed. Rebuilding cache. = La fuente parece haber cambiado. Reconstruyendo información guardada.
|
||||||
|
Could not find font line height in cached DB. Trying brute force. = No se pudo encontrar la altura de línea en la base de datos. Intentando con fuerza bruta.
|
||||||
|
Registered %s and %s = Registrados %s y %s
|
||||||
|
signs loaded = letreros cargados
|
|
@ -0,0 +1,180 @@
|
||||||
|
|
||||||
|
#
|
||||||
|
# Language: Français
|
||||||
|
# Author: Calinou
|
||||||
|
#
|
||||||
|
|
||||||
|
### kitchen_cabinet.lua ###
|
||||||
|
Kitchen Cabinet = Meuble de cuisine
|
||||||
|
## 1: Player name, 2: position
|
||||||
|
%s moves stuff in kitchen cabinet at %s = %s déplace des objets dans un meuble de cuisine à %s
|
||||||
|
%s moves stuff to kitchen cabinet at %s = %s édplace des objets vers un meuble de cuisine à %s
|
||||||
|
%s takes stuff from kitchen cabinet at %s = %s prend des objets d'un meuble de cuisine à %s
|
||||||
|
Half-height Kitchen Cabinet (on ceiling) = Meuble de cuisine réduit en hauteur (sur le plafond)
|
||||||
|
Under-sink cabinet = Meuble sous évier
|
||||||
|
Kitchen Cabinet with sink = Meuble de cuisine avec lavabo
|
||||||
|
|
||||||
|
### door_models.lua ###
|
||||||
|
Mahogany Closet Door = Porte en bois d'acajou
|
||||||
|
Oak Closet Door = Porte en bois de chêne
|
||||||
|
Fancy Wood/Glass Door = Porte artistique en bois et verre
|
||||||
|
Glass Office Door = Porte en verre
|
||||||
|
Glass and Wood, Mahogany-colored = Porte couleur acajou en bois et verre
|
||||||
|
Glass and Wood, Oak-colored = Porte couleur chêne en bois et verre
|
||||||
|
Glass and Wood, White = Porte blanche en bois et verre
|
||||||
|
Plain Wooden Door = Porte en bois simple
|
||||||
|
left = gauche
|
||||||
|
right = droite
|
||||||
|
## 1: Side the doors opens to
|
||||||
|
(Top Half, %s-opening) = (partie supérieur, charnière à %s)
|
||||||
|
(%s-opening) = (charnière à %s)
|
||||||
|
|
||||||
|
### door_nodes.lua ###
|
||||||
|
Not enough vertical space to place a door! = Pas assez d'espace vertical pour placer une porte !
|
||||||
|
|
||||||
|
### crafts.lua ###
|
||||||
|
Brass Ingot = Lingot de laiton
|
||||||
|
Bucket of white paint = Seau de peinture blanche
|
||||||
|
Legs for Small Utility table = Pieds pour table basse
|
||||||
|
Plastic sheet = Bout de plastique
|
||||||
|
Silicon lump = Silicone
|
||||||
|
Simple Integrated Circuit = Circuit intégré simple
|
||||||
|
Small Wooden Drawer = Petit tiroir en bois
|
||||||
|
Terracotta Roof Tile = Tuile de toit en terre cuite
|
||||||
|
Titanium Dioxide = Dioxide de titane
|
||||||
|
Uncooked Terracotta Base = Base de terre non cuite
|
||||||
|
Unprocessed Plastic base = Base de plastique non transformée
|
||||||
|
|
||||||
|
### fences.lua ###
|
||||||
|
Barbed Wire Fence = Barrière en fil barbelé
|
||||||
|
Barbed Wire Fence Gate = Porte de barrière en fil barbelé
|
||||||
|
Brass Fence/railing = Barrière en laiton
|
||||||
|
Brass Fence/railing with sign = Barrière en laiton avec pancarte
|
||||||
|
Chainlink Fence = Grillage
|
||||||
|
Chainlink Fence Gate = Porte de grillage
|
||||||
|
Chainlink Fence Gate (open) = Porte de grillage (ouverte)
|
||||||
|
Unpainted Picket Fence = Barrière en piquets non peinte
|
||||||
|
Unpainted Picket Fence Gate = Porte de barrière en piquets non peinte
|
||||||
|
White Picket Fence = Barrière en piquets blanche
|
||||||
|
White Picket Fence Gate = Porte de barrière en piquets blanche
|
||||||
|
Wooden Privacy Fence = Barrière en bois
|
||||||
|
Wrought Iron Fence/railing = Barrière en fer forgé
|
||||||
|
Wrought Iron Fence/railing with sign = Barrière en fer forgé avec pancarte
|
||||||
|
want to simply place the wielded item like usual. = veut simplement placer l'objet comme d'habitude.
|
||||||
|
|
||||||
|
### init.lua ###
|
||||||
|
Loaded! = Chargé !
|
||||||
|
Asphalt Shingles = Bardeaux d'asphalte
|
||||||
|
Black Plastic Flower Pot = Pot de fleur en plastique noir
|
||||||
|
Brass Pole = Barre en laiton
|
||||||
|
Brass Table Legs = Pieds de table en laiton
|
||||||
|
red = rouges
|
||||||
|
green = vertes
|
||||||
|
blue = bleues
|
||||||
|
white = blanches
|
||||||
|
pink = roses
|
||||||
|
violet = violettes
|
||||||
|
## 1: Color name
|
||||||
|
Curtains (%s) = Volets (%s)
|
||||||
|
Drop-Ceiling Tile = Dalle suspendue au plafond
|
||||||
|
Glass Skylight = Verre
|
||||||
|
Glass Table (Small, Round) = Table en verre (petite, ronde)
|
||||||
|
Glass Table (Small, Square) = Table en verre (petite, carrée)
|
||||||
|
Green Plastic Flower Pot = Pot de fleur en plastique vert
|
||||||
|
Large Area Rug = Grande couverture
|
||||||
|
Large Glass Table Piece = Grand bout de verre de table
|
||||||
|
Large Stereo Speaker = Grand haut-parleur stéréo
|
||||||
|
Legs for Utility Table = Pieds pour table basse
|
||||||
|
Projection Screen Material = Matériel pour projecteur
|
||||||
|
Small Surround Speaker = Petit haut-parleur surround
|
||||||
|
Small Throw Rug = Petite couverture
|
||||||
|
Stereo Receiver = Récepteur stéréo
|
||||||
|
Terracotta Flower Pot = Pot de fleur en terre cuite
|
||||||
|
Terracotta Roofing = Tuile en terre cuite
|
||||||
|
Textured Ceiling Paint = Papier peint avec motif pour plafond
|
||||||
|
Utility Table = Table basse
|
||||||
|
Utility table mk2 = Table basse MK2
|
||||||
|
Wooden Shutter (Black) = Volet en bois (noir)
|
||||||
|
Wooden Shutter (Dark Grey) = Volet en bois (gris foncé)
|
||||||
|
Wooden Shutter (Forest Green) = Volet en bois (vert foncé)
|
||||||
|
Wooden Shutter (Grey) = Volet en bois (gris)
|
||||||
|
Wooden Shutter (Light Blue) = Volet en bois (bleu clair)
|
||||||
|
Wooden Shutter (Purple) = Volet en bois (violet)
|
||||||
|
Wooden Shutter (Red) = Volet en bois (rouge)
|
||||||
|
Wooden Shutter (Unpainted Mahogany) = Volet en bois (acajou non peint)
|
||||||
|
Wooden Shutter (Unpainted Oak) = Volet en bois (chêne non peint)
|
||||||
|
Wooden Shutter (White) = Volet en bois (blanc)
|
||||||
|
Wooden Shutter (Yellow) = Volet en bois (jaune)
|
||||||
|
Wooden Tabletop piece = Bout de dessus de table
|
||||||
|
Wooden Tabletop (Small, Round) = Dessus de table (petit, rond)
|
||||||
|
Wooden Tabletop (Small, Square) = Dessus de table (petit, carré)
|
||||||
|
Wood Shingles = Bardeaux de bois
|
||||||
|
Wrought Iron Pole = Barre de fer forgé
|
||||||
|
someone = quelqu'un
|
||||||
|
## 1: Player name
|
||||||
|
Sorry, %s owns that spot. = Désolé, %s est propriétaire de cette zone.
|
||||||
|
|
||||||
|
### lighting.lua ###
|
||||||
|
White Glowlight (small cube) = Lampe blanche (petit cube)
|
||||||
|
White Glowlight (small cube, on ceiling) = Lampe blanche (petit cube, sur le plafond)
|
||||||
|
White Glowlight (thick) = Lampe blanche (épaisse)
|
||||||
|
White Glowlight (thick, on wall) = Lampe blanche (épaisse, sur le mur)
|
||||||
|
White Glowlight (thin) = Lampe blanche (fine)
|
||||||
|
White Glowlight (thin, on wall) = Lampe blanche (fine, sur le mur)
|
||||||
|
Yellow Glowlight (small cube) = Lampe jaune (petit cube)
|
||||||
|
Yellow Glowlight (small cube, on ceiling) = Lampe jaune (petit cube, sur le plafond)
|
||||||
|
Yellow Glowlight (thick) = Lampe jaune (épaisse)
|
||||||
|
Yellow Glowlight (thick, on wall) = Lampe jaune (épaisse, sur le mur)
|
||||||
|
Yellow Glowlight (thin) = Lampe jaune (fine)
|
||||||
|
Yellow Glowlight (thin, on wall) = Lampe jaune (fine, sur le mur)
|
||||||
|
|
||||||
|
### locked.lua ###
|
||||||
|
## 1: Item description, 2: Owner name
|
||||||
|
%s (owned by %s) = %s (propriété de %s)
|
||||||
|
## 1: Player name, 2: Item description, 3: Owner name, 4: Position
|
||||||
|
%s tried to access a %s belonging to %s at %s = %s a essayé d'accéder à %s qui est propriété de %s à %s
|
||||||
|
## 1: Item description
|
||||||
|
%s (Locked) = %s (verrouillé)
|
||||||
|
Locked Cabinet = Meuble verrouillé
|
||||||
|
Locked Nightstand = Table de chevet verrouillée
|
||||||
|
Locked Fridge = Réfrégirateur verrouillé
|
||||||
|
Locked Oven = Four verrouillé
|
||||||
|
|
||||||
|
### nightstands.lua ###
|
||||||
|
Mahogany Nightstand with One Drawer = Table de chevet en acajou avec un tiroir
|
||||||
|
Mahogany Nightstand with Two Drawers = Table de chevet en acajou avec deux tiroirs
|
||||||
|
Oak Nightstand with One Drawer = Table de chevet en chêne avec un tiroir
|
||||||
|
Oak Nightstand with Two Drawers = Table de chevet en chêne avec deux tiroirs
|
||||||
|
## 1: Player name, 2: position
|
||||||
|
%s moves stuff in nightstand at %s = %s déplace des objets dans une table de chevet à %s
|
||||||
|
%s moves stuff to nightstand at %s = %s déplace des objets vers une table de chevet à %s
|
||||||
|
%s takes stuff from nightstand at %s = %s prend des objets d'une table de chevet à %s
|
||||||
|
One-drawer Nightstand = Table de chevet avec un tiroir
|
||||||
|
Two-drawer Nightstand = Table de chevet avec deux tiroirs
|
||||||
|
|
||||||
|
### oven.lua ###
|
||||||
|
Oven = Four
|
||||||
|
## 1: Item name
|
||||||
|
Could not insert '%s' = Ne peut insérer '%s'
|
||||||
|
## 1: Percentage
|
||||||
|
Oven active: %d%% = Four actif : %d%%
|
||||||
|
Oven out of fuel = Four sans carburant
|
||||||
|
Oven is empty = Four vide
|
||||||
|
|
||||||
|
### refrigerator.lua ###
|
||||||
|
Refrigerator = Réfrégirateur
|
||||||
|
## 1: Player name, 2: position
|
||||||
|
%s moves stuff in refrigerator at %s = %s déplace des objets dans un réfrégirateur à %s
|
||||||
|
%s moves stuff to refrigerator at %s = %s déplace des objets vers un réfrégirateur à %s
|
||||||
|
%s takes stuff from refrigerator at %s = %s prend des objets d'un réfrégirateur à %s
|
||||||
|
Not enough vertical space to place a refrigerator! = Pas assez d'espace vertical pour placer un réfrégirateur !
|
||||||
|
|
||||||
|
### television.lua ###
|
||||||
|
Small CRT Television = Petite télévision à tube cathodique
|
||||||
|
|
||||||
|
### signs_lib.lua ###
|
||||||
|
E: character map file not found = E: fichier de table de caractère non trouvé
|
||||||
|
## 1: Full String, 2: pos in string, 3: current char at pos
|
||||||
|
W: unknown symbol in '%s' at %d (probably %s) = A: symbole inconnu dans '%s' dans %d (probablement %s)
|
||||||
|
%s wrote "%s" to sign at %s =
|
||||||
|
signs loaded =
|
|
@ -0,0 +1,198 @@
|
||||||
|
|
||||||
|
# Brazilian Portuguese translation of homedecor
|
||||||
|
# Last update: 2013/11/10
|
||||||
|
# Last translator: Aracnus <frederico@teia.bio.br>
|
||||||
|
|
||||||
|
### Special strings ###
|
||||||
|
|
||||||
|
### kitchen_cabinet.lua ###
|
||||||
|
Kitchen Cabinet = Armário de cozinha
|
||||||
|
## 1: Player name, 2: position
|
||||||
|
%s moves stuff in kitchen cabinet at %s = %s moveu itens no armário de cozinha em %s
|
||||||
|
%s moves stuff to kitchen cabinet at %s = %s moveu itens para o armário de cozinha em %s
|
||||||
|
%s takes stuff from kitchen cabinet at %s = %s retirou itens do armário de cozinha em %s
|
||||||
|
Half-height Kitchen Cabinet (on ceiling) = Meio armário de cozinha (no teto)
|
||||||
|
Under-sink cabinet = Armário sob a pia
|
||||||
|
Kitchen Cabinet with sink = Armário de cozinha com pia
|
||||||
|
|
||||||
|
### door_models.lua ###
|
||||||
|
Mahogany Closet Door = Porta do armário de mogno
|
||||||
|
Oak Closet Door = Porta do armário de carvalho
|
||||||
|
Fancy Wood/Glass Door = Porta de madeira/vidro trabalhada
|
||||||
|
Glass Office Door = Porta de escritório de vidro
|
||||||
|
Glass and Wood, Mahogany-colored = Vidro e madeira (mogno)
|
||||||
|
Glass and Wood, Oak-colored = Vidro e madeira (carvalho)
|
||||||
|
Glass and Wood, White = Vidro e madeira (branca)
|
||||||
|
Plain Wooden Door = Porta de madeira simples
|
||||||
|
left = esquerda
|
||||||
|
right = direita
|
||||||
|
## 1: Side the doors opens to
|
||||||
|
(Top Half, %s-opening) = (Metade superior, abre para %s)
|
||||||
|
(%s-opening) = (abre para %s)
|
||||||
|
|
||||||
|
|
||||||
|
### door_nodes.lua ###
|
||||||
|
Not enough vertical space to place a door! = Não existe espaço vertical suficiente para colocar uma porta.
|
||||||
|
|
||||||
|
### crafts.lua ###
|
||||||
|
Brass Ingot = Lingote de bronze
|
||||||
|
Bucket of white paint = Balde de tinta branca
|
||||||
|
Legs for Small Utility table = Pernas para mesa pequena
|
||||||
|
Plastic sheet = Folha de plástico
|
||||||
|
Silicon lump = Massa de silício
|
||||||
|
Simple Integrated Circuit = Circuito integrado simples
|
||||||
|
Small Wooden Drawer = Gaveta pequena de madeira
|
||||||
|
Terracotta Roof Tile = Telha de terracota
|
||||||
|
Titanium Dioxide = Dióxido de titânio
|
||||||
|
Uncooked Terracotta Base = Base bruta de terracota
|
||||||
|
Unprocessed Plastic base = Base de plástico não processada
|
||||||
|
|
||||||
|
### door_models.lua ###
|
||||||
|
|
||||||
|
### door_nodes.lua ###
|
||||||
|
|
||||||
|
### fences.lua ###
|
||||||
|
Barbed Wire Fence = Cerca de arame farpado
|
||||||
|
Barbed Wire Fence Gate = Portão da cerca de arame farpado
|
||||||
|
Brass Fence/railing = Cerca/corrimão de bronze
|
||||||
|
Brass Fence/railing with sign = Cerca/corrimão de bronze, com placa
|
||||||
|
Chainlink Fence = Cerca de tela de arame
|
||||||
|
Chainlink Fence Gate = Portão da cerca de tela de arame
|
||||||
|
Chainlink Fence Gate (open) = Portão da cerca de tela de arame (aberto)
|
||||||
|
Unpainted Picket Fence = Cerca de tábuas não pintada
|
||||||
|
Unpainted Picket Fence Gate = Portão da cerca de madeira não pintado
|
||||||
|
White Picket Fence = Cerca de madeira branca
|
||||||
|
White Picket Fence Gate = Portão da cerca de madeira branco
|
||||||
|
Wooden Privacy Fence = Cerca fechada de mandeira
|
||||||
|
Wrought Iron Fence/railing = Cerca/corrimão de ferro forjado
|
||||||
|
Wrought Iron Fence/railing with sign = Cerca/corrimão de ferro forjado, com placa
|
||||||
|
want to simply place the wielded item like usual. = quer somente colocar o item empunhado normalmente.
|
||||||
|
|
||||||
|
### furniture_medieval.lua ###
|
||||||
|
Bars = Barras
|
||||||
|
Binding Bars = Barras do canto
|
||||||
|
Chains = Correntes
|
||||||
|
Wall Torch = Tocha de parede
|
||||||
|
|
||||||
|
### furniture_bathroom.lua ###
|
||||||
|
Toilet = Vaso sanitário
|
||||||
|
Sink = Pia
|
||||||
|
Taps = Torneira
|
||||||
|
Shower Tray = Ralo do chuveiro
|
||||||
|
Shower Head = Chuveiro
|
||||||
|
|
||||||
|
### init.lua ###
|
||||||
|
Loaded! = Carregado!
|
||||||
|
Asphalt Shingles = Telhas de asfalto
|
||||||
|
Black Plastic Flower Pot = Vaso de flor de plástico preto
|
||||||
|
Brass Pole = Poste de bronze
|
||||||
|
Brass Table Legs = Pernas da mesa de bronze
|
||||||
|
red = vermelho
|
||||||
|
green = verde
|
||||||
|
blue = azul
|
||||||
|
white = branco
|
||||||
|
pink = rosa
|
||||||
|
violet = violeta
|
||||||
|
## 1: Color name
|
||||||
|
Curtains (%s) = Cortina (%s)
|
||||||
|
Drop-Ceiling Tile = Placa de teto
|
||||||
|
Glass Skylight = Claraboia de vidro
|
||||||
|
Glass Table (Small, Round) = Mesa de vidro (pequena, redonda)
|
||||||
|
Glass Table (Small, Square) = Mesa de vidro (pequena, quadrada)
|
||||||
|
Green Plastic Flower Pot = Vaso de flor de plástico verde
|
||||||
|
Large Area Rug = Tapete grande
|
||||||
|
Large Glass Table Piece = Pedaço da mesa grande de vidro
|
||||||
|
Large Stereo Speaker = Auto-falante grande
|
||||||
|
Legs for Utility Table = Pernas para mesa
|
||||||
|
Projection Screen Material = Material de tela de projeção
|
||||||
|
Small Surround Speaker = Auto-falante pequeno
|
||||||
|
Small Throw Rug = Tapete pequeno
|
||||||
|
Stereo Receiver = Aparelho de som
|
||||||
|
Terracotta Flower Pot = Vaso de flor de terracota
|
||||||
|
Terracotta Roofing = Telhado de terracota
|
||||||
|
Textured Ceiling Paint = Pintura texturizada do teto
|
||||||
|
Utility Table = Mesa de trabalho
|
||||||
|
Utility table mk2 = Mesa de trabalho mk2
|
||||||
|
Wooden Shutter (Black) = Persiana de madeira (preta)
|
||||||
|
Wooden Shutter (Dark Grey) = Persiana de madeira (cinza escura)
|
||||||
|
Wooden Shutter (Forest Green) = Persiana de madeira (verde)
|
||||||
|
Wooden Shutter (Grey) = Persiana de madeira (cinza)
|
||||||
|
Wooden Shutter (Light Blue) = Persiana de madeira (azul clara)
|
||||||
|
Wooden Shutter (Purple) = Persiana de madeira (roxa)
|
||||||
|
Wooden Shutter (Red) = Persiana de madeira (vermelha)
|
||||||
|
Wooden Shutter (Unpainted Mahogany) = Persiana de madeira (mogno)
|
||||||
|
Wooden Shutter (Unpainted Oak) = Persiana de madeira (carvalho)
|
||||||
|
Wooden Shutter (White) = Persiana de madeira (branca)
|
||||||
|
Wooden Shutter (Yellow) = Persiana de madeira (amarela)
|
||||||
|
Wooden Tabletop piece = Pedaço do tampo da mesa
|
||||||
|
Wooden Tabletop (Small, Round) = Tampo da mesa (pequeno, arredondado)
|
||||||
|
Wooden Tabletop (Small, Square) = Tampo da mesa (pequeno, quadrado)
|
||||||
|
Wood Shingles = Telhas de madeira
|
||||||
|
Wrought Iron Pole = Poste de ferro forjado
|
||||||
|
someone = alguém
|
||||||
|
## 1: Player name
|
||||||
|
Sorry, %s owns that spot. = Desculpe, mas esse local pertence a %s.
|
||||||
|
|
||||||
|
### lighting.lua ###
|
||||||
|
White Glowlight (small cube) = Arandela branca (cubo pequeno)
|
||||||
|
White Glowlight (small cube, on ceiling) = Arandela branca (cubo pequeno, na parede)
|
||||||
|
White Glowlight (thick) = Arandela branca (grossa)
|
||||||
|
White Glowlight (thick, on wall) = Arandela branca (grossa, na parede)
|
||||||
|
White Glowlight (thin) = Arandela branca (fina)
|
||||||
|
White Glowlight (thin, on wall) = Arandela branca (fina, na parede)
|
||||||
|
Yellow Glowlight (small cube) = Arandela amarela (cubo pequeno)
|
||||||
|
Yellow Glowlight (small cube, on ceiling) = Arandela amarela (cubo pequeno, na parede)
|
||||||
|
Yellow Glowlight (thick) = Arandela amarela (grossa)
|
||||||
|
Yellow Glowlight (thick, on wall) = Arandela amarela (grossa, na parede)
|
||||||
|
Yellow Glowlight (thin) = Arandela amarela (fina)
|
||||||
|
Yellow Glowlight (thin, on wall) = Arandela amarela (fina, na parede)
|
||||||
|
|
||||||
|
### locked.lua ###
|
||||||
|
## 1: Item description, 2: Owner name
|
||||||
|
%s (owned by %s) = %s (pertence a %s)
|
||||||
|
## 1: Player name, 2: Item description, 3: Owner name, 4: Position
|
||||||
|
%s tried to access a %s belonging to %s at %s = %s tentou acessar %s pertencente a %s em %s
|
||||||
|
## 1: Item description
|
||||||
|
%s (Locked) = %s (trancado)
|
||||||
|
Locked Cabinet = Armário trancado
|
||||||
|
Locked Nightstand = Criado-mudo trancado
|
||||||
|
|
||||||
|
### nightstands.lua ###
|
||||||
|
Mahogany Nightstand with One Drawer = Criado-mudo de mogno, com uma gaveta
|
||||||
|
Mahogany Nightstand with Two Drawers = Criado-mudo de mogno, com duas gavetas
|
||||||
|
Oak Nightstand with One Drawer = Criado-mudo de carvalho, com uma gaveta
|
||||||
|
Oak Nightstand with Two Drawers = Criado-mudo de carvalho, com duas gavetas
|
||||||
|
## 1: Player name, 2: position
|
||||||
|
%s moves stuff in nightstand at %s = %s moveu item(ns) no criado-mudo em %s
|
||||||
|
%s moves stuff to nightstand at %s = %s moveu item(ns) para o criado-mudo em %s
|
||||||
|
%s takes stuff from nightstand at %s = %s tirou item(ns) do criado-mudo em %s
|
||||||
|
One-drawer Nightstand = Criado-mudo com uma gaveta
|
||||||
|
Two-drawer Nightstand = Criado-mudo com duas gavetas
|
||||||
|
|
||||||
|
### oven.lua ###
|
||||||
|
Oven = Forno
|
||||||
|
## 1: Item name
|
||||||
|
Could not insert '%s' = Não foi possível inserir '%s'
|
||||||
|
## 1: Percentage
|
||||||
|
Oven active: %d%% = Forno ativo: %d%%
|
||||||
|
Oven out of fuel = O forno está sem combustível
|
||||||
|
Oven is empty = O forno está vazio
|
||||||
|
|
||||||
|
### refrigerator.lua ###
|
||||||
|
Refrigerator = Geladeira
|
||||||
|
## 1: Player name, 2: position
|
||||||
|
%s moves stuff in refrigerator at %s = %s moveu item(ns) na geladeira em %s
|
||||||
|
%s moves stuff to refrigerator at %s = %s moveu item(ns) para a geladeira em %s
|
||||||
|
%s takes stuff from refrigerator at %s = %s tirou item(ns) da geladeira em %s
|
||||||
|
Not enough vertical space to place a refrigerator! = Não existe espaço vertical suficiente para adicionar uma geladeira.
|
||||||
|
|
||||||
|
### television.lua ###
|
||||||
|
Small CRT Television = TV de tubo pequena
|
||||||
|
|
||||||
|
### signs_lib.lua ###
|
||||||
|
%s wrote "%s" to sign at %s = %s escreveu "%s" na placa em %s
|
||||||
|
Reading cached character database. = Lendo banco de dados de caracteres no cache.
|
||||||
|
Font seems to have changed. Rebuilding cache. = Aparentemente as fontes foram alteradas. Reconstruindo o cache.
|
||||||
|
Could not find font line height in cached DB. Trying brute force. = Não foi possível encontrar a altura da linha da fonte no cache do BD. Tentando na marra.
|
||||||
|
Registered %s and %s = %s e %s registrados
|
||||||
|
signs loaded = placas carregadas
|
|
@ -0,0 +1,198 @@
|
||||||
|
|
||||||
|
##########################
|
||||||
|
# Template language file #
|
||||||
|
##########################
|
||||||
|
|
||||||
|
### Special strings ###
|
||||||
|
|
||||||
|
### kitchen_cabinet.lua ###
|
||||||
|
Kitchen Cabinet =
|
||||||
|
## 1: Player name, 2: position
|
||||||
|
%s moves stuff in kitchen cabinet at %s =
|
||||||
|
%s moves stuff to kitchen cabinet at %s =
|
||||||
|
%s takes stuff from kitchen cabinet at %s =
|
||||||
|
Half-height Kitchen Cabinet (on ceiling) =
|
||||||
|
Under-sink cabinet =
|
||||||
|
Kitchen Cabinet with sink =
|
||||||
|
|
||||||
|
### door_models.lua ###
|
||||||
|
Mahogany Closet Door =
|
||||||
|
Oak Closet Door =
|
||||||
|
Fancy Wood/Glass Door =
|
||||||
|
Glass Office Door =
|
||||||
|
Glass and Wood, Mahogany-colored =
|
||||||
|
Glass and Wood, Oak-colored =
|
||||||
|
Glass and Wood, White =
|
||||||
|
Plain Wooden Door =
|
||||||
|
left =
|
||||||
|
right =
|
||||||
|
## 1: Side the doors opens to
|
||||||
|
(Top Half, %s-opening) =
|
||||||
|
(%s-opening) =
|
||||||
|
|
||||||
|
|
||||||
|
### door_nodes.lua ###
|
||||||
|
Not enough vertical space to place a door! =
|
||||||
|
|
||||||
|
### crafts.lua ###
|
||||||
|
Brass Ingot =
|
||||||
|
Bucket of white paint =
|
||||||
|
Legs for Small Utility table =
|
||||||
|
Plastic sheet =
|
||||||
|
Silicon lump =
|
||||||
|
Simple Integrated Circuit =
|
||||||
|
Small Wooden Drawer =
|
||||||
|
Terracotta Roof Tile =
|
||||||
|
Titanium Dioxide =
|
||||||
|
Uncooked Terracotta Base =
|
||||||
|
Unprocessed Plastic base =
|
||||||
|
|
||||||
|
### door_models.lua ###
|
||||||
|
|
||||||
|
### door_nodes.lua ###
|
||||||
|
|
||||||
|
### fences.lua ###
|
||||||
|
Barbed Wire Fence =
|
||||||
|
Barbed Wire Fence Gate =
|
||||||
|
Brass Fence/railing =
|
||||||
|
Brass Fence/railing with sign =
|
||||||
|
Chainlink Fence =
|
||||||
|
Chainlink Fence Gate =
|
||||||
|
Chainlink Fence Gate (open) =
|
||||||
|
Unpainted Picket Fence =
|
||||||
|
Unpainted Picket Fence Gate =
|
||||||
|
White Picket Fence =
|
||||||
|
White Picket Fence Gate =
|
||||||
|
Wooden Privacy Fence =
|
||||||
|
Wrought Iron Fence/railing =
|
||||||
|
Wrought Iron Fence/railing with sign =
|
||||||
|
want to simply place the wielded item like usual. =
|
||||||
|
|
||||||
|
### furniture_medieval.lua ###
|
||||||
|
Bars =
|
||||||
|
Binding Bars =
|
||||||
|
Chains =
|
||||||
|
Wall Torch =
|
||||||
|
|
||||||
|
### furniture_bathroom.lua ###
|
||||||
|
Toilet =
|
||||||
|
Sink =
|
||||||
|
Taps =
|
||||||
|
Shower Tray =
|
||||||
|
Shower Head =
|
||||||
|
|
||||||
|
### init.lua ###
|
||||||
|
Loaded! =
|
||||||
|
Asphalt Shingles =
|
||||||
|
Black Plastic Flower Pot =
|
||||||
|
Brass Pole =
|
||||||
|
Brass Table Legs =
|
||||||
|
red =
|
||||||
|
green =
|
||||||
|
blue =
|
||||||
|
white =
|
||||||
|
pink =
|
||||||
|
violet =
|
||||||
|
## 1: Color name
|
||||||
|
Curtains (%s) =
|
||||||
|
Drop-Ceiling Tile =
|
||||||
|
Glass Skylight =
|
||||||
|
Glass Table (Small, Round) =
|
||||||
|
Glass Table (Small, Square) =
|
||||||
|
Green Plastic Flower Pot =
|
||||||
|
Large Area Rug =
|
||||||
|
Large Glass Table Piece =
|
||||||
|
Large Stereo Speaker =
|
||||||
|
Legs for Utility Table =
|
||||||
|
Projection Screen Material =
|
||||||
|
Small Surround Speaker =
|
||||||
|
Small Throw Rug =
|
||||||
|
Stereo Receiver =
|
||||||
|
Terracotta Flower Pot =
|
||||||
|
Terracotta Roofing =
|
||||||
|
Textured Ceiling Paint =
|
||||||
|
Utility Table =
|
||||||
|
Utility table mk2 =
|
||||||
|
Wooden Shutter (Black) =
|
||||||
|
Wooden Shutter (Dark Grey) =
|
||||||
|
Wooden Shutter (Forest Green) =
|
||||||
|
Wooden Shutter (Grey) =
|
||||||
|
Wooden Shutter (Light Blue) =
|
||||||
|
Wooden Shutter (Purple) =
|
||||||
|
Wooden Shutter (Red) =
|
||||||
|
Wooden Shutter (Unpainted Mahogany) =
|
||||||
|
Wooden Shutter (Unpainted Oak) =
|
||||||
|
Wooden Shutter (White) =
|
||||||
|
Wooden Shutter (Yellow) =
|
||||||
|
Wooden Tabletop piece =
|
||||||
|
Wooden Tabletop (Small, Round) =
|
||||||
|
Wooden Tabletop (Small, Square) =
|
||||||
|
Wood Shingles =
|
||||||
|
Wrought Iron Pole =
|
||||||
|
someone =
|
||||||
|
## 1: Player name
|
||||||
|
Sorry, %s owns that spot. =
|
||||||
|
|
||||||
|
### lighting.lua ###
|
||||||
|
White Glowlight (small cube) =
|
||||||
|
White Glowlight (small cube, on ceiling) =
|
||||||
|
White Glowlight (thick) =
|
||||||
|
White Glowlight (thick, on wall) =
|
||||||
|
White Glowlight (thin) =
|
||||||
|
White Glowlight (thin, on wall) =
|
||||||
|
Yellow Glowlight (small cube) =
|
||||||
|
Yellow Glowlight (small cube, on ceiling) =
|
||||||
|
Yellow Glowlight (thick) =
|
||||||
|
Yellow Glowlight (thick, on wall) =
|
||||||
|
Yellow Glowlight (thin) =
|
||||||
|
Yellow Glowlight (thin, on wall) =
|
||||||
|
|
||||||
|
### locked.lua ###
|
||||||
|
## 1: Item description, 2: Owner name
|
||||||
|
%s (owned by %s) =
|
||||||
|
## 1: Player name, 2: Item description, 3: Owner name, 4: Position
|
||||||
|
%s tried to access a %s belonging to %s at %s =
|
||||||
|
## 1: Item description
|
||||||
|
%s (Locked) =
|
||||||
|
Locked Cabinet =
|
||||||
|
Locked Nightstand =
|
||||||
|
|
||||||
|
### nightstands.lua ###
|
||||||
|
Mahogany Nightstand with One Drawer =
|
||||||
|
Mahogany Nightstand with Two Drawers =
|
||||||
|
Oak Nightstand with One Drawer =
|
||||||
|
Oak Nightstand with Two Drawers =
|
||||||
|
## 1: Player name, 2: position
|
||||||
|
%s moves stuff in nightstand at %s =
|
||||||
|
%s moves stuff to nightstand at %s =
|
||||||
|
%s takes stuff from nightstand at %s =
|
||||||
|
One-drawer Nightstand =
|
||||||
|
Two-drawer Nightstand =
|
||||||
|
|
||||||
|
### oven.lua ###
|
||||||
|
Oven =
|
||||||
|
## 1: Item name
|
||||||
|
Could not insert '%s' =
|
||||||
|
## 1: Percentage
|
||||||
|
Oven active: %d%% =
|
||||||
|
Oven out of fuel =
|
||||||
|
Oven is empty =
|
||||||
|
|
||||||
|
### refrigerator.lua ###
|
||||||
|
Refrigerator =
|
||||||
|
## 1: Player name, 2: position
|
||||||
|
%s moves stuff in refrigerator at %s =
|
||||||
|
%s moves stuff to refrigerator at %s =
|
||||||
|
%s takes stuff from refrigerator at %s =
|
||||||
|
Not enough vertical space to place a refrigerator! =
|
||||||
|
|
||||||
|
### television.lua ###
|
||||||
|
Small CRT Television =
|
||||||
|
|
||||||
|
### signs_lib.lua ###
|
||||||
|
%s wrote "%s" to sign at %s =
|
||||||
|
Reading cached character database. =
|
||||||
|
Font seems to have changed. Rebuilding cache. =
|
||||||
|
Could not find font line height in cached DB. Trying brute force. =
|
||||||
|
Registered %s and %s =
|
||||||
|
signs loaded =
|
|
@ -0,0 +1,354 @@
|
||||||
|
--Poudlard mod by Perlipop
|
||||||
|
--Code imported from moreblocks by Calinou
|
||||||
|
|
||||||
|
|
||||||
|
-- Blocks
|
||||||
|
minetest.register_node("poudlard:poudstone", {
|
||||||
|
description = "Poudstone",
|
||||||
|
tiles = {"poudlard_poudstone.png"},
|
||||||
|
is_ground_content = true,
|
||||||
|
groups = {cracky=3, stone=2},
|
||||||
|
sounds = default.node_sound_stone_defaults(),
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_node("poudlard:poudwood", {
|
||||||
|
description = "Poudlard Wooden Planks",
|
||||||
|
tiles = {"poudlard_poudwood.png"},
|
||||||
|
is_ground_content = true,
|
||||||
|
groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,flammable=3},
|
||||||
|
sounds = default.node_sound_wood_defaults(),
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("poudlard:redblock", {
|
||||||
|
description = "Red block",
|
||||||
|
tiles = {"poudlard_redblock.png"},
|
||||||
|
is_ground_content = true,
|
||||||
|
groups = {cracky=3, stone=2},
|
||||||
|
sounds = default.node_sound_stone_defaults(),
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("poudlard:blackblock", {
|
||||||
|
description = "black block",
|
||||||
|
tiles = {"poudlard_blackblock.png"},
|
||||||
|
is_ground_content = true,
|
||||||
|
groups = {cracky=3, stone=2},
|
||||||
|
sounds = default.node_sound_stone_defaults(),
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("poudlard:junglewood", {
|
||||||
|
description = "Jungle Wooden Planks",
|
||||||
|
tiles = {"poudlard_junglewood.png"},
|
||||||
|
paramtype2 = "facedir",
|
||||||
|
is_ground_content = true,
|
||||||
|
groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,flammable=3},
|
||||||
|
sounds = default.node_sound_wood_defaults(),
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("poudlard:stonebrick", {
|
||||||
|
description = "Stone Bricks",
|
||||||
|
tiles = {"poudlard_stonebrick.png"},
|
||||||
|
is_ground_content = true,
|
||||||
|
groups = {cracky=3},
|
||||||
|
sounds = default.node_sound_stone_defaults(),
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_node("poudlard:circlestonebricks", {
|
||||||
|
description = "Circle Stone Bricks",
|
||||||
|
tiles = {"poudlard_circlestonebrick.png"},
|
||||||
|
is_ground_content = true,
|
||||||
|
groups = {cracky=3},
|
||||||
|
sounds = default.node_sound_stone_defaults(),
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("poudlard:ironstonebricks", {
|
||||||
|
description = "Iron Stone Bricks",
|
||||||
|
tiles = {"poudlard_ironstonebrick.png"},
|
||||||
|
is_ground_content = true,
|
||||||
|
groups = {cracky=3},
|
||||||
|
sounds = default.node_sound_stone_defaults(),
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("poudlard:stone_tile", {
|
||||||
|
description = "Stonesquare",
|
||||||
|
tiles = {"poudlard_stonesquare.png"},
|
||||||
|
is_ground_content = true,
|
||||||
|
groups = {cracky=3},
|
||||||
|
sounds = default.node_sound_stone_defaults(),
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("poudlard:split_stone_tile", {
|
||||||
|
description = "Split Stonesquare",
|
||||||
|
tiles = {"poudlard_splitstonesquare_top.png", "poudlard_splitstonesquare.png"},
|
||||||
|
is_ground_content = true,
|
||||||
|
groups = {cracky=3},
|
||||||
|
sounds = default.node_sound_stone_defaults(),
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("poudlard:plankstone", {
|
||||||
|
description = "Plankstone",
|
||||||
|
tiles = {
|
||||||
|
"poudlard_plankstone.png",
|
||||||
|
"poudlard_plankstone.png",
|
||||||
|
"poudlard_plankstone.png",
|
||||||
|
"poudlard_plankstone.png",
|
||||||
|
"poudlard_plankstone_2.png",
|
||||||
|
"poudlard_plankstone_2.png",
|
||||||
|
},
|
||||||
|
is_ground_content = true,
|
||||||
|
groups = {cracky=3},
|
||||||
|
sounds = default.node_sound_stone_defaults(),
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("poudlard:ironglass", {
|
||||||
|
description = "Iron Glass",
|
||||||
|
drawtype = "glasslike",
|
||||||
|
tiles = {"poudlard_ironglass.png"},
|
||||||
|
inventory_image = minetest.inventorycube("poudlard_ironglass.png"),
|
||||||
|
paramtype = "light",
|
||||||
|
sunlight_propagates = true,
|
||||||
|
is_ground_content = true,
|
||||||
|
groups = {snappy=2,cracky=3,oddly_breakable_by_hand=3},
|
||||||
|
sounds = default.node_sound_glass_defaults(),
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("poudlard:coalglass", {
|
||||||
|
description = "Coal Glass",
|
||||||
|
drawtype = "glasslike",
|
||||||
|
tiles = {"poudlard_coalglass.png"},
|
||||||
|
inventory_image = minetest.inventorycube("poudlard_coalglass.png"),
|
||||||
|
paramtype = "light",
|
||||||
|
sunlight_propagates = true,
|
||||||
|
is_ground_content = true,
|
||||||
|
groups = {snappy=2,cracky=3,oddly_breakable_by_hand=3},
|
||||||
|
sounds = default.node_sound_glass_defaults(),
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("poudlard:cleanglass", {
|
||||||
|
description = "Clean Glass",
|
||||||
|
drawtype = "glasslike",
|
||||||
|
tiles = {"poudlard_cleanglass.png"},
|
||||||
|
inventory_image = minetest.inventorycube("poudlard_cleanglass.png"),
|
||||||
|
paramtype = "light",
|
||||||
|
sunlight_propagates = true,
|
||||||
|
is_ground_content = true,
|
||||||
|
groups = {snappy=2,cracky=3,oddly_breakable_by_hand=3},
|
||||||
|
sounds = default.node_sound_glass_defaults(),
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_node("poudlard:cactuschecker", {
|
||||||
|
description = "Cactus Checker",
|
||||||
|
tiles = {
|
||||||
|
"poudlard_cactuschecker.png",
|
||||||
|
"poudlard_cactuschecker.png",
|
||||||
|
"poudlard_cactuschecker.png",
|
||||||
|
"poudlard_cactuschecker.png",
|
||||||
|
"poudlard_cactuschecker_2.png",
|
||||||
|
"poudlard_cactuschecker_2.png",
|
||||||
|
},
|
||||||
|
is_ground_content = true,
|
||||||
|
groups = {cracky=3},
|
||||||
|
sounds = default.node_sound_stone_defaults(),
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("poudlard:emptybookshelf", {
|
||||||
|
description = "Empty Bookshelf",
|
||||||
|
tiles = {"default_wood.png", "default_wood.png", "poudlard_emptybookshelf.png"},
|
||||||
|
is_ground_content = true,
|
||||||
|
groups = {snappy=2,choppy=3,oddly_breakable_by_hand=2,flammable=3},
|
||||||
|
sounds = default.node_sound_wood_defaults(),
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_node("poudlard:coalstone", {
|
||||||
|
description = "Coal Stone",
|
||||||
|
tiles = {"poudlard_coalstone.png"},
|
||||||
|
is_ground_content = true,
|
||||||
|
groups = {cracky=3},
|
||||||
|
sounds = default.node_sound_stone_defaults(),
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("poudlard:ironstone", {
|
||||||
|
description = "Iron Stone",
|
||||||
|
tiles = {"poudlard_ironstone.png"},
|
||||||
|
is_ground_content = true,
|
||||||
|
groups = {cracky=3},
|
||||||
|
sounds = default.node_sound_stone_defaults(),
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("poudlard:coalchecker", {
|
||||||
|
description = "Coal Checker",
|
||||||
|
tiles = {
|
||||||
|
"poudlard_coalchecker.png",
|
||||||
|
"poudlard_coalchecker.png",
|
||||||
|
"poudlard_coalchecker.png",
|
||||||
|
"poudlard_coalchecker.png",
|
||||||
|
"poudlard_coalchecker_2.png",
|
||||||
|
"poudlard_coalchecker_2.png",
|
||||||
|
},
|
||||||
|
is_ground_content = true,
|
||||||
|
groups = {cracky=3},
|
||||||
|
sounds = default.node_sound_stone_defaults(),
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("poudlard:ironchecker", {
|
||||||
|
description = "Iron Checker",
|
||||||
|
tiles = {
|
||||||
|
"poudlard_ironchecker.png",
|
||||||
|
"poudlard_ironchecker.png",
|
||||||
|
"poudlard_ironchecker.png",
|
||||||
|
"poudlard_ironchecker.png",
|
||||||
|
"poudlard_ironchecker_2.png",
|
||||||
|
"poudlard_ironchecker_2.png",
|
||||||
|
},
|
||||||
|
is_ground_content = true,
|
||||||
|
groups = {cracky=3},
|
||||||
|
sounds = default.node_sound_stone_defaults(),
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("poudlard:trapstone", {
|
||||||
|
description = "Trapstone",
|
||||||
|
tiles = {"poudlard_trapstone.png"},
|
||||||
|
walkable = false,
|
||||||
|
is_ground_content = true,
|
||||||
|
groups = {cracky=3},
|
||||||
|
sounds = default.node_sound_stone_defaults(),
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("poudlard:trapglass", {
|
||||||
|
description = "Trapglass",
|
||||||
|
drawtype = "glasslike",
|
||||||
|
tiles = {"poudlard_trapglass.png"},
|
||||||
|
inventory_image = minetest.inventorycube("poudlard_trapglass.png"),
|
||||||
|
paramtype = "light",
|
||||||
|
sunlight_propagates = true,
|
||||||
|
walkable = false,
|
||||||
|
is_ground_content = true,
|
||||||
|
groups = {snappy=2,cracky=3,oddly_breakable_by_hand=3},
|
||||||
|
sounds = default.node_sound_glass_defaults(),
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("poudlard:fence_junglewood", {
|
||||||
|
description = "Jungle Wood Fence",
|
||||||
|
drawtype = "fencelike",
|
||||||
|
tiles = {"poudlard_junglewood.png"},
|
||||||
|
inventory_image = "poudlard_junglewood_fence.png",
|
||||||
|
wield_image = "poudlard_junglewood_fence.png",
|
||||||
|
paramtype = "light",
|
||||||
|
is_ground_content = true,
|
||||||
|
selection_box = {
|
||||||
|
type = "fixed",
|
||||||
|
fixed = {-1/7, -1/2, -1/7, 1/7, 1/2, 1/7},
|
||||||
|
},
|
||||||
|
groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,flammable=2},
|
||||||
|
sounds = default.node_sound_wood_defaults(),
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("poudlard:horizontaltree", {
|
||||||
|
description = "Horizontal Tree",
|
||||||
|
tiles = {"default_tree.png", "default_tree.png", "poudlard_horizontaltree.png",
|
||||||
|
"poudlard_horizontaltree.png", "default_tree_top.png", "default_tree_top.png"},
|
||||||
|
paramtype2 = "facedir",
|
||||||
|
groups = {tree=1,snappy=1,choppy=2,oddly_breakable_by_hand=1,flammable=2},
|
||||||
|
sounds = default.node_sound_wood_defaults(),
|
||||||
|
furnace_burntime = 30,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_node("poudlard:allfacestree", {
|
||||||
|
description = "All-faces Tree",
|
||||||
|
tiles = {"default_tree_top.png"},
|
||||||
|
groups = {tree=1,snappy=1,choppy=2,oddly_breakable_by_hand=1,flammable=2},
|
||||||
|
sounds = default.node_sound_wood_defaults(),
|
||||||
|
furnace_burntime = 30,
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("poudlard:alltree", {
|
||||||
|
description = "All-faces Tree",
|
||||||
|
tiles = {"default_tree.png"},
|
||||||
|
groups = {tree=1,snappy=1,choppy=2,oddly_breakable_by_hand=1,flammable=2},
|
||||||
|
sounds = default.node_sound_wood_defaults(),
|
||||||
|
furnace_burntime = 30,
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("poudlard:superglowglass", {
|
||||||
|
description = "Super Glowglass",
|
||||||
|
drawtype = "glasslike",
|
||||||
|
tiles = {"poudlard_glowglass.png"},
|
||||||
|
inventory_image = minetest.inventorycube("poudlard_glowglass.png"),
|
||||||
|
paramtype = "light",
|
||||||
|
sunlight_propagates = true,
|
||||||
|
light_source = 15,
|
||||||
|
is_ground_content = true,
|
||||||
|
groups = {snappy=2,cracky=3,oddly_breakable_by_hand=3},
|
||||||
|
sounds = default.node_sound_glass_defaults(),
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("poudlard:rope", {
|
||||||
|
description = "Rope",
|
||||||
|
drawtype = "signlike",
|
||||||
|
tiles = {"poudlard_rope.png"},
|
||||||
|
inventory_image = "poudlard_rope.png",
|
||||||
|
wield_image = "poudlard_rope.png",
|
||||||
|
paramtype = "light",
|
||||||
|
paramtype2 = "wallmounted",
|
||||||
|
is_ground_content = true,
|
||||||
|
walkable = false,
|
||||||
|
climbable = true,
|
||||||
|
selection_box = {
|
||||||
|
type = "wallmounted",
|
||||||
|
},
|
||||||
|
groups = {snappy=3,flammable=2},
|
||||||
|
sounds = default.node_sound_leaves_defaults(),
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("poudlard:wood_tile", {
|
||||||
|
description = "Wooden Tile",
|
||||||
|
tiles = {"poudlard_wood_tile.png", "poudlard_wood_tile.png", "poudlard_wood_tile.png", "poudlard_wood_tile.png", "poudlard_wood_tile.png^[transformR90", "poudlard_wood_tile.png^[transformR90"},
|
||||||
|
inventory_image = {"poudlard_wood_tile.png", "poudlard_wood_tile.png"},
|
||||||
|
paramtype2 = "facedir",
|
||||||
|
groups = {snappy=1,choppy=2,oddly_breakable_by_hand=2,flammable=3},
|
||||||
|
sounds = default.node_sound_wood_defaults(),
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("poudlard:wood_tile_full", {
|
||||||
|
description = "Full Wooden Tile",
|
||||||
|
tiles = {"poudlard_wood_tile_full.png", "poudlard_wood_tile_full.png", "poudlard_wood_tile_full.png",
|
||||||
|
"poudlard_wood_tile_full.png", "poudlard_wood_tile_full.png^[transformR90", "poudlard_wood_tile_full.png^[transformR90"},
|
||||||
|
inventory_image = {"poudlard_wood_tile_full.png", "poudlard_wood_tile_full.png"},
|
||||||
|
paramtype2 = "facedir",
|
||||||
|
groups = {snappy=1,choppy=2,oddly_breakable_by_hand=2,flammable=3},
|
||||||
|
sounds = default.node_sound_wood_defaults(),
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("poudlard:wood_tile_center", {
|
||||||
|
description = "Centered Wooden Tile",
|
||||||
|
tiles = {"poudlard_wood_tile_center.png", "poudlard_wood_tile_center.png", "poudlard_wood_tile_center.png", "poudlard_wood_tile_center.png", "poudlard_wood_tile_center.png^[transformR90", "poudlard_wood_tile_center.png^[transformR90"},
|
||||||
|
inventory_image = {"poudlard_wood_tile_center.png", "poudlard_wood_tile_center.png"},
|
||||||
|
paramtype2 = "facedir",
|
||||||
|
groups = {snappy=1,choppy=2,oddly_breakable_by_hand=2,flammable=3},
|
||||||
|
sounds = default.node_sound_wood_defaults(),
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("poudlard:secretbookshelf", {
|
||||||
|
description = "Secret_bookshelf",
|
||||||
|
tiles = {"default_wood.png", "default_wood.png","poudlard_secretbookshelf.png"},
|
||||||
|
walkable = false,
|
||||||
|
is_ground_content = true,
|
||||||
|
groups = {cracky=3},
|
||||||
|
sounds = default.node_sound_stone_defaults(),
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Items
|
||||||
|
|
||||||
|
minetest.register_craftitem("poudlard:sweeper", {
|
||||||
|
description = "Sweeper",
|
||||||
|
inventory_image = "poudlard_sweeper.png",
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("poudlard:junglestick", {
|
||||||
|
description = "Jungle Stick",
|
||||||
|
inventory_image = "poudlard_junglestick.png",
|
||||||
|
})
|
|
@ -0,0 +1,699 @@
|
||||||
|
For the Code:
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU General Public License is a free, copyleft license for
|
||||||
|
software and other kinds of works.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
the GNU General Public License is intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users. We, the Free Software Foundation, use the
|
||||||
|
GNU General Public License for most of our software; it applies also to
|
||||||
|
any other work released this way by its authors. You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
them if you wish), that you receive source code or can get it if you
|
||||||
|
want it, that you can change the software or use pieces of it in new
|
||||||
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to prevent others from denying you
|
||||||
|
these rights or asking you to surrender the rights. Therefore, you have
|
||||||
|
certain responsibilities if you distribute copies of the software, or if
|
||||||
|
you modify it: responsibilities to respect the freedom of others.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must pass on to the recipients the same
|
||||||
|
freedoms that you received. You must make sure that they, too, receive
|
||||||
|
or can get the source code. And you must show them these terms so they
|
||||||
|
know their rights.
|
||||||
|
|
||||||
|
Developers that use the GNU GPL protect your rights with two steps:
|
||||||
|
(1) assert copyright on the software, and (2) offer you this License
|
||||||
|
giving you legal permission to copy, distribute and/or modify it.
|
||||||
|
|
||||||
|
For the developers' and authors' protection, the GPL clearly explains
|
||||||
|
that there is no warranty for this free software. For both users' and
|
||||||
|
authors' sake, the GPL requires that modified versions be marked as
|
||||||
|
changed, so that their problems will not be attributed erroneously to
|
||||||
|
authors of previous versions.
|
||||||
|
|
||||||
|
Some devices are designed to deny users access to install or run
|
||||||
|
modified versions of the software inside them, although the manufacturer
|
||||||
|
can do so. This is fundamentally incompatible with the aim of
|
||||||
|
protecting users' freedom to change the software. The systematic
|
||||||
|
pattern of such abuse occurs in the area of products for individuals to
|
||||||
|
use, which is precisely where it is most unacceptable. Therefore, we
|
||||||
|
have designed this version of the GPL to prohibit the practice for those
|
||||||
|
products. If such problems arise substantially in other domains, we
|
||||||
|
stand ready to extend this provision to those domains in future versions
|
||||||
|
of the GPL, as needed to protect the freedom of users.
|
||||||
|
|
||||||
|
Finally, every program is threatened constantly by software patents.
|
||||||
|
States should not allow patents to restrict development and use of
|
||||||
|
software on general-purpose computers, but in those that do, we wish to
|
||||||
|
avoid the special danger that patents applied to a free program could
|
||||||
|
make it effectively proprietary. To prevent this, the GPL assures that
|
||||||
|
patents cannot be used to render the program non-free.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Use with the GNU Affero General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU Affero General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the special requirements of the GNU Affero General Public License,
|
||||||
|
section 13, concerning interaction through a network will apply to the
|
||||||
|
combination as such.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program does terminal interaction, make it output a short
|
||||||
|
notice like this when it starts in an interactive mode:
|
||||||
|
|
||||||
|
<program> Copyright (C) <year> <name of author>
|
||||||
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, your program's commands
|
||||||
|
might be different; for a GUI interface, you would use an "about box".
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU GPL, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
The GNU General Public License does not permit incorporating your program
|
||||||
|
into proprietary programs. If your program is a subroutine library, you
|
||||||
|
may consider it more useful to permit linking proprietary applications with
|
||||||
|
the library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License. But first, please read
|
||||||
|
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||||
|
|
||||||
|
|
||||||
|
----------
|
||||||
|
|
||||||
|
For the textures and everything else:
|
||||||
|
|
||||||
|
|
||||||
|
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||||
|
Version 2, December 2004
|
||||||
|
|
||||||
|
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
||||||
|
|
||||||
|
Everyone is permitted to copy and distribute verbatim or modified
|
||||||
|
copies of this license document, and changing it is allowed as long
|
||||||
|
as the name is changed.
|
||||||
|
|
||||||
|
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||||
|
|
||||||
|
This license is commonly known as "WTFPL".
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
This is what I consider to be a fairly feature-filled home decor mod.
|
||||||
|
It supplies a bunch of stuff found in most homes, like flower pots, home
|
||||||
|
electronics, brass and wrought-iron tables, and lots more!
|
||||||
|
|
||||||
|
All items can be accessed either by crafting various other items
|
||||||
|
together, or with the usual /give commands. To get a list of the actual
|
||||||
|
node names, just go into the homedecor/ folder and run the listnodes.sh
|
||||||
|
Bash script. Note that a few of the listed nodes are kinda useless by
|
||||||
|
themselves (like the various parts of the folding doors).
|
||||||
|
|
||||||
|
All of the images used for the recipes in the forum post tracking this
|
||||||
|
mod are included in the crafting-guide/ folder.
|
||||||
|
|
||||||
|
Most stuff can be made from materials found through a game world. Some
|
||||||
|
stuff can only be crafted by using materials from another mod (look for
|
||||||
|
the orange highlights). Currently, this mod can use materials from
|
||||||
|
moreores, mesecons, wool, and unifieddyes if present. You can still use
|
||||||
|
the usual /give commands to get the items that depend on these mods if
|
||||||
|
you don't use them installed.
|
||||||
|
|
||||||
|
This mod is still a work-in-progress, but should be complete enough not
|
||||||
|
to irritate anyone. :-) Namely, dressers still need to be fleshed out,
|
||||||
|
many items can be used as fuel but the burn times need tuning, and I
|
||||||
|
need to tune the cook time and fuel usage on the four smelted items.
|
||||||
|
|
||||||
|
This mod was put together using a recent git pull, and requires a
|
||||||
|
build/pull dated June 17, 2012 or later. Most stuff should work fine on
|
||||||
|
older builds as well, but a few nodes in this mod require Nodebox
|
||||||
|
support, a feature added to Minetest on that date. It will NOT work
|
||||||
|
with Minetest v0.3 (that version doesn't support mods).
|
||||||
|
|
||||||
|
Much of the code (especially for the doors) plus the bucket were taken
|
||||||
|
from the files which come with Minetest and altered to suit. Many
|
||||||
|
thanks to Jeija for coming up with an elegant cylinder using nodeboxes;
|
||||||
|
see his 'irregular' mods). His code is used herein (you can guess where
|
||||||
|
:-) ).
|
||||||
|
|
||||||
|
Dependencies: none (just the game's default stuff)
|
||||||
|
|
||||||
|
Recommends: buckets, flowers, unifieddyes, junglegrass, moreores,
|
||||||
|
mesecons, wool
|
||||||
|
|
||||||
|
The distribution archive also supplies a copy of Ironzorg's Flowers mod
|
||||||
|
and of my Unified Dyes mod, since this mod provides more stuff when
|
||||||
|
those two are present. You can remove these if you want - they're only
|
||||||
|
needed if you want to craft the various dyed/colored items.
|
|
@ -0,0 +1,90 @@
|
||||||
|
|
||||||
|
-- Test
|
||||||
|
|
||||||
|
|
||||||
|
local chaircolors = {
|
||||||
|
{ "black", "Black" },
|
||||||
|
{ "yellow", "Yellow" },
|
||||||
|
{ "red", "Red" },
|
||||||
|
{ "violet", "Violet" },
|
||||||
|
{ "blue", "Blue" },
|
||||||
|
{ "dark_green", "Dark Green" },
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in ipairs(chaircolors) do
|
||||||
|
color = chaircolors[i][1]
|
||||||
|
name = chaircolors[i][2]
|
||||||
|
minetest.register_node("poudlard:armchair_"..color, {
|
||||||
|
description = "Armchair ("..name..")",
|
||||||
|
tiles = {
|
||||||
|
"forniture_armchair_top_"..color..".png",
|
||||||
|
"forniture_armchair_top_"..color..".png",
|
||||||
|
"forniture_armchair_lat1_"..color..".png",
|
||||||
|
"forniture_armchair_lat1_"..color..".png",
|
||||||
|
"forniture_armchair_lat2_"..color..".png",
|
||||||
|
"forniture_armchair_lat2_"..color..".png",
|
||||||
|
},
|
||||||
|
drawtype = "nodebox",
|
||||||
|
sunlight_propagates = true,
|
||||||
|
paramtype = "light",
|
||||||
|
paramtype2 = "facedir",
|
||||||
|
node_box = {
|
||||||
|
type = "fixed",
|
||||||
|
fixed = {
|
||||||
|
{ -0.50, -0.50, -0.45, -0.30, 0.05, 0.30 },
|
||||||
|
{ -0.45, -0.50, -0.50, -0.35, 0.05, -0.45 },
|
||||||
|
{ -0.45, 0.05, -0.45, -0.35, 0.10, 0.15 },
|
||||||
|
{ 0.30, -0.50, -0.45, 0.50, 0.05, 0.30 },
|
||||||
|
{ 0.35, -0.50, -0.50, 0.45, 0.05, -0.45 },
|
||||||
|
{ 0.35, 0.05, -0.45, 0.45, 0.10, 0.15 },
|
||||||
|
{ -0.50, -0.50, 0.30, 0.50, 0.45, 0.50 },
|
||||||
|
{ -0.45, 0.45, 0.35, 0.45, 0.50, 0.45 },
|
||||||
|
{ -0.30, -0.45, -0.35, 0.30, -0.10, 0.30 },
|
||||||
|
{ -0.30, -0.45, -0.40, 0.30, -0.15, -0.35 },
|
||||||
|
{ -0.50, 0.05, 0.15, -0.30, 0.45, 0.30 },
|
||||||
|
{ -0.45, 0.10, 0.10, -0.35, 0.45, 0.15 },
|
||||||
|
{ -0.45, 0.45, 0.15, -0.35, 0.50, 0.35 },
|
||||||
|
{ 0.30, 0.05, 0.15, 0.50, 0.45, 0.30 },
|
||||||
|
{ 0.35, 0.10, 0.10, 0.45, 0.45, 0.15 },
|
||||||
|
{ 0.35, 0.45, 0.15, 0.45, 0.50, 0.35 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2},
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craft({
|
||||||
|
output = "poudlard:armchair_"..color.." 2",
|
||||||
|
recipe = {
|
||||||
|
{ "wool:"..color,""},
|
||||||
|
{ "default:wood","default:wood" },
|
||||||
|
{ "wool:"..color,"wool:"..color },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Aliases
|
||||||
|
|
||||||
|
minetest.register_alias("poudecor:armchair", "poudecor:armchair_black")
|
||||||
|
minetest.register_alias('armchair', 'poudlard:armchair')
|
||||||
|
|
||||||
|
-- Aliases for 3homedecor.
|
||||||
|
|
||||||
|
minetest.register_alias("homedecor:armchair_black", "poudecor:armchair_black")
|
||||||
|
minetest.register_alias("homedecor:armchair_yellow", "poudecor:armchair_yellow")
|
||||||
|
minetest.register_alias("homedecor:armchair_violet", "poudecor:armchair_violet")
|
||||||
|
minetest.register_alias("homedecor:armchair_red", "poudecor:armchair_red")
|
||||||
|
minetest.register_alias("homedecor:armchair_dark_green", "poudecor:armchair_dark_green")
|
||||||
|
minetest.register_alias("homedecor:armchair_blue", "poudecor:armchair_blue")
|
||||||
|
|
||||||
|
-- Aliases for poudlard
|
||||||
|
minetest.register_alias("poudecor:armchair_black", "poudlard:armchair_black")
|
||||||
|
minetest.register_alias("poudecor:armchair_yellow", "poudlard:armchair_yellow")
|
||||||
|
minetest.register_alias("poudecor:armchair_violet", "poudlard:armchair_violet")
|
||||||
|
minetest.register_alias("poudecor:armchair_red", "poudlard:armchair_red")
|
||||||
|
minetest.register_alias("poudecor:armchair_dark_green", "poudlard:armchair_dark_green")
|
||||||
|
minetest.register_alias("poudecor:armchair_blue", "poudlard:armchair_blue")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
Very light version of "homedecor" by Perlipop + raccordable images for curtains
|
||||||
|
Most code and all textures by Vanessa Ezekowitz.
|
||||||
|
|
||||||
|
|
||||||
|
Some code copied and modified from the game's default mods (especially
|
||||||
|
doors) and ironzorg's flowers mod.
|
||||||
|
|
||||||
|
Licenses: For the lua code, GPL. For all images and everything else, WTFPL.
|
|
@ -0,0 +1,102 @@
|
||||||
|
-- Crafting for homedecor mod (includes folding) by Vanessa Ezekowitz
|
||||||
|
-- 2012-06-12
|
||||||
|
--
|
||||||
|
-- Mostly my own code; overall template borrowed from game default
|
||||||
|
--
|
||||||
|
-- License: GPL
|
||||||
|
--
|
||||||
|
|
||||||
|
-- Load translation library if intllib is installed
|
||||||
|
|
||||||
|
local S
|
||||||
|
if (minetest.get_modpath("intllib")) then
|
||||||
|
dofile(minetest.get_modpath("intllib").."/intllib.lua")
|
||||||
|
S = intllib.Getter(minetest.get_current_modname())
|
||||||
|
else
|
||||||
|
S = function ( s ) return s end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- Nightstand -----------------------------
|
||||||
|
|
||||||
|
minetest.register_craft( {
|
||||||
|
output = "poudlard:nightstand_1",
|
||||||
|
recipe = {
|
||||||
|
{ "moreblocks:emptybookshelf" },
|
||||||
|
{ "moreblocks:emptybookshelf" },
|
||||||
|
{ "default:wood" },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_craft({
|
||||||
|
type = "fuel",
|
||||||
|
recipe = "poudlard:nightstand_1",
|
||||||
|
burntime = 30,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_craft( {
|
||||||
|
type = "shapeless",
|
||||||
|
output = "poudlard:nightstand_2",
|
||||||
|
recipe = {
|
||||||
|
"moreblocks:emptybookshelf",
|
||||||
|
"moreblocks:emptybookshelf",
|
||||||
|
"default:junglewood",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craft({
|
||||||
|
type = "fuel",
|
||||||
|
recipe = "poudlard:nightstand_2",
|
||||||
|
burntime = 30,
|
||||||
|
})
|
||||||
|
--
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- Curtains ---------------------------------
|
||||||
|
|
||||||
|
local curtaincolors = {
|
||||||
|
"red",
|
||||||
|
"orange",
|
||||||
|
"green",
|
||||||
|
"dark_green",
|
||||||
|
"yellow",
|
||||||
|
"blue",
|
||||||
|
"white",
|
||||||
|
"dark_grey",
|
||||||
|
"black",
|
||||||
|
"violet"
|
||||||
|
}
|
||||||
|
|
||||||
|
for c in ipairs(curtaincolors) do
|
||||||
|
local color = curtaincolors[c]
|
||||||
|
minetest.register_craft( {
|
||||||
|
output = "poudlard:curtain_"..color.." 3",
|
||||||
|
recipe = {
|
||||||
|
{ "wool:"..color, "", ""},
|
||||||
|
{ "wool:"..color, "", ""},
|
||||||
|
{ "wool:"..color, "", ""},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
|
||||||
|
--
|
||||||
|
|
||||||
|
--
|
||||||
|
--
|
||||||
|
--
|
||||||
|
|
||||||
|
--
|
||||||
|
|
||||||
|
--
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
-- Various misc. nodes
|
||||||
|
|
||||||
|
-- Load translation library if intllib is installed
|
||||||
|
|
||||||
|
local S
|
||||||
|
if (minetest.get_modpath("intllib")) then
|
||||||
|
dofile(minetest.get_modpath("intllib").."/intllib.lua")
|
||||||
|
S = intllib.Getter(minetest.get_current_modname())
|
||||||
|
else
|
||||||
|
S = function ( s ) return s end
|
||||||
|
end
|
||||||
|
|
||||||
|
--
|
||||||
|
|
||||||
|
local curtaincolors = {
|
||||||
|
"red",
|
||||||
|
"green",
|
||||||
|
"blue",
|
||||||
|
"white",
|
||||||
|
"orange",
|
||||||
|
"dark_green",
|
||||||
|
"yellow",
|
||||||
|
"dark_grey",
|
||||||
|
"black",
|
||||||
|
"violet"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for c in ipairs(curtaincolors) do
|
||||||
|
local color = curtaincolors[c]
|
||||||
|
local color_d = S(curtaincolors[c])
|
||||||
|
|
||||||
|
minetest.register_node("poudlard:curtain_"..color, {
|
||||||
|
description = S("Curtains (%s)"):format(color_d),
|
||||||
|
tiles = { "homedecor_curtain_"..color..".png" },
|
||||||
|
inventory_image = "homedecor_curtain_"..color..".png",
|
||||||
|
wield_image = "homedecor_curtain_"..color..".png",
|
||||||
|
drawtype = 'signlike',
|
||||||
|
sunlight_propagates = true,
|
||||||
|
paramtype = "light",
|
||||||
|
paramtype2 = "facedir",
|
||||||
|
walkable = false,
|
||||||
|
groups = { snappy = 3 },
|
||||||
|
sounds = default.node_sound_leaves_defaults(),
|
||||||
|
paramtype2 = 'wallmounted',
|
||||||
|
selection_box = {
|
||||||
|
type = "wallmounted",
|
||||||
|
--wall_side = = <default>
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if color_d ~= color then
|
||||||
|
minetest.register_alias("poudlard:curtain_"..color_d, "poudlard:curtain_"..color)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-------------- Alias for homedecor
|
||||||
|
|
||||||
|
minetest.register_alias("homedecor:curtain_yellow", "poudecor:curtain_yellow")
|
||||||
|
minetest.register_alias("homedecor:curtain_violet", "poudecor:curtain_violet")
|
||||||
|
minetest.register_alias("homedecor:curtain_red", "poudecor:curtain_red")
|
||||||
|
minetest.register_alias("homedecor:curtain_dark_green", "poudecor:curtain_dark_green")
|
||||||
|
minetest.register_alias("homedecor:curtain_green", "poudecor:curtain_green")
|
||||||
|
minetest.register_alias("homedecor:curtain_blue", "poudecor:curtain_blue")
|
||||||
|
minetest.register_alias("homedecor:curtain_white", "poudecor:curtain_white")
|
||||||
|
minetest.register_alias("homedecor:curtain_orange", "poudecor:curtain_orange")
|
||||||
|
minetest.register_alias("homedecor:curtain_dark_grey", "poudecor:curtain_dark_grey")
|
||||||
|
minetest.register_alias("homedecor:curtain_black", "poudecor:curtain_black")
|
||||||
|
|
||||||
|
-------------- Alias for poudecort
|
||||||
|
|
||||||
|
minetest.register_alias("poudecor:curtain_yellow", "poudlard:curtain_yellow")
|
||||||
|
minetest.register_alias("poudecor:curtain_violet", "poudlard:curtain_violet")
|
||||||
|
minetest.register_alias("poudecor:curtain_red", "poudlard:curtain_red")
|
||||||
|
minetest.register_alias("poudecor:curtain_dark_green", "poudlard:curtain_dark_green")
|
||||||
|
minetest.register_alias("poudecor:curtain_green", "poudlard:curtain_green")
|
||||||
|
minetest.register_alias("poudecor:curtain_blue", "poudlard:curtain_blue")
|
||||||
|
minetest.register_alias("poudecor:curtain_white", "poudlard:curtain_white")
|
||||||
|
minetest.register_alias("poudecor:curtain_orange", "poudlard:curtain_orange")
|
||||||
|
minetest.register_alias("poudecor:curtain_dark_grey", "poudlard:curtain_dark_grey")
|
||||||
|
minetest.register_alias("poudecor:curtain_black", "poudlard:curtain_black")
|
|
@ -0,0 +1,15 @@
|
||||||
|
|
||||||
|
minetest.register_craft({
|
||||||
|
type = "fuel",
|
||||||
|
recipe = "poudlard:armchair",
|
||||||
|
burntime = 30,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_craft({
|
||||||
|
output = "poudlard:torch_wall 10",
|
||||||
|
recipe = {
|
||||||
|
{ "default:coal_lump" },
|
||||||
|
{ "default:steel_ingot" },
|
||||||
|
},
|
||||||
|
})
|
|
@ -0,0 +1,13 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
echo "Node listing as of "`date` > nodes.txt
|
||||||
|
|
||||||
|
for i in *.lua; do
|
||||||
|
echo -e "\nIn $i:\n" >> nodes.txt
|
||||||
|
cat $i | grep "minetest.register_node(" | \
|
||||||
|
sed "s/minetest.register_node(.homedecor:/homedecor:/; s/., {//" | \
|
||||||
|
sort >> nodes.txt
|
||||||
|
done
|
||||||
|
|
||||||
|
less nodes.txt
|
||||||
|
rm -f nodes.txt
|
|
@ -0,0 +1,194 @@
|
||||||
|
|
||||||
|
#
|
||||||
|
# Language: Español
|
||||||
|
# Author: Diego Martínez <lkaezadl3@gmail.com>
|
||||||
|
#
|
||||||
|
|
||||||
|
### kitchen_cabinet.lua ###
|
||||||
|
Kitchen Cabinet = Gabinete de Cocina
|
||||||
|
## 1: Player name, 2: position
|
||||||
|
%s moves stuff in kitchen cabinet at %s = %s mueve cosas en gabinete de cocina en %s
|
||||||
|
%s moves stuff to kitchen cabinet at %s = %s mueve cosas al gabinete de cocina en %s
|
||||||
|
%s takes stuff from kitchen cabinet at %s = %s toma cosas del gabinete de cocina en %s
|
||||||
|
Half-height Kitchen Cabinet (on ceiling) = Gabinete de cocina de media altura (en techo)
|
||||||
|
Under-sink cabinet = Gabinete con Lavabo
|
||||||
|
Kitchen Cabinet with sink = Gabinete de cocina con lavabo
|
||||||
|
|
||||||
|
### door_models.lua ###
|
||||||
|
Mahogany Closet Door = Puerta de Armario de Caoba
|
||||||
|
Oak Closet Door = Puerta de Armario de Roble
|
||||||
|
Fancy Wood/Glass Door = Puerta de Madera y Cristal de Lujo
|
||||||
|
Glass Office Door = Puerta de Oficina de Cristal
|
||||||
|
Glass and Wood, Mahogany-colored = Cristal y Madera, color Caoba
|
||||||
|
Glass and Wood, Oak-colored = Cristal y Madera, color Roble
|
||||||
|
Glass and Wood, White = Cristal y Madera, color Blanco
|
||||||
|
Plain Wooden Door = Puerta Simple de Madera
|
||||||
|
left = izquierda
|
||||||
|
right = derecha
|
||||||
|
## 1: Side the doors opens to
|
||||||
|
(Top Half, %s-opening) = (Parte Superior, abre a la %s)
|
||||||
|
(%s-opening) = (abre a la %s)
|
||||||
|
|
||||||
|
### door_nodes.lua ###
|
||||||
|
Not enough vertical space to place a door! = ¡No hay suficiente espacio vertical para colocar una puerta!
|
||||||
|
|
||||||
|
### crafts.lua ###
|
||||||
|
Brass Ingot = Lingote de Latón
|
||||||
|
Bucket of white paint = Cubo de Pintura Blanca
|
||||||
|
Legs for Small Utility table = Patas de Mesa Utilitaria Pequeña
|
||||||
|
Plastic sheet = Lámina de Plástico
|
||||||
|
Silicon lump = Terrón de Silicio
|
||||||
|
Simple Integrated Circuit = Circuito Integrado Simple
|
||||||
|
Small Wooden Drawer = Cajón Pequeño de Madera
|
||||||
|
Terracotta Roof Tile = Teja de Terracota
|
||||||
|
Titanium Dioxide = Dióxido de Titanio
|
||||||
|
Uncooked Terracotta Base = Base de Terracota sin Cocer
|
||||||
|
Unprocessed Plastic base = Base de Plástico sin Procesar
|
||||||
|
|
||||||
|
### fences.lua ###
|
||||||
|
Barbed Wire Fence = Cerca de Alambre de Púas
|
||||||
|
Barbed Wire Fence Gate = Portón de Cerca de Alambre de Púas
|
||||||
|
Brass Fence/railing = Cerca/Barandilla de Latón
|
||||||
|
Brass Fence/railing with sign = Cerca/Barandilla de Latón con Letrero
|
||||||
|
Chainlink Fence = Cerca de Cadenas
|
||||||
|
Chainlink Fence Gate = Portón de Cerca de Cadenas
|
||||||
|
Chainlink Fence Gate (open) = Portón de Cerca de Cadenas (Abierto)
|
||||||
|
Unpainted Picket Fence = Cerca de Piquete sin pintar
|
||||||
|
Unpainted Picket Fence Gate = Portón de Cerca de Piquete sin pintar
|
||||||
|
White Picket Fence = Cerca de Piquete blanca
|
||||||
|
White Picket Fence Gate = Portón de Cerca de Piquete blanca
|
||||||
|
Wooden Privacy Fence = Cerca privada de madera
|
||||||
|
Wrought Iron Fence/railing = Cerca/Barandilla de Hierro Forjado
|
||||||
|
Wrought Iron Fence/railing with sign = Cerca/Barandilla de Hierro Forjado con Letrero
|
||||||
|
want to simply place the wielded item like usual. = solo se desea colocar el objeto empuñado normalmente.
|
||||||
|
|
||||||
|
### furniture_medieval.lua ###
|
||||||
|
Bars = Barras
|
||||||
|
Binding Bars = Barras de Unión
|
||||||
|
Chains = Cadenas
|
||||||
|
Wall Torch = Antorcha de Pared
|
||||||
|
|
||||||
|
### furniture_bathroom.lua ###
|
||||||
|
Toilet = Inodoro
|
||||||
|
Sink = Lavabo
|
||||||
|
Taps = Grifo
|
||||||
|
Shower Tray = Piso de Ducha
|
||||||
|
Shower Head = Ducha
|
||||||
|
|
||||||
|
### init.lua ###
|
||||||
|
Loaded! = ¡Cargado!
|
||||||
|
Asphalt Shingles = Tejas de Asfalto
|
||||||
|
Black Plastic Flower Pot = Florero de Plástico Negro
|
||||||
|
Brass Pole = Poste de Latón
|
||||||
|
Brass Table Legs = Patas de Mesa de Latón
|
||||||
|
red = rojas
|
||||||
|
green = verdes
|
||||||
|
blue = azules
|
||||||
|
white = blancas
|
||||||
|
pink = rosas
|
||||||
|
violet = violetas
|
||||||
|
## 1: Color name
|
||||||
|
Curtains (%s) = Cortinas (%s)
|
||||||
|
Drop-Ceiling Tile = Cielorraso
|
||||||
|
Glass Skylight = Claraboya de Cristal
|
||||||
|
Glass Table (Small, Round) = Mesa de Cristal (Pequeña, Redonda)
|
||||||
|
Glass Table (Small, Square) = Mesa de Cristal (Pequeña, Cuadrada)
|
||||||
|
Green Plastic Flower Pot = Florero de Plástico Negro
|
||||||
|
Large Area Rug = Manta Grande
|
||||||
|
Large Glass Table Piece = Pieza de Mesa de Cristal Grande
|
||||||
|
Large Stereo Speaker = Altavoz de Estéreo Grande
|
||||||
|
Legs for Utility Table = Patas de Mesa Utilitaria
|
||||||
|
Projection Screen Material = Material de Pantalla de Proyección
|
||||||
|
Small Surround Speaker = Pequeño Altavoz Envolvente
|
||||||
|
Small Throw Rug = Manta Pequeña
|
||||||
|
Stereo Receiver = Receptor Estéreo
|
||||||
|
Terracotta Flower Pot = Florero de Terracota
|
||||||
|
Terracotta Roofing = Tejado de Terracota
|
||||||
|
Textured Ceiling Paint = Pintura Texturada para Techo
|
||||||
|
Utility Table = Mesa Utilitaria
|
||||||
|
Utility table mk2 = Mesa Utilitaria mk2
|
||||||
|
Wooden Shutter (Black) = Obturador de Madera (Negro)
|
||||||
|
Wooden Shutter (Dark Grey) = Obturador de Madera (Gris Oscuro)
|
||||||
|
Wooden Shutter (Forest Green) = Obturador de Madera (Verde Bosque)
|
||||||
|
Wooden Shutter (Grey) = Obturador de Madera (Gris)
|
||||||
|
Wooden Shutter (Light Blue) = Obturador de Madera (Azul Claro)
|
||||||
|
Wooden Shutter (Purple) = Obturador de Madera (Púrpura)
|
||||||
|
Wooden Shutter (Red) = Obturador de Madera (Rojo)
|
||||||
|
Wooden Shutter (Unpainted Mahogany) = Obturador de Madera (Caoba sin Pintar)
|
||||||
|
Wooden Shutter (Unpainted Oak) = Obturador de Madera (Roble sin Pintar)
|
||||||
|
Wooden Shutter (White) = Obturador de Madera (Blanco)
|
||||||
|
Wooden Shutter (Yellow) = Obturador de Madera (Amarillo)
|
||||||
|
Wooden Tabletop piece = Pieza de Mesa de Madera
|
||||||
|
Wooden Tabletop (Small, Round) = Pieza de Mesa de Madera (Pequeña, Redonda)
|
||||||
|
Wooden Tabletop (Small, Square) = Pieza de Mesa de Madera (Pequeña, Cuadrada)
|
||||||
|
Wood Shingles = Tejas de Madera
|
||||||
|
Wrought Iron Pole = Poste de Hierro Forjado
|
||||||
|
someone = alguien
|
||||||
|
## 1: Player name
|
||||||
|
Sorry, %s owns that spot. = Lo siento, %s es dueño de ése lugar.
|
||||||
|
|
||||||
|
### lighting.lua ###
|
||||||
|
White Glowlight (small cube) = Luz Blanca (cubo pequeño)
|
||||||
|
White Glowlight (small cube, on ceiling) = Luz Blanca (cubo pequeño, en techo)
|
||||||
|
White Glowlight (thick) = Luz Blanca (Gruesa)
|
||||||
|
White Glowlight (thick, on wall) = Luz Blanca (Gruesa, en pared)
|
||||||
|
White Glowlight (thin) = Luz Blanca (Fina)
|
||||||
|
White Glowlight (thin, on wall) = Luz Blanca (Fina, en pared)
|
||||||
|
Yellow Glowlight (small cube) = Luz Amarilla (cubo pequeño)
|
||||||
|
Yellow Glowlight (small cube, on ceiling) = Luz Amarilla (cubo pequeño, en techo)
|
||||||
|
Yellow Glowlight (thick) = Luz Amarilla (Gruesa)
|
||||||
|
Yellow Glowlight (thick, on wall) = Luz Amarilla (Gruesa, en pared)
|
||||||
|
Yellow Glowlight (thin) = Luz Amarilla (Fina)
|
||||||
|
Yellow Glowlight (thin, on wall) = Luz Amarilla (Fina, en pared)
|
||||||
|
|
||||||
|
### locked.lua ###
|
||||||
|
## 1: Item description, 2: Owner name
|
||||||
|
%s (owned by %s) = %s (propiedad de %s)
|
||||||
|
## 1: Player name, 2: Item description, 3: Owner name, 4: Position
|
||||||
|
%s tried to access a %s belonging to %s at %s = %s ha intentado acceder un(a) %s propiedad de %s en %s
|
||||||
|
## 1: Item description
|
||||||
|
%s (Locked) = %s (Cerrado)
|
||||||
|
Locked Cabinet = Gabinete Cerrado
|
||||||
|
Locked Nightstand = Mesa de Noche Cerrada
|
||||||
|
Locked Fridge = Refri Cerrado
|
||||||
|
Locked Oven = Estufa Cerrada
|
||||||
|
|
||||||
|
### nightstands.lua ###
|
||||||
|
Mahogany Nightstand with One Drawer = Mesa de Noche de Caoba, un Cajón
|
||||||
|
Mahogany Nightstand with Two Drawers = Mesa de Noche de Caoba, dos Cajones
|
||||||
|
Oak Nightstand with One Drawer = Mesa de Noche de Roble, un Cajón
|
||||||
|
Oak Nightstand with Two Drawers = Mesa de Noche de Roble, dos Cajones
|
||||||
|
## 1: Player name, 2: position
|
||||||
|
%s moves stuff in nightstand at %s = %s mueve cosas en mesa de noche en %s
|
||||||
|
%s moves stuff to nightstand at %s = %s mueve cosas hacia mesa de noche en %s
|
||||||
|
%s takes stuff from nightstand at %s = %s mueve cosas desde mesa de noche en %s
|
||||||
|
One-drawer Nightstand = Mesa de Noche de un Cajón
|
||||||
|
Two-drawer Nightstand = Mesa de Noche de dos Cajones
|
||||||
|
|
||||||
|
### oven.lua ###
|
||||||
|
Oven = Estufa
|
||||||
|
## 1: Item name
|
||||||
|
Could not insert '%s' = No se pudo insertar '%s'
|
||||||
|
## 1: Percentage
|
||||||
|
Oven active: %d%% = Estufa activa: %d%%
|
||||||
|
Oven out of fuel = Estufa sin combustible
|
||||||
|
Oven is empty = Estufavacía
|
||||||
|
|
||||||
|
### refrigerator.lua ###
|
||||||
|
Refrigerator = Refrigerador
|
||||||
|
## 1: Player name, 2: position
|
||||||
|
%s moves stuff in refrigerator at %s = %s mueve cosas en refrigerador en %s
|
||||||
|
%s moves stuff to refrigerator at %s = %s mueve cosas hacia refrigerador en %s
|
||||||
|
%s takes stuff from refrigerator at %s = %s mueve cosas desde refrigerador en %s
|
||||||
|
Not enough vertical space to place a refrigerator! = ¡No hay suficiente espacio vertical para colocar un refrigerador!
|
||||||
|
|
||||||
|
### television.lua ###
|
||||||
|
Small CRT Television = Pequeña Televisión CRT
|
||||||
|
|
||||||
|
### signs_lib.lua ###
|
||||||
|
%s wrote "%s" to sign at %s = %s ha escrito "%s" en el letrero en %s
|
||||||
|
Reading cached character database. = Leyendo base de datos de catacteres.
|
||||||
|
Font seems to have changed. Rebuilding cache. = La fuente parece haber cambiado. Reconstruyendo información guardada.
|
||||||
|
Could not find font line height in cached DB. Trying brute force. = No se pudo encontrar la altura de línea en la base de datos. Intentando con fuerza bruta.
|
||||||
|
Registered %s and %s = Registrados %s y %s
|
||||||
|
signs loaded = letreros cargados
|
|
@ -0,0 +1,180 @@
|
||||||
|
|
||||||
|
#
|
||||||
|
# Language: Français
|
||||||
|
# Author: Calinou
|
||||||
|
#
|
||||||
|
|
||||||
|
### kitchen_cabinet.lua ###
|
||||||
|
Kitchen Cabinet = Meuble de cuisine
|
||||||
|
## 1: Player name, 2: position
|
||||||
|
%s moves stuff in kitchen cabinet at %s = %s déplace des objets dans un meuble de cuisine à %s
|
||||||
|
%s moves stuff to kitchen cabinet at %s = %s édplace des objets vers un meuble de cuisine à %s
|
||||||
|
%s takes stuff from kitchen cabinet at %s = %s prend des objets d'un meuble de cuisine à %s
|
||||||
|
Half-height Kitchen Cabinet (on ceiling) = Meuble de cuisine réduit en hauteur (sur le plafond)
|
||||||
|
Under-sink cabinet = Meuble sous évier
|
||||||
|
Kitchen Cabinet with sink = Meuble de cuisine avec lavabo
|
||||||
|
|
||||||
|
### door_models.lua ###
|
||||||
|
Mahogany Closet Door = Porte en bois d'acajou
|
||||||
|
Oak Closet Door = Porte en bois de chêne
|
||||||
|
Fancy Wood/Glass Door = Porte artistique en bois et verre
|
||||||
|
Glass Office Door = Porte en verre
|
||||||
|
Glass and Wood, Mahogany-colored = Porte couleur acajou en bois et verre
|
||||||
|
Glass and Wood, Oak-colored = Porte couleur chêne en bois et verre
|
||||||
|
Glass and Wood, White = Porte blanche en bois et verre
|
||||||
|
Plain Wooden Door = Porte en bois simple
|
||||||
|
left = gauche
|
||||||
|
right = droite
|
||||||
|
## 1: Side the doors opens to
|
||||||
|
(Top Half, %s-opening) = (partie supérieur, charnière à %s)
|
||||||
|
(%s-opening) = (charnière à %s)
|
||||||
|
|
||||||
|
### door_nodes.lua ###
|
||||||
|
Not enough vertical space to place a door! = Pas assez d'espace vertical pour placer une porte !
|
||||||
|
|
||||||
|
### crafts.lua ###
|
||||||
|
Brass Ingot = Lingot de laiton
|
||||||
|
Bucket of white paint = Seau de peinture blanche
|
||||||
|
Legs for Small Utility table = Pieds pour table basse
|
||||||
|
Plastic sheet = Bout de plastique
|
||||||
|
Silicon lump = Silicone
|
||||||
|
Simple Integrated Circuit = Circuit intégré simple
|
||||||
|
Small Wooden Drawer = Petit tiroir en bois
|
||||||
|
Terracotta Roof Tile = Tuile de toit en terre cuite
|
||||||
|
Titanium Dioxide = Dioxide de titane
|
||||||
|
Uncooked Terracotta Base = Base de terre non cuite
|
||||||
|
Unprocessed Plastic base = Base de plastique non transformée
|
||||||
|
|
||||||
|
### fences.lua ###
|
||||||
|
Barbed Wire Fence = Barrière en fil barbelé
|
||||||
|
Barbed Wire Fence Gate = Porte de barrière en fil barbelé
|
||||||
|
Brass Fence/railing = Barrière en laiton
|
||||||
|
Brass Fence/railing with sign = Barrière en laiton avec pancarte
|
||||||
|
Chainlink Fence = Grillage
|
||||||
|
Chainlink Fence Gate = Porte de grillage
|
||||||
|
Chainlink Fence Gate (open) = Porte de grillage (ouverte)
|
||||||
|
Unpainted Picket Fence = Barrière en piquets non peinte
|
||||||
|
Unpainted Picket Fence Gate = Porte de barrière en piquets non peinte
|
||||||
|
White Picket Fence = Barrière en piquets blanche
|
||||||
|
White Picket Fence Gate = Porte de barrière en piquets blanche
|
||||||
|
Wooden Privacy Fence = Barrière en bois
|
||||||
|
Wrought Iron Fence/railing = Barrière en fer forgé
|
||||||
|
Wrought Iron Fence/railing with sign = Barrière en fer forgé avec pancarte
|
||||||
|
want to simply place the wielded item like usual. = veut simplement placer l'objet comme d'habitude.
|
||||||
|
|
||||||
|
### init.lua ###
|
||||||
|
Loaded! = Chargé !
|
||||||
|
Asphalt Shingles = Bardeaux d'asphalte
|
||||||
|
Black Plastic Flower Pot = Pot de fleur en plastique noir
|
||||||
|
Brass Pole = Barre en laiton
|
||||||
|
Brass Table Legs = Pieds de table en laiton
|
||||||
|
red = rouges
|
||||||
|
green = vertes
|
||||||
|
blue = bleues
|
||||||
|
white = blanches
|
||||||
|
pink = roses
|
||||||
|
violet = violettes
|
||||||
|
## 1: Color name
|
||||||
|
Curtains (%s) = Volets (%s)
|
||||||
|
Drop-Ceiling Tile = Dalle suspendue au plafond
|
||||||
|
Glass Skylight = Verre
|
||||||
|
Glass Table (Small, Round) = Table en verre (petite, ronde)
|
||||||
|
Glass Table (Small, Square) = Table en verre (petite, carrée)
|
||||||
|
Green Plastic Flower Pot = Pot de fleur en plastique vert
|
||||||
|
Large Area Rug = Grande couverture
|
||||||
|
Large Glass Table Piece = Grand bout de verre de table
|
||||||
|
Large Stereo Speaker = Grand haut-parleur stéréo
|
||||||
|
Legs for Utility Table = Pieds pour table basse
|
||||||
|
Projection Screen Material = Matériel pour projecteur
|
||||||
|
Small Surround Speaker = Petit haut-parleur surround
|
||||||
|
Small Throw Rug = Petite couverture
|
||||||
|
Stereo Receiver = Récepteur stéréo
|
||||||
|
Terracotta Flower Pot = Pot de fleur en terre cuite
|
||||||
|
Terracotta Roofing = Tuile en terre cuite
|
||||||
|
Textured Ceiling Paint = Papier peint avec motif pour plafond
|
||||||
|
Utility Table = Table basse
|
||||||
|
Utility table mk2 = Table basse MK2
|
||||||
|
Wooden Shutter (Black) = Volet en bois (noir)
|
||||||
|
Wooden Shutter (Dark Grey) = Volet en bois (gris foncé)
|
||||||
|
Wooden Shutter (Forest Green) = Volet en bois (vert foncé)
|
||||||
|
Wooden Shutter (Grey) = Volet en bois (gris)
|
||||||
|
Wooden Shutter (Light Blue) = Volet en bois (bleu clair)
|
||||||
|
Wooden Shutter (Purple) = Volet en bois (violet)
|
||||||
|
Wooden Shutter (Red) = Volet en bois (rouge)
|
||||||
|
Wooden Shutter (Unpainted Mahogany) = Volet en bois (acajou non peint)
|
||||||
|
Wooden Shutter (Unpainted Oak) = Volet en bois (chêne non peint)
|
||||||
|
Wooden Shutter (White) = Volet en bois (blanc)
|
||||||
|
Wooden Shutter (Yellow) = Volet en bois (jaune)
|
||||||
|
Wooden Tabletop piece = Bout de dessus de table
|
||||||
|
Wooden Tabletop (Small, Round) = Dessus de table (petit, rond)
|
||||||
|
Wooden Tabletop (Small, Square) = Dessus de table (petit, carré)
|
||||||
|
Wood Shingles = Bardeaux de bois
|
||||||
|
Wrought Iron Pole = Barre de fer forgé
|
||||||
|
someone = quelqu'un
|
||||||
|
## 1: Player name
|
||||||
|
Sorry, %s owns that spot. = Désolé, %s est propriétaire de cette zone.
|
||||||
|
|
||||||
|
### lighting.lua ###
|
||||||
|
White Glowlight (small cube) = Lampe blanche (petit cube)
|
||||||
|
White Glowlight (small cube, on ceiling) = Lampe blanche (petit cube, sur le plafond)
|
||||||
|
White Glowlight (thick) = Lampe blanche (épaisse)
|
||||||
|
White Glowlight (thick, on wall) = Lampe blanche (épaisse, sur le mur)
|
||||||
|
White Glowlight (thin) = Lampe blanche (fine)
|
||||||
|
White Glowlight (thin, on wall) = Lampe blanche (fine, sur le mur)
|
||||||
|
Yellow Glowlight (small cube) = Lampe jaune (petit cube)
|
||||||
|
Yellow Glowlight (small cube, on ceiling) = Lampe jaune (petit cube, sur le plafond)
|
||||||
|
Yellow Glowlight (thick) = Lampe jaune (épaisse)
|
||||||
|
Yellow Glowlight (thick, on wall) = Lampe jaune (épaisse, sur le mur)
|
||||||
|
Yellow Glowlight (thin) = Lampe jaune (fine)
|
||||||
|
Yellow Glowlight (thin, on wall) = Lampe jaune (fine, sur le mur)
|
||||||
|
|
||||||
|
### locked.lua ###
|
||||||
|
## 1: Item description, 2: Owner name
|
||||||
|
%s (owned by %s) = %s (propriété de %s)
|
||||||
|
## 1: Player name, 2: Item description, 3: Owner name, 4: Position
|
||||||
|
%s tried to access a %s belonging to %s at %s = %s a essayé d'accéder à %s qui est propriété de %s à %s
|
||||||
|
## 1: Item description
|
||||||
|
%s (Locked) = %s (verrouillé)
|
||||||
|
Locked Cabinet = Meuble verrouillé
|
||||||
|
Locked Nightstand = Table de chevet verrouillée
|
||||||
|
Locked Fridge = Réfrégirateur verrouillé
|
||||||
|
Locked Oven = Four verrouillé
|
||||||
|
|
||||||
|
### nightstands.lua ###
|
||||||
|
Mahogany Nightstand with One Drawer = Table de chevet en acajou avec un tiroir
|
||||||
|
Mahogany Nightstand with Two Drawers = Table de chevet en acajou avec deux tiroirs
|
||||||
|
Oak Nightstand with One Drawer = Table de chevet en chêne avec un tiroir
|
||||||
|
Oak Nightstand with Two Drawers = Table de chevet en chêne avec deux tiroirs
|
||||||
|
## 1: Player name, 2: position
|
||||||
|
%s moves stuff in nightstand at %s = %s déplace des objets dans une table de chevet à %s
|
||||||
|
%s moves stuff to nightstand at %s = %s déplace des objets vers une table de chevet à %s
|
||||||
|
%s takes stuff from nightstand at %s = %s prend des objets d'une table de chevet à %s
|
||||||
|
One-drawer Nightstand = Table de chevet avec un tiroir
|
||||||
|
Two-drawer Nightstand = Table de chevet avec deux tiroirs
|
||||||
|
|
||||||
|
### oven.lua ###
|
||||||
|
Oven = Four
|
||||||
|
## 1: Item name
|
||||||
|
Could not insert '%s' = Ne peut insérer '%s'
|
||||||
|
## 1: Percentage
|
||||||
|
Oven active: %d%% = Four actif : %d%%
|
||||||
|
Oven out of fuel = Four sans carburant
|
||||||
|
Oven is empty = Four vide
|
||||||
|
|
||||||
|
### refrigerator.lua ###
|
||||||
|
Refrigerator = Réfrégirateur
|
||||||
|
## 1: Player name, 2: position
|
||||||
|
%s moves stuff in refrigerator at %s = %s déplace des objets dans un réfrégirateur à %s
|
||||||
|
%s moves stuff to refrigerator at %s = %s déplace des objets vers un réfrégirateur à %s
|
||||||
|
%s takes stuff from refrigerator at %s = %s prend des objets d'un réfrégirateur à %s
|
||||||
|
Not enough vertical space to place a refrigerator! = Pas assez d'espace vertical pour placer un réfrégirateur !
|
||||||
|
|
||||||
|
### television.lua ###
|
||||||
|
Small CRT Television = Petite télévision à tube cathodique
|
||||||
|
|
||||||
|
### signs_lib.lua ###
|
||||||
|
E: character map file not found = E: fichier de table de caractère non trouvé
|
||||||
|
## 1: Full String, 2: pos in string, 3: current char at pos
|
||||||
|
W: unknown symbol in '%s' at %d (probably %s) = A: symbole inconnu dans '%s' dans %d (probablement %s)
|
||||||
|
%s wrote "%s" to sign at %s =
|
||||||
|
signs loaded =
|
|
@ -0,0 +1,198 @@
|
||||||
|
|
||||||
|
# Brazilian Portuguese translation of homedecor
|
||||||
|
# Last update: 2013/11/10
|
||||||
|
# Last translator: Aracnus <frederico@teia.bio.br>
|
||||||
|
|
||||||
|
### Special strings ###
|
||||||
|
|
||||||
|
### kitchen_cabinet.lua ###
|
||||||
|
Kitchen Cabinet = Armário de cozinha
|
||||||
|
## 1: Player name, 2: position
|
||||||
|
%s moves stuff in kitchen cabinet at %s = %s moveu itens no armário de cozinha em %s
|
||||||
|
%s moves stuff to kitchen cabinet at %s = %s moveu itens para o armário de cozinha em %s
|
||||||
|
%s takes stuff from kitchen cabinet at %s = %s retirou itens do armário de cozinha em %s
|
||||||
|
Half-height Kitchen Cabinet (on ceiling) = Meio armário de cozinha (no teto)
|
||||||
|
Under-sink cabinet = Armário sob a pia
|
||||||
|
Kitchen Cabinet with sink = Armário de cozinha com pia
|
||||||
|
|
||||||
|
### door_models.lua ###
|
||||||
|
Mahogany Closet Door = Porta do armário de mogno
|
||||||
|
Oak Closet Door = Porta do armário de carvalho
|
||||||
|
Fancy Wood/Glass Door = Porta de madeira/vidro trabalhada
|
||||||
|
Glass Office Door = Porta de escritório de vidro
|
||||||
|
Glass and Wood, Mahogany-colored = Vidro e madeira (mogno)
|
||||||
|
Glass and Wood, Oak-colored = Vidro e madeira (carvalho)
|
||||||
|
Glass and Wood, White = Vidro e madeira (branca)
|
||||||
|
Plain Wooden Door = Porta de madeira simples
|
||||||
|
left = esquerda
|
||||||
|
right = direita
|
||||||
|
## 1: Side the doors opens to
|
||||||
|
(Top Half, %s-opening) = (Metade superior, abre para %s)
|
||||||
|
(%s-opening) = (abre para %s)
|
||||||
|
|
||||||
|
|
||||||
|
### door_nodes.lua ###
|
||||||
|
Not enough vertical space to place a door! = Não existe espaço vertical suficiente para colocar uma porta.
|
||||||
|
|
||||||
|
### crafts.lua ###
|
||||||
|
Brass Ingot = Lingote de bronze
|
||||||
|
Bucket of white paint = Balde de tinta branca
|
||||||
|
Legs for Small Utility table = Pernas para mesa pequena
|
||||||
|
Plastic sheet = Folha de plástico
|
||||||
|
Silicon lump = Massa de silício
|
||||||
|
Simple Integrated Circuit = Circuito integrado simples
|
||||||
|
Small Wooden Drawer = Gaveta pequena de madeira
|
||||||
|
Terracotta Roof Tile = Telha de terracota
|
||||||
|
Titanium Dioxide = Dióxido de titânio
|
||||||
|
Uncooked Terracotta Base = Base bruta de terracota
|
||||||
|
Unprocessed Plastic base = Base de plástico não processada
|
||||||
|
|
||||||
|
### door_models.lua ###
|
||||||
|
|
||||||
|
### door_nodes.lua ###
|
||||||
|
|
||||||
|
### fences.lua ###
|
||||||
|
Barbed Wire Fence = Cerca de arame farpado
|
||||||
|
Barbed Wire Fence Gate = Portão da cerca de arame farpado
|
||||||
|
Brass Fence/railing = Cerca/corrimão de bronze
|
||||||
|
Brass Fence/railing with sign = Cerca/corrimão de bronze, com placa
|
||||||
|
Chainlink Fence = Cerca de tela de arame
|
||||||
|
Chainlink Fence Gate = Portão da cerca de tela de arame
|
||||||
|
Chainlink Fence Gate (open) = Portão da cerca de tela de arame (aberto)
|
||||||
|
Unpainted Picket Fence = Cerca de tábuas não pintada
|
||||||
|
Unpainted Picket Fence Gate = Portão da cerca de madeira não pintado
|
||||||
|
White Picket Fence = Cerca de madeira branca
|
||||||
|
White Picket Fence Gate = Portão da cerca de madeira branco
|
||||||
|
Wooden Privacy Fence = Cerca fechada de mandeira
|
||||||
|
Wrought Iron Fence/railing = Cerca/corrimão de ferro forjado
|
||||||
|
Wrought Iron Fence/railing with sign = Cerca/corrimão de ferro forjado, com placa
|
||||||
|
want to simply place the wielded item like usual. = quer somente colocar o item empunhado normalmente.
|
||||||
|
|
||||||
|
### furniture_medieval.lua ###
|
||||||
|
Bars = Barras
|
||||||
|
Binding Bars = Barras do canto
|
||||||
|
Chains = Correntes
|
||||||
|
Wall Torch = Tocha de parede
|
||||||
|
|
||||||
|
### furniture_bathroom.lua ###
|
||||||
|
Toilet = Vaso sanitário
|
||||||
|
Sink = Pia
|
||||||
|
Taps = Torneira
|
||||||
|
Shower Tray = Ralo do chuveiro
|
||||||
|
Shower Head = Chuveiro
|
||||||
|
|
||||||
|
### init.lua ###
|
||||||
|
Loaded! = Carregado!
|
||||||
|
Asphalt Shingles = Telhas de asfalto
|
||||||
|
Black Plastic Flower Pot = Vaso de flor de plástico preto
|
||||||
|
Brass Pole = Poste de bronze
|
||||||
|
Brass Table Legs = Pernas da mesa de bronze
|
||||||
|
red = vermelho
|
||||||
|
green = verde
|
||||||
|
blue = azul
|
||||||
|
white = branco
|
||||||
|
pink = rosa
|
||||||
|
violet = violeta
|
||||||
|
## 1: Color name
|
||||||
|
Curtains (%s) = Cortina (%s)
|
||||||
|
Drop-Ceiling Tile = Placa de teto
|
||||||
|
Glass Skylight = Claraboia de vidro
|
||||||
|
Glass Table (Small, Round) = Mesa de vidro (pequena, redonda)
|
||||||
|
Glass Table (Small, Square) = Mesa de vidro (pequena, quadrada)
|
||||||
|
Green Plastic Flower Pot = Vaso de flor de plástico verde
|
||||||
|
Large Area Rug = Tapete grande
|
||||||
|
Large Glass Table Piece = Pedaço da mesa grande de vidro
|
||||||
|
Large Stereo Speaker = Auto-falante grande
|
||||||
|
Legs for Utility Table = Pernas para mesa
|
||||||
|
Projection Screen Material = Material de tela de projeção
|
||||||
|
Small Surround Speaker = Auto-falante pequeno
|
||||||
|
Small Throw Rug = Tapete pequeno
|
||||||
|
Stereo Receiver = Aparelho de som
|
||||||
|
Terracotta Flower Pot = Vaso de flor de terracota
|
||||||
|
Terracotta Roofing = Telhado de terracota
|
||||||
|
Textured Ceiling Paint = Pintura texturizada do teto
|
||||||
|
Utility Table = Mesa de trabalho
|
||||||
|
Utility table mk2 = Mesa de trabalho mk2
|
||||||
|
Wooden Shutter (Black) = Persiana de madeira (preta)
|
||||||
|
Wooden Shutter (Dark Grey) = Persiana de madeira (cinza escura)
|
||||||
|
Wooden Shutter (Forest Green) = Persiana de madeira (verde)
|
||||||
|
Wooden Shutter (Grey) = Persiana de madeira (cinza)
|
||||||
|
Wooden Shutter (Light Blue) = Persiana de madeira (azul clara)
|
||||||
|
Wooden Shutter (Purple) = Persiana de madeira (roxa)
|
||||||
|
Wooden Shutter (Red) = Persiana de madeira (vermelha)
|
||||||
|
Wooden Shutter (Unpainted Mahogany) = Persiana de madeira (mogno)
|
||||||
|
Wooden Shutter (Unpainted Oak) = Persiana de madeira (carvalho)
|
||||||
|
Wooden Shutter (White) = Persiana de madeira (branca)
|
||||||
|
Wooden Shutter (Yellow) = Persiana de madeira (amarela)
|
||||||
|
Wooden Tabletop piece = Pedaço do tampo da mesa
|
||||||
|
Wooden Tabletop (Small, Round) = Tampo da mesa (pequeno, arredondado)
|
||||||
|
Wooden Tabletop (Small, Square) = Tampo da mesa (pequeno, quadrado)
|
||||||
|
Wood Shingles = Telhas de madeira
|
||||||
|
Wrought Iron Pole = Poste de ferro forjado
|
||||||
|
someone = alguém
|
||||||
|
## 1: Player name
|
||||||
|
Sorry, %s owns that spot. = Desculpe, mas esse local pertence a %s.
|
||||||
|
|
||||||
|
### lighting.lua ###
|
||||||
|
White Glowlight (small cube) = Arandela branca (cubo pequeno)
|
||||||
|
White Glowlight (small cube, on ceiling) = Arandela branca (cubo pequeno, na parede)
|
||||||
|
White Glowlight (thick) = Arandela branca (grossa)
|
||||||
|
White Glowlight (thick, on wall) = Arandela branca (grossa, na parede)
|
||||||
|
White Glowlight (thin) = Arandela branca (fina)
|
||||||
|
White Glowlight (thin, on wall) = Arandela branca (fina, na parede)
|
||||||
|
Yellow Glowlight (small cube) = Arandela amarela (cubo pequeno)
|
||||||
|
Yellow Glowlight (small cube, on ceiling) = Arandela amarela (cubo pequeno, na parede)
|
||||||
|
Yellow Glowlight (thick) = Arandela amarela (grossa)
|
||||||
|
Yellow Glowlight (thick, on wall) = Arandela amarela (grossa, na parede)
|
||||||
|
Yellow Glowlight (thin) = Arandela amarela (fina)
|
||||||
|
Yellow Glowlight (thin, on wall) = Arandela amarela (fina, na parede)
|
||||||
|
|
||||||
|
### locked.lua ###
|
||||||
|
## 1: Item description, 2: Owner name
|
||||||
|
%s (owned by %s) = %s (pertence a %s)
|
||||||
|
## 1: Player name, 2: Item description, 3: Owner name, 4: Position
|
||||||
|
%s tried to access a %s belonging to %s at %s = %s tentou acessar %s pertencente a %s em %s
|
||||||
|
## 1: Item description
|
||||||
|
%s (Locked) = %s (trancado)
|
||||||
|
Locked Cabinet = Armário trancado
|
||||||
|
Locked Nightstand = Criado-mudo trancado
|
||||||
|
|
||||||
|
### nightstands.lua ###
|
||||||
|
Mahogany Nightstand with One Drawer = Criado-mudo de mogno, com uma gaveta
|
||||||
|
Mahogany Nightstand with Two Drawers = Criado-mudo de mogno, com duas gavetas
|
||||||
|
Oak Nightstand with One Drawer = Criado-mudo de carvalho, com uma gaveta
|
||||||
|
Oak Nightstand with Two Drawers = Criado-mudo de carvalho, com duas gavetas
|
||||||
|
## 1: Player name, 2: position
|
||||||
|
%s moves stuff in nightstand at %s = %s moveu item(ns) no criado-mudo em %s
|
||||||
|
%s moves stuff to nightstand at %s = %s moveu item(ns) para o criado-mudo em %s
|
||||||
|
%s takes stuff from nightstand at %s = %s tirou item(ns) do criado-mudo em %s
|
||||||
|
One-drawer Nightstand = Criado-mudo com uma gaveta
|
||||||
|
Two-drawer Nightstand = Criado-mudo com duas gavetas
|
||||||
|
|
||||||
|
### oven.lua ###
|
||||||
|
Oven = Forno
|
||||||
|
## 1: Item name
|
||||||
|
Could not insert '%s' = Não foi possível inserir '%s'
|
||||||
|
## 1: Percentage
|
||||||
|
Oven active: %d%% = Forno ativo: %d%%
|
||||||
|
Oven out of fuel = O forno está sem combustível
|
||||||
|
Oven is empty = O forno está vazio
|
||||||
|
|
||||||
|
### refrigerator.lua ###
|
||||||
|
Refrigerator = Geladeira
|
||||||
|
## 1: Player name, 2: position
|
||||||
|
%s moves stuff in refrigerator at %s = %s moveu item(ns) na geladeira em %s
|
||||||
|
%s moves stuff to refrigerator at %s = %s moveu item(ns) para a geladeira em %s
|
||||||
|
%s takes stuff from refrigerator at %s = %s tirou item(ns) da geladeira em %s
|
||||||
|
Not enough vertical space to place a refrigerator! = Não existe espaço vertical suficiente para adicionar uma geladeira.
|
||||||
|
|
||||||
|
### television.lua ###
|
||||||
|
Small CRT Television = TV de tubo pequena
|
||||||
|
|
||||||
|
### signs_lib.lua ###
|
||||||
|
%s wrote "%s" to sign at %s = %s escreveu "%s" na placa em %s
|
||||||
|
Reading cached character database. = Lendo banco de dados de caracteres no cache.
|
||||||
|
Font seems to have changed. Rebuilding cache. = Aparentemente as fontes foram alteradas. Reconstruindo o cache.
|
||||||
|
Could not find font line height in cached DB. Trying brute force. = Não foi possível encontrar a altura da linha da fonte no cache do BD. Tentando na marra.
|
||||||
|
Registered %s and %s = %s e %s registrados
|
||||||
|
signs loaded = placas carregadas
|
|
@ -0,0 +1,198 @@
|
||||||
|
|
||||||
|
##########################
|
||||||
|
# Template language file #
|
||||||
|
##########################
|
||||||
|
|
||||||
|
### Special strings ###
|
||||||
|
|
||||||
|
### kitchen_cabinet.lua ###
|
||||||
|
Kitchen Cabinet =
|
||||||
|
## 1: Player name, 2: position
|
||||||
|
%s moves stuff in kitchen cabinet at %s =
|
||||||
|
%s moves stuff to kitchen cabinet at %s =
|
||||||
|
%s takes stuff from kitchen cabinet at %s =
|
||||||
|
Half-height Kitchen Cabinet (on ceiling) =
|
||||||
|
Under-sink cabinet =
|
||||||
|
Kitchen Cabinet with sink =
|
||||||
|
|
||||||
|
### door_models.lua ###
|
||||||
|
Mahogany Closet Door =
|
||||||
|
Oak Closet Door =
|
||||||
|
Fancy Wood/Glass Door =
|
||||||
|
Glass Office Door =
|
||||||
|
Glass and Wood, Mahogany-colored =
|
||||||
|
Glass and Wood, Oak-colored =
|
||||||
|
Glass and Wood, White =
|
||||||
|
Plain Wooden Door =
|
||||||
|
left =
|
||||||
|
right =
|
||||||
|
## 1: Side the doors opens to
|
||||||
|
(Top Half, %s-opening) =
|
||||||
|
(%s-opening) =
|
||||||
|
|
||||||
|
|
||||||
|
### door_nodes.lua ###
|
||||||
|
Not enough vertical space to place a door! =
|
||||||
|
|
||||||
|
### crafts.lua ###
|
||||||
|
Brass Ingot =
|
||||||
|
Bucket of white paint =
|
||||||
|
Legs for Small Utility table =
|
||||||
|
Plastic sheet =
|
||||||
|
Silicon lump =
|
||||||
|
Simple Integrated Circuit =
|
||||||
|
Small Wooden Drawer =
|
||||||
|
Terracotta Roof Tile =
|
||||||
|
Titanium Dioxide =
|
||||||
|
Uncooked Terracotta Base =
|
||||||
|
Unprocessed Plastic base =
|
||||||
|
|
||||||
|
### door_models.lua ###
|
||||||
|
|
||||||
|
### door_nodes.lua ###
|
||||||
|
|
||||||
|
### fences.lua ###
|
||||||
|
Barbed Wire Fence =
|
||||||
|
Barbed Wire Fence Gate =
|
||||||
|
Brass Fence/railing =
|
||||||
|
Brass Fence/railing with sign =
|
||||||
|
Chainlink Fence =
|
||||||
|
Chainlink Fence Gate =
|
||||||
|
Chainlink Fence Gate (open) =
|
||||||
|
Unpainted Picket Fence =
|
||||||
|
Unpainted Picket Fence Gate =
|
||||||
|
White Picket Fence =
|
||||||
|
White Picket Fence Gate =
|
||||||
|
Wooden Privacy Fence =
|
||||||
|
Wrought Iron Fence/railing =
|
||||||
|
Wrought Iron Fence/railing with sign =
|
||||||
|
want to simply place the wielded item like usual. =
|
||||||
|
|
||||||
|
### furniture_medieval.lua ###
|
||||||
|
Bars =
|
||||||
|
Binding Bars =
|
||||||
|
Chains =
|
||||||
|
Wall Torch =
|
||||||
|
|
||||||
|
### furniture_bathroom.lua ###
|
||||||
|
Toilet =
|
||||||
|
Sink =
|
||||||
|
Taps =
|
||||||
|
Shower Tray =
|
||||||
|
Shower Head =
|
||||||
|
|
||||||
|
### init.lua ###
|
||||||
|
Loaded! =
|
||||||
|
Asphalt Shingles =
|
||||||
|
Black Plastic Flower Pot =
|
||||||
|
Brass Pole =
|
||||||
|
Brass Table Legs =
|
||||||
|
red =
|
||||||
|
green =
|
||||||
|
blue =
|
||||||
|
white =
|
||||||
|
pink =
|
||||||
|
violet =
|
||||||
|
## 1: Color name
|
||||||
|
Curtains (%s) =
|
||||||
|
Drop-Ceiling Tile =
|
||||||
|
Glass Skylight =
|
||||||
|
Glass Table (Small, Round) =
|
||||||
|
Glass Table (Small, Square) =
|
||||||
|
Green Plastic Flower Pot =
|
||||||
|
Large Area Rug =
|
||||||
|
Large Glass Table Piece =
|
||||||
|
Large Stereo Speaker =
|
||||||
|
Legs for Utility Table =
|
||||||
|
Projection Screen Material =
|
||||||
|
Small Surround Speaker =
|
||||||
|
Small Throw Rug =
|
||||||
|
Stereo Receiver =
|
||||||
|
Terracotta Flower Pot =
|
||||||
|
Terracotta Roofing =
|
||||||
|
Textured Ceiling Paint =
|
||||||
|
Utility Table =
|
||||||
|
Utility table mk2 =
|
||||||
|
Wooden Shutter (Black) =
|
||||||
|
Wooden Shutter (Dark Grey) =
|
||||||
|
Wooden Shutter (Forest Green) =
|
||||||
|
Wooden Shutter (Grey) =
|
||||||
|
Wooden Shutter (Light Blue) =
|
||||||
|
Wooden Shutter (Purple) =
|
||||||
|
Wooden Shutter (Red) =
|
||||||
|
Wooden Shutter (Unpainted Mahogany) =
|
||||||
|
Wooden Shutter (Unpainted Oak) =
|
||||||
|
Wooden Shutter (White) =
|
||||||
|
Wooden Shutter (Yellow) =
|
||||||
|
Wooden Tabletop piece =
|
||||||
|
Wooden Tabletop (Small, Round) =
|
||||||
|
Wooden Tabletop (Small, Square) =
|
||||||
|
Wood Shingles =
|
||||||
|
Wrought Iron Pole =
|
||||||
|
someone =
|
||||||
|
## 1: Player name
|
||||||
|
Sorry, %s owns that spot. =
|
||||||
|
|
||||||
|
### lighting.lua ###
|
||||||
|
White Glowlight (small cube) =
|
||||||
|
White Glowlight (small cube, on ceiling) =
|
||||||
|
White Glowlight (thick) =
|
||||||
|
White Glowlight (thick, on wall) =
|
||||||
|
White Glowlight (thin) =
|
||||||
|
White Glowlight (thin, on wall) =
|
||||||
|
Yellow Glowlight (small cube) =
|
||||||
|
Yellow Glowlight (small cube, on ceiling) =
|
||||||
|
Yellow Glowlight (thick) =
|
||||||
|
Yellow Glowlight (thick, on wall) =
|
||||||
|
Yellow Glowlight (thin) =
|
||||||
|
Yellow Glowlight (thin, on wall) =
|
||||||
|
|
||||||
|
### locked.lua ###
|
||||||
|
## 1: Item description, 2: Owner name
|
||||||
|
%s (owned by %s) =
|
||||||
|
## 1: Player name, 2: Item description, 3: Owner name, 4: Position
|
||||||
|
%s tried to access a %s belonging to %s at %s =
|
||||||
|
## 1: Item description
|
||||||
|
%s (Locked) =
|
||||||
|
Locked Cabinet =
|
||||||
|
Locked Nightstand =
|
||||||
|
|
||||||
|
### nightstands.lua ###
|
||||||
|
Mahogany Nightstand with One Drawer =
|
||||||
|
Mahogany Nightstand with Two Drawers =
|
||||||
|
Oak Nightstand with One Drawer =
|
||||||
|
Oak Nightstand with Two Drawers =
|
||||||
|
## 1: Player name, 2: position
|
||||||
|
%s moves stuff in nightstand at %s =
|
||||||
|
%s moves stuff to nightstand at %s =
|
||||||
|
%s takes stuff from nightstand at %s =
|
||||||
|
One-drawer Nightstand =
|
||||||
|
Two-drawer Nightstand =
|
||||||
|
|
||||||
|
### oven.lua ###
|
||||||
|
Oven =
|
||||||
|
## 1: Item name
|
||||||
|
Could not insert '%s' =
|
||||||
|
## 1: Percentage
|
||||||
|
Oven active: %d%% =
|
||||||
|
Oven out of fuel =
|
||||||
|
Oven is empty =
|
||||||
|
|
||||||
|
### refrigerator.lua ###
|
||||||
|
Refrigerator =
|
||||||
|
## 1: Player name, 2: position
|
||||||
|
%s moves stuff in refrigerator at %s =
|
||||||
|
%s moves stuff to refrigerator at %s =
|
||||||
|
%s takes stuff from refrigerator at %s =
|
||||||
|
Not enough vertical space to place a refrigerator! =
|
||||||
|
|
||||||
|
### television.lua ###
|
||||||
|
Small CRT Television =
|
||||||
|
|
||||||
|
### signs_lib.lua ###
|
||||||
|
%s wrote "%s" to sign at %s =
|
||||||
|
Reading cached character database. =
|
||||||
|
Font seems to have changed. Rebuilding cache. =
|
||||||
|
Could not find font line height in cached DB. Trying brute force. =
|
||||||
|
Registered %s and %s =
|
||||||
|
signs loaded =
|
|
@ -0,0 +1,154 @@
|
||||||
|
-- This file supplies nightstands
|
||||||
|
-- Load translation library if intllib is installed
|
||||||
|
|
||||||
|
local S
|
||||||
|
if (minetest.get_modpath("intllib")) then
|
||||||
|
dofile(minetest.get_modpath("intllib").."/intllib.lua")
|
||||||
|
S = intllib.Getter(minetest.get_current_modname())
|
||||||
|
else
|
||||||
|
S = function ( s ) return s end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- OAK NIGHTSTAND
|
||||||
|
|
||||||
|
minetest.register_node('poudlard:nightstand_1', {
|
||||||
|
drawtype = "nodebox",
|
||||||
|
description = S("Oak Nightstand with Two Drawers"),
|
||||||
|
tiles = { 'homedecor_nightstand_oak_top.png',
|
||||||
|
'homedecor_nightstand_oak_bottom.png',
|
||||||
|
'homedecor_nightstand_oak_right.png',
|
||||||
|
'homedecor_nightstand_oak_left.png',
|
||||||
|
'homedecor_nightstand_oak_back.png',
|
||||||
|
'homedecor_nightstand_oak_2_drawer_front.png'},
|
||||||
|
sunlight_propagates = false,
|
||||||
|
paramtype = "light",
|
||||||
|
paramtype2 = "facedir",
|
||||||
|
walkable = true,
|
||||||
|
selection_box = {
|
||||||
|
type = "fixed",
|
||||||
|
fixed = { -0.5, -0.5, -0.5, 0.5, 0.5, 0.5 }
|
||||||
|
},
|
||||||
|
node_box = {
|
||||||
|
type = "fixed",
|
||||||
|
fixed = {
|
||||||
|
{ -8/16, -8/16, -30/64, 8/16, 8/16, 8/16 }, -- main body
|
||||||
|
{ -7/16, 1/16, -32/64, 7/16, 7/16, -29/64 }, -- top drawer face
|
||||||
|
{ -7/16, -7/16, -32/64, 7/16, -1/16, -29/64 }, -- bottom drawer face
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
groups = { snappy = 3 },
|
||||||
|
sounds = default.node_sound_wood_defaults(),
|
||||||
|
on_construct = function(pos)
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
meta:set_string("formspec",
|
||||||
|
"size[8,7]"..
|
||||||
|
"list[current_name;main;0,0;8,2;]"..
|
||||||
|
"list[current_player;main;0,3;8,4;]")
|
||||||
|
meta:set_string("infotext", S("Two-drawer Nightstand"))
|
||||||
|
local inv = meta:get_inventory()
|
||||||
|
inv:set_size("main", 16)
|
||||||
|
end,
|
||||||
|
can_dig = function(pos,player)
|
||||||
|
local meta = minetest.get_meta(pos);
|
||||||
|
local inv = meta:get_inventory()
|
||||||
|
return inv:is_empty("main")
|
||||||
|
end,
|
||||||
|
on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
|
||||||
|
minetest.log("action", S("%s moves stuff in nightstand at %s"):format(
|
||||||
|
player:get_player_name(),
|
||||||
|
minetest.pos_to_string(pos)
|
||||||
|
))
|
||||||
|
end,
|
||||||
|
on_metadata_inventory_put = function(pos, listname, index, stack, player)
|
||||||
|
minetest.log("action", S("%s moves stuff to nightstand at %s"):format(
|
||||||
|
player:get_player_name(),
|
||||||
|
minetest.pos_to_string(pos)
|
||||||
|
))
|
||||||
|
end,
|
||||||
|
on_metadata_inventory_take = function(pos, listname, index, stack, player)
|
||||||
|
minetest.log("action", S("%s takes stuff from nightstand at %s"):format(
|
||||||
|
player:get_player_name(),
|
||||||
|
minetest.pos_to_string(pos)
|
||||||
|
))
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
--MAHOGANY NIGHSTAND -----------------------
|
||||||
|
|
||||||
|
minetest.register_node('poudlard:nightstand_2', {
|
||||||
|
drawtype = "nodebox",
|
||||||
|
description = S("Mahogany Nightstand with Two Drawers"),
|
||||||
|
tiles = { 'homedecor_nightstand_mahogany_top.png',
|
||||||
|
'homedecor_nightstand_mahogany_bottom.png',
|
||||||
|
'homedecor_nightstand_mahogany_right.png',
|
||||||
|
'homedecor_nightstand_mahogany_left.png',
|
||||||
|
'homedecor_nightstand_mahogany_back.png',
|
||||||
|
'homedecor_nightstand_mahogany_2_drawer_front.png'},
|
||||||
|
sunlight_propagates = false,
|
||||||
|
paramtype = "light",
|
||||||
|
paramtype2 = "facedir",
|
||||||
|
walkable = true,
|
||||||
|
selection_box = {
|
||||||
|
type = "fixed",
|
||||||
|
fixed = { -0.5, -0.5, -0.5, 0.5, 0.5, 0.5 }
|
||||||
|
},
|
||||||
|
node_box = {
|
||||||
|
type = "fixed",
|
||||||
|
fixed = {
|
||||||
|
{ -8/16, -8/16, -30/64, 8/16, 8/16, 8/16 }, -- main body
|
||||||
|
{ -7/16, 1/16, -32/64, 7/16, 7/16, -29/64 }, -- top drawer face
|
||||||
|
{ -7/16, -7/16, -32/64, 7/16, -1/16, -29/64 }, -- bottom drawer face
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
groups = { snappy = 3 },
|
||||||
|
sounds = default.node_sound_wood_defaults(),
|
||||||
|
on_construct = function(pos)
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
meta:set_string("formspec",
|
||||||
|
"size[8,7]"..
|
||||||
|
"list[current_name;main;0,0;8,2;]"..
|
||||||
|
"list[current_player;main;0,3;8,4;]")
|
||||||
|
meta:set_string("infotext", S("Two-drawer Nightstand"))
|
||||||
|
local inv = meta:get_inventory()
|
||||||
|
inv:set_size("main", 16)
|
||||||
|
end,
|
||||||
|
can_dig = function(pos,player)
|
||||||
|
local meta = minetest.get_meta(pos);
|
||||||
|
local inv = meta:get_inventory()
|
||||||
|
return inv:is_empty("main")
|
||||||
|
end,
|
||||||
|
on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
|
||||||
|
minetest.log("action", S("%s moves stuff in nightstand at %s"):format(
|
||||||
|
player:get_player_name(),
|
||||||
|
minetest.pos_to_string(pos)
|
||||||
|
))
|
||||||
|
end,
|
||||||
|
on_metadata_inventory_put = function(pos, listname, index, stack, player)
|
||||||
|
minetest.log("action", S("%s moves stuff to nightstand at %s"):format(
|
||||||
|
player:get_player_name(),
|
||||||
|
minetest.pos_to_string(pos)
|
||||||
|
))
|
||||||
|
end,
|
||||||
|
on_metadata_inventory_take = function(pos, listname, index, stack, player)
|
||||||
|
minetest.log("action", S("%s takes stuff from nightstand at %s"):format(
|
||||||
|
player:get_player_name(),
|
||||||
|
minetest.pos_to_string(pos)
|
||||||
|
))
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-------Alias for homedecor
|
||||||
|
minetest.register_alias("homedecor:nightstand_oak_two_drawers", "poudecor:nightstand_1")
|
||||||
|
minetest.register_alias("homedecor:nightstand_mahogany_two_drawerst", "poudecor:nightstand_2")
|
||||||
|
|
||||||
|
|
||||||
|
-------Alias for Poudlard
|
||||||
|
minetest.register_alias("poudecor:nightstand_1", "poudlard:nightstand_1")
|
||||||
|
minetest.register_alias("poudecor:nightstand_2", "poudlard:nightstand_2")
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
|
||||||
|
-- Load translation library if intllib is installed
|
||||||
|
|
||||||
|
local S
|
||||||
|
if (minetest.get_modpath("intllib")) then
|
||||||
|
dofile(minetest.get_modpath("intllib").."/intllib.lua")
|
||||||
|
S = intllib.Getter(minetest.get_current_modname())
|
||||||
|
else
|
||||||
|
S = function ( s ) return s end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_node("poudlard:torch_wall", {
|
||||||
|
description = S("Wall Torch"),
|
||||||
|
drawtype = "nodebox",
|
||||||
|
tiles = {
|
||||||
|
"forniture_torch_wall_s.png",
|
||||||
|
"forniture_torch_wall_i.png",
|
||||||
|
{
|
||||||
|
name="forniture_torch_wall_anim.png",
|
||||||
|
animation={
|
||||||
|
type="vertical_frames",
|
||||||
|
aspect_w=40,
|
||||||
|
aspect_h=40,
|
||||||
|
length=1.0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
inventory_image="3dforniture_inv_torch_wall.png",
|
||||||
|
paramtype = "light",
|
||||||
|
paramtype2 = "facedir",
|
||||||
|
node_box = {
|
||||||
|
type = "fixed",
|
||||||
|
fixed = {
|
||||||
|
{ -0.05, -0.45, 0.45, 0.05, -0.35, 0.50, },
|
||||||
|
{ -0.05, -0.35, 0.40, 0.05, -0.25, 0.50, },
|
||||||
|
{ -0.05, -0.25, 0.35, 0.05, -0.15, 0.45, },
|
||||||
|
{ -0.05, -0.15, 0.30, 0.05, -0.05, 0.40, },
|
||||||
|
{ -0.05, -0.05, 0.25, 0.05, 0.00, 0.35, },
|
||||||
|
{ -0.10, 0.00, 0.20, 0.10, 0.05, 0.40, },
|
||||||
|
{ -0.15, 0.05, 0.15, 0.15, 0.15, 0.45, },
|
||||||
|
{ -0.10, 0.15, 0.20, 0.10, 0.25, 0.40, },
|
||||||
|
{ -0.05, 0.25, 0.25, 0.05, 0.35, 0.35, },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
sunlight_propagates = true,
|
||||||
|
walkable = false,
|
||||||
|
light_source = 14,
|
||||||
|
selection_box = {
|
||||||
|
type = "fixed",
|
||||||
|
fixed = { -0.15, -0.45, 0.15, 0.15,0.35, 0.5 },
|
||||||
|
},
|
||||||
|
groups = {cracky=2},
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
minetest.register_alias("homedecor:torch_wall", "poudecor:torch_wall")
|
||||||
|
|
||||||
|
minetest.register_alias("poudecor:torch_wall", "poudlard:torch_wall")
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
All code and textures from
|
||||||
|
- moreblocks and stairsplus by Calinou
|
||||||
|
- "homedecor" by Vanessa Ezekowitz.
|
||||||
|
|
||||||
|
Just a matter of more light versions by Perlipop.
|
||||||
|
+ raccordable images for curtains
|
||||||
|
|
||||||
|
|
||||||
|
Licenses: For the lua code, GPL. For all images and everything else, WTFPL.
|
|
@ -0,0 +1,225 @@
|
||||||
|
|
||||||
|
|
||||||
|
-- Nodes will be called <modname>:{stair,slab,panel,micro}_<subname>
|
||||||
|
function poudlard.register_stair_and_slab_and_panel_and_micro(modname, subname, recipeitem, groups, images, desc_stair, desc_slab, desc_panel, desc_micro, drop)
|
||||||
|
poudlard.register_stair(modname, subname, recipeitem, groups, images, desc_stair, drop)
|
||||||
|
poudlard.register_slab(modname, subname, recipeitem, groups, images, desc_slab, drop)
|
||||||
|
poudlard.register_panel(modname, subname, recipeitem, groups, images, desc_panel, drop)
|
||||||
|
poudlard.register_micro(modname, subname, recipeitem, groups, images, desc_micro, drop)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "poudstone", "poudlard:poudstone",
|
||||||
|
{snappy=1,choppy=2,oddly_breakable_by_hand=2,flammable=3, not_in_creative_inventory=0},
|
||||||
|
{"poudlard_poudstone.png"},
|
||||||
|
"Poudlard stone Stairs",
|
||||||
|
"Poudlard stone Slab",
|
||||||
|
"Poudlard stone Panel",
|
||||||
|
"Poudlard stone Microblock",
|
||||||
|
"poudstone")
|
||||||
|
|
||||||
|
poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "poudwood", "poudlard:poudwood",
|
||||||
|
{snappy=1,choppy=2,oddly_breakable_by_hand=2,flammable=3, not_in_creative_inventory=0},
|
||||||
|
{"poudlard_poudwood.png"},
|
||||||
|
"Poudlard Wood Stairs",
|
||||||
|
"Poudlard Wood Slab",
|
||||||
|
"POudlard Wood Panel",
|
||||||
|
"Poudlard Wood Microblock",
|
||||||
|
"poudwood")
|
||||||
|
|
||||||
|
|
||||||
|
poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "redblock", "poudlard:redblock",
|
||||||
|
{snappy=1,choppy=2,oddly_breakable_by_hand=2,flammable=3, not_in_creative_inventory=0},
|
||||||
|
{"poudlard_redblock.png"},
|
||||||
|
"redblock Stairs",
|
||||||
|
"redblock Slab",
|
||||||
|
"redblock Panel",
|
||||||
|
"redblock Microblock",
|
||||||
|
"redblock")
|
||||||
|
|
||||||
|
poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "blackblock", "poudlard:blackblock",
|
||||||
|
{snappy=1,choppy=2,oddly_breakable_by_hand=2,flammable=3, not_in_creative_inventory=0},
|
||||||
|
{"poudlard_blackblock.png"},
|
||||||
|
"blackblock Stairs",
|
||||||
|
"blackblock Slab",
|
||||||
|
"blackblock Panel",
|
||||||
|
"blackblock Microblock",
|
||||||
|
"blackblock")
|
||||||
|
|
||||||
|
|
||||||
|
poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "wood", "default:wood",
|
||||||
|
{snappy=1,choppy=2,oddly_breakable_by_hand=2,flammable=3},
|
||||||
|
{"default_wood.png"},
|
||||||
|
"Wooden Stairs",
|
||||||
|
"Wooden Slab",
|
||||||
|
"Wooden Panel",
|
||||||
|
"Wooden Microblock",
|
||||||
|
"wood",
|
||||||
|
"facedir")
|
||||||
|
|
||||||
|
poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "stone", "default:stone",
|
||||||
|
{cracky=3},
|
||||||
|
{"default_stone.png"},
|
||||||
|
"Stone Stairs",
|
||||||
|
"Stone Slab",
|
||||||
|
"Stone Panel",
|
||||||
|
"Stone Microblock",
|
||||||
|
"cobble",
|
||||||
|
"none")
|
||||||
|
|
||||||
|
poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "cobble", "default:cobble",
|
||||||
|
{cracky=3},
|
||||||
|
{"default_cobble.png"},
|
||||||
|
"Cobblestone Stairs",
|
||||||
|
"Cobblestone Slab",
|
||||||
|
"Cobblestone Panel",
|
||||||
|
"Cobblestone Microblock",
|
||||||
|
"cobble",
|
||||||
|
"none")
|
||||||
|
|
||||||
|
poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "mossycobble", "default:mossycobble",
|
||||||
|
{cracky=3},
|
||||||
|
{"default_mossycobble.png"},
|
||||||
|
"Mossy Cobblestone Stairs",
|
||||||
|
"Mossy Cobblestone Slab",
|
||||||
|
"Mossy Cobblestone Panel",
|
||||||
|
"Mossy Cobblestone Microblock",
|
||||||
|
"mossycobble",
|
||||||
|
"none")
|
||||||
|
|
||||||
|
|
||||||
|
poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "sandstone", "default:sandstone",
|
||||||
|
{crumbly=2,cracky=2},
|
||||||
|
{"default_sandstone.png"},
|
||||||
|
"Sandstone Stairs",
|
||||||
|
"Sandstone Slab",
|
||||||
|
"Sandstone Panel",
|
||||||
|
"Sandstone Microblock",
|
||||||
|
"sandstone",
|
||||||
|
"none")
|
||||||
|
|
||||||
|
poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "steelblock", "default:steelblock",
|
||||||
|
{snappy=1,bendy=2,cracky=1,melty=2,level=2},
|
||||||
|
{"default_steel_block.png"},
|
||||||
|
"Steel Block Stairs",
|
||||||
|
"Steel Block Slab",
|
||||||
|
"Steel Block Panel",
|
||||||
|
"Steel Microblock",
|
||||||
|
"steelblock",
|
||||||
|
"none")
|
||||||
|
|
||||||
|
poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "desert_stone", "default:desert_stone",
|
||||||
|
{cracky=3},
|
||||||
|
{"default_desert_stone.png"},
|
||||||
|
"Desert Stone Stairs",
|
||||||
|
"Desert Stone Slab",
|
||||||
|
"Desert Stone Panel",
|
||||||
|
"Desert Stone Microblock",
|
||||||
|
"desert_stone",
|
||||||
|
"none")
|
||||||
|
|
||||||
|
poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "glass", "default:glass",
|
||||||
|
{snappy=2,cracky=3,oddly_breakable_by_hand=3},
|
||||||
|
{"default_glass.png"},
|
||||||
|
"Glass Stairs",
|
||||||
|
"Glass Slab",
|
||||||
|
"Glass Panel",
|
||||||
|
"Glass Microblock",
|
||||||
|
"glass",
|
||||||
|
"none")
|
||||||
|
|
||||||
|
poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "tree", "default:tree",
|
||||||
|
{tree=1,snappy=1,choppy=2,oddly_breakable_by_hand=1,flammable=2},
|
||||||
|
{"default_tree.png"},
|
||||||
|
"Tree Stairs",
|
||||||
|
"Tree Slab",
|
||||||
|
"Tree Panel",
|
||||||
|
"Tree Microblock",
|
||||||
|
"tree",
|
||||||
|
"none")
|
||||||
|
|
||||||
|
poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "jungletree", "default:jungletree",
|
||||||
|
{tree=1,snappy=1,choppy=2,oddly_breakable_by_hand=1,flammable=2},
|
||||||
|
{"default_jungletree_top.png", "default_jungletree_top.png", "default_jungletree.png"},
|
||||||
|
"Jungle Tree Stairs",
|
||||||
|
"Jungle Tree Slab",
|
||||||
|
"Jungle Tree Panel",
|
||||||
|
"Jungle Tree Microblock",
|
||||||
|
"jungletree",
|
||||||
|
"none")
|
||||||
|
|
||||||
|
poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "stonebrick", "default:stonebrick",
|
||||||
|
{cracky=3, not_in_creative_inventory=1},
|
||||||
|
{"default_stone_brick.png"},
|
||||||
|
"Stone Bricks Stairs",
|
||||||
|
"Stone Bricks Slab",
|
||||||
|
"Stone Bricks Panel",
|
||||||
|
"Stone Bricks Microblock",
|
||||||
|
"stonebrick")
|
||||||
|
|
||||||
|
poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "ironstonebricks", "poudlard:ironstonebricks",
|
||||||
|
{cracky=3, not_in_creative_inventory=0},
|
||||||
|
{"poudlard_ironstonebrick.png"},
|
||||||
|
"Iron Stone Bricks Stairs",
|
||||||
|
"Iron Stone Bricks Slab",
|
||||||
|
"Iron Stone Bricks Panel",
|
||||||
|
"Iron Stone Bricks Microblock",
|
||||||
|
"ironstonebricks")
|
||||||
|
|
||||||
|
poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "stone_tile", "poudlard:stone_tile",
|
||||||
|
{cracky=3, not_in_creative_inventory=0},
|
||||||
|
{"poudlard_stonesquare.png"},
|
||||||
|
"Stonesquare Stairs",
|
||||||
|
"Stonesquare Slab",
|
||||||
|
"Stonesquare Panel",
|
||||||
|
"Stonesquare Microblock",
|
||||||
|
"stone_tile")
|
||||||
|
|
||||||
|
poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "split_stone_tile", "poudlard:split_stone_tile",
|
||||||
|
{cracky=3},
|
||||||
|
{"poudlard_splitstonesquare_top.png", "poudlard_splitstonesquare.png"},
|
||||||
|
"Split Stonesquare Stairs",
|
||||||
|
"Split Stonesquare Slab",
|
||||||
|
"Split Stonesquare Panel",
|
||||||
|
"Split Stonesquare Microblock",
|
||||||
|
"split_stone_tile")
|
||||||
|
|
||||||
|
poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "junglewood", "poudlard:junglewood",
|
||||||
|
{snappy=1,choppy=2,oddly_breakable_by_hand=2,flammable=3, not_in_creative_inventory01},
|
||||||
|
{"poudlard_junglewood.png"},
|
||||||
|
"Jungle Wood Stairs",
|
||||||
|
"Jungle Wood Slab",
|
||||||
|
"Jungle Wood Panel",
|
||||||
|
"Jungle Wood Microblock",
|
||||||
|
"junglewood")
|
||||||
|
|
||||||
|
poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "circlestonebricks", "poudlard:circlestonebricks",
|
||||||
|
{cracky=3, not_in_creative_inventory=0},
|
||||||
|
{"poudlard_circlestonebrick.png"},
|
||||||
|
"Circle Stone Brick Stairs",
|
||||||
|
"Circle Stone Brick Slab",
|
||||||
|
"Cricle Stone Brick Panel",
|
||||||
|
"Circle Stone Brick Microblock",
|
||||||
|
"circlestonebricks")
|
||||||
|
|
||||||
|
poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "plankstone", "poudlard:plankstone",
|
||||||
|
{cracky=3, not_in_creative_inventory=0},
|
||||||
|
{"poudlard_plankstone.png"},
|
||||||
|
"Plankstone Stairs",
|
||||||
|
"Plankstone Slab",
|
||||||
|
"Plankstone Panel",
|
||||||
|
"Plankstone Microblock",
|
||||||
|
"plankstone")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
poudlard.register_stair_and_slab_and_panel_and_micro("poudlard", "ironstone", "poudlard:ironstone",
|
||||||
|
{cracky=3, not_in_creative_inventory=0},
|
||||||
|
{"poudlard_ironstone.png"},
|
||||||
|
"Iron Stone Stairs",
|
||||||
|
"Iron Stone Slab",
|
||||||
|
"Iron Stone Panel",
|
||||||
|
"Iron Stone Microblock",
|
||||||
|
"ironstone")
|
||||||
|
|
||||||
|
|
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 476 B |
After Width: | Height: | Size: 408 B |
After Width: | Height: | Size: 422 B |
After Width: | Height: | Size: 433 B |
After Width: | Height: | Size: 422 B |
After Width: | Height: | Size: 429 B |
After Width: | Height: | Size: 442 B |
After Width: | Height: | Size: 375 B |
After Width: | Height: | Size: 391 B |
After Width: | Height: | Size: 395 B |
After Width: | Height: | Size: 391 B |
After Width: | Height: | Size: 401 B |
After Width: | Height: | Size: 481 B |
After Width: | Height: | Size: 398 B |