Punto de partida.
En la carpeta "no-mod" están almacenados algunos mods que son interesantes y hay que mirar. -- Yawinmaster
|
@ -0,0 +1,4 @@
|
|||
[Dolphin]
|
||||
PreviewsShown=true
|
||||
Timestamp=2016,12,29,21,12,14
|
||||
Version=3
|
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 7.3 KiB |
After Width: | Height: | Size: 7.2 KiB |
|
@ -0,0 +1,29 @@
|
|||
# This is a game specify minetest.conf file, do not edit
|
||||
|
||||
time_speed = 72
|
||||
|
||||
movement_acceleration_default = 1.8
|
||||
movement_acceleration_air = 1
|
||||
#movement_acceleration_fast = 10
|
||||
|
||||
movement_speed_walk = 4.2
|
||||
movement_speed_crouch = 1.3
|
||||
movement_speed_fast = 10.8
|
||||
|
||||
movement_speed_jump = 6.6
|
||||
#movement_speed_climb = 2
|
||||
#movement_speed_descend = 6
|
||||
|
||||
#movement_liquid_fluidity = 1
|
||||
#movement_liquid_fluidity_smooth = 0.5
|
||||
movement_liquid_sink = 23
|
||||
|
||||
movement_gravity = 10.3
|
||||
|
||||
keepInventory = true
|
||||
|
||||
enable_bed_respawn = true
|
||||
enable_bed_night_skip = true
|
||||
|
||||
give_initial_stuff = true
|
||||
initial_stuff = default:pick_steel,default:axe_steel,default:shovel_steel,default:torch 99,default:cobble 99
|
|
@ -0,0 +1,15 @@
|
|||
[mod] Visible Player Armor [3d_armor]
|
||||
=====================================
|
||||
|
||||
depends: default, inventory_plus, unified_skins
|
||||
|
||||
Adds craftable armor that is visible to other players. Each armor item worn contibutes to
|
||||
a player's armor group level making them less vulnerable to weapons.
|
||||
|
||||
Armor takes damage when a player is hurt but also offers a percentage chance of healing.
|
||||
|
||||
default settings: [minetest.conf]
|
||||
|
||||
# Set number of seconds between armor updates.
|
||||
3d_armor_update_time = 1
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
-- Armor Configuration (defaults)
|
||||
|
||||
-- Increase this if you get initialization glitches when a player first joins.
|
||||
ARMOR_INIT_DELAY = 1
|
||||
|
||||
-- Number of initialization attempts.
|
||||
-- Use in conjunction with ARMOR_INIT_DELAY if initialization problems persist.
|
||||
ARMOR_INIT_TIMES = 1
|
||||
|
||||
-- Increase this if armor is not getting into bones due to server lag.
|
||||
ARMOR_BONES_DELAY = 1
|
||||
|
||||
-- How often player armor/wield items are updated.
|
||||
ARMOR_UPDATE_TIME = 1
|
||||
|
||||
-- Drop armor when a player dies.
|
||||
-- Uses bones mod if present, otherwise items are dropped around the player.
|
||||
ARMOR_DROP = true
|
||||
|
||||
-- Pulverise armor when a player dies, overrides ARMOR_DROP.
|
||||
ARMOR_DESTROY = false
|
||||
|
||||
-- You can use this to increase or decrease overall armor effectiveness,
|
||||
-- eg: ARMOR_LEVEL_MULTIPLIER = 0.5 will reduce armor level by half.
|
||||
ARMOR_LEVEL_MULTIPLIER = 1
|
||||
|
||||
-- You can use this to increase or decrease overall armor healing,
|
||||
-- eg: ARMOR_HEAL_MULTIPLIER = 0 will disable healing altogether.
|
||||
ARMOR_HEAL_MULTIPLIER = 1
|
||||
|
||||
-- You can also use this file to execute arbitary lua code
|
||||
-- eg: Dumb the armor down if using Simple Mobs
|
||||
if minetest.get_modpath("mobs") then
|
||||
ARMOR_LEVEL_MULTIPLIER = 0.5
|
||||
ARMOR_HEAL_MULTIPLIER = 0
|
||||
end
|
||||
|
|
@ -0,0 +1,481 @@
|
|||
ARMOR_INIT_DELAY = 1
|
||||
ARMOR_INIT_TIMES = 1
|
||||
ARMOR_BONES_DELAY = 1
|
||||
ARMOR_UPDATE_TIME = 1
|
||||
ARMOR_DROP = minetest.get_modpath("bones") ~= nil
|
||||
ARMOR_DESTROY = false
|
||||
ARMOR_LEVEL_MULTIPLIER = 1
|
||||
ARMOR_HEAL_MULTIPLIER = 1
|
||||
|
||||
local modpath = minetest.get_modpath(ARMOR_MOD_NAME)
|
||||
local worldpath = minetest.get_worldpath()
|
||||
local input = io.open(modpath.."/armor.conf", "r")
|
||||
if input then
|
||||
dofile(modpath.."/armor.conf")
|
||||
input:close()
|
||||
input = nil
|
||||
end
|
||||
input = io.open(worldpath.."/armor.conf", "r")
|
||||
if input then
|
||||
dofile(worldpath.."/armor.conf")
|
||||
input:close()
|
||||
input = nil
|
||||
end
|
||||
|
||||
local time = 0
|
||||
|
||||
armor = {
|
||||
player_hp = {},
|
||||
elements = {"head", "torso", "legs", "feet"},
|
||||
physics = {"jump","speed","gravity"},
|
||||
--[[formspec = "size[8,8.5]list[detached:player_name_armor;armor;0,1;2,3;]"
|
||||
.."image[2,0.75;2,4;armor_preview]"
|
||||
.."list[current_player;main;0,4.5;8,4;]"
|
||||
.."list[current_player;craft;4,1;3,3;]"
|
||||
.."list[current_player;craftpreview;7,2;1,1;]",]]
|
||||
textures = {},
|
||||
default_skin = "character",
|
||||
}
|
||||
|
||||
--[[if inventory_plus then
|
||||
armor.formspec = "size[8,8.5]button[0,0;2,0.5;main;Back]"
|
||||
.."list[detached:player_name_armor;armor;0,1;2,3;]"
|
||||
.."image[2.5,0.75;2,4;armor_preview]"
|
||||
.."label[5,1;Level: armor_level]"
|
||||
.."label[5,1.5;Heal: armor_heal]"
|
||||
.."list[current_player;main;0,4.5;8,4;]"
|
||||
elseif unified_inventory then
|
||||
unified_inventory.register_button("armor", {
|
||||
type = "image",
|
||||
image = "inventory_plus_armor.png",
|
||||
})
|
||||
unified_inventory.register_page("armor", {
|
||||
get_formspec = function(player)
|
||||
local name = player:get_player_name()
|
||||
local formspec = "background[0.06,0.99;7.92,7.52;3d_armor_ui_form.png]"
|
||||
.."label[0,0;Armor]"
|
||||
.."list[detached:"..name.."_armor;armor;0,1;2,3;]"
|
||||
.."image[2.5,0.75;2,4;"..armor.textures[name].preview.."]"
|
||||
.."label[5,1;Level: "..armor.def[name].level.."]"
|
||||
.."label[5,1.5;Heal: "..armor.def[name].heal.."]"
|
||||
return {formspec=formspec}
|
||||
end,
|
||||
})
|
||||
end]]
|
||||
|
||||
armor.def = {
|
||||
state = 0,
|
||||
count = 0,
|
||||
}
|
||||
|
||||
armor.update_player_visuals = function(self, player)
|
||||
if not player then
|
||||
return
|
||||
end
|
||||
local name = player:get_player_name()
|
||||
if self.textures[name] then
|
||||
default.player_set_textures(player, {
|
||||
self.textures[name].skin,
|
||||
self.textures[name].armor,
|
||||
self.textures[name].wielditem,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
armor.set_player_armor = function(self, player)
|
||||
if not player then
|
||||
return
|
||||
end
|
||||
local name = player:get_player_name()
|
||||
local player_inv = player:get_inventory()
|
||||
if not name then
|
||||
minetest.log("error", "Failed to read player name")
|
||||
return
|
||||
elseif not player_inv then
|
||||
minetest.log("error", "Failed to read player inventory")
|
||||
return
|
||||
end
|
||||
local armor_texture = "3d_armor_trans.png"
|
||||
local armor_level = 0
|
||||
local armor_heal = 0
|
||||
local state = 0
|
||||
local items = 0
|
||||
local elements = {}
|
||||
local textures = {}
|
||||
local physics_o = {speed=1,gravity=1,jump=1}
|
||||
local material = {type=nil, count=1}
|
||||
--local preview = armor:get_player_skin(name).."_preview.png"
|
||||
for _,v in ipairs(self.elements) do
|
||||
elements[v] = false
|
||||
end
|
||||
for i=1, 4 do
|
||||
local stack = player_inv:get_stack("armor", i)
|
||||
local item = stack:get_name()
|
||||
if stack:get_count() == 1 then
|
||||
local def = stack:get_definition()
|
||||
for k, v in pairs(elements) do
|
||||
if v == false then
|
||||
local level = def.groups["armor_"..k]
|
||||
if level then
|
||||
local texture = item:gsub("%:", "_")
|
||||
table.insert(textures, texture..".png")
|
||||
--preview = preview.."^"..texture.."_preview.png"
|
||||
armor_level = armor_level + level
|
||||
state = state + stack:get_wear()
|
||||
items = items + 1
|
||||
local heal = def.groups["armor_heal"] or 0
|
||||
armor_heal = armor_heal + heal
|
||||
for kk,vv in ipairs(self.physics) do
|
||||
local o_value = def.groups["physics_"..vv]
|
||||
if o_value then
|
||||
physics_o[vv] = physics_o[vv] + o_value
|
||||
end
|
||||
end
|
||||
local mat = string.match(item, "%:.+_(.+)$")
|
||||
if material.type then
|
||||
if material.type == mat then
|
||||
material.count = material.count + 1
|
||||
end
|
||||
else
|
||||
material.type = mat
|
||||
end
|
||||
elements[k] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
--[[if minetest.get_modpath("shields") then
|
||||
armor_level = armor_level * 0.9
|
||||
end]]
|
||||
if material.type and material.count == #self.elements then
|
||||
armor_level = armor_level * 1.1
|
||||
end
|
||||
armor_level = armor_level * ARMOR_LEVEL_MULTIPLIER
|
||||
armor_heal = armor_heal * ARMOR_HEAL_MULTIPLIER
|
||||
if #textures > 0 then
|
||||
armor_texture = table.concat(textures, "^")
|
||||
end
|
||||
local armor_groups = {fleshy=100}
|
||||
if armor_level > 0 then
|
||||
armor_groups.level = math.floor(armor_level / 20)
|
||||
armor_groups.fleshy = 100 - armor_level
|
||||
end
|
||||
player:set_armor_groups(armor_groups)
|
||||
player:set_physics_override(physics_o)
|
||||
self.textures[name].armor = armor_texture
|
||||
--self.textures[name].preview = preview
|
||||
self.def[name].state = state
|
||||
self.def[name].count = items
|
||||
self.def[name].level = armor_level
|
||||
self.def[name].heal = armor_heal
|
||||
self.def[name].jump = physics_o.jump
|
||||
self.def[name].speed = physics_o.speed
|
||||
self.def[name].gravity = physics_o.gravity
|
||||
self:update_player_visuals(player)
|
||||
end
|
||||
|
||||
armor.update_armor = function(self, player)
|
||||
if not player then
|
||||
return
|
||||
end
|
||||
local name = player:get_player_name()
|
||||
local hp = player:get_hp() or 0
|
||||
if hp == 0 or hp == self.player_hp[name] then
|
||||
return
|
||||
end
|
||||
if self.player_hp[name] > hp then
|
||||
local player_inv = player:get_inventory()
|
||||
local armor_inv = minetest.get_inventory({type="detached", name=name.."_armor"})
|
||||
if not player_inv then
|
||||
minetest.log("error", "Failed to read player inventory")
|
||||
return
|
||||
elseif not armor_inv then
|
||||
minetest.log("error", "Failed to read detached inventory")
|
||||
return
|
||||
end
|
||||
local heal_max = 0
|
||||
local state = 0
|
||||
local items = 0
|
||||
for i=1, 6 do
|
||||
local stack = player_inv:get_stack("armor", i)
|
||||
if stack:get_count() > 0 then
|
||||
local use = stack:get_definition().groups["armor_use"] or 0
|
||||
local heal = stack:get_definition().groups["armor_heal"] or 0
|
||||
local item = stack:get_name()
|
||||
stack:add_wear(use)
|
||||
armor_inv:set_stack("armor", i, stack)
|
||||
player_inv:set_stack("armor", i, stack)
|
||||
state = state + stack:get_wear()
|
||||
items = items + 1
|
||||
if stack:get_count() == 0 then
|
||||
local desc = minetest.registered_items[item].description
|
||||
if desc then
|
||||
minetest.chat_send_player(name, "Your "..desc.." got destroyed!")
|
||||
end
|
||||
self:set_player_armor(player)
|
||||
armor:update_inventory(player)
|
||||
end
|
||||
heal_max = heal_max + heal
|
||||
end
|
||||
end
|
||||
self.def[name].state = state
|
||||
self.def[name].count = items
|
||||
heal_max = heal_max * ARMOR_HEAL_MULTIPLIER
|
||||
if heal_max > math.random(100) then
|
||||
player:set_hp(self.player_hp[name])
|
||||
return
|
||||
end
|
||||
end
|
||||
self.player_hp[name] = hp
|
||||
end
|
||||
|
||||
armor.get_player_skin = function(self, name)
|
||||
local skin = nil
|
||||
if skins then
|
||||
skin = skins.skins[name]
|
||||
elseif u_skins then
|
||||
skin = u_skins.u_skins[name]
|
||||
end
|
||||
return skin or armor.default_skin
|
||||
end
|
||||
|
||||
armor.get_armor_formspec = function(self, name)
|
||||
local formspec = armor.formspec:gsub("player_name", name)
|
||||
--formspec = formspec:gsub("armor_preview", armor.textures[name].preview)
|
||||
formspec = formspec:gsub("armor_level", armor.def[name].level)
|
||||
return formspec:gsub("armor_heal", armor.def[name].heal)
|
||||
end
|
||||
|
||||
--[[armor.update_inventory = function(self, player)
|
||||
local name = player:get_player_name()
|
||||
if unified_inventory then
|
||||
if unified_inventory.current_page[name] == "armor" then
|
||||
unified_inventory.set_inventory_formspec(player, "armor")
|
||||
end
|
||||
else
|
||||
local formspec = armor:get_armor_formspec(name)
|
||||
if inventory_plus then
|
||||
local page = player:get_inventory_formspec()
|
||||
if page:find("detached:"..name.."_armor") then
|
||||
inventory_plus.set_inventory_formspec(player, formspec)
|
||||
end
|
||||
else
|
||||
player:set_inventory_formspec(formspec)
|
||||
end
|
||||
end
|
||||
end]]
|
||||
|
||||
-- Register Player Model
|
||||
|
||||
default.player_register_model("3d_armor_character.x", {
|
||||
animation_speed = 30,
|
||||
textures = {
|
||||
armor.default_skin..".png",
|
||||
"3d_armor_trans.png",
|
||||
"3d_armor_trans.png",
|
||||
},
|
||||
animations = {
|
||||
stand = {x=0, y=79},
|
||||
lay = {x=162, y=166},
|
||||
walk = {x=168, y=187},
|
||||
mine = {x=189, y=198},
|
||||
walk_mine = {x=200, y=219},
|
||||
sit = {x=81, y=160},
|
||||
},
|
||||
})
|
||||
|
||||
-- Register Callbacks
|
||||
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
local name = player:get_player_name()
|
||||
if inventory_plus and fields.armor then
|
||||
local formspec = armor:get_armor_formspec(name)
|
||||
inventory_plus.set_inventory_formspec(player, formspec)
|
||||
return
|
||||
end
|
||||
for field, _ in pairs(fields) do
|
||||
if string.find(field, "skins_set_") then
|
||||
minetest.after(0, function(player)
|
||||
local skin = armor:get_player_skin(name)
|
||||
armor.textures[name].skin = skin..".png"
|
||||
armor:set_player_armor(player)
|
||||
end, player)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_on_joinplayer(function(player)
|
||||
default.player_set_model(player, "3d_armor_character.x")
|
||||
local name = player:get_player_name()
|
||||
local player_inv = player:get_inventory()
|
||||
local armor_inv = minetest.create_detached_inventory(name.."_armor",{
|
||||
on_put = function(inv, listname, index, stack, player)
|
||||
player:get_inventory():set_stack(listname, index, stack)
|
||||
armor:set_player_armor(player)
|
||||
--armor:update_inventory(player)
|
||||
end,
|
||||
on_take = function(inv, listname, index, stack, player)
|
||||
player:get_inventory():set_stack(listname, index, nil)
|
||||
armor:set_player_armor(player)
|
||||
--armor:update_inventory(player)
|
||||
end,
|
||||
on_move = function(inv, from_list, from_index, to_list, to_index, count, player)
|
||||
local plaver_inv = player:get_inventory()
|
||||
local stack = inv:get_stack(to_list, to_index)
|
||||
player_inv:set_stack(to_list, to_index, stack)
|
||||
player_inv:set_stack(from_list, from_index, nil)
|
||||
armor:set_player_armor(player)
|
||||
--armor:update_inventory(player)
|
||||
end,
|
||||
allow_put = function(inv, listname, index, stack, player)
|
||||
return 1
|
||||
end,
|
||||
allow_take = function(inv, listname, index, stack, player)
|
||||
return stack:get_count()
|
||||
end,
|
||||
allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
|
||||
return count
|
||||
end,
|
||||
})
|
||||
--[[if inventory_plus then
|
||||
inventory_plus.register_button(player,"armor", "Armor")
|
||||
end]]
|
||||
armor_inv:set_size("armor", 4)
|
||||
player_inv:set_size("armor", 4)
|
||||
for i=1, 4 do
|
||||
local stack = player_inv:get_stack("armor", i)
|
||||
armor_inv:set_stack("armor", i, stack)
|
||||
end
|
||||
|
||||
-- Legacy support, import player's armor from old inventory format
|
||||
for _,v in pairs(armor.elements) do
|
||||
local list = "armor_"..v
|
||||
armor_inv:add_item("armor", player_inv:get_stack(list, 1))
|
||||
player_inv:set_stack(list, 1, nil)
|
||||
end
|
||||
|
||||
armor.player_hp[name] = 0
|
||||
armor.def[name] = {
|
||||
state = 0,
|
||||
count = 0,
|
||||
level = 0,
|
||||
heal = 0,
|
||||
jump = 1,
|
||||
speed = 1,
|
||||
gravity = 1,
|
||||
}
|
||||
armor.textures[name] = {
|
||||
skin = armor.default_skin..".png",
|
||||
armor = "3d_armor_trans.png",
|
||||
wielditem = "3d_armor_trans.png",
|
||||
preview = armor.default_skin.."_preview.png",
|
||||
}
|
||||
if minetest.get_modpath("skins") then
|
||||
local skin = skins.skins[name]
|
||||
if skin and skins.get_type(skin) == skins.type.MODEL then
|
||||
armor.textures[name].skin = skin..".png"
|
||||
end
|
||||
elseif minetest.get_modpath("simple_skins") then
|
||||
local skin = skins.skins[name]
|
||||
if skin then
|
||||
armor.textures[name].skin = skin..".png"
|
||||
end
|
||||
--[[elseif minetest.get_modpath("u_skins") then
|
||||
local skin = u_skins.u_skins[name]
|
||||
if skin and u_skins.get_type(skin) == u_skins.type.MODEL then
|
||||
armor.textures[name].skin = skin..".png"
|
||||
end]]
|
||||
end
|
||||
if minetest.get_modpath("player_textures") then
|
||||
local filename = minetest.get_modpath("player_textures").."/textures/player_"..name
|
||||
local f = io.open(filename..".png")
|
||||
if f then
|
||||
f:close()
|
||||
armor.textures[name].skin = "player_"..name..".png"
|
||||
end
|
||||
end
|
||||
for i=1, ARMOR_INIT_TIMES do
|
||||
minetest.after(ARMOR_INIT_DELAY * i, function(player)
|
||||
armor:set_player_armor(player)
|
||||
if inventory_plus == nil and unified_inventory == nil then
|
||||
--armor:update_inventory(player)
|
||||
end
|
||||
end, player)
|
||||
end
|
||||
end)
|
||||
|
||||
if ARMOR_DROP == true or ARMOR_DESTROY == true then
|
||||
minetest.register_on_dieplayer(function(player)
|
||||
local name = player:get_player_name()
|
||||
local pos = player:getpos()
|
||||
if name and pos then
|
||||
local drop = {}
|
||||
local player_inv = player:get_inventory()
|
||||
local armor_inv = minetest.get_inventory({type="detached", name=name.."_armor"})
|
||||
for i=1, player_inv:get_size("armor") do
|
||||
local stack = armor_inv:get_stack("armor", i)
|
||||
if stack:get_count() > 0 then
|
||||
table.insert(drop, stack)
|
||||
armor_inv:set_stack("armor", i, nil)
|
||||
player_inv:set_stack("armor", i, nil)
|
||||
end
|
||||
end
|
||||
armor:set_player_armor(player)
|
||||
--[[if unified_inventory then
|
||||
unified_inventory.set_inventory_formspec(player, "craft")
|
||||
elseif inventory_plus then
|
||||
local formspec = inventory_plus.get_formspec(player,"main")
|
||||
inventory_plus.set_inventory_formspec(player, formspec)
|
||||
else
|
||||
armor:update_inventory(player)
|
||||
end]]
|
||||
if ARMOR_DESTROY == false then
|
||||
if minetest.get_modpath("bones") then
|
||||
minetest.after(ARMOR_BONES_DELAY, function()
|
||||
pos = vector.round(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
if node.name == "bones:bones" then
|
||||
local meta = minetest.get_meta(pos)
|
||||
local owner = meta:get_string("owner")
|
||||
local inv = meta:get_inventory()
|
||||
if name == owner then
|
||||
for _,stack in ipairs(drop) do
|
||||
if inv:room_for_item("main", stack) then
|
||||
inv:add_item("main", stack)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
else
|
||||
for _,stack in ipairs(drop) do
|
||||
local obj = minetest.add_item(pos, stack)
|
||||
if obj then
|
||||
local x = math.random(1, 5)
|
||||
if math.random(1,2) == 1 then
|
||||
x = -x
|
||||
end
|
||||
local z = math.random(1, 5)
|
||||
if math.random(1,2) == 1 then
|
||||
z = -z
|
||||
end
|
||||
obj:setvelocity({x=1/x, y=obj:getvelocity().y, z=1/z})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
minetest.register_globalstep(function(dtime)
|
||||
time = time + dtime
|
||||
if time > ARMOR_UPDATE_TIME then
|
||||
for _,player in ipairs(minetest.get_connected_players()) do
|
||||
armor:update_armor(player)
|
||||
end
|
||||
time = 0
|
||||
end
|
||||
end)
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
3d_armor -- Crafting Guide
|
||||
--------------------------
|
||||
|
||||
Helmets:
|
||||
|
||||
+---+---+---+
|
||||
| X | X | X |
|
||||
+---+---+---+
|
||||
| X | | X |
|
||||
+---+---+---+
|
||||
| | | |
|
||||
+---+---+---+
|
||||
|
||||
[3d_armor:helmet_wood] X = [default:wood]
|
||||
[3d_armor:helmet_steel] X = [default:steel_ingot]
|
||||
[3d_armor:helmet_bronze] X = [default:bronze_ingot]
|
||||
[3d_armor:helmet_diamond] X = [default:diamond]
|
||||
|
||||
Chestplates:
|
||||
|
||||
+---+---+---+
|
||||
| X | | X |
|
||||
+---+---+---+
|
||||
| X | X | X |
|
||||
+---+---+---+
|
||||
| X | X | X |
|
||||
+---+---+---+
|
||||
|
||||
[3d_armor:chestplate_wood] X = [default:wood]
|
||||
[3d_armor:chestplate_steel] X = [default:steel_ingot]
|
||||
[3d_armor:chestplate_bronze] X = [default:bronze_ingot]
|
||||
[3d_armor:chestplate_diamond] X = [default:diamond]
|
||||
|
||||
Leggings:
|
||||
|
||||
+---+---+---+
|
||||
| X | X | X |
|
||||
+---+---+---+
|
||||
| X | | X |
|
||||
+---+---+---+
|
||||
| X | | X |
|
||||
+---+---+---+
|
||||
|
||||
[3d_armor:leggings_wood] X = [default:wood]
|
||||
[3d_armor:leggings_steel] X = [default:steel_ingot]
|
||||
[3d_armor:leggings_bronze] X = [default:bronze_ingot]
|
||||
[3d_armor:leggings_diamond] X = [default:diamond]
|
||||
|
||||
Boots:
|
||||
|
||||
+---+---+---+
|
||||
| X | | X |
|
||||
+---+---+---+
|
||||
| X | | X |
|
||||
+---+---+---+
|
||||
|
||||
[3d_armor:boots_wood] X = [default:wood]
|
||||
[3d_armor:boots_steel] X = [default:steel_ingot]
|
||||
[3d_armor:boots_bronze] X = [default:bronze_ingot
|
||||
[3d_armor:boots_diamond] X = [default:diamond]
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
default
|
||||
|
|
@ -0,0 +1,195 @@
|
|||
ARMOR_MOD_NAME = minetest.get_current_modname()
|
||||
dofile(minetest.get_modpath(minetest.get_current_modname()).."/armor.lua")
|
||||
|
||||
-- Regisiter Head Armor
|
||||
|
||||
minetest.register_tool("3d_armor:helmet_leather", {
|
||||
description = "Leather Helmet",
|
||||
inventory_image = "3d_armor_inv_helmet_leather.png",
|
||||
groups = {armor_head=5, armor_heal=0, armor_use=100},
|
||||
wear = 0,
|
||||
})
|
||||
|
||||
minetest.register_tool("3d_armor:helmet_steel", {
|
||||
description = "Steel Helmet",
|
||||
inventory_image = "3d_armor_inv_helmet_steel.png",
|
||||
groups = {armor_head=10, armor_heal=5, armor_use=250},
|
||||
wear = 0,
|
||||
})
|
||||
|
||||
minetest.register_tool("3d_armor:helmet_gold", {
|
||||
description = "Golden Helmet",
|
||||
inventory_image = "3d_armor_inv_helmet_gold.png",
|
||||
groups = {armor_head=15, armor_heal=10, armor_use=500},
|
||||
wear = 0,
|
||||
})
|
||||
|
||||
minetest.register_tool("3d_armor:helmet_diamond",{
|
||||
description = "Diamond Helmet",
|
||||
inventory_image = "3d_armor_inv_helmet_diamond.png",
|
||||
groups = {armor_head=20, armor_heal=15, armor_use=750},
|
||||
wear = 0,
|
||||
})
|
||||
|
||||
minetest.register_tool("3d_armor:helmet_chain", {
|
||||
description = "Chain Helmet",
|
||||
inventory_image = "3d_armor_inv_helmet_chain.png",
|
||||
groups = {armor_head=15, armor_heal=10, armor_use=500},
|
||||
wear = 0,
|
||||
})
|
||||
|
||||
-- Regisiter Torso Armor
|
||||
|
||||
minetest.register_tool("3d_armor:chestplate_leather", {
|
||||
description = "Leather Chestplate",
|
||||
inventory_image = "3d_armor_inv_chestplate_leather.png",
|
||||
groups = {armor_torso=15, armor_heal=0, armor_use=100},
|
||||
wear = 0,
|
||||
})
|
||||
|
||||
minetest.register_tool("3d_armor:chestplate_steel", {
|
||||
description = "Steel Chestplate",
|
||||
inventory_image = "3d_armor_inv_chestplate_steel.png",
|
||||
groups = {armor_torso=20, armor_heal=5, armor_use=250},
|
||||
wear = 0,
|
||||
})
|
||||
|
||||
minetest.register_tool("3d_armor:chestplate_gold", {
|
||||
description = "Golden Chestplate",
|
||||
inventory_image = "3d_armor_inv_chestplate_gold.png",
|
||||
groups = {armor_torso=25, armor_heal=10, armor_use=500},
|
||||
wear = 0,
|
||||
})
|
||||
|
||||
minetest.register_tool("3d_armor:chestplate_diamond",{
|
||||
description = "Diamond Helmet",
|
||||
inventory_image = "3d_armor_inv_chestplate_diamond.png",
|
||||
groups = {armor_torso=30, armor_heal=15, armor_use=750},
|
||||
wear = 0,
|
||||
})
|
||||
|
||||
minetest.register_tool("3d_armor:chestplate_chain", {
|
||||
description = "Chain Chestplate",
|
||||
inventory_image = "3d_armor_inv_chestplate_chain.png",
|
||||
groups = {armor_torso=25, armor_heal=10, armor_use=500},
|
||||
wear = 0,
|
||||
})
|
||||
|
||||
-- Regisiter Leg Armor
|
||||
|
||||
minetest.register_tool("3d_armor:leggings_leather", {
|
||||
description = "Leather Leggings",
|
||||
inventory_image = "3d_armor_inv_leggings_leather.png",
|
||||
groups = {armor_legs=10, armor_heal=0, armor_use=100},
|
||||
wear = 0,
|
||||
})
|
||||
|
||||
minetest.register_tool("3d_armor:leggings_steel", {
|
||||
description = "Steel Leggings",
|
||||
inventory_image = "3d_armor_inv_leggings_steel.png",
|
||||
groups = {armor_legs=15, armor_heal=5, armor_use=250},
|
||||
wear = 0,
|
||||
})
|
||||
|
||||
minetest.register_tool("3d_armor:leggings_gold", {
|
||||
description = "Golden Leggings",
|
||||
inventory_image = "3d_armor_inv_leggings_gold.png",
|
||||
groups = {armor_legs=20, armor_heal=10, armor_use=500},
|
||||
wear = 0,
|
||||
})
|
||||
|
||||
minetest.register_tool("3d_armor:leggings_diamond",{
|
||||
description = "Diamond Helmet",
|
||||
inventory_image = "3d_armor_inv_leggings_diamond.png",
|
||||
groups = {armor_legs=25, armor_heal=15, armor_use=750},
|
||||
wear = 0,
|
||||
})
|
||||
|
||||
minetest.register_tool("3d_armor:leggings_chain", {
|
||||
description = "Chain Leggings",
|
||||
inventory_image = "3d_armor_inv_leggings_chain.png",
|
||||
groups = {armor_legs=20, armor_heal=10, armor_use=500},
|
||||
wear = 0,
|
||||
})
|
||||
-- Regisiter Boots
|
||||
|
||||
minetest.register_tool("3d_armor:boots_leather", {
|
||||
description = "Leather Boots",
|
||||
inventory_image = "3d_armor_inv_boots_leather.png",
|
||||
groups = {armor_feet=5, armor_heal=0, armor_use=100},
|
||||
wear = 0,
|
||||
})
|
||||
|
||||
minetest.register_tool("3d_armor:boots_steel", {
|
||||
description = "Steel Boots",
|
||||
inventory_image = "3d_armor_inv_boots_steel.png",
|
||||
groups = {armor_feet=10, armor_heal=5, armor_use=250},
|
||||
wear = 0,
|
||||
})
|
||||
|
||||
minetest.register_tool("3d_armor:boots_gold", {
|
||||
description = "Golden Boots",
|
||||
inventory_image = "3d_armor_inv_boots_gold.png",
|
||||
groups = {armor_feet=15, armor_heal=10, armor_use=500},
|
||||
wear = 0,
|
||||
})
|
||||
|
||||
minetest.register_tool("3d_armor:boots_diamond",{
|
||||
description = "Diamond Helmet",
|
||||
inventory_image = "3d_armor_inv_boots_diamond.png",
|
||||
groups = {armor_feet=20, armor_heal=15, armor_use=750},
|
||||
wear = 0,
|
||||
})
|
||||
|
||||
minetest.register_tool("3d_armor:boots_chain", {
|
||||
description = "Chain Boots",
|
||||
inventory_image = "3d_armor_inv_boots_chain.png",
|
||||
groups = {armor_feet=15, armor_heal=10, armor_use=500},
|
||||
wear = 0,
|
||||
})
|
||||
|
||||
-- Register Craft Recipies
|
||||
|
||||
local craft_ingreds = {
|
||||
leather = "default:wood",
|
||||
steel = "default:steel_ingot",
|
||||
gold = "default:gold_ingot",
|
||||
diamond = "default:diamond",
|
||||
chain = "fire:fire",
|
||||
}
|
||||
|
||||
for k, v in pairs(craft_ingreds) do
|
||||
minetest.register_craft({
|
||||
output = "3d_armor:helmet_"..k,
|
||||
recipe = {
|
||||
{v, v, v},
|
||||
{v, "", v},
|
||||
{"", "", ""},
|
||||
},
|
||||
})
|
||||
minetest.register_craft({
|
||||
output = "3d_armor:chestplate_"..k,
|
||||
recipe = {
|
||||
{v, "", v},
|
||||
{v, v, v},
|
||||
{v, v, v},
|
||||
},
|
||||
})
|
||||
minetest.register_craft({
|
||||
output = "3d_armor:leggings_"..k,
|
||||
recipe = {
|
||||
{v, v, v},
|
||||
{v, "", v},
|
||||
{v, "", v},
|
||||
},
|
||||
})
|
||||
minetest.register_craft({
|
||||
output = "3d_armor:boots_"..k,
|
||||
recipe = {
|
||||
{v, "", v},
|
||||
{v, "", v},
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
[Dolphin]
|
||||
PreviewsShown=true
|
||||
Timestamp=2016,12,29,21,12,41
|
||||
Version=3
|
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 643 B |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 275 B |
After Width: | Height: | Size: 248 B |
After Width: | Height: | Size: 248 B |
After Width: | Height: | Size: 433 B |
After Width: | Height: | Size: 241 B |
After Width: | Height: | Size: 318 B |
After Width: | Height: | Size: 277 B |
After Width: | Height: | Size: 277 B |
After Width: | Height: | Size: 472 B |
After Width: | Height: | Size: 269 B |
After Width: | Height: | Size: 266 B |
After Width: | Height: | Size: 221 B |
After Width: | Height: | Size: 229 B |
After Width: | Height: | Size: 341 B |
After Width: | Height: | Size: 216 B |
After Width: | Height: | Size: 236 B |
After Width: | Height: | Size: 197 B |
After Width: | Height: | Size: 197 B |
After Width: | Height: | Size: 372 B |
After Width: | Height: | Size: 191 B |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 146 B |
|
@ -0,0 +1,7 @@
|
|||
3D Armor - Visible Player Armor
|
||||
===============================
|
||||
|
||||
Source Code: Copyright (C) 2013 Stuart Jones - LGPL
|
||||
|
||||
Special credit to Jordach and MirceaKitsune for providing the default 3d character model.
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
Modpack - 3d Armor
|
||||
==================
|
||||
|
||||
[mod] Unified Skins [unified_skins]
|
||||
-----------------------------------
|
||||
|
||||
depends: default
|
||||
|
||||
A 3d character model re-texturing api used as the framework for this modpack.
|
||||
|
||||
Compatible with player skins mod [skins] by Zeg9 and Player Textures [player_textures] by sdzen.
|
||||
|
||||
Note: Currently only supports 64x32px player skins.
|
||||
|
||||
[mod] Visible Wielded Items [wieldview]
|
||||
---------------------------------------
|
||||
|
||||
depends: unified_skins
|
||||
|
||||
Makes hand wielded items visible to other players.
|
||||
|
||||
Note: Currently only supports 16x16px texture packs, sorry!
|
||||
|
||||
[mod] Visible Player Armor [3d_armor]
|
||||
-------------------------------------
|
||||
|
||||
depends: unified_skins, inventory_plus
|
||||
|
||||
Adds craftable armor that is visible to other players. Each armor item worn contributes to
|
||||
a player's armor group level making them less vulnerable to weapons.
|
||||
|
||||
Armor takes damage when a player is hurt, however, many armor items offer a 'stackable'
|
||||
percentage chance of restoring the lost health points.
|
||||
|
||||
[mod] Shields [shields]
|
||||
-------------------------------------
|
||||
|
||||
depends: 3d_armor
|
||||
|
||||
Originally a part of 3d_armor, shields have been re-included as an optional extra.
|
||||
If you do not want shields then simply remove the shields folder from the modpack.
|
|
@ -0,0 +1,7 @@
|
|||
A 3d character model re-texturing api used as the framework for this modpack.
|
||||
|
||||
depends: default
|
||||
|
||||
Compatible with player skins mod [skins] by Zeg9 and Player Textures [player_textures] by sdzen.
|
||||
|
||||
Note: Currently only 64x32px player skins.
|
|
@ -0,0 +1 @@
|
|||
default
|
|
@ -0,0 +1,47 @@
|
|||
--[[
|
||||
uniskins = {
|
||||
skin = {},
|
||||
armor = {},
|
||||
wielditem = {},
|
||||
default_skin = "character.png",
|
||||
default_texture = "uniskins_trans.png",
|
||||
}
|
||||
|
||||
uniskins.update_player_visuals = function(self, player)
|
||||
if not player then
|
||||
return
|
||||
end
|
||||
local name = player:get_player_name()
|
||||
player:set_properties({
|
||||
visual = "mesh",
|
||||
mesh = "uniskins_character.x",
|
||||
textures = {
|
||||
self.skin[name],
|
||||
self.armor[name],
|
||||
self.wielditem[name]
|
||||
},
|
||||
visual_size = {x=1, y=1},
|
||||
})
|
||||
end
|
||||
|
||||
minetest.register_on_joinplayer(function(player)
|
||||
local name = player:get_player_name()
|
||||
uniskins.skin[name] = uniskins.default_skin
|
||||
uniskins.armor[name] = uniskins.default_texture
|
||||
uniskins.wielditem[name] = uniskins.default_texture
|
||||
if minetest.get_modpath("player_textures") then
|
||||
local filename = minetest.get_modpath("player_textures").."/textures/player_"..name
|
||||
local f = io.open(filename..".png")
|
||||
if f then
|
||||
f:close()
|
||||
uniskins.skin[name] = "player_"..name..".png"
|
||||
end
|
||||
end
|
||||
if minetest.get_modpath("skins") then
|
||||
local skin = skins.skins[name]
|
||||
if skin and skins.get_type(skin) == skins.type.MODEL then
|
||||
uniskins.skin[name] = skin..".png"
|
||||
end
|
||||
end
|
||||
end)
|
||||
]]
|
|
@ -0,0 +1,4 @@
|
|||
[Dolphin]
|
||||
PreviewsShown=true
|
||||
Timestamp=2016,12,29,21,12,52
|
||||
Version=3
|
After Width: | Height: | Size: 146 B |
|
@ -0,0 +1,17 @@
|
|||
[mod] visible wielded items [wieldview]
|
||||
=======================================
|
||||
|
||||
depends: default, unified_skins
|
||||
|
||||
Makes hand wielded items visible to other players. Compatible with player skins mod [skins].
|
||||
|
||||
Note: Currently only supports 16x16px texture packs, sorry!
|
||||
|
||||
default settings: [minetest.conf]
|
||||
|
||||
# Set number of seconds between visible wielded item updates.
|
||||
wieldview_update_time = 2
|
||||
|
||||
# Show nodes as tiles, disabled by default
|
||||
wieldview_node_tiles = false
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
default
|
||||
3d_armor
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
local time = 0
|
||||
local update_time = tonumber(minetest.setting_get("wieldview_update_time"))
|
||||
if not update_time then
|
||||
update_time = 2
|
||||
minetest.setting_set("wieldview_update_time", tostring(update_time))
|
||||
end
|
||||
local node_tiles = minetest.setting_getbool("wieldview_node_tiles")
|
||||
if not node_tiles then
|
||||
node_tiles = false
|
||||
minetest.setting_set("wieldview_node_tiles", "false")
|
||||
end
|
||||
|
||||
wieldview = {
|
||||
wielded_item = {},
|
||||
transform = {},
|
||||
}
|
||||
|
||||
dofile(minetest.get_modpath(minetest.get_current_modname()).."/transform.lua")
|
||||
|
||||
wieldview.get_item_texture = function(self, item)
|
||||
local texture = "3d_armor_trans.png"
|
||||
if item ~= "" then
|
||||
if minetest.registered_items[item] then
|
||||
local inventory_image = minetest.registered_items[item].inventory_image
|
||||
if inventory_image and inventory_image ~= "" then
|
||||
texture = inventory_image
|
||||
elseif node_tiles == true and minetest.registered_items[item].tiles then
|
||||
texture = minetest.registered_items[item].tiles[1]
|
||||
end
|
||||
end
|
||||
if wieldview.transform[item] then
|
||||
texture = texture.."^[transform"..wieldview.transform[item]
|
||||
end
|
||||
end
|
||||
return texture
|
||||
end
|
||||
|
||||
wieldview.update_wielded_item = function(self, player)
|
||||
if not player then
|
||||
return
|
||||
end
|
||||
local name = player:get_player_name()
|
||||
local stack = player:get_wielded_item()
|
||||
local item = stack:get_name()
|
||||
if not item then
|
||||
return
|
||||
end
|
||||
if self.wielded_item[name] then
|
||||
if self.wielded_item[name] == item then
|
||||
return
|
||||
end
|
||||
armor.textures[name].wielditem = self:get_item_texture(item)
|
||||
armor:update_player_visuals(player)
|
||||
end
|
||||
self.wielded_item[name] = item
|
||||
end
|
||||
|
||||
minetest.register_on_joinplayer(function(player)
|
||||
local name = player:get_player_name()
|
||||
wieldview.wielded_item[name] = ""
|
||||
minetest.after(0, function(player)
|
||||
wieldview:update_wielded_item(player)
|
||||
end, player)
|
||||
end)
|
||||
|
||||
minetest.register_globalstep(function(dtime)
|
||||
time = time + dtime
|
||||
if time > update_time then
|
||||
for _,player in ipairs(minetest.get_connected_players()) do
|
||||
wieldview:update_wielded_item(player)
|
||||
end
|
||||
time = 0
|
||||
end
|
||||
end)
|
|
@ -0,0 +1,24 @@
|
|||
-- Wielded Item Transformations - http://dev.minetest.net/texture
|
||||
|
||||
wieldview_transform = {
|
||||
["default:torch"]="R270",
|
||||
["default:sapling"]="R270",
|
||||
["flowers:dandelion_white"]="R270",
|
||||
["flowers:dandelion_yellow"]="R270",
|
||||
["flowers:geranium"]="R270",
|
||||
["flowers:rose"]="R270",
|
||||
["flowers:tulip"]="R270",
|
||||
["flowers:viola"]="R270",
|
||||
["bucket:bucket_empty"]="R270",
|
||||
["bucket:bucket_water"]="R270",
|
||||
["bucket:bucket_lava"]="R270",
|
||||
["screwdriver:screwdriver"]="R270",
|
||||
["screwdriver:screwdriver1"]="R270",
|
||||
["screwdriver:screwdriver2"]="R270",
|
||||
["screwdriver:screwdriver3"]="R270",
|
||||
["screwdriver:screwdriver4"]="R270",
|
||||
["vessels:glass_bottle"]="R270",
|
||||
["vessels:drinking_glass"]="R270",
|
||||
["vessels:steel_bottle"]="R270",
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
Minetest Game mod: beds
|
||||
=======================
|
||||
See license.txt for license information.
|
||||
|
||||
Authors of source code
|
||||
----------------------
|
||||
Originally by BlockMen (MIT)
|
||||
Various Minetest developers and contributors (MIT)
|
||||
|
||||
Authors of media (textures)
|
||||
---------------------------
|
||||
BlockMen (CC BY-SA 3.0)
|
||||
|
||||
This mod adds a bed to Minetest which allows to skip the night.
|
||||
To sleep, rightclick the bed. If playing in singleplayer mode the night gets skipped
|
||||
immediately. If playing multiplayer you get shown how many other players are in bed too,
|
||||
if all players are sleeping the night gets skipped. The night skip can be forced if more
|
||||
than 50% of the players are lying in bed and use this option.
|
||||
|
||||
Another feature is a controlled respawning. If you have slept in bed (not just lying in
|
||||
it) your respawn point is set to the beds location and you will respawn there after
|
||||
death.
|
||||
You can disable the respawn at beds by setting "enable_bed_respawn = false" in
|
||||
minetest.conf.
|
||||
You can disable the night skip feature by setting "enable_bed_night_skip = false" in
|
||||
minetest.conf or by using the /set command in-game.
|
|
@ -0,0 +1,158 @@
|
|||
|
||||
local reverse = true
|
||||
|
||||
local function destruct_bed(pos, n)
|
||||
local node = minetest.get_node(pos)
|
||||
local other
|
||||
|
||||
if n == 2 then
|
||||
local dir = minetest.facedir_to_dir(node.param2)
|
||||
other = vector.subtract(pos, dir)
|
||||
elseif n == 1 then
|
||||
local dir = minetest.facedir_to_dir(node.param2)
|
||||
other = vector.add(pos, dir)
|
||||
end
|
||||
|
||||
if reverse then
|
||||
reverse = not reverse
|
||||
minetest.remove_node(other)
|
||||
minetest.check_for_falling(other)
|
||||
else
|
||||
reverse = not reverse
|
||||
end
|
||||
end
|
||||
|
||||
function beds.register_bed(name, def)
|
||||
minetest.register_node(name .. "_bottom", {
|
||||
description = def.description,
|
||||
inventory_image = def.inventory_image,
|
||||
wield_image = def.wield_image,
|
||||
drawtype = "nodebox",
|
||||
tiles = def.tiles.bottom,
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
is_ground_content = false,
|
||||
stack_max = 1,
|
||||
groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 3, bed = 1},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = def.nodebox.bottom,
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = def.selectionbox,
|
||||
},
|
||||
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
local under = pointed_thing.under
|
||||
local pos
|
||||
if minetest.registered_items[minetest.get_node(under).name].buildable_to then
|
||||
pos = under
|
||||
else
|
||||
pos = pointed_thing.above
|
||||
end
|
||||
|
||||
if minetest.is_protected(pos, placer:get_player_name()) and
|
||||
not minetest.check_player_privs(placer, "protection_bypass") then
|
||||
minetest.record_protection_violation(pos, placer:get_player_name())
|
||||
return itemstack
|
||||
end
|
||||
|
||||
local node_def = minetest.registered_nodes[minetest.get_node(pos).name]
|
||||
if not node_def or not node_def.buildable_to then
|
||||
return itemstack
|
||||
end
|
||||
|
||||
local dir = minetest.dir_to_facedir(placer:get_look_dir())
|
||||
local botpos = vector.add(pos, minetest.facedir_to_dir(dir))
|
||||
|
||||
if minetest.is_protected(botpos, placer:get_player_name()) and
|
||||
not minetest.check_player_privs(placer, "protection_bypass") then
|
||||
minetest.record_protection_violation(botpos, placer:get_player_name())
|
||||
return itemstack
|
||||
end
|
||||
|
||||
local botdef = minetest.registered_nodes[minetest.get_node(botpos).name]
|
||||
if not botdef or not botdef.buildable_to then
|
||||
return itemstack
|
||||
end
|
||||
|
||||
minetest.set_node(pos, {name = name .. "_bottom", param2 = dir})
|
||||
minetest.set_node(botpos, {name = name .. "_top", param2 = dir})
|
||||
|
||||
if not minetest.setting_getbool("creative_mode") then
|
||||
itemstack:take_item()
|
||||
end
|
||||
return itemstack
|
||||
end,
|
||||
|
||||
on_destruct = function(pos)
|
||||
destruct_bed(pos, 1)
|
||||
end,
|
||||
|
||||
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
|
||||
beds.on_rightclick(pos, clicker)
|
||||
return itemstack
|
||||
end,
|
||||
|
||||
on_rotate = function(pos, node, user, mode, new_param2)
|
||||
local dir = minetest.facedir_to_dir(node.param2)
|
||||
local p = vector.add(pos, dir)
|
||||
local node2 = minetest.get_node_or_nil(p)
|
||||
if not node2 or not minetest.get_item_group(node2.name, "bed") == 2 or
|
||||
not node.param2 == node2.param2 then
|
||||
return false
|
||||
end
|
||||
if minetest.is_protected(p, user:get_player_name()) then
|
||||
minetest.record_protection_violation(p, user:get_player_name())
|
||||
return false
|
||||
end
|
||||
if mode ~= screwdriver.ROTATE_FACE then
|
||||
return false
|
||||
end
|
||||
local newp = vector.add(pos, minetest.facedir_to_dir(new_param2))
|
||||
local node3 = minetest.get_node_or_nil(newp)
|
||||
local node_def = node3 and minetest.registered_nodes[node3.name]
|
||||
if not node_def or not node_def.buildable_to then
|
||||
return false
|
||||
end
|
||||
if minetest.is_protected(newp, user:get_player_name()) then
|
||||
minetest.record_protection_violation(newp, user:get_player_name())
|
||||
return false
|
||||
end
|
||||
node.param2 = new_param2
|
||||
-- do not remove_node here - it will trigger destroy_bed()
|
||||
minetest.set_node(p, {name = "air"})
|
||||
minetest.set_node(pos, node)
|
||||
minetest.set_node(newp, {name = name .. "_top", param2 = new_param2})
|
||||
return true
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_node(name .. "_top", {
|
||||
drawtype = "nodebox",
|
||||
tiles = def.tiles.top,
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
is_ground_content = false,
|
||||
pointable = false,
|
||||
groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 3, bed = 2},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
drop = name .. "_bottom",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = def.nodebox.top,
|
||||
},
|
||||
on_destruct = function(pos)
|
||||
destruct_bed(pos, 2)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_alias(name, name .. "_bottom")
|
||||
|
||||
minetest.register_craft({
|
||||
output = name,
|
||||
recipe = def.recipe
|
||||
})
|
||||
end
|
|
@ -0,0 +1,104 @@
|
|||
-- Fancy shaped bed
|
||||
|
||||
beds.register_bed("beds:fancy_bed", {
|
||||
description = "Fancy Bed",
|
||||
inventory_image = "beds_bed_fancy.png",
|
||||
wield_image = "beds_bed_fancy.png",
|
||||
tiles = {
|
||||
bottom = {
|
||||
"beds_bed_top1.png",
|
||||
"default_wood.png",
|
||||
"beds_bed_side1.png",
|
||||
"beds_bed_side1.png^[transformFX",
|
||||
"default_wood.png",
|
||||
"beds_bed_foot.png",
|
||||
},
|
||||
top = {
|
||||
"beds_bed_top2.png",
|
||||
"default_wood.png",
|
||||
"beds_bed_side2.png",
|
||||
"beds_bed_side2.png^[transformFX",
|
||||
"beds_bed_head.png",
|
||||
"default_wood.png",
|
||||
}
|
||||
},
|
||||
nodebox = {
|
||||
bottom = {
|
||||
{-0.5, -0.5, -0.5, -0.375, -0.065, -0.4375},
|
||||
{0.375, -0.5, -0.5, 0.5, -0.065, -0.4375},
|
||||
{-0.5, -0.375, -0.5, 0.5, -0.125, -0.4375},
|
||||
{-0.5, -0.375, -0.5, -0.4375, -0.125, 0.5},
|
||||
{0.4375, -0.375, -0.5, 0.5, -0.125, 0.5},
|
||||
{-0.4375, -0.3125, -0.4375, 0.4375, -0.0625, 0.5},
|
||||
},
|
||||
top = {
|
||||
{-0.5, -0.5, 0.4375, -0.375, 0.1875, 0.5},
|
||||
{0.375, -0.5, 0.4375, 0.5, 0.1875, 0.5},
|
||||
{-0.5, 0, 0.4375, 0.5, 0.125, 0.5},
|
||||
{-0.5, -0.375, 0.4375, 0.5, -0.125, 0.5},
|
||||
{-0.5, -0.375, -0.5, -0.4375, -0.125, 0.5},
|
||||
{0.4375, -0.375, -0.5, 0.5, -0.125, 0.5},
|
||||
{-0.4375, -0.3125, -0.5, 0.4375, -0.0625, 0.4375},
|
||||
}
|
||||
},
|
||||
selectionbox = {-0.5, -0.5, -0.5, 0.5, 0.06, 1.5},
|
||||
recipe = {
|
||||
{"", "", "group:stick"},
|
||||
{"wool:red", "wool:red", "wool:white"},
|
||||
{"group:wood", "group:wood", "group:wood"},
|
||||
},
|
||||
})
|
||||
|
||||
-- Simple shaped bed
|
||||
|
||||
beds.register_bed("beds:bed", {
|
||||
description = "Simple Bed",
|
||||
inventory_image = "beds_bed.png",
|
||||
wield_image = "beds_bed.png",
|
||||
tiles = {
|
||||
bottom = {
|
||||
"beds_bed_top_bottom.png^[transformR90",
|
||||
"default_wood.png",
|
||||
"beds_bed_side_bottom_r.png",
|
||||
"beds_bed_side_bottom_r.png^[transformfx",
|
||||
"beds_transparent.png",
|
||||
"beds_bed_side_bottom.png"
|
||||
},
|
||||
top = {
|
||||
"beds_bed_top_top.png^[transformR90",
|
||||
"default_wood.png",
|
||||
"beds_bed_side_top_r.png",
|
||||
"beds_bed_side_top_r.png^[transformfx",
|
||||
"beds_bed_side_top.png",
|
||||
"beds_transparent.png",
|
||||
}
|
||||
},
|
||||
nodebox = {
|
||||
bottom = {-0.5, -0.5, -0.5, 0.5, 0.06, 0.5},
|
||||
top = {-0.5, -0.5, -0.5, 0.5, 0.06, 0.5},
|
||||
},
|
||||
selectionbox = {-0.5, -0.5, -0.5, 0.5, 0.06, 1.5},
|
||||
recipe = {
|
||||
{"wool:red", "wool:red", "wool:white"},
|
||||
{"group:wood", "group:wood", "group:wood"}
|
||||
},
|
||||
})
|
||||
|
||||
-- Aliases for PilzAdam's beds mod
|
||||
|
||||
minetest.register_alias("beds:bed_bottom_red", "beds:bed_bottom")
|
||||
minetest.register_alias("beds:bed_top_red", "beds:bed_top")
|
||||
|
||||
-- Fuel
|
||||
|
||||
minetest.register_craft({
|
||||
type = "fuel",
|
||||
recipe = "beds:fancy_bed_bottom",
|
||||
burntime = 13,
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "fuel",
|
||||
recipe = "beds:bed_bottom",
|
||||
burntime = 12,
|
||||
})
|
|
@ -0,0 +1,2 @@
|
|||
default
|
||||
wool
|
|
@ -0,0 +1,220 @@
|
|||
local pi = math.pi
|
||||
local player_in_bed = 0
|
||||
local is_sp = minetest.is_singleplayer()
|
||||
local enable_respawn = minetest.setting_getbool("enable_bed_respawn")
|
||||
if enable_respawn == nil then
|
||||
enable_respawn = true
|
||||
end
|
||||
|
||||
-- Helper functions
|
||||
|
||||
local function get_look_yaw(pos)
|
||||
local n = minetest.get_node(pos)
|
||||
if n.param2 == 1 then
|
||||
return pi / 2, n.param2
|
||||
elseif n.param2 == 3 then
|
||||
return -pi / 2, n.param2
|
||||
elseif n.param2 == 0 then
|
||||
return pi, n.param2
|
||||
else
|
||||
return 0, n.param2
|
||||
end
|
||||
end
|
||||
|
||||
local function is_night_skip_enabled()
|
||||
local enable_night_skip = minetest.setting_getbool("enable_bed_night_skip")
|
||||
if enable_night_skip == nil then
|
||||
enable_night_skip = true
|
||||
end
|
||||
return enable_night_skip
|
||||
end
|
||||
|
||||
local function check_in_beds(players)
|
||||
local in_bed = beds.player
|
||||
if not players then
|
||||
players = minetest.get_connected_players()
|
||||
end
|
||||
|
||||
for n, player in ipairs(players) do
|
||||
local name = player:get_player_name()
|
||||
if not in_bed[name] then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
return #players > 0
|
||||
end
|
||||
|
||||
local function lay_down(player, pos, bed_pos, state, skip)
|
||||
local name = player:get_player_name()
|
||||
local hud_flags = player:hud_get_flags()
|
||||
|
||||
if not player or not name then
|
||||
return
|
||||
end
|
||||
|
||||
-- stand up
|
||||
if state ~= nil and not state then
|
||||
local p = beds.pos[name] or nil
|
||||
if beds.player[name] ~= nil then
|
||||
beds.player[name] = nil
|
||||
player_in_bed = player_in_bed - 1
|
||||
end
|
||||
-- skip here to prevent sending player specific changes (used for leaving players)
|
||||
if skip then
|
||||
return
|
||||
end
|
||||
if p then
|
||||
player:setpos(p)
|
||||
end
|
||||
|
||||
-- physics, eye_offset, etc
|
||||
player:set_eye_offset({x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0})
|
||||
player:set_look_horizontal(math.random(1, 180) / 100)
|
||||
default.player_attached[name] = false
|
||||
player:set_physics_override(1, 1, 1)
|
||||
hud_flags.wielditem = true
|
||||
default.player_set_animation(player, "stand" , 30)
|
||||
|
||||
-- lay down
|
||||
else
|
||||
beds.player[name] = 1
|
||||
beds.pos[name] = pos
|
||||
player_in_bed = player_in_bed + 1
|
||||
|
||||
-- physics, eye_offset, etc
|
||||
player:set_eye_offset({x = 0, y = -13, z = 0}, {x = 0, y = 0, z = 0})
|
||||
local yaw, param2 = get_look_yaw(bed_pos)
|
||||
player:set_look_horizontal(yaw)
|
||||
local dir = minetest.facedir_to_dir(param2)
|
||||
local p = {x = bed_pos.x + dir.x / 2, y = bed_pos.y, z = bed_pos.z + dir.z / 2}
|
||||
player:set_physics_override(0, 0, 0)
|
||||
player:setpos(p)
|
||||
default.player_attached[name] = true
|
||||
hud_flags.wielditem = false
|
||||
default.player_set_animation(player, "lay" , 0)
|
||||
end
|
||||
|
||||
player:hud_set_flags(hud_flags)
|
||||
end
|
||||
|
||||
local function update_formspecs(finished)
|
||||
local ges = #minetest.get_connected_players()
|
||||
local form_n
|
||||
local is_majority = (ges / 2) < player_in_bed
|
||||
|
||||
if finished then
|
||||
form_n = beds.formspec .. "label[2.7,11; Good morning.]"
|
||||
else
|
||||
form_n = beds.formspec .. "label[2.2,11;" .. tostring(player_in_bed) ..
|
||||
" of " .. tostring(ges) .. " players are in bed]"
|
||||
if is_majority and is_night_skip_enabled() then
|
||||
form_n = form_n .. "button_exit[2,8;4,0.75;force;Force night skip]"
|
||||
end
|
||||
end
|
||||
|
||||
for name,_ in pairs(beds.player) do
|
||||
minetest.show_formspec(name, "beds_form", form_n)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Public functions
|
||||
|
||||
function beds.kick_players()
|
||||
for name, _ in pairs(beds.player) do
|
||||
local player = minetest.get_player_by_name(name)
|
||||
lay_down(player, nil, nil, false)
|
||||
end
|
||||
end
|
||||
|
||||
function beds.skip_night()
|
||||
minetest.set_timeofday(0.23)
|
||||
end
|
||||
|
||||
function beds.on_rightclick(pos, player)
|
||||
local name = player:get_player_name()
|
||||
local ppos = player:getpos()
|
||||
local tod = minetest.get_timeofday()
|
||||
|
||||
if tod > 0.2 and tod < 0.805 then
|
||||
if beds.player[name] then
|
||||
lay_down(player, nil, nil, false)
|
||||
end
|
||||
minetest.chat_send_player(name, "You can only sleep at night.")
|
||||
return
|
||||
end
|
||||
|
||||
-- move to bed
|
||||
if not beds.player[name] then
|
||||
lay_down(player, ppos, pos)
|
||||
beds.set_spawns() -- save respawn positions when entering bed
|
||||
else
|
||||
lay_down(player, nil, nil, false)
|
||||
end
|
||||
|
||||
if not is_sp then
|
||||
update_formspecs(false)
|
||||
end
|
||||
|
||||
-- skip the night and let all players stand up
|
||||
if check_in_beds() then
|
||||
minetest.after(2, function()
|
||||
if not is_sp then
|
||||
update_formspecs(is_night_skip_enabled())
|
||||
end
|
||||
if is_night_skip_enabled() then
|
||||
beds.skip_night()
|
||||
beds.kick_players()
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Callbacks
|
||||
-- Only register respawn callback if respawn enabled
|
||||
if enable_respawn then
|
||||
-- respawn player at bed if enabled and valid position is found
|
||||
minetest.register_on_respawnplayer(function(player)
|
||||
local name = player:get_player_name()
|
||||
local pos = beds.spawn[name]
|
||||
if pos then
|
||||
player:setpos(pos)
|
||||
return true
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
local name = player:get_player_name()
|
||||
lay_down(player, nil, nil, false, true)
|
||||
beds.player[name] = nil
|
||||
if check_in_beds() then
|
||||
minetest.after(2, function()
|
||||
update_formspecs(is_night_skip_enabled())
|
||||
if is_night_skip_enabled() then
|
||||
beds.skip_night()
|
||||
beds.kick_players()
|
||||
end
|
||||
end)
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
if formname ~= "beds_form" then
|
||||
return
|
||||
end
|
||||
if fields.quit or fields.leave then
|
||||
lay_down(player, nil, nil, false)
|
||||
update_formspecs(false)
|
||||
end
|
||||
|
||||
if fields.force then
|
||||
update_formspecs(is_night_skip_enabled())
|
||||
if is_night_skip_enabled() then
|
||||
beds.skip_night()
|
||||
beds.kick_players()
|
||||
end
|
||||
end
|
||||
end)
|
|
@ -0,0 +1,17 @@
|
|||
beds = {}
|
||||
beds.player = {}
|
||||
beds.pos = {}
|
||||
beds.spawn = {}
|
||||
|
||||
beds.formspec = "size[8,15;true]" ..
|
||||
"bgcolor[#080808BB; true]" ..
|
||||
"button_exit[2,12;4,0.75;leave;Leave Bed]"
|
||||
|
||||
local modpath = minetest.get_modpath("beds")
|
||||
|
||||
-- Load files
|
||||
|
||||
dofile(modpath .. "/functions.lua")
|
||||
dofile(modpath .. "/api.lua")
|
||||
dofile(modpath .. "/beds.lua")
|
||||
dofile(modpath .. "/spawns.lua")
|
|
@ -0,0 +1,60 @@
|
|||
License of source code
|
||||
----------------------
|
||||
|
||||
The MIT License (MIT)
|
||||
Copyright (C) 2014-2016 BlockMen
|
||||
Copyright (C) 2014-2016 Various Minetest developers and contributors
|
||||
|
||||
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.
|
||||
|
||||
For more details:
|
||||
https://opensource.org/licenses/MIT
|
||||
|
||||
|
||||
Licenses of media (textures)
|
||||
----------------------------
|
||||
|
||||
Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
|
||||
Copyright (C) 2014-2016 BlockMen
|
||||
|
||||
You are free to:
|
||||
Share — copy and redistribute the material in any medium or format.
|
||||
Adapt — remix, transform, and build upon the material for any purpose, even commercially.
|
||||
The licensor cannot revoke these freedoms as long as you follow the license terms.
|
||||
|
||||
Under the following terms:
|
||||
|
||||
Attribution — You must give appropriate credit, provide a link to the license, and
|
||||
indicate if changes were made. You may do so in any reasonable manner, but not in any way
|
||||
that suggests the licensor endorses you or your use.
|
||||
|
||||
ShareAlike — If you remix, transform, or build upon the material, you must distribute
|
||||
your contributions under the same license as the original.
|
||||
|
||||
No additional restrictions — You may not apply legal terms or technological measures that
|
||||
legally restrict others from doing anything the license permits.
|
||||
|
||||
Notices:
|
||||
|
||||
You do not have to comply with the license for elements of the material in the public
|
||||
domain or where your use is permitted by an applicable exception or limitation.
|
||||
No warranties are given. The license may not give you all of the permissions necessary
|
||||
for your intended use. For example, other rights such as publicity, privacy, or moral
|
||||
rights may limit how you use the material.
|
||||
|
||||
For more details:
|
||||
http://creativecommons.org/licenses/by-sa/3.0/
|
|
@ -0,0 +1,63 @@
|
|||
local world_path = minetest.get_worldpath()
|
||||
local org_file = world_path .. "/beds_spawns"
|
||||
local file = world_path .. "/beds_spawns"
|
||||
local bkwd = false
|
||||
|
||||
-- check for PA's beds mod spawns
|
||||
local cf = io.open(world_path .. "/beds_player_spawns", "r")
|
||||
if cf ~= nil then
|
||||
io.close(cf)
|
||||
file = world_path .. "/beds_player_spawns"
|
||||
bkwd = true
|
||||
end
|
||||
|
||||
function beds.read_spawns()
|
||||
local spawns = beds.spawn
|
||||
local input = io.open(file, "r")
|
||||
if input and not bkwd then
|
||||
repeat
|
||||
local x = input:read("*n")
|
||||
if x == nil then
|
||||
break
|
||||
end
|
||||
local y = input:read("*n")
|
||||
local z = input:read("*n")
|
||||
local name = input:read("*l")
|
||||
spawns[name:sub(2)] = {x = x, y = y, z = z}
|
||||
until input:read(0) == nil
|
||||
io.close(input)
|
||||
elseif input and bkwd then
|
||||
beds.spawn = minetest.deserialize(input:read("*all"))
|
||||
input:close()
|
||||
beds.save_spawns()
|
||||
os.rename(file, file .. ".backup")
|
||||
file = org_file
|
||||
end
|
||||
end
|
||||
|
||||
beds.read_spawns()
|
||||
|
||||
function beds.save_spawns()
|
||||
if not beds.spawn then
|
||||
return
|
||||
end
|
||||
local data = {}
|
||||
local output = io.open(org_file, "w")
|
||||
for k, v in pairs(beds.spawn) do
|
||||
table.insert(data, string.format("%.1f %.1f %.1f %s\n", v.x, v.y, v.z, k))
|
||||
end
|
||||
output:write(table.concat(data))
|
||||
io.close(output)
|
||||
end
|
||||
|
||||
function beds.set_spawns()
|
||||
for name,_ in pairs(beds.player) do
|
||||
local player = minetest.get_player_by_name(name)
|
||||
local p = player:getpos()
|
||||
-- but don't change spawn location if borrowing a bed
|
||||
if not minetest.is_protected(p, name) then
|
||||
beds.spawn[name] = p
|
||||
end
|
||||
end
|
||||
beds.save_spawns()
|
||||
end
|
After Width: | Height: | Size: 540 B |
After Width: | Height: | Size: 537 B |
After Width: | Height: | Size: 390 B |
After Width: | Height: | Size: 387 B |
After Width: | Height: | Size: 296 B |
After Width: | Height: | Size: 316 B |
After Width: | Height: | Size: 561 B |
After Width: | Height: | Size: 537 B |
After Width: | Height: | Size: 611 B |
After Width: | Height: | Size: 596 B |
After Width: | Height: | Size: 583 B |
After Width: | Height: | Size: 616 B |
After Width: | Height: | Size: 495 B |
After Width: | Height: | Size: 556 B |
After Width: | Height: | Size: 143 B |
|
@ -0,0 +1,15 @@
|
|||
Minetest Game mod: boats
|
||||
========================
|
||||
See license.txt for license information.
|
||||
|
||||
Authors of source code
|
||||
----------------------
|
||||
Originally by PilzAdam (MIT)
|
||||
Various Minetest developers and contributors (MIT)
|
||||
|
||||
Authors of media (textures and model)
|
||||
-------------------------------------
|
||||
Textures: Zeg9 (CC BY-SA 3.0)
|
||||
Model: thetoon and Zeg9 (CC BY-SA 3.0),
|
||||
modified by PavelS(SokolovPavel) (CC BY-SA 3.0),
|
||||
modified by sofar (CC BY-SA 3.0)
|
|
@ -0,0 +1 @@
|
|||
default
|
|
@ -0,0 +1,260 @@
|
|||
--
|
||||
-- Helper functions
|
||||
--
|
||||
|
||||
local function is_water(pos)
|
||||
local nn = minetest.get_node(pos).name
|
||||
return minetest.get_item_group(nn, "water") ~= 0
|
||||
end
|
||||
|
||||
|
||||
local function get_sign(i)
|
||||
if i == 0 then
|
||||
return 0
|
||||
else
|
||||
return i / math.abs(i)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function get_velocity(v, yaw, y)
|
||||
local x = -math.sin(yaw) * v
|
||||
local z = math.cos(yaw) * v
|
||||
return {x = x, y = y, z = z}
|
||||
end
|
||||
|
||||
|
||||
local function get_v(v)
|
||||
return math.sqrt(v.x ^ 2 + v.z ^ 2)
|
||||
end
|
||||
|
||||
--
|
||||
-- Boat entity
|
||||
--
|
||||
|
||||
local boat = {
|
||||
physical = true,
|
||||
-- Warning: Do not change the position of the collisionbox top surface,
|
||||
-- lowering it causes the boat to fall through the world if underwater
|
||||
collisionbox = {-0.5, -0.35, -0.5, 0.5, 0.3, 0.5},
|
||||
visual = "mesh",
|
||||
mesh = "boats_boat.obj",
|
||||
textures = {"default_wood.png"},
|
||||
|
||||
driver = nil,
|
||||
v = 0,
|
||||
last_v = 0,
|
||||
removed = false
|
||||
}
|
||||
|
||||
|
||||
function boat.on_rightclick(self, clicker)
|
||||
if not clicker or not clicker:is_player() then
|
||||
return
|
||||
end
|
||||
local name = clicker:get_player_name()
|
||||
if self.driver and clicker == self.driver then
|
||||
self.driver = nil
|
||||
clicker:set_detach()
|
||||
default.player_attached[name] = false
|
||||
default.player_set_animation(clicker, "stand" , 30)
|
||||
local pos = clicker:getpos()
|
||||
pos = {x = pos.x, y = pos.y + 0.2, z = pos.z}
|
||||
minetest.after(0.1, function()
|
||||
clicker:setpos(pos)
|
||||
end)
|
||||
elseif not self.driver then
|
||||
local attach = clicker:get_attach()
|
||||
if attach and attach:get_luaentity() then
|
||||
local luaentity = attach:get_luaentity()
|
||||
if luaentity.driver then
|
||||
luaentity.driver = nil
|
||||
end
|
||||
clicker:set_detach()
|
||||
end
|
||||
self.driver = clicker
|
||||
clicker:set_attach(self.object, "",
|
||||
{x = 0, y = 11, z = -3}, {x = 0, y = 0, z = 0})
|
||||
default.player_attached[name] = true
|
||||
minetest.after(0.2, function()
|
||||
default.player_set_animation(clicker, "sit" , 30)
|
||||
end)
|
||||
clicker:set_look_horizontal(self.object:getyaw())
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function boat.on_activate(self, staticdata, dtime_s)
|
||||
self.object:set_armor_groups({immortal = 1})
|
||||
if staticdata then
|
||||
self.v = tonumber(staticdata)
|
||||
end
|
||||
self.last_v = self.v
|
||||
end
|
||||
|
||||
|
||||
function boat.get_staticdata(self)
|
||||
return tostring(self.v)
|
||||
end
|
||||
|
||||
|
||||
function boat.on_punch(self, puncher)
|
||||
if not puncher or not puncher:is_player() or self.removed then
|
||||
return
|
||||
end
|
||||
if self.driver and puncher == self.driver then
|
||||
self.driver = nil
|
||||
puncher:set_detach()
|
||||
default.player_attached[puncher:get_player_name()] = false
|
||||
end
|
||||
if not self.driver then
|
||||
self.removed = true
|
||||
local inv = puncher:get_inventory()
|
||||
if not minetest.setting_getbool("creative_mode")
|
||||
or not inv:contains_item("main", "boats:boat") then
|
||||
local leftover = inv:add_item("main", "boats:boat")
|
||||
-- if no room in inventory add a replacement boat to the world
|
||||
if not leftover:is_empty() then
|
||||
minetest.add_item(self.object:getpos(), leftover)
|
||||
end
|
||||
end
|
||||
-- delay remove to ensure player is detached
|
||||
minetest.after(0.1, function()
|
||||
self.object:remove()
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function boat.on_step(self, dtime)
|
||||
self.v = get_v(self.object:getvelocity()) * get_sign(self.v)
|
||||
if self.driver then
|
||||
local ctrl = self.driver:get_player_control()
|
||||
local yaw = self.object:getyaw()
|
||||
if ctrl.up then
|
||||
self.v = self.v + 0.1
|
||||
elseif ctrl.down then
|
||||
self.v = self.v - 0.1
|
||||
end
|
||||
if ctrl.left then
|
||||
if self.v < 0 then
|
||||
self.object:setyaw(yaw - (1 + dtime) * 0.03)
|
||||
else
|
||||
self.object:setyaw(yaw + (1 + dtime) * 0.03)
|
||||
end
|
||||
elseif ctrl.right then
|
||||
if self.v < 0 then
|
||||
self.object:setyaw(yaw + (1 + dtime) * 0.03)
|
||||
else
|
||||
self.object:setyaw(yaw - (1 + dtime) * 0.03)
|
||||
end
|
||||
end
|
||||
end
|
||||
local velo = self.object:getvelocity()
|
||||
if self.v == 0 and velo.x == 0 and velo.y == 0 and velo.z == 0 then
|
||||
self.object:setpos(self.object:getpos())
|
||||
return
|
||||
end
|
||||
local s = get_sign(self.v)
|
||||
self.v = self.v - 0.02 * s
|
||||
if s ~= get_sign(self.v) then
|
||||
self.object:setvelocity({x = 0, y = 0, z = 0})
|
||||
self.v = 0
|
||||
return
|
||||
end
|
||||
if math.abs(self.v) > 5 then
|
||||
self.v = 5 * get_sign(self.v)
|
||||
end
|
||||
|
||||
local p = self.object:getpos()
|
||||
p.y = p.y - 0.5
|
||||
local new_velo
|
||||
local new_acce = {x = 0, y = 0, z = 0}
|
||||
if not is_water(p) then
|
||||
local nodedef = minetest.registered_nodes[minetest.get_node(p).name]
|
||||
if (not nodedef) or nodedef.walkable then
|
||||
self.v = 0
|
||||
new_acce = {x = 0, y = 1, z = 0}
|
||||
else
|
||||
new_acce = {x = 0, y = -9.8, z = 0}
|
||||
end
|
||||
new_velo = get_velocity(self.v, self.object:getyaw(),
|
||||
self.object:getvelocity().y)
|
||||
self.object:setpos(self.object:getpos())
|
||||
else
|
||||
p.y = p.y + 1
|
||||
if is_water(p) then
|
||||
local y = self.object:getvelocity().y
|
||||
if y >= 5 then
|
||||
y = 5
|
||||
elseif y < 0 then
|
||||
new_acce = {x = 0, y = 20, z = 0}
|
||||
else
|
||||
new_acce = {x = 0, y = 5, z = 0}
|
||||
end
|
||||
new_velo = get_velocity(self.v, self.object:getyaw(), y)
|
||||
self.object:setpos(self.object:getpos())
|
||||
else
|
||||
new_acce = {x = 0, y = 0, z = 0}
|
||||
if math.abs(self.object:getvelocity().y) < 1 then
|
||||
local pos = self.object:getpos()
|
||||
pos.y = math.floor(pos.y) + 0.5
|
||||
self.object:setpos(pos)
|
||||
new_velo = get_velocity(self.v, self.object:getyaw(), 0)
|
||||
else
|
||||
new_velo = get_velocity(self.v, self.object:getyaw(),
|
||||
self.object:getvelocity().y)
|
||||
self.object:setpos(self.object:getpos())
|
||||
end
|
||||
end
|
||||
end
|
||||
self.object:setvelocity(new_velo)
|
||||
self.object:setacceleration(new_acce)
|
||||
end
|
||||
|
||||
|
||||
minetest.register_entity("boats:boat", boat)
|
||||
|
||||
|
||||
minetest.register_craftitem("boats:boat", {
|
||||
description = "Boat",
|
||||
inventory_image = "boats_inventory.png",
|
||||
wield_image = "boats_wield.png",
|
||||
wield_scale = {x = 2, y = 2, z = 1},
|
||||
liquids_pointable = true,
|
||||
groups = {flammable = 2},
|
||||
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
if pointed_thing.type ~= "node" then
|
||||
return itemstack
|
||||
end
|
||||
if not is_water(pointed_thing.under) then
|
||||
return itemstack
|
||||
end
|
||||
pointed_thing.under.y = pointed_thing.under.y + 0.5
|
||||
boat = minetest.add_entity(pointed_thing.under, "boats:boat")
|
||||
if boat then
|
||||
boat:setyaw(placer:get_look_horizontal())
|
||||
if not minetest.setting_getbool("creative_mode") then
|
||||
itemstack:take_item()
|
||||
end
|
||||
end
|
||||
return itemstack
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
minetest.register_craft({
|
||||
output = "boats:boat",
|
||||
recipe = {
|
||||
{"", "", "" },
|
||||
{"group:wood", "", "group:wood"},
|
||||
{"group:wood", "group:wood", "group:wood"},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "fuel",
|
||||
recipe = "boats:boat",
|
||||
burntime = 20,
|
||||
})
|
|
@ -0,0 +1,63 @@
|
|||
License of source code
|
||||
----------------------
|
||||
|
||||
The MIT License (MIT)
|
||||
Copyright (C) 2012-2016 PilzAdam
|
||||
Copyright (C) 2012-2016 Various Minetest developers and contributors
|
||||
|
||||
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.
|
||||
|
||||
For more details:
|
||||
https://opensource.org/licenses/MIT
|
||||
|
||||
|
||||
Licenses of media (textures and model)
|
||||
--------------------------------------
|
||||
|
||||
Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
|
||||
Copyright (C) 2012-2016 Zeg9
|
||||
Copyright (C) 2012-2016 thetoon
|
||||
Copyright (C) 2012-2016 PavelS(SokolovPavel)
|
||||
Copyright (C) 2016 sofar (sofar@foo-projects.org)
|
||||
|
||||
You are free to:
|
||||
Share — copy and redistribute the material in any medium or format.
|
||||
Adapt — remix, transform, and build upon the material for any purpose, even commercially.
|
||||
The licensor cannot revoke these freedoms as long as you follow the license terms.
|
||||
|
||||
Under the following terms:
|
||||
|
||||
Attribution — You must give appropriate credit, provide a link to the license, and
|
||||
indicate if changes were made. You may do so in any reasonable manner, but not in any way
|
||||
that suggests the licensor endorses you or your use.
|
||||
|
||||
ShareAlike — If you remix, transform, or build upon the material, you must distribute
|
||||
your contributions under the same license as the original.
|
||||
|
||||
No additional restrictions — You may not apply legal terms or technological measures that
|
||||
legally restrict others from doing anything the license permits.
|
||||
|
||||
Notices:
|
||||
|
||||
You do not have to comply with the license for elements of the material in the public
|
||||
domain or where your use is permitted by an applicable exception or limitation.
|
||||
No warranties are given. The license may not give you all of the permissions necessary
|
||||
for your intended use. For example, other rights such as publicity, privacy, or moral
|
||||
rights may limit how you use the material.
|
||||
|
||||
For more details:
|
||||
http://creativecommons.org/licenses/by-sa/3.0/
|