Merge branch 'master' of https://git.minetest.land/Wuzzy/MineClone2
9
API.md
|
@ -39,7 +39,7 @@ A lot of things are possible by using one of the APIs in the mods. Note that not
|
|||
* Dispenser support: `ITEMS/REDSTONE/mcl_dispensers`
|
||||
|
||||
## Mobs
|
||||
* Mobs: `ENTITIES/mcl_mods`
|
||||
* Mobs: `ENTITIES/mcl_mobs`
|
||||
|
||||
MineClone 2 uses its own mobs framework, called “Mobs Redo: MineClone 2 Edition” or “MRM” for short.
|
||||
This is a fork of Mobs Redo [`mobs`] by TenPlus1.
|
||||
|
@ -67,6 +67,9 @@ chances are good that it works out of the box.
|
|||
* Get flowing direction of liquids: `CORE/flowlib`
|
||||
* `on_walk_over` callback for nodes: `CORE/walkover`
|
||||
* Get node names close to player (to reduce constant querying): `PLAYER/mcl_playerinfo`
|
||||
* Explosion API
|
||||
* Music discs API
|
||||
* Flowers and flower pots
|
||||
|
||||
### Unstable APIs
|
||||
The following APIs may be subject to change in future. You could already use these APIs but there will probably be breaking changes in the future, or the API is not as fleshed out as it should be. Use at your own risk!
|
||||
|
@ -79,12 +82,10 @@ The following APIs may be subject to change in future. You could already use the
|
|||
|
||||
### Planned APIs
|
||||
|
||||
* Flowers
|
||||
* Saplings and trees
|
||||
* Custom banner patterns
|
||||
* Custom dimensions
|
||||
* Custom portals
|
||||
* Music discs
|
||||
* Dispenser and dropper support
|
||||
* Proper sky and weather APIs
|
||||
* Explosion API
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ The basic digging time groups determine by which tools a node can be dug.
|
|||
* `swordy=1`: Diggable by sword (any material), and this node is *not* a cobweb
|
||||
* `swordy_cobweb=1`: Diggable by sword (any material), and this node is a cobweb
|
||||
* `shearsy=1`: Diggable by shears, and this node is *not* wool
|
||||
* `shearsy=wool=1`: Diggable by shears, and this node is wool
|
||||
* `shearsy_wool=1`: Diggable by shears, and this node is wool
|
||||
* `handy=1`: Breakable by hand and this node gives it useful drop when dug by hand. All nodes which are breakable by pickaxe, axe, shovel, sword or shears are also automatically breakable by hand, but not neccess
|
||||
* `creative_breakable=1`: Block is breakable by hand in creative mode. This group is implied if the node belongs to any other digging group
|
||||
|
||||
|
|
|
@ -12,14 +12,15 @@ local function detach_driver(self)
|
|||
if not self._driver then
|
||||
return
|
||||
end
|
||||
if self._driver:is_player() then
|
||||
mcl_player.player_attached[self._driver:get_player_name()] = nil
|
||||
self._driver:set_detach()
|
||||
self._driver:set_eye_offset({x=0, y=0, z=0},{x=0, y=0, z=0})
|
||||
mcl_player.player_set_animation(self._driver, "stand" , 30)
|
||||
end
|
||||
mcl_player.player_attached[self._driver] = nil
|
||||
local player = minetest.get_player_by_name(self._driver)
|
||||
self._driver = nil
|
||||
self._start_pos = nil
|
||||
if player then
|
||||
player:set_detach()
|
||||
player:set_eye_offset({x=0, y=0, z=0},{x=0, y=0, z=0})
|
||||
mcl_player.player_set_animation(player, "stand" , 30)
|
||||
end
|
||||
end
|
||||
|
||||
local function activate_tnt_minecart(self, timer)
|
||||
|
@ -61,7 +62,7 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
|
|||
|
||||
on_rightclick = on_rightclick,
|
||||
|
||||
_driver = nil, -- player (or mob) who sits in and controls the minecart (only for minecart!)
|
||||
_driver = nil, -- player who sits in and controls the minecart (only for minecart!)
|
||||
_punched = false, -- used to re-send _velocity and position
|
||||
_velocity = {x=0, y=0, z=0}, -- only used on punch
|
||||
_start_pos = nil, -- Used to calculate distance for “On A Rail” achievement
|
||||
|
@ -96,101 +97,111 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
|
|||
end
|
||||
|
||||
function cart:on_punch(puncher, time_from_last_punch, tool_capabilities, direction)
|
||||
-- Punch: Pick up minecart (unless TNT was ignited)
|
||||
if self._boomtimer then return end
|
||||
if self._driver then
|
||||
detach_driver(self)
|
||||
end
|
||||
local pos = self.object:get_pos()
|
||||
|
||||
-- Disable detector rail
|
||||
local rou_pos = vector.round(pos)
|
||||
local node = minetest.get_node(rou_pos)
|
||||
if node.name == "mcl_minecarts:detector_rail_on" then
|
||||
local newnode = {name="mcl_minecarts:detector_rail", param2 = node.param2}
|
||||
minetest.swap_node(rou_pos, newnode)
|
||||
mesecon.receptor_off(rou_pos)
|
||||
if not self._railtype then
|
||||
local node = minetest.get_node(vector.floor(pos)).name
|
||||
self._railtype = minetest.get_item_group(node, "connect_to_raillike")
|
||||
end
|
||||
|
||||
-- Drop items and remove cart entity
|
||||
if not minetest.is_creative_enabled(puncher:get_player_name()) then
|
||||
for d=1, #drop do
|
||||
minetest.add_item(self.object:get_pos(), drop[d])
|
||||
if not puncher or not puncher:is_player() then
|
||||
local cart_dir = mcl_minecarts:get_rail_direction(pos, {x=1, y=0, z=0}, nil, nil, self._railtype)
|
||||
if vector.equals(cart_dir, {x=0, y=0, z=0}) then
|
||||
return
|
||||
end
|
||||
elseif puncher and puncher:is_player() then
|
||||
local inv = puncher:get_inventory()
|
||||
for d=1, #drop do
|
||||
if not inv:contains_item("main", drop[d]) then
|
||||
inv:add_item("main", drop[d])
|
||||
self._velocity = vector.multiply(cart_dir, 3)
|
||||
self._old_pos = nil
|
||||
self._punched = true
|
||||
return
|
||||
end
|
||||
|
||||
-- Punch+sneak: Pick up minecart (unless TNT was ignited)
|
||||
if puncher:get_player_control().sneak and not self._boomtimer then
|
||||
if self._driver then
|
||||
if self._old_pos then
|
||||
self.object:set_pos(self._old_pos)
|
||||
end
|
||||
detach_driver(self)
|
||||
end
|
||||
|
||||
-- Disable detector rail
|
||||
local rou_pos = vector.round(pos)
|
||||
local node = minetest.get_node(rou_pos)
|
||||
if node.name == "mcl_minecarts:detector_rail_on" then
|
||||
local newnode = {name="mcl_minecarts:detector_rail", param2 = node.param2}
|
||||
minetest.swap_node(rou_pos, newnode)
|
||||
mesecon.receptor_off(rou_pos)
|
||||
end
|
||||
|
||||
-- Drop items and remove cart entity
|
||||
if not minetest.is_creative_enabled(puncher:get_player_name()) then
|
||||
for d=1, #drop do
|
||||
minetest.add_item(self.object:get_pos(), drop[d])
|
||||
end
|
||||
elseif puncher and puncher:is_player() then
|
||||
local inv = puncher:get_inventory()
|
||||
for d=1, #drop do
|
||||
if not inv:contains_item("main", drop[d]) then
|
||||
inv:add_item("main", drop[d])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self.object:remove()
|
||||
return
|
||||
end
|
||||
|
||||
self.object:remove()
|
||||
local vel = self.object:get_velocity()
|
||||
if puncher:get_player_name() == self._driver then
|
||||
if math.abs(vel.x + vel.z) > 7 then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local punch_dir = mcl_minecarts:velocity_to_dir(puncher:get_look_dir())
|
||||
punch_dir.y = 0
|
||||
local cart_dir = mcl_minecarts:get_rail_direction(pos, punch_dir, nil, nil, self._railtype)
|
||||
if vector.equals(cart_dir, {x=0, y=0, z=0}) then
|
||||
return
|
||||
end
|
||||
|
||||
time_from_last_punch = math.min(time_from_last_punch, tool_capabilities.full_punch_interval)
|
||||
local f = 3 * (time_from_last_punch / tool_capabilities.full_punch_interval)
|
||||
|
||||
self._velocity = vector.multiply(cart_dir, f)
|
||||
self._old_pos = nil
|
||||
self._punched = true
|
||||
end
|
||||
|
||||
cart.on_activate_by_rail = on_activate_by_rail
|
||||
|
||||
function cart:on_step(dtime)
|
||||
local ctrl, player = nil, nil
|
||||
local update = {}
|
||||
local vel = self.object:get_velocity()
|
||||
local pos, rou_pos, node
|
||||
pos = self.object:get_pos()
|
||||
rou_pos = vector.round(pos)
|
||||
node = minetest.get_node(rou_pos)
|
||||
local g = minetest.get_item_group(node.name, "connect_to_raillike")
|
||||
if self._driver and self._driver:is_player() then
|
||||
player = self._driver
|
||||
ctrl = player:get_player_control()
|
||||
-- player detach
|
||||
if ctrl.sneak then
|
||||
detach_driver(self)
|
||||
return
|
||||
end
|
||||
if g == self._railtype then
|
||||
if ctrl.right then
|
||||
local c = vector.multiply(minetest.yaw_to_dir(self._driver:get_look_horizontal()-1.57), 0.2)
|
||||
self.object:set_velocity(vector.add(vel, {x=c.x, y=0, z=c.z}))
|
||||
end
|
||||
if ctrl.left then
|
||||
local c = vector.multiply(minetest.yaw_to_dir(self._driver:get_look_horizontal()+1.57), 0.2)
|
||||
self.object:set_velocity(vector.add(vel, {x=c.x, y=0, z=c.z}))
|
||||
end
|
||||
if ctrl.up then
|
||||
local c = vector.multiply(self._driver:get_look_dir(), 0.2)
|
||||
self.object:set_velocity(vector.add(vel, {x=c.x, y=0, z=c.z}))
|
||||
end
|
||||
if ctrl.down then
|
||||
local c = vector.multiply(self._driver:get_look_dir(), 0.2)
|
||||
self.object:set_velocity(vector.subtract(vel, {x=c.x, y=0, z=c.z}))
|
||||
if self._driver then
|
||||
player = minetest.get_player_by_name(self._driver)
|
||||
if player then
|
||||
ctrl = player:get_player_control()
|
||||
-- player detach
|
||||
if ctrl.sneak then
|
||||
detach_driver(self)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local vel = self.object:get_velocity()
|
||||
local update = {}
|
||||
if self._last_float_check == nil then
|
||||
self._last_float_check = 0
|
||||
else
|
||||
self._last_float_check = self._last_float_check + dtime
|
||||
end
|
||||
local pos, rou_pos, node
|
||||
-- Drop minecart if it isn't on a rail anymore
|
||||
if self._last_float_check >= mcl_minecarts.check_float_time then
|
||||
|
||||
|
||||
for _,object in pairs(minetest.get_objects_inside_radius(pos, 1.3)) do
|
||||
if object ~= self.object then
|
||||
local mob = object:get_luaentity()
|
||||
if mob then mob = mob._cmi_is_mob == true end
|
||||
if mob and (not self._driver) and not object:get_attach() then
|
||||
self._driver = object
|
||||
object:set_attach(self.object, "", {x=0, y=-1.75, z=-2}, {x=0, y=0, z=0})
|
||||
mobs:set_animation(self.object, "stand")
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
pos = self.object:get_pos()
|
||||
rou_pos = vector.round(pos)
|
||||
node = minetest.get_node(rou_pos)
|
||||
local g = minetest.get_item_group(node.name, "connect_to_raillike")
|
||||
if g ~= self._railtype and self._railtype ~= nil then
|
||||
-- Detach driver
|
||||
if player then
|
||||
|
@ -289,12 +300,8 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
|
|||
end
|
||||
end
|
||||
|
||||
if update.vel then
|
||||
if self._punched then
|
||||
vel = vector.add(vel, self._velocity)
|
||||
if vel.x>8 then vel.x = 8 end
|
||||
if vel.x<-8 then vel.x = -8 end
|
||||
if vel.z>8 then vel.z = 8 end
|
||||
if vel.z<-8 then vel.z = -8 end
|
||||
self.object:set_velocity(vel)
|
||||
self._old_dir.y = 0
|
||||
elseif vector.equals(vel, {x=0, y=0, z=0}) and (not has_fuel) then
|
||||
|
@ -619,14 +626,17 @@ register_minecart(
|
|||
"mcl_minecarts_minecart_normal.png",
|
||||
{"mcl_minecarts:minecart"},
|
||||
function(self, clicker)
|
||||
if not clicker or not clicker:is_player() then return end
|
||||
if clicker == self._driver then
|
||||
local name = clicker:get_player_name()
|
||||
if not clicker or not clicker:is_player() then
|
||||
return
|
||||
end
|
||||
local player_name = clicker:get_player_name()
|
||||
if self._driver and player_name == self._driver then
|
||||
detach_driver(self)
|
||||
else
|
||||
local name = clicker:get_player_name()
|
||||
self._driver = clicker
|
||||
elseif not self._driver then
|
||||
self._driver = player_name
|
||||
self._start_pos = self.object:get_pos()
|
||||
mcl_player.player_attached[name] = true
|
||||
mcl_player.player_attached[player_name] = true
|
||||
clicker:set_attach(self.object, "", {x=0, y=-1.75, z=-2}, {x=0, y=0, z=0})
|
||||
mcl_player.player_attached[name] = true
|
||||
minetest.after(0.2, function(name)
|
||||
|
@ -637,7 +647,6 @@ register_minecart(
|
|||
mcl_tmp_message.message(clicker, S("Sneak to dismount"))
|
||||
end
|
||||
end, name)
|
||||
clicker:set_look_horizontal(self.object:get_yaw())
|
||||
end
|
||||
end, activate_normal_minecart
|
||||
)
|
||||
|
|
|
@ -451,6 +451,6 @@ mobs:spawn_specific("mobs_mc:donkey", mobs_mc.spawn.grassland_savanna, {"air"},
|
|||
-- spawn eggs
|
||||
mobs:register_egg("mobs_mc:horse", S("Horse"), "mobs_mc_spawn_icon_horse.png", 0)
|
||||
mobs:register_egg("mobs_mc:skeleton_horse", S("Skeleton Horse"), "mobs_mc_spawn_icon_horse_skeleton.png", 0)
|
||||
mobs:register_egg("mobs_mc:zombie_horse", S("Zombie Horse"), "mobs_mc_spawn_icon_horse_zombie.png", 0)
|
||||
--mobs:register_egg("mobs_mc:zombie_horse", S("Zombie Horse"), "mobs_mc_spawn_icon_horse_zombie.png", 0)
|
||||
mobs:register_egg("mobs_mc:donkey", S("Donkey"), "mobs_mc_spawn_icon_donkey.png", 0)
|
||||
mobs:register_egg("mobs_mc:mule", S("Mule"), "mobs_mc_spawn_icon_mule.png", 0)
|
||||
|
|
Before Width: | Height: | Size: 11 KiB |
|
@ -35,53 +35,13 @@ S("Arrows might get stuck on solid blocks and can be retrieved again. They are a
|
|||
end,
|
||||
})
|
||||
|
||||
-- This is a fake node, used as model for the arrow entity.
|
||||
-- It's not supposed to be usable as item or real node.
|
||||
-- TODO: Use a proper mesh for the arrow entity
|
||||
minetest.register_node("mcl_bows:arrow_box", {
|
||||
drawtype = "nodebox",
|
||||
is_ground_content = false,
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
-- Shaft
|
||||
{-6.5/17, -1.5/17, -1.5/17, -4.5/17, 1.5/17, 1.5/17},
|
||||
{-4.5/17, -0.5/17, -0.5/17, 5.5/17, 0.5/17, 0.5/17},
|
||||
{5.5/17, -1.5/17, -1.5/17, 6.5/17, 1.5/17, 1.5/17},
|
||||
-- Tip
|
||||
{-4.5/17, 2.5/17, 2.5/17, -3.5/17, -2.5/17, -2.5/17},
|
||||
{-8.5/17, 0.5/17, 0.5/17, -6.5/17, -0.5/17, -0.5/17},
|
||||
-- Fletching
|
||||
{6.5/17, 1.5/17, 1.5/17, 7.5/17, 2.5/17, 2.5/17},
|
||||
{7.5/17, -2.5/17, 2.5/17, 6.5/17, -1.5/17, 1.5/17},
|
||||
{7.5/17, 2.5/17, -2.5/17, 6.5/17, 1.5/17, -1.5/17},
|
||||
{6.5/17, -1.5/17, -1.5/17, 7.5/17, -2.5/17, -2.5/17},
|
||||
|
||||
{7.5/17, 2.5/17, 2.5/17, 8.5/17, 3.5/17, 3.5/17},
|
||||
{8.5/17, -3.5/17, 3.5/17, 7.5/17, -2.5/17, 2.5/17},
|
||||
{8.5/17, 3.5/17, -3.5/17, 7.5/17, 2.5/17, -2.5/17},
|
||||
{7.5/17, -2.5/17, -2.5/17, 8.5/17, -3.5/17, -3.5/17},
|
||||
}
|
||||
},
|
||||
tiles = {"mcl_bows_arrow.png^[transformFX", "mcl_bows_arrow.png^[transformFX", "mcl_bows_arrow_back.png", "mcl_bows_arrow_front.png", "mcl_bows_arrow.png", "mcl_bows_arrow.png^[transformFX"},
|
||||
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false,
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
sunlight_propagates = true,
|
||||
groups = {not_in_creative_inventory=1, dig_immediate=3},
|
||||
drop = "",
|
||||
node_placement_prediction = "",
|
||||
on_construct = function(pos)
|
||||
minetest.log("error", "[mcl_bows] Trying to construct mcl_bows:arrow_box at "..minetest.pos_to_string(pos))
|
||||
minetest.remove_node(pos)
|
||||
end,
|
||||
})
|
||||
|
||||
local ARROW_ENTITY={
|
||||
physical = true,
|
||||
visual = "wielditem",
|
||||
visual_size = {x=0.4, y=0.4},
|
||||
textures = {"mcl_bows:arrow_box"},
|
||||
pointable = false,
|
||||
visual = "mesh",
|
||||
mesh = "mcl_bows_arrow.obj",
|
||||
visual_size = {x=-1, y=1},
|
||||
textures = {"mcl_bows_arrow.png"},
|
||||
collisionbox = {-0.19, -0.125, -0.19, 0.19, 0.125, 0.19},
|
||||
collide_with_objects = false,
|
||||
_fire_damage_resistant = true,
|
||||
|
@ -185,6 +145,25 @@ ARROW_ENTITY.on_step = function(self, dtime)
|
|||
|
||||
-- Check for object "collision". Done every tick (hopefully this is not too stressing)
|
||||
else
|
||||
|
||||
if self._damage >= 9 then
|
||||
minetest.add_particlespawner({
|
||||
amount = 1,
|
||||
time = .001,
|
||||
minpos = pos,
|
||||
maxpos = pos,
|
||||
minvel = vector.new(-0.1,-0.1,-0.1),
|
||||
maxvel = vector.new(0.1,0.1,0.1),
|
||||
minexptime = 0.5,
|
||||
maxexptime = 0.5,
|
||||
minsize = 2,
|
||||
maxsize = 2,
|
||||
collisiondetection = false,
|
||||
vertical = false,
|
||||
texture = "mobs_mc_arrow_particle.png",
|
||||
glow = 1,
|
||||
})
|
||||
end
|
||||
-- We just check for any hurtable objects nearby.
|
||||
-- The radius of 3 is fairly liberal, but anything lower than than will cause
|
||||
-- arrow to hilariously go through mobs often.
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
# Blender v2.91.0 OBJ File: ''
|
||||
# www.blender.org
|
||||
mtllib mcl_bows_arrow.mtl
|
||||
o Plane
|
||||
v -3.782006 -1.443249 0.000500
|
||||
v -3.782006 1.444249 0.000500
|
||||
v 3.782006 1.444249 0.000500
|
||||
v 3.782006 -1.443249 0.000500
|
||||
v 3.331104 1.069925 1.085017
|
||||
v 3.331104 -1.100076 1.085017
|
||||
v 3.331104 1.069925 -1.064830
|
||||
v 3.331104 -1.100076 -1.064829
|
||||
v 3.782006 0.001000 1.443749
|
||||
v 3.782006 0.001000 -1.443750
|
||||
v -3.782006 0.001000 -1.443749
|
||||
v -3.782006 0.001000 1.443750
|
||||
v 3.782006 0.000000 -1.443750
|
||||
v 3.782006 0.000000 1.443749
|
||||
v -3.782006 0.000000 1.443750
|
||||
v -3.782006 0.000000 -1.443749
|
||||
v 3.782006 1.444249 -0.000500
|
||||
v 3.782006 -1.443249 -0.000500
|
||||
v -3.782006 -1.443249 -0.000500
|
||||
v -3.782006 1.444249 -0.000500
|
||||
vt 0.000000 0.300000
|
||||
vt 0.000000 0.700000
|
||||
vt 1.000000 0.700000
|
||||
vt 1.000000 0.300000
|
||||
vt -0.007553 -0.000373
|
||||
vt 0.296712 -0.000373
|
||||
vt 0.296712 0.298611
|
||||
vt -0.007553 0.298611
|
||||
vt 0.000000 0.300000
|
||||
vt 1.000000 0.300000
|
||||
vt 1.000000 0.700000
|
||||
vt 0.000000 0.700000
|
||||
vt 0.000000 0.300000
|
||||
vt 1.000000 0.300000
|
||||
vt 1.000000 0.700000
|
||||
vt 0.000000 0.700000
|
||||
vt 0.000000 0.300000
|
||||
vt 0.000000 0.700000
|
||||
vt 1.000000 0.700000
|
||||
vt 1.000000 0.300000
|
||||
vn -0.0000 -0.0000 -1.0000
|
||||
vn 1.0000 -0.0000 0.0000
|
||||
vn 0.0000 1.0000 0.0000
|
||||
vn 0.0000 0.0000 1.0000
|
||||
vn 0.0000 -1.0000 0.0000
|
||||
usemtl Material.002
|
||||
s off
|
||||
f 17/1/1 18/2/1 19/3/1 20/4/1
|
||||
f 8/5/2 7/6/2 5/7/2 6/8/2
|
||||
f 10/9/3 11/10/3 12/11/3 9/12/3
|
||||
f 3/13/4 2/14/4 1/15/4 4/16/4
|
||||
f 13/17/5 14/18/5 15/19/5 16/20/5
|
Before Width: | Height: | Size: 173 B After Width: | Height: | Size: 359 B |
Before Width: | Height: | Size: 132 B After Width: | Height: | Size: 212 B |
Before Width: | Height: | Size: 317 B After Width: | Height: | Size: 260 B |
|
@ -0,0 +1,21 @@
|
|||
# mcl_buckets
|
||||
Add an API to register buckets to mcl
|
||||
|
||||
## mcl_buckets.register_liquid(def)
|
||||
|
||||
Register a new liquid
|
||||
Accept folowing params:
|
||||
* source_place = a string or function.
|
||||
* string: name of the node to place
|
||||
* function(pos): will returns name of the node to place with pos being the placement position
|
||||
* source_take = table of liquid source node names to take
|
||||
* itemname = itemstring of the new bucket item (or nil if liquid is not takeable)
|
||||
* inventory_image = texture of the new bucket item (ignored if itemname == nil)
|
||||
* name = user-visible bucket description
|
||||
* longdesc = long explanatory description (for help)
|
||||
* usagehelp = short usage explanation (for help)
|
||||
* tt_help = very short tooltip help
|
||||
* extra_check(pos, placer) = optional function(pos) which can returns false to avoid placing the liquid. Placer is object/player who is placing the liquid, can be nil.
|
||||
* groups = optional list of item groups
|
||||
|
||||
This function can be called from any mod (which depends on this one)
|
|
@ -1,4 +1,5 @@
|
|||
local S = minetest.get_translator("mcl_buckets")
|
||||
local modpath = minetest.get_modpath(minetest.get_current_modname())
|
||||
|
||||
-- Minetest 0.4 mod: bucket
|
||||
-- See README.txt for licensing and other information.
|
||||
|
@ -45,43 +46,27 @@ local place_liquid = function(pos, itemstring)
|
|||
minetest.add_node(pos, {name=itemstring, param2=fullness})
|
||||
end
|
||||
|
||||
-- Register a new liquid
|
||||
-- source_place = a string or function.
|
||||
-- * string: name of the node to place
|
||||
-- * function(pos): will returns name of the node to place with pos being the placement position
|
||||
-- source_take = table of liquid source node names to take
|
||||
-- itemname = itemstring of the new bucket item (or nil if liquid is not takeable)
|
||||
-- inventory_image = texture of the new bucket item (ignored if itemname == nil)
|
||||
-- name = user-visible bucket description
|
||||
-- longdesc = long explanatory description (for help)
|
||||
-- usagehelp = short usage explanation (for help)
|
||||
-- tt_help = very short tooltip help
|
||||
-- extra_check(pos, placer) = optional function(pos) which can returns false to avoid placing the liquid.
|
||||
-- placer is object/player who is placing the liquid, can be nil
|
||||
-- groups = optional list of item groups
|
||||
--
|
||||
-- This function can be called from any mod (which depends on this one)
|
||||
function mcl_buckets.register_liquid(source_place, source_take, itemname, inventory_image, name, longdesc, usagehelp, tt_help, extra_check, groups)
|
||||
for i=1, #source_take do
|
||||
mcl_buckets.liquids[source_take[i]] = {
|
||||
source_place = source_place,
|
||||
source_take = source_take[i],
|
||||
itemname = itemname,
|
||||
function mcl_buckets.register_liquid(def)
|
||||
for i=1, #def.source_take do
|
||||
mcl_buckets.liquids[def.source_take[i]] = {
|
||||
source_place = def.source_place,
|
||||
source_take = def.source_take[i],
|
||||
itemname = def.itemname,
|
||||
}
|
||||
if type(source_place) == "string" then
|
||||
mcl_buckets.liquids[source_place] = mcl_buckets.liquids[source_take[i]]
|
||||
if type(def.source_place) == "string" then
|
||||
mcl_buckets.liquids[def.source_place] = mcl_buckets.liquids[def.source_take[i]]
|
||||
end
|
||||
end
|
||||
|
||||
if itemname ~= nil then
|
||||
minetest.register_craftitem(itemname, {
|
||||
description = name,
|
||||
_doc_items_longdesc = longdesc,
|
||||
_doc_items_usagehelp = usagehelp,
|
||||
_tt_help = tt_help,
|
||||
inventory_image = inventory_image,
|
||||
if def.itemname ~= nil then
|
||||
minetest.register_craftitem(def.itemname, {
|
||||
description = def.name,
|
||||
_doc_items_longdesc = def.longdesc,
|
||||
_doc_items_usagehelp = def.usagehelp,
|
||||
_tt_help = def.tt_help,
|
||||
inventory_image = def.inventory_image,
|
||||
stack_max = 16,
|
||||
groups = groups,
|
||||
groups = def.groups,
|
||||
on_place = function(itemstack, user, pointed_thing)
|
||||
-- Must be pointing to node
|
||||
if pointed_thing.type ~= "node" then
|
||||
|
@ -99,10 +84,10 @@ function mcl_buckets.register_liquid(source_place, source_take, itemname, invent
|
|||
end
|
||||
|
||||
local node_place
|
||||
if type(source_place) == "function" then
|
||||
node_place = source_place(place_pos)
|
||||
if type(def.source_place) == "function" then
|
||||
node_place = def.source_place(place_pos)
|
||||
else
|
||||
node_place = source_place
|
||||
node_place = def.source_place
|
||||
end
|
||||
-- Check if pointing to a buildable node
|
||||
local item = itemstack:get_name()
|
||||
|
@ -163,17 +148,17 @@ function mcl_buckets.register_liquid(source_place, source_take, itemname, invent
|
|||
end,
|
||||
_on_dispense = function(stack, pos, droppos, dropnode, dropdir)
|
||||
local iname = stack:get_name()
|
||||
local buildable = minetest.registered_nodes[dropnode.name].buildable_to
|
||||
local buildable = minetest.registered_nodes[dropnode.name].buildable_to or dropnode.name == "mcl_portals:portal"
|
||||
|
||||
if extra_check and extra_check(droppos, nil) == false then
|
||||
if def.extra_check and def.extra_check(droppos, nil) == false then
|
||||
-- Fail placement of liquid
|
||||
elseif buildable then
|
||||
-- buildable; replace the node
|
||||
local node_place
|
||||
if type(source_place) == "function" then
|
||||
node_place = source_place(droppos)
|
||||
if type(def.source_place) == "function" then
|
||||
node_place = def.source_place(droppos)
|
||||
else
|
||||
node_place = source_place
|
||||
node_place = def.source_place
|
||||
end
|
||||
place_liquid(droppos, node_place)
|
||||
stack:set_name("mcl_buckets:bucket_empty")
|
||||
|
@ -292,114 +277,4 @@ minetest.register_craftitem("mcl_buckets:bucket_empty", {
|
|||
end,
|
||||
})
|
||||
|
||||
if mod_mcl_core then
|
||||
-- Lava bucket
|
||||
mcl_buckets.register_liquid(
|
||||
function(pos)
|
||||
local dim = mcl_worlds.pos_to_dimension(pos)
|
||||
if dim == "nether" then
|
||||
return "mcl_nether:nether_lava_source"
|
||||
else
|
||||
return "mcl_core:lava_source"
|
||||
end
|
||||
end,
|
||||
{"mcl_core:lava_source", "mcl_nether:nether_lava_source"},
|
||||
"mcl_buckets:bucket_lava",
|
||||
"bucket_lava.png",
|
||||
S("Lava Bucket"),
|
||||
S("A bucket can be used to collect and release liquids. This one is filled with hot lava, safely contained inside. Use with caution."),
|
||||
S("Get in a safe distance and place the bucket to empty it and create a lava source at this spot. Don't burn yourself!"),
|
||||
S("Places a lava source")
|
||||
)
|
||||
|
||||
-- Water bucket
|
||||
mcl_buckets.register_liquid(
|
||||
"mcl_core:water_source",
|
||||
{"mcl_core:water_source"},
|
||||
"mcl_buckets:bucket_water",
|
||||
"bucket_water.png",
|
||||
S("Water Bucket"),
|
||||
S("A bucket can be used to collect and release liquids. This one is filled with water."),
|
||||
S("Place it to empty the bucket and create a water source."),
|
||||
S("Places a water source"),
|
||||
function(pos, placer)
|
||||
-- Check protection
|
||||
local placer_name = ""
|
||||
if placer ~= nil then
|
||||
placer_name = placer:get_player_name()
|
||||
end
|
||||
if placer and minetest.is_protected(pos, placer_name) then
|
||||
minetest.record_protection_violation(pos, placer_name)
|
||||
return false
|
||||
end
|
||||
local nn = minetest.get_node(pos).name
|
||||
-- Pour water into cauldron
|
||||
if minetest.get_item_group(nn, "cauldron") ~= 0 then
|
||||
-- Put water into cauldron
|
||||
if nn ~= "mcl_cauldrons:cauldron_3" then
|
||||
minetest.set_node(pos, {name="mcl_cauldrons:cauldron_3"})
|
||||
end
|
||||
sound_place("mcl_core:water_source", pos)
|
||||
return false
|
||||
-- Evaporate water if used in Nether (except on cauldron)
|
||||
else
|
||||
local dim = mcl_worlds.pos_to_dimension(pos)
|
||||
if dim == "nether" then
|
||||
minetest.sound_play("fire_extinguish_flame", {pos = pos, gain = 0.25, max_hear_distance = 16}, true)
|
||||
return false
|
||||
end
|
||||
end
|
||||
end,
|
||||
{ water_bucket = 1 }
|
||||
)
|
||||
end
|
||||
|
||||
if mod_mclx_core then
|
||||
-- River water bucket
|
||||
mcl_buckets.register_liquid(
|
||||
"mclx_core:river_water_source",
|
||||
{"mclx_core:river_water_source"},
|
||||
"mcl_buckets:bucket_river_water",
|
||||
"bucket_river_water.png",
|
||||
S("River Water Bucket"),
|
||||
S("A bucket can be used to collect and release liquids. This one is filled with river water."),
|
||||
S("Place it to empty the bucket and create a river water source."),
|
||||
S("Places a river water source"),
|
||||
function(pos, placer)
|
||||
-- Check protection
|
||||
local placer_name = ""
|
||||
if placer ~= nil then
|
||||
placer_name = placer:get_player_name()
|
||||
end
|
||||
if placer and minetest.is_protected(pos, placer_name) then
|
||||
minetest.record_protection_violation(pos, placer_name)
|
||||
return false
|
||||
end
|
||||
local nn = minetest.get_node(pos).name
|
||||
-- Pour into cauldron
|
||||
if minetest.get_item_group(nn, "cauldron") ~= 0 then
|
||||
-- Put water into cauldron
|
||||
if nn ~= "mcl_cauldrons:cauldron_3r" then
|
||||
minetest.set_node(pos, {name="mcl_cauldrons:cauldron_3r"})
|
||||
end
|
||||
sound_place("mcl_core:water_source", pos)
|
||||
return false
|
||||
else
|
||||
-- Evaporate water if used in Nether (except on cauldron)
|
||||
local dim = mcl_worlds.pos_to_dimension(pos)
|
||||
if dim == "nether" then
|
||||
minetest.sound_play("fire_extinguish_flame", {pos = pos, gain = 0.25, max_hear_distance = 16}, true)
|
||||
return false
|
||||
end
|
||||
end
|
||||
end,
|
||||
{ water_bucket = 1 }
|
||||
)
|
||||
end
|
||||
|
||||
minetest.register_craft({
|
||||
type = "fuel",
|
||||
recipe = "mcl_buckets:bucket_lava",
|
||||
burntime = 1000,
|
||||
replacements = {{"mcl_buckets:bucket_lava", "mcl_buckets:bucket_empty"}},
|
||||
})
|
||||
dofile(modpath.."/register.lua")
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
local mod_mcl_core = minetest.get_modpath("mcl_core")
|
||||
local mod_mclx_core = minetest.get_modpath("mclx_core")
|
||||
|
||||
if mod_mcl_core then
|
||||
-- Lava bucket
|
||||
mcl_buckets.register_liquid({
|
||||
source_place = function(pos)
|
||||
local dim = mcl_worlds.pos_to_dimension(pos)
|
||||
if dim == "nether" then
|
||||
return "mcl_nether:nether_lava_source"
|
||||
else
|
||||
return "mcl_core:lava_source"
|
||||
end
|
||||
end,
|
||||
source_take = {"mcl_core:lava_source", "mcl_nether:nether_lava_source"},
|
||||
itemname = "mcl_buckets:bucket_lava",
|
||||
inventory_image = "bucket_lava.png",
|
||||
name = S("Lava Bucket"),
|
||||
longdesc = S("A bucket can be used to collect and release liquids. This one is filled with hot lava, safely contained inside. Use with caution."),
|
||||
usagehelp = S("Get in a safe distance and place the bucket to empty it and create a lava source at this spot. Don't burn yourself!"),
|
||||
tt_help = S("Places a lava source")
|
||||
})
|
||||
|
||||
-- Water bucket
|
||||
mcl_buckets.register_liquid({
|
||||
source_place = "mcl_core:water_source",
|
||||
source_take = {"mcl_core:water_source"},
|
||||
itemname = "mcl_buckets:bucket_water",
|
||||
inventory_image = "bucket_water.png",
|
||||
name = S("Water Bucket"),
|
||||
longdesc = S("A bucket can be used to collect and release liquids. This one is filled with water."),
|
||||
usagehelp = S("Place it to empty the bucket and create a water source."),
|
||||
tt_help = S("Places a water source"),
|
||||
extra_check = function(pos, placer)
|
||||
-- Check protection
|
||||
local placer_name = ""
|
||||
if placer ~= nil then
|
||||
placer_name = placer:get_player_name()
|
||||
end
|
||||
if placer and minetest.is_protected(pos, placer_name) then
|
||||
minetest.record_protection_violation(pos, placer_name)
|
||||
return false
|
||||
end
|
||||
local nn = minetest.get_node(pos).name
|
||||
-- Pour water into cauldron
|
||||
if minetest.get_item_group(nn, "cauldron") ~= 0 then
|
||||
-- Put water into cauldron
|
||||
if nn ~= "mcl_cauldrons:cauldron_3" then
|
||||
minetest.set_node(pos, {name="mcl_cauldrons:cauldron_3"})
|
||||
end
|
||||
sound_place("mcl_core:water_source", pos)
|
||||
return false
|
||||
-- Evaporate water if used in Nether (except on cauldron)
|
||||
else
|
||||
local dim = mcl_worlds.pos_to_dimension(pos)
|
||||
if dim == "nether" then
|
||||
minetest.sound_play("fire_extinguish_flame", {pos = pos, gain = 0.25, max_hear_distance = 16}, true)
|
||||
return false
|
||||
end
|
||||
end
|
||||
end,
|
||||
groups = { water_bucket = 1 },
|
||||
})
|
||||
end
|
||||
|
||||
if mod_mclx_core then
|
||||
-- River water bucket
|
||||
mcl_buckets.register_liquid({
|
||||
source_place = "mclx_core:river_water_source",
|
||||
source_take = {"mclx_core:river_water_source"},
|
||||
itemname = "mcl_buckets:bucket_river_water",
|
||||
inventory_image = "bucket_river_water.png",
|
||||
name = S("River Water Bucket"),
|
||||
longdesc = S("A bucket can be used to collect and release liquids. This one is filled with river water."),
|
||||
usagehelp = S("Place it to empty the bucket and create a river water source."),
|
||||
tt_help = S("Places a river water source"),
|
||||
extra_check = function(pos, placer)
|
||||
-- Check protection
|
||||
local placer_name = ""
|
||||
if placer ~= nil then
|
||||
placer_name = placer:get_player_name()
|
||||
end
|
||||
if placer and minetest.is_protected(pos, placer_name) then
|
||||
minetest.record_protection_violation(pos, placer_name)
|
||||
return false
|
||||
end
|
||||
local nn = minetest.get_node(pos).name
|
||||
-- Pour into cauldron
|
||||
if minetest.get_item_group(nn, "cauldron") ~= 0 then
|
||||
-- Put water into cauldron
|
||||
if nn ~= "mcl_cauldrons:cauldron_3r" then
|
||||
minetest.set_node(pos, {name="mcl_cauldrons:cauldron_3r"})
|
||||
end
|
||||
sound_place("mcl_core:water_source", pos)
|
||||
return false
|
||||
else
|
||||
-- Evaporate water if used in Nether (except on cauldron)
|
||||
local dim = mcl_worlds.pos_to_dimension(pos)
|
||||
if dim == "nether" then
|
||||
minetest.sound_play("fire_extinguish_flame", {pos = pos, gain = 0.25, max_hear_distance = 16}, true)
|
||||
return false
|
||||
end
|
||||
end
|
||||
end,
|
||||
groups = { water_bucket = 1 },
|
||||
})
|
||||
end
|
||||
|
||||
minetest.register_craft({
|
||||
type = "fuel",
|
||||
recipe = "mcl_buckets:bucket_lava",
|
||||
burntime = 1000,
|
||||
replacements = {{"mcl_buckets:bucket_lava", "mcl_buckets:bucket_empty"}},
|
||||
})
|
|
@ -1,3 +0,0 @@
|
|||
mcl_init
|
||||
mcl_formspec
|
||||
mcl_sounds
|
|
@ -1 +0,0 @@
|
|||
Adds a crafting table.
|
|
@ -1,5 +1,36 @@
|
|||
local S = minetest.get_translator("mcl_crafting_table")
|
||||
local formspec_escape = minetest.formspec_escape
|
||||
local show_formspec = minetest.show_formspec
|
||||
local C = minetest.colorize
|
||||
local text_color = mcl_colors.BLACK or "#313131"
|
||||
local itemslot_bg = mcl_formspec.get_itemslot_bg
|
||||
|
||||
mcl_crafting_table = {}
|
||||
function mcl_crafting_table.show_crafting_form(player)
|
||||
player:get_inventory():set_width("craft", 3)
|
||||
player:get_inventory():set_size("craft", 9)
|
||||
|
||||
show_formspec(player:get_player_name(), "main",
|
||||
"size[9,8.75]"..
|
||||
"image[4.7,1.5;1.5,1;gui_crafting_arrow.png]"..
|
||||
"label[0,4;"..formspec_escape(C(text_color, S("Inventory"))).."]".. --"#313131"
|
||||
"list[current_player;main;0,4.5;9,3;9]"..
|
||||
itemslot_bg(0,4.5,9,3)..
|
||||
"list[current_player;main;0,7.74;9,1;]"..
|
||||
itemslot_bg(0,7.74,9,1)..
|
||||
"label[1.75,0;"..formspec_escape(C(text_color, S("Crafting"))).."]"..
|
||||
"list[current_player;craft;1.75,0.5;3,3;]"..
|
||||
itemslot_bg(1.75,0.5,3,3)..
|
||||
"list[current_player;craftpreview;6.1,1.5;1,1;]"..
|
||||
itemslot_bg(6.1,1.5,1,1)..
|
||||
"image_button[0.75,1.5;1,1;craftguide_book.png;__mcl_craftguide;]"..
|
||||
"tooltip[__mcl_craftguide;"..formspec_escape(S("Recipe book")).."]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[current_player;craft]"
|
||||
)
|
||||
end
|
||||
|
||||
local show_crafting_form = mcl_crafting_table.show_crafting_form --cache function for better performances
|
||||
minetest.register_node("mcl_crafting_table:crafting_table", {
|
||||
description = S("Crafting Table"),
|
||||
_tt_help = S("3×3 crafting grid"),
|
||||
|
@ -12,27 +43,7 @@ minetest.register_node("mcl_crafting_table:crafting_table", {
|
|||
paramtype2 = "facedir",
|
||||
groups = {handy=1,axey=1, deco_block=1, material_wood=1,flammable=-1},
|
||||
on_rightclick = function(pos, node, player, itemstack)
|
||||
player:get_inventory():set_width("craft", 3)
|
||||
player:get_inventory():set_size("craft", 9)
|
||||
|
||||
local form = "size[9,8.75]"..
|
||||
"image[4.7,1.5;1.5,1;gui_crafting_arrow.png]"..
|
||||
"label[0,4;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]"..
|
||||
"list[current_player;main;0,4.5;9,3;9]"..
|
||||
mcl_formspec.get_itemslot_bg(0,4.5,9,3)..
|
||||
"list[current_player;main;0,7.74;9,1;]"..
|
||||
mcl_formspec.get_itemslot_bg(0,7.74,9,1)..
|
||||
"label[1.75,0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Crafting"))).."]"..
|
||||
"list[current_player;craft;1.75,0.5;3,3;]"..
|
||||
mcl_formspec.get_itemslot_bg(1.75,0.5,3,3)..
|
||||
"list[current_player;craftpreview;6.1,1.5;1,1;]"..
|
||||
mcl_formspec.get_itemslot_bg(6.1,1.5,1,1)..
|
||||
"image_button[0.75,1.5;1,1;craftguide_book.png;__mcl_craftguide;]"..
|
||||
"tooltip[__mcl_craftguide;"..minetest.formspec_escape(S("Recipe book")).."]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[current_player;craft]"
|
||||
|
||||
minetest.show_formspec(player:get_player_name(), "main", form)
|
||||
show_crafting_form(player)
|
||||
end,
|
||||
sounds = mcl_sounds.node_sound_wood_defaults(),
|
||||
_mcl_blast_resistance = 2.5,
|
||||
|
|
|
@ -1 +1,4 @@
|
|||
name = mcl_crafting_table
|
||||
description = Adds a crafting table.
|
||||
depends = mcl_init, mcl_formspec, mcl_sounds
|
||||
optional_depends = mcl_colors
|
||||
|
|
|
@ -28,7 +28,72 @@ local alldirs=
|
|||
{ x = 0, y = 0, z = 1}
|
||||
}
|
||||
|
||||
-- 3 exptime variants because the animation is not tied to particle expiration time.
|
||||
-- 3 colorized variants to imitate minecraft's
|
||||
local smoke_pdef_base = {
|
||||
amount = 0.001,
|
||||
time = 0,
|
||||
-- minpos = vector.add(pos, { x = -0.45, y = -0.45, z = -0.45 }),
|
||||
-- maxpos = vector.add(pos, { x = 0.45, y = 0.45, z = 0.45 }),
|
||||
minvel = { x = -0.1, y = 0.3, z = -0.1 },
|
||||
maxvel = { x = 0.1, y = 1.6, z = 0.1 },
|
||||
-- minexptime = 3 exptime variants,
|
||||
-- maxexptime = 3 exptime variants
|
||||
minsize = 4.0,
|
||||
maxsize = 4.5,
|
||||
-- texture = "mcl_particles_smoke_anim.png^[colorize:#000000:(3 colourize variants)",
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 8,
|
||||
aspect_h = 8,
|
||||
-- length = 3 exptime variants
|
||||
},
|
||||
collisiondetection = true,
|
||||
}
|
||||
local smoke_pdef_cached = {}
|
||||
local spawn_smoke = function(pos)
|
||||
local min = math.min
|
||||
local new_minpos = vector.add(pos, { x = -0.45, y = -0.45, z = -0.45 })
|
||||
local new_maxpos = vector.add(pos, { x = 0.45, y = 0.45, z = 0.45 })
|
||||
|
||||
-- populate the cache
|
||||
if not next(smoke_pdef_cached) then
|
||||
-- the last frame plays for 1/8 * N seconds, so we can take advantage of it
|
||||
-- to have varying exptime for each variant.
|
||||
local exptimes = { 0.75, 1.5, 4.0 }
|
||||
local colorizes = { "199", "209", "243" } -- round(78%, 82%, 90% of 256) - 1
|
||||
|
||||
local id = 1
|
||||
for _,exptime in ipairs(exptimes) do
|
||||
for _,colorize in ipairs(colorizes) do
|
||||
smoke_pdef_base.minpos = new_minpos
|
||||
smoke_pdef_base.maxpos = new_maxpos
|
||||
smoke_pdef_base.maxexptime = exptime
|
||||
smoke_pdef_base.animation.length = exptime + 0.1
|
||||
-- minexptime must be set such that the last frame is actully rendered,
|
||||
-- even if its very short. Larger exptime -> larger range
|
||||
smoke_pdef_base.minexptime = min(exptime, (7.0/8.0 * (exptime + 0.1) + 0.1))
|
||||
smoke_pdef_base.texture = "mcl_particles_smoke_anim.png^[colorize:#000000:" ..colorize
|
||||
|
||||
smoke_pdef_cached[id] = table.copy(smoke_pdef_base)
|
||||
|
||||
mcl_particles.add_node_particlespawner(pos, smoke_pdef_cached[id], "high")
|
||||
|
||||
id = id + 1
|
||||
end
|
||||
end
|
||||
|
||||
-- cache already populated
|
||||
else
|
||||
for i, smoke_pdef in ipairs(smoke_pdef_cached) do
|
||||
smoke_pdef.minpos = new_minpos
|
||||
smoke_pdef.maxpos = new_maxpos
|
||||
mcl_particles.add_node_particlespawner(pos, smoke_pdef, "high")
|
||||
end
|
||||
end
|
||||
|
||||
--[[ Old smoke pdef
|
||||
local spawn_smoke = function(pos)
|
||||
mcl_particles.add_node_particlespawner(pos, {
|
||||
amount = 0.1,
|
||||
time = 0,
|
||||
|
@ -48,6 +113,8 @@ local spawn_smoke = function(pos)
|
|||
length = 2.1,
|
||||
},
|
||||
}, "high")
|
||||
-- ]]
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
|
|
|
@ -64,7 +64,7 @@ local function destroy_nether_portal(pos)
|
|||
local meta = minetest.get_meta(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
local nn, orientation = node.name, node.param2
|
||||
local obsidian = nn == "mcl_core:obsidian"
|
||||
local obsidian = nn == "mcl_core:obsidian"
|
||||
|
||||
local has_meta = minetest.string_to_pos(meta:get_string("portal_frame1"))
|
||||
if has_meta then
|
||||
|
@ -138,8 +138,6 @@ minetest.register_node("mcl_portals:portal", {
|
|||
sunlight_propagates = true,
|
||||
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "blend" or true,
|
||||
walkable = false,
|
||||
diggable = false,
|
||||
pointable = false,
|
||||
buildable_to = false,
|
||||
is_ground_content = false,
|
||||
drop = "",
|
||||
|
@ -152,7 +150,8 @@ minetest.register_node("mcl_portals:portal", {
|
|||
{-0.5, -0.5, -0.1, 0.5, 0.5, 0.1},
|
||||
},
|
||||
},
|
||||
groups = {portal=1, not_in_creative_inventory = 1},
|
||||
groups = { creative_breakable = 1, portal = 1, not_in_creative_inventory = 1 },
|
||||
sounds = mcl_sounds.node_sound_glass_defaults(),
|
||||
on_destruct = destroy_nether_portal,
|
||||
|
||||
_mcl_hardness = -1,
|
||||
|
@ -583,7 +582,7 @@ local function check_and_light_shape(pos, orientation)
|
|||
meta:set_string("portal_time", tostring(0))
|
||||
meta:set_string("portal_target", "")
|
||||
end
|
||||
return true
|
||||
return true
|
||||
end
|
||||
|
||||
-- Attempts to light a Nether portal at pos
|
||||
|
@ -842,7 +841,7 @@ minetest.override_item("mcl_core:obsidian", {
|
|||
_on_ignite = function(user, pointed_thing)
|
||||
local x, y, z = pointed_thing.under.x, pointed_thing.under.y, pointed_thing.under.z
|
||||
-- Check empty spaces around obsidian and light all frames found:
|
||||
local portals_placed =
|
||||
local portals_placed =
|
||||
mcl_portals.light_nether_portal({x = x - 1, y = y, z = z}) or mcl_portals.light_nether_portal({x = x + 1, y = y, z = z}) or
|
||||
mcl_portals.light_nether_portal({x = x, y = y - 1, z = z}) or mcl_portals.light_nether_portal({x = x, y = y + 1, z = z}) or
|
||||
mcl_portals.light_nether_portal({x = x, y = y, z = z - 1}) or mcl_portals.light_nether_portal({x = x, y = y, z = z + 1})
|
||||
|
@ -863,4 +862,3 @@ minetest.override_item("mcl_core:obsidian", {
|
|||
end
|
||||
end,
|
||||
})
|
||||
|
||||
|
|
|
@ -100,9 +100,10 @@ function mcl_potions.register_arrow(name, desc, color, def)
|
|||
|
||||
local ARROW_ENTITY={
|
||||
physical = true,
|
||||
visual = "wielditem",
|
||||
visual_size = {x=0.4, y=0.4},
|
||||
textures = {"mcl_potions:"..name.."_arrow_box"},
|
||||
visual = "mesh",
|
||||
mesh = "mcl_bows_arrow.obj",
|
||||
visual_size = {x=1, y=1},
|
||||
textures = arrow_image(color, 100),
|
||||
collisionbox = {-0.19, -0.125, -0.19, 0.19, 0.125, 0.19},
|
||||
collide_with_objects = false,
|
||||
|
||||
|
@ -177,6 +178,26 @@ function mcl_potions.register_arrow(name, desc, color, def)
|
|||
|
||||
-- Check for object "collision". Done every tick (hopefully this is not too stressing)
|
||||
else
|
||||
|
||||
if self._damage == 10 or self._damage == 9 then
|
||||
minetest.add_particlespawner({
|
||||
amount = 1,
|
||||
time = .001,
|
||||
minpos = pos,
|
||||
maxpos = pos,
|
||||
minvel = vector.new(-0.1,-0.1,-0.1),
|
||||
maxvel = vector.new(0.1,0.1,0.1),
|
||||
minexptime = 0.5,
|
||||
maxexptime = 0.5,
|
||||
minsize = 2,
|
||||
maxsize = 2,
|
||||
collisiondetection = false,
|
||||
vertical = false,
|
||||
texture = "mobs_mc_arrow_particle.png",
|
||||
glow = 1,
|
||||
})
|
||||
end
|
||||
|
||||
-- We just check for any hurtable objects nearby.
|
||||
-- The radius of 3 is fairly liberal, but anything lower than than will cause
|
||||
-- arrow to hilariously go through mobs often.
|
||||
|
|
|
@ -6,6 +6,16 @@ mcl_player = {}
|
|||
-- Note: This is currently broken due to a bug in Irrlicht, leave at 0
|
||||
local animation_blend = 0
|
||||
|
||||
local function get_mouse_button(player)
|
||||
local controls = player:get_player_control()
|
||||
local get_wielded_item_name = player:get_wielded_item():get_name()
|
||||
if controls.RMB and not string.find(player:get_wielded_item():get_name(), "mcl_bows:bow") or controls.LMB then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
mcl_player.registered_player_models = { }
|
||||
|
||||
-- Local for speed.
|
||||
|
@ -174,30 +184,30 @@ minetest.register_globalstep(function(dtime)
|
|||
player_anim[name] = nil
|
||||
player_sneak[name] = controls.sneak
|
||||
end
|
||||
if controls.LMB and not controls.sneak and head_in_water and is_sprinting == true then
|
||||
if get_mouse_button(player) == true and not controls.sneak and head_in_water and is_sprinting == true then
|
||||
player_set_animation(player, "swim_walk_mine", animation_speed_mod)
|
||||
elseif not controls.sneak and head_in_water and is_sprinting == true then
|
||||
player_set_animation(player, "swim_walk", animation_speed_mod)
|
||||
elseif is_sprinting == true and controls.LMB and not controls.sneak and not head_in_water then
|
||||
elseif is_sprinting == true and get_mouse_button(player) == true and not controls.sneak and not head_in_water then
|
||||
player_set_animation(player, "run_walk_mine", animation_speed_mod)
|
||||
elseif controls.LMB and not controls.sneak then
|
||||
elseif get_mouse_button(player) == true and not controls.sneak then
|
||||
player_set_animation(player, "walk_mine", animation_speed_mod)
|
||||
elseif controls.LMB and controls.sneak and is_sprinting ~= true then
|
||||
elseif get_mouse_button(player) == true and controls.sneak and is_sprinting ~= true then
|
||||
player_set_animation(player, "sneak_walk_mine", animation_speed_mod)
|
||||
elseif is_sprinting == true and not controls.sneak and not head_in_water then
|
||||
player_set_animation(player, "run_walk", animation_speed_mod)
|
||||
elseif controls.sneak and not controls.LMB then
|
||||
elseif controls.sneak and not get_mouse_button(player) == true then
|
||||
player_set_animation(player, "sneak_walk", animation_speed_mod)
|
||||
else
|
||||
player_set_animation(player, "walk", animation_speed_mod)
|
||||
end
|
||||
elseif controls.LMB and not controls.sneak and head_in_water and is_sprinting == true then
|
||||
elseif get_mouse_button(player) == true and not controls.sneak and head_in_water and is_sprinting == true then
|
||||
player_set_animation(player, "swim_mine")
|
||||
elseif not controls.LMB and not controls.sneak and head_in_water and is_sprinting == true then
|
||||
elseif not get_mouse_button(player) == true and not controls.sneak and head_in_water and is_sprinting == true then
|
||||
player_set_animation(player, "swim_stand")
|
||||
elseif controls.LMB and not controls.sneak then
|
||||
elseif get_mouse_button(player) == true and not controls.sneak then
|
||||
player_set_animation(player, "mine")
|
||||
elseif controls.LMB and controls.sneak then
|
||||
elseif get_mouse_button(player) == true and controls.sneak then
|
||||
player_set_animation(player, "sneak_mine")
|
||||
elseif not controls.sneak and head_in_water and is_sprinting == true then
|
||||
player_set_animation(player, "swim_stand", animation_speed_mod)
|
||||
|
|
|
@ -50,16 +50,27 @@ end
|
|||
|
||||
local function setSprinting(playerName, sprinting) --Sets the state of a player (0=stopped/moving, 1=sprinting)
|
||||
local player = minetest.get_player_by_name(playerName)
|
||||
local controls = player:get_player_control()
|
||||
if players[playerName] then
|
||||
players[playerName].sprinting = sprinting
|
||||
if sprinting == true then
|
||||
players[playerName].fov = math.min(players[playerName].fov + 0.05, 1.2)
|
||||
player:set_fov(players[playerName].fov, true, 0.15)
|
||||
playerphysics.add_physics_factor(player, "speed", "mcl_sprint:sprint", mcl_sprint.SPEED)
|
||||
elseif sprinting == false then
|
||||
if sprinting == true or controls.RMB and string.find(player:get_wielded_item():get_name(), "mcl_bows:bow") and player:get_wielded_item():get_name() ~= "mcl_bows:bow" then
|
||||
if sprinting == true then
|
||||
players[playerName].fov = math.min(players[playerName].fov + 0.05, 1.2)
|
||||
players[playerName].fade_time = .15
|
||||
else
|
||||
players[playerName].fov = .7
|
||||
players[playerName].fade_time = .3
|
||||
end
|
||||
player:set_fov(players[playerName].fov, true, players[playerName].fade_time)
|
||||
if sprinting == true then
|
||||
playerphysics.add_physics_factor(player, "speed", "mcl_sprint:sprint", mcl_sprint.SPEED)
|
||||
end
|
||||
elseif sprinting == false and player:get_wielded_item():get_name() ~= "mcl_bows:bow_0" and player:get_wielded_item():get_name() ~= "mcl_bows:bow_1" and player:get_wielded_item():get_name() ~= "mcl_bows:bow_2" then
|
||||
players[playerName].fov = math.max(players[playerName].fov - 0.05, 1.0)
|
||||
player:set_fov(players[playerName].fov, true, 0.15)
|
||||
playerphysics.remove_physics_factor(player, "speed", "mcl_sprint:sprint")
|
||||
if sprinting == false then
|
||||
playerphysics.remove_physics_factor(player, "speed", "mcl_sprint:sprint")
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
|