Compare commits

...

27 Commits

Author SHA1 Message Date
loosewheel
eaf6a679c3 Add files via upload 2022-02-19 14:08:26 +10:00
loosewheel
f41ab00398 Add files via upload 2022-02-19 14:06:27 +10:00
loosewheel
7f42fde4a0 Add files via upload 2022-02-19 14:04:44 +10:00
loosewheel
6f8a194042 Add files via upload 2022-02-16 01:49:12 +10:00
loosewheel
84ddc82c95 Add files via upload 2022-02-16 01:46:56 +10:00
loosewheel
36aaf42d9a Add files via upload 2022-02-15 07:14:40 +10:00
loosewheel
c879735c84 Add files via upload 2022-02-15 07:06:04 +10:00
loosewheel
76a8d37edb Add files via upload 2022-02-15 06:31:00 +10:00
loosewheel
1a450bdc2a Add files via upload 2022-02-15 06:28:44 +10:00
loosewheel
c11eb22f31 Add files via upload 2022-02-15 06:26:14 +10:00
loosewheel
e4aabe5ebe Add files via upload 2022-02-15 06:25:24 +10:00
loosewheel
3cfd9adb1f Add files via upload 2022-02-15 06:24:40 +10:00
loosewheel
51ab3bdc3c Add files via upload 2022-02-05 02:14:40 +10:00
loosewheel
f873bb551f Add files via upload 2022-02-05 02:08:42 +10:00
loosewheel
326275cea6 Add files via upload 2022-02-05 02:07:16 +10:00
loosewheel
f869a4c40b Add files via upload 2022-02-05 02:05:18 +10:00
loosewheel
37488db8b9 Add files via upload 2022-02-05 02:04:35 +10:00
loosewheel
cf54a3d548 Add files via upload 2022-02-05 02:03:48 +10:00
loosewheel
9519eae026 Add files via upload 2022-01-20 17:58:09 +10:00
loosewheel
5caa7b6408 Add files via upload 2022-01-08 20:03:32 +10:00
loosewheel
6d4369ee91 Add files via upload 2022-01-07 18:55:19 +10:00
loosewheel
c7ec545ef7 Add files via upload 2022-01-07 18:53:39 +10:00
loosewheel
923faa59a3 Add files via upload 2022-01-07 18:50:47 +10:00
loosewheel
201c01131f Add files via upload 2022-01-07 18:49:57 +10:00
loosewheel
a0c9dd1d0c Add files via upload 2022-01-07 18:49:14 +10:00
loosewheel
c43dab66d7 Add files via upload 2021-12-06 21:15:05 +10:00
loosewheel
ca31c40d8b Add files via upload 2021-12-05 01:24:47 +10:00
38 changed files with 2642 additions and 130 deletions

452
camera.lua Normal file
View File

@@ -0,0 +1,452 @@
local utils = ...
local S = utils.S
if utils.digilines_supported then
local function is_drop (obj)
if obj then
local entity = obj.get_luaentity and obj:get_luaentity ()
return (entity and entity.name and entity.name == "__builtin:item")
end
return false
end
local function get_entity_dims (obj)
local dims = { -0.5, 0, -0.5, 0.5, 2, 0.5 }
local found = false
if obj.get_luaentity then
local entity = obj:get_luaentity ()
if entity and entity.name then
local def = minetest.registered_entities[entity.name]
if def and type (def.collisionbox) == "table" then
dims = { def.collisionbox[1] or -0.5,
def.collisionbox[2] or -0.5,
def.collisionbox[3] or -0.5,
def.collisionbox[4] or 0.5,
def.collisionbox[5] or 0.5,
def.collisionbox[6] or 0.5 }
found = true
end
end
end
if not found then
local props = obj:get_properties ()
if props and props.collisionbox and type (props.collisionbox) == "table" then
dims = { props.collisionbox[1] or -0.5,
props.collisionbox[2] or -0.5,
props.collisionbox[3] or -0.5,
props.collisionbox[4] or 0.5,
props.collisionbox[5] or 0.5,
props.collisionbox[6] or 0.5 }
end
end
dims[1] = math.min (dims[1], dims[3])
dims[3] = dims[1]
dims[4] = math.max (dims[4], dims[6])
dims[6] = dims[4]
if (dims[3] - dims[1]) < 1 then
dims[1] = -0.5
dims[3] = -0.5
dims[4] = 0.5
dims[6] = 0.5
end
return dims
end
local function get_entity (pos)
local objects = minetest.get_objects_inside_radius (pos, 2.0)
if #objects > 0 then
for _, obj in ipairs (objects) do
if obj.get_pos then
if obj:is_player () then
local epos = vector.round (obj:get_pos ())
if epos.x == pos.x and epos.z == pos.z and
(epos.y == pos.y or epos.y == pos.y - 1) then
return 1
end
end
if not is_drop (obj) then
local epos = vector.new (obj:get_pos ())
local dims = get_entity_dims (obj)
if pos.x >= (epos.x + dims[1]) and pos.x <= (epos.x + dims[4]) and
pos.y >= (epos.y + dims[2]) and pos.y <= (epos.y + dims[5]) and
pos.z >= (epos.z + dims[3]) and pos.z <= (epos.z + dims[6]) then
return 2
end
end
end
end
end
return nil
end
local function camera_scan (pos, resolution, distance)
local node = utils.get_far_node (pos)
local image = { }
for y = 1, resolution, 1 do
image[y] = { }
for x = 1, resolution, 1 do
image[y][x] = "000000"
end
end
if node then
local dir = vector.multiply (minetest.facedir_to_dir (node.param2), -1)
local last_pos = nil
local last_color = "000000"
local view = (distance * 1.414213562) / resolution
for dist = distance, 1, -1 do
local scale = dist / distance
for y = 1, resolution, 1 do
for x = 1, resolution, 1 do
local horz = (x - (resolution / 2)) * scale * view
local vert = (y - (resolution / 2)) * scale * view
local tpos = nil
if dir.x ~= 0 then
tpos = vector.round ({ x = (dist * dir.x) + pos.x, y = pos.y - vert, z = horz + pos.z })
else
tpos = vector.round ({ x = horz + pos.x, y = pos.y - vert, z = (dist * dir.z) + pos.z })
end
if last_pos and vector.equals (last_pos, tpos) then
if last_color then
image[y][x] = last_color
end
else
local entity = get_entity (tpos)
if entity == 1 then
local color = (((distance - dist) / distance) * 98) + 30
last_color = string.format ("00%02X00", color)
image[y][x] = last_color
elseif entity == 2 then
local color = (((distance - dist) / distance) * 98) + 30
last_color = string.format ("0000%02X", color)
image[y][x] = last_color
else
local node = utils.get_far_node (tpos)
if node and node.name ~= "air" then
local color = (((distance - dist) / distance) * 98) + 30
last_color = string.format ("%02X%02X%02X", color, color, color)
image[y][x] = last_color
else
last_color = nil
end
end
end
last_pos = tpos
end
end
end
end
return image
end
local function send_scan (pos)
local meta = minetest.get_meta (pos)
if meta then
local channel = meta:get_string ("channel")
if channel:len () > 0 then
local image = camera_scan (pos,
tonumber (meta:get_string ("resolution")),
tonumber (meta:get_string ("distance")))
utils.digilines_receptor_send (pos,
utils.digilines_default_rules,
channel,
image)
end
end
end
local function after_place_node (pos, placer, itemstack, pointed_thing)
local meta = minetest.get_meta (pos)
local spec =
"formspec_version[3]"..
"size[8.5,5.5;true]"..
"field[1.0,1.0;4.0,0.8;channel;Channel;${channel}]"..
"button[5.5,1.0;2.0,0.8;setchannel;Set]"..
"field[1.0,2.5;4.0,0.8;distance;Distance;${distance}]"..
"button[5.5,2.5;2.0,0.8;setdistance;Set]"..
"field[1.0,4.0;4.0,0.8;resolution;Resolution;${resolution}]"..
"button[5.5,4.0;2.0,0.8;setresolution;Set]"
meta:set_string ("formspec", spec)
meta:set_string ("distance", "5")
meta:set_string ("resolution", "16")
-- If return true no item is taken from itemstack
return false
end
local function after_place_node_locked (pos, placer, itemstack, pointed_thing)
after_place_node (pos, placer, itemstack, pointed_thing)
if placer and placer:is_player () then
local meta = minetest.get_meta (pos)
meta:set_string ("owner", placer:get_player_name ())
meta:set_string ("infotext", "Camera (owned by "..placer:get_player_name ()..")")
end
-- If return true no item is taken from itemstack
return false
end
local function on_receive_fields (pos, formname, fields, sender)
if not utils.can_interact_with_node (pos, sender) then
return
end
if fields.setchannel then
local meta = minetest.get_meta (pos)
if meta then
meta:set_string ("channel", fields.channel)
end
end
if fields.setdistance then
local meta = minetest.get_meta (pos)
if meta then
local distance = math.min (math.max (tonumber (fields.distance) or 1, 1), 16)
fields.distance = tostring (distance)
meta:set_string ("distance", tostring (distance))
end
end
if fields.setresolution then
local meta = minetest.get_meta (pos)
if meta then
local resolution = math.min (math.max (tonumber (fields.resolution) or 1, 1), 128)
fields.resolution = tostring (resolution)
meta:set_string ("resolution", tostring (resolution))
end
end
end
local function can_dig (pos, player)
if not utils.can_interact_with_node (pos, player) then
return false
end
return true
end
local function on_blast (pos, intensity)
local meta = minetest.get_meta (pos)
if meta then
if intensity >= 1.0 then
minetest.remove_node (pos)
else -- intensity < 1.0
local node = minetest.get_node_or_nil (pos)
if node then
local items = minetest.get_node_drops (node, nil)
if items and #items > 0 then
local stack = ItemStack (items[1])
if stack then
preserve_metadata (pos, node, meta, { stack })
utils.item_drop (stack, nil, pos)
minetest.remove_node (pos)
end
end
end
end
end
end
local function on_rightclick (pos, node, clicker, itemstack, pointed_thing)
if not utils.can_interact_with_node (pos, clicker) then
if clicker and clicker:is_player () then
local owner = "<unknown>"
local meta = minetest.get_meta (pos)
if meta then
owner = meta:get_string ("owner")
end
local spec =
"formspec_version[3]"..
"size[8.0,4.0,false]"..
"label[1.0,1.0;Owned by "..minetest.formspec_escape (owner).."]"..
"button_exit[3.0,2.0;2.0,1.0;close;Close]"
minetest.show_formspec (clicker:get_player_name (),
"lwcomponents:component_privately_owned",
spec)
end
end
return itemstack
end
local function digilines_support ()
if utils.digilines_supported then
return
{
wire =
{
rules = utils.digilines_default_rules,
},
effector =
{
action = function (pos, node, channel, msg)
local meta = minetest.get_meta(pos)
if meta then
local this_channel = meta:get_string ("channel")
if this_channel ~= "" and this_channel == channel and
type (msg) == "string" then
local m = { }
for w in string.gmatch(msg, "[^%s]+") do
m[#m + 1] = w
end
if m[1] == "scan" then
send_scan (pos)
elseif m[1] == "distance" then
local distance = math.min (math.max (tonumber (m[2] or 5) or 5, 1), 16)
meta:set_string ("distance", tostring (distance))
elseif m[1] == "resolution" then
local resolution = math.min (math.max (tonumber (m[2] or 16) or 16, 1), 128)
meta:set_string ("resolution", tostring (resolution))
end
end
end
end,
}
}
end
return nil
end
minetest.register_node("lwcomponents:camera", {
description = S("Camera"),
tiles = { "lwcamera.png", "lwcamera.png", "lwcamera.png",
"lwcamera.png", "lwcamera.png", "lwcamera_lens.png"},
is_ground_content = false,
groups = { cracky = 3 },
sounds = default.node_sound_stone_defaults (),
paramtype = "none",
param1 = 0,
paramtype2 = "facedir",
param2 = 0,
floodable = false,
drop = "lwcomponents:camera",
_digistuff_channelcopier_fieldname = "channel",
digiline = digilines_support (),
on_receive_fields = on_receive_fields,
can_dig = can_dig,
after_place_node = after_place_node,
on_blast = on_blast,
on_rightclick = on_rightclick
})
minetest.register_node("lwcomponents:camera_locked", {
description = S("Camera (locked)"),
tiles = { "lwcamera.png", "lwcamera.png", "lwcamera.png",
"lwcamera.png", "lwcamera.png", "lwcamera_lens.png"},
is_ground_content = false,
groups = { cracky = 3 },
sounds = default.node_sound_stone_defaults (),
paramtype = "none",
param1 = 0,
paramtype2 = "facedir",
param2 = 0,
floodable = false,
drop = "lwcomponents:camera_locked",
_digistuff_channelcopier_fieldname = "channel",
digiline = digilines_support (),
on_receive_fields = on_receive_fields,
can_dig = can_dig,
after_place_node = after_place_node_locked,
on_blast = on_blast,
on_rightclick = on_rightclick
})
end -- utils.digilines_supported
--

View File

@@ -74,3 +74,43 @@ v0.1.12
* Added cannon shells.
* Fixed bug in utils.is_creative.
* Increased cannon pitch to -20 to 70.
v0.1.13
* Removed optional dependency lwdrops.
v0.1.14
* Calls on_drop when item is dropped.
v0.1.15
* Fixed bug call to clear_map in fan on_blast.
* Added pistons.
v0.1.16
* Fixed piston interaction with non-walkable nodes.
v0.1.17
* Fixed unintended global variable in pistons.lua.
v0.1.18
* Added mesecons through wire.
v0.1.19
* Added camera.
v0.1.20
* Valid distance and resolution for camera set by digilines message.
* Imposed maximum resolution of 128 for cameras.
v0.1.21
* Minor bug fix, movefloor global.
* Fixed movefloor so player doesn't fall through floor.
* Transfer timer in moved nodes for pistons.

View File

@@ -49,7 +49,21 @@ minetest.register_craft( {
{ "default:iron_lump", "default:coalblock" },
},
})
end
end -- minetest.global_exists ("fire")
if utils.mesecon_supported then
minetest.register_craft( {
output = "lwcomponents:through_wire_off 2",
recipe = {
{ "", "mesecons:wire_00000000_off" },
{ "mesecons:wire_00000000_off", "" },
},
})
end -- utils.mesecon_supported
@@ -218,6 +232,26 @@ minetest.register_craft( {
},
})
minetest.register_craft({
output = "lwcomponents:piston 2",
recipe = {
{ "group:wood", "group:wood", "group:wood" },
{ "default:cobble", "default:steel_ingot", "default:cobble" },
{ "default:stone", "default:copper_ingot", "default:stone" },
}
})
minetest.register_craft({
output = "lwcomponents:piston_sticky",
recipe = {
{"group:sapling"},
{"lwcomponents:piston"},
}
})
end -- utils.digilines_supported or utils.mesecon_supported
@@ -261,6 +295,24 @@ minetest.register_craft( {
},
})
minetest.register_craft( {
output = "lwcomponents:camera",
recipe = {
{ "default:copper_ingot", "default:iron_lump" },
{ "default:chest", "default:stone" },
},
})
minetest.register_craft( {
output = "lwcomponents:camera_locked",
recipe = {
{ "default:copper_ingot", "default:iron_lump" },
{ "default:chest_locked", "default:stone" },
},
})
end -- utils.digilines_supported
@@ -280,7 +332,7 @@ end -- utils.digilines_supported and utils.digistuff_supported
if utils.mesecon_supported and mesecon.mvps_push then
if utils.mesecon_supported then
minetest.register_craft ({
output = "lwcomponents:movefloor",
@@ -291,7 +343,7 @@ minetest.register_craft ({
}
})
end -- utils.mesecon_supported and mesecon.mvps_push
end -- utils.mesecon_supported

View File

@@ -1,5 +1,4 @@
default
lwdrops?
mesecons?
digilines?
unifieddyes?

View File

@@ -73,7 +73,7 @@ end
local function place_node (itemname, pos)
local function place_node (item, pos)
local node = minetest.get_node_or_nil ({ x = pos.x, y = pos.y - 1, z = pos.z })
if not node then
@@ -100,8 +100,8 @@ local function place_node (itemname, pos)
end
end
local stack = ItemStack (itemname)
local itemdef = utils.find_item_def (itemname)
local stack = ItemStack (item)
local itemdef = utils.find_item_def (stack:get_name ())
if stack and itemdef then
local placed = false
@@ -122,23 +122,23 @@ local function place_node (itemname, pos)
end
if itemdef and itemdef.on_place then
local result, msg = pcall (itemdef.on_place, stack, nil, pointed_thing)
local result, leftover = pcall (itemdef.on_place, stack, nil, pointed_thing)
placed = result
if not placed then
if utils.settings.alert_handler_errors then
minetest.log ("error", "on_place handler for "..itemname.." crashed - "..msg)
minetest.log ("error", "on_place handler for "..stack:get_name ().." crashed - "..leftover)
end
end
end
if not placed then
if not minetest.registered_nodes[itemname] then
if not minetest.registered_nodes[stack:get_name ()] then
return false
end
minetest.set_node (pos, { name = itemname, param1 = 0, param2 = 0 })
minetest.set_node (pos, { name = stack:get_name (), param1 = 0, param2 = 0 })
if itemdef and itemdef.after_place_node then
local result, msg = pcall (itemdef.after_place_node, pos, nil, stack, pointed_thing)
@@ -154,11 +154,13 @@ local function place_node (itemname, pos)
pcall (minetest.sound_play, itemdef.sounds.place, { pos = pos })
end
end
end
return true
end
return false
end
-- slot:
@@ -219,7 +221,7 @@ local function deploy_item (pos, node, slot, range)
local deploypos = get_deploy_pos (pos, node.param2, range)
if item and deploypos then
if place_node (name, deploypos) then
if place_node (stack, deploypos) then
stack:set_count (stack:get_count () - 1)
inv:set_stack ("main", slot, stack)

View File

@@ -130,7 +130,7 @@ end
local function get_entity_height (objref)
if objref.get_luaentity then
entity = objref:get_luaentity ()
local entity = objref:get_luaentity ()
if entity and entity.name then
def = minetest.registered_entities[entity.name]
@@ -165,7 +165,7 @@ local function detect (pos)
local object = minetest.get_objects_inside_radius (pos, radius + 0.5)
local detected_list = { }
for i = 1, #object do
for i = 1, #object, 1 do
if object[i]:is_player () then
-- player

41
docs/camera.txt Normal file
View File

@@ -0,0 +1,41 @@
Camera
------
* This block is only available if digilines is loaded.
Cameras take an image in the direction they are facing. The colors in the
image represent what is being viewed. Nodes are gray, entities are blue and
players are green. The closer they are to the camera the brighter the color.
The viewing distance of the camera is 1 to 16 nodes. Also acts as a
digilines conductor.
Only the owner can dig or access the form of the locked version.
UI
Channel - digilines channel of camera.
Distance - the viewing distance forward from the camera (1 to 16).
Resolution - the image resolution (for both width and height, 1 to 128).
Digilines messages
"scan"
Sends a digilines message with the camera's channel and a table of the
image as the message (see below).
"distance n"
Sets the viewing distance of the camera. Will be clipped between 1 and
16.
"resolution n"
Sets the image resolution of the camera.
The image is an indexed table of indexed tables. Each inner table is one
line of the image ordered top to bottom. There are resolution number of
lines. Each line has a string value for each pixel of that line left to
right. The string is a hex color string eg. "00FF00". There are resolution
number of pixels per line.
The image format is compatible with digistuff's digiscreens and lwcomputers'
digiscreens and digipanels. It is best to set the resolution of the camera
to the resolution of the display, then the image from the camera can be sent
straight to the display device.

View File

@@ -1,6 +1,6 @@
MoveFloor
---------
* This block is only available if mesecons and mesecons_mvps is loaded.
* This block is only available if mesecons is loaded.
The MoveFloor block responds to a mesecons power source in the 4 horizontal
directions. If the power source is one higher the MoveFloor moves up to

31
docs/pistons.txt Normal file
View File

@@ -0,0 +1,31 @@
Pistons and sticky pistons
--------------------------
* These blocks are only available if digilines and/or mesecons are loaded.
Pistons push up to the setting Maximum piston nodes (default 15) in front
of the pusher when extended. Sticky piston draw back a single node in
front of the pusher when retracted. Piston also act as a digilines
conductor.
UI
Channel - digilines channel of piston.
Single move - pusher extends 1 node if checked, otherwise 2 nodes.
Mesecons
Piston extends while power is turned on.
Digilines messages
"extend n"
Extends the piston pusher to extent n (0, 1 or 2). If n is not given
pusher extends to maximum extent. 0 is retracted.
"retract"
Same as 'extend 0'.
"single"
Sets piston to single move mode.
"double"
Sets piston to double move mode.

7
docs/through_wire.txt Normal file
View File

@@ -0,0 +1,7 @@
Mesecons Through Wire
---------------------
* This block is only available if mesecons is loaded.
Will transmit mesecons power when placed one to two blocks apart opposing
each other, through solid blocks or open space. Can also be used as a mesecons
crossover.

View File

@@ -199,14 +199,10 @@ local function on_blast (pos, intensity)
if meta then
if intensity >= 1.0 then
clear_map (pos)
minetest.remove_node (pos)
else -- intensity < 1.0
clear_map (pos)
local node = minetest.get_node_or_nil (pos)
if node then
local items = minetest.get_node_drops (node, nil)

View File

@@ -1,4 +1,4 @@
local version = "0.1.12"
local version = "0.1.21"
local mod_storage = minetest.get_mod_storage ()
@@ -34,6 +34,9 @@ loadfile (modpath.."/fan.lua") (utils)
loadfile (modpath.."/conduit.lua") (utils, mod_storage)
loadfile (modpath.."/cannon.lua") (utils)
loadfile (modpath.."/cannon_shell.lua") (utils)
loadfile (modpath.."/pistons.lua") (utils)
loadfile (modpath.."/through_wire.lua") (utils)
loadfile (modpath.."/camera.lua") (utils)
loadfile (modpath.."/extras.lua") (utils)
loadfile (modpath.."/digiswitch.lua") (utils)
loadfile (modpath.."/movefloor.lua") (utils)

View File

@@ -13,6 +13,8 @@ without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
See the GNU Lesser General Public License for more details:
https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
Mesecons through wire code was adapted from mesecons_receiver.
lwsiren-buzz.ogg
@@ -59,6 +61,16 @@ https://creativecommons.org/licenses/by/4.0/
lwmovefloor.ogg
---------------
https://www.freesoundslibrary.com/elevator-sound-effect-elevator-ride-doors-closing-and-opening/
License: Attribution 4.0 International (CC BY 4.0). You are allowed to use
sound effects free of charge and royalty free in your multimedia projects
for commercial or non-commercial purposes.
Media license
-------------
siren images derived from images from https://openclipart.org, which is
@@ -67,6 +79,9 @@ public domain.
fan images derived from images from https://openclipart.org, which is
public domain.
camera lens images derived from images from https://openclipart.org, which
is public domain.
player button images derived from mesecons button image.
cannon firing and explosion sound from tnt (TumeniNodes/steveygos93),
@@ -74,6 +89,8 @@ released under CC0 1.0 (originally from https://freesound.org/s/80401/)
boom image from tnt, released under CC BY-SA 3.0.
Piston images and sounds from mesecons_pistons, released under CC-BY-SA 3.0.
All other media, or media not covered by a licence, is licensed
Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)

View File

@@ -3,4 +3,4 @@ description = Various components for mesecons and digilines.
title = LWComponents
name = lwcomponents
depends = default
optional_depends = lwdrops, mesecons, digilines, unifieddyes, intllib, hopper, digistuff
optional_depends = mesecons, digilines, unifieddyes, intllib, hopper, digistuff

143
models/piston_normal_1.obj Normal file
View File

@@ -0,0 +1,143 @@
# Blender v2.82 (sub 7) OBJ File: ''
# www.blender.org
mtllib piston_normal_1.mtl
o cube
v 0.500000 -0.500000 0.500000
v -0.500000 -0.500000 0.500000
v -0.500000 -0.500000 -0.312500
v 0.500000 -0.500000 -0.312500
v 0.500000 0.500000 0.500000
v 0.500000 0.500000 -0.312500
v -0.500000 0.500000 0.500000
v -0.500000 0.500000 -0.312500
vt 0.666667 0.666667
vt 1.000000 0.666667
vt 1.000000 0.937500
vt 0.666667 0.937500
vt 0.666667 0.666667
vt 1.000000 0.666667
vt 1.000000 0.937500
vt 0.666667 0.937500
vt 0.666667 0.666667
vt 1.000000 0.666667
vt 1.000000 0.937500
vt 0.666667 0.937500
vt 0.666667 0.666667
vt 1.000000 0.666667
vt 1.000000 0.937500
vt 0.666667 0.937500
vt 0.333333 0.333333
vt 0.666667 0.333333
vt 0.666667 0.666667
vt 0.333333 0.666667
vt 0.333333 0.666667
vt 0.666667 1.000000
vt 0.333333 1.000000
vn 0.0000 -1.0000 0.0000
vn 1.0000 -0.0000 0.0000
vn 0.0000 1.0000 0.0000
vn -1.0000 -0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 0.0000 -0.0000 1.0000
usemtl m_7
s 1
f 1/1/1 2/2/1 3/3/1 4/4/1
f 5/5/2 1/6/2 4/7/2 6/8/2
f 7/9/3 5/10/3 6/11/3 8/12/3
f 2/13/4 7/14/4 8/15/4 3/16/4
f 8/17/5 6/18/5 4/19/5 3/20/5
f 2/21/6 1/1/6 5/22/6 7/23/6
o cube.000
v 0.500000 -0.500000 -1.312500
v -0.500000 -0.500000 -1.312500
v -0.500000 -0.500000 -1.500000
v 0.500000 -0.500000 -1.500000
v 0.500000 0.500000 -1.312500
v 0.500000 0.500000 -1.500000
v -0.500000 0.500000 -1.312500
v -0.500000 0.500000 -1.500000
vt 0.666667 0.937500
vt 1.000000 0.937500
vt 1.000000 1.000000
vt 0.666667 1.000000
vt 0.666667 0.937500
vt 1.000000 0.937500
vt 1.000000 1.000000
vt 0.666667 1.000000
vt 0.666667 0.937500
vt 1.000000 0.937500
vt 1.000000 1.000000
vt 0.666667 1.000000
vt 0.666667 0.937500
vt 1.000000 0.937500
vt 1.000000 1.000000
vt 0.666667 1.000000
vt 0.333333 0.000000
vt 0.666667 0.000000
vt 0.666667 0.333333
vt 0.333333 0.333333
vt 0.666667 0.333333
vt 1.000000 0.333333
vt 1.000000 0.666667
vt 0.666667 0.666667
vn 0.0000 -1.0000 0.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 1.0000 0.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 0.0000 0.0000 1.0000
usemtl m_7
s 1
f 9/24/7 10/25/7 11/26/7 12/27/7
f 13/28/8 9/29/8 12/30/8 14/31/8
f 15/32/9 13/33/9 14/34/9 16/35/9
f 10/36/10 15/37/10 16/38/10 11/39/10
f 16/40/11 14/41/11 12/42/11 11/43/11
f 10/44/12 9/45/12 13/46/12 15/47/12
o cube.001
v 0.125000 -0.125000 0.375000
v -0.125000 -0.125000 0.375000
v -0.125000 -0.125000 -1.375000
v 0.125000 -0.125000 -1.375000
v 0.125000 0.125000 0.375000
v 0.125000 0.125000 -1.375000
v -0.125000 0.125000 0.375000
v -0.125000 0.125000 -1.375000
vt 0.125000 0.354167
vt 0.208333 0.354167
vt 0.208333 0.979167
vt 0.125000 0.979167
vt 0.125000 0.354167
vt 0.208333 0.354167
vt 0.208333 0.979167
vt 0.125000 0.979167
vt 0.125000 0.354167
vt 0.208333 0.354167
vt 0.208333 0.979167
vt 0.125000 0.979167
vt 0.125000 0.354167
vt 0.208333 0.354167
vt 0.208333 0.979167
vt 0.125000 0.979167
vt 0.458333 0.130208
vt 0.541667 0.130208
vt 0.541667 0.213542
vt 0.458333 0.213542
vt 0.791667 0.463542
vt 0.875000 0.463542
vt 0.875000 0.546875
vt 0.791667 0.546875
vn 0.0000 -1.0000 -0.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 1.0000 0.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 0.0000 0.0000 1.0000
usemtl m_7
s 1
f 17/48/13 18/49/13 19/50/13 20/51/13
f 21/52/14 17/53/14 20/54/14 22/55/14
f 23/56/15 21/57/15 22/58/15 24/59/15
f 18/60/16 23/61/16 24/62/16 19/63/16
f 24/64/17 22/65/17 20/66/17 19/67/17
f 18/68/18 17/69/18 21/70/18 23/71/18

143
models/piston_normal_2.obj Normal file
View File

@@ -0,0 +1,143 @@
# Blender v2.82 (sub 7) OBJ File: ''
# www.blender.org
mtllib piston_normal_2.mtl
o cube.011
v 0.500000 -0.500000 0.500000
v -0.500000 -0.500000 0.500000
v -0.500000 -0.500000 -0.312500
v 0.500000 -0.500000 -0.312500
v 0.500000 0.500000 0.500000
v 0.500000 0.500000 -0.312500
v -0.500000 0.500000 0.500000
v -0.500000 0.500000 -0.312500
vt 0.666667 0.666667
vt 1.000000 0.666667
vt 1.000000 0.937500
vt 0.666667 0.937500
vt 0.666667 0.666667
vt 1.000000 0.666667
vt 1.000000 0.937500
vt 0.666667 0.937500
vt 0.666667 0.666667
vt 1.000000 0.666667
vt 1.000000 0.937500
vt 0.666667 0.937500
vt 0.666667 0.666667
vt 1.000000 0.666667
vt 1.000000 0.937500
vt 0.666667 0.937500
vt 0.333333 0.333333
vt 0.666667 0.333333
vt 0.666667 0.666667
vt 0.333333 0.666667
vt 0.333333 0.666667
vt 0.666667 1.000000
vt 0.333333 1.000000
vn 0.0000 -1.0000 0.0000
vn 1.0000 -0.0000 0.0000
vn 0.0000 1.0000 0.0000
vn -1.0000 -0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 0.0000 -0.0000 1.0000
usemtl m_0.001
s 1
f 1/1/1 2/2/1 3/3/1 4/4/1
f 5/5/2 1/6/2 4/7/2 6/8/2
f 7/9/3 5/10/3 6/11/3 8/12/3
f 2/13/4 7/14/4 8/15/4 3/16/4
f 8/17/5 6/18/5 4/19/5 3/20/5
f 2/21/6 1/1/6 5/22/6 7/23/6
o cube.012
v 0.500000 -0.500000 -2.312500
v -0.500000 -0.500000 -2.312500
v -0.500000 -0.500000 -2.500000
v 0.500000 -0.500000 -2.500000
v 0.500000 0.500000 -2.312500
v 0.500000 0.500000 -2.500000
v -0.500000 0.500000 -2.312500
v -0.500000 0.500000 -2.500000
vt 0.666667 0.937500
vt 1.000000 0.937500
vt 1.000000 1.000000
vt 0.666667 1.000000
vt 0.666667 0.937500
vt 1.000000 0.937500
vt 1.000000 1.000000
vt 0.666667 1.000000
vt 0.666667 0.937500
vt 1.000000 0.937500
vt 1.000000 1.000000
vt 0.666667 1.000000
vt 0.666667 0.937500
vt 1.000000 0.937500
vt 1.000000 1.000000
vt 0.666667 1.000000
vt 0.333333 0.000000
vt 0.666667 0.000000
vt 0.666667 0.333333
vt 0.333333 0.333333
vt 0.666667 0.333333
vt 1.000000 0.333333
vt 1.000000 0.666667
vt 0.666667 0.666667
vn 0.0000 -1.0000 -0.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 1.0000 0.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 0.0000 0.0000 1.0000
usemtl m_0.001
s 1
f 9/24/7 10/25/7 11/26/7 12/27/7
f 13/28/8 9/29/8 12/30/8 14/31/8
f 15/32/9 13/33/9 14/34/9 16/35/9
f 10/36/10 15/37/10 16/38/10 11/39/10
f 16/40/11 14/41/11 12/42/11 11/43/11
f 10/44/12 9/45/12 13/46/12 15/47/12
o cube.013
v 0.125000 -0.125000 0.375000
v -0.125000 -0.125000 0.375000
v -0.125000 -0.125000 -2.375000
v 0.125000 -0.125000 -2.375000
v 0.125000 0.125000 0.375000
v 0.125000 0.125000 -2.375000
v -0.125000 0.125000 0.375000
v -0.125000 0.125000 -2.375000
vt 0.125000 0.020833
vt 0.208333 0.020833
vt 0.208333 0.979167
vt 0.125000 0.979167
vt 0.125000 0.020833
vt 0.208333 0.020833
vt 0.208333 0.979167
vt 0.125000 0.979167
vt 0.125000 0.020833
vt 0.208333 0.020833
vt 0.208333 0.979167
vt 0.125000 0.979167
vt 0.125000 0.020833
vt 0.208333 0.020833
vt 0.208333 0.979167
vt 0.125000 0.979167
vt 0.562500 0.229167
vt 0.458333 0.229167
vt 0.458333 0.125000
vt 0.562500 0.125000
vt 0.875000 0.458333
vt 0.791667 0.458333
vt 0.791667 0.541667
vt 0.875000 0.541667
vn 0.0000 -1.0000 -0.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 1.0000 0.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 0.0000 0.0000 1.0000
usemtl m_0.001
s 1
f 17/48/13 18/49/13 19/50/13 20/51/13
f 21/52/14 17/53/14 20/54/14 22/55/14
f 23/56/15 21/57/15 22/58/15 24/59/15
f 18/60/16 23/61/16 24/62/16 19/63/16
f 24/64/17 22/65/17 20/66/17 19/67/17
f 18/68/18 17/69/18 21/70/18 23/71/18

143
models/piston_sticky_1.obj Normal file
View File

@@ -0,0 +1,143 @@
# Blender v2.82 (sub 7) OBJ File: ''
# www.blender.org
mtllib piston_sticky_1.mtl
o cube.002
v 0.500000 -0.500000 0.500000
v -0.500000 -0.500000 0.500000
v -0.500000 -0.500000 -0.312500
v 0.500000 -0.500000 -0.312500
v 0.500000 0.500000 0.500000
v 0.500000 0.500000 -0.312500
v -0.500000 0.500000 0.500000
v -0.500000 0.500000 -0.312500
vt 0.666667 0.666667
vt 1.000000 0.666667
vt 1.000000 0.937500
vt 0.666667 0.937500
vt 0.666667 0.666667
vt 1.000000 0.666667
vt 1.000000 0.937500
vt 0.666667 0.937500
vt 0.666667 0.666667
vt 1.000000 0.666667
vt 1.000000 0.937500
vt 0.666667 0.937500
vt 0.666667 0.666667
vt 1.000000 0.666667
vt 1.000000 0.937500
vt 0.666667 0.937500
vt 0.333333 0.333333
vt 0.666667 0.333333
vt 0.666667 0.666667
vt 0.333333 0.666667
vt 0.333333 0.666667
vt 0.666667 1.000000
vt 0.333333 1.000000
vn 0.0000 -1.0000 0.0000
vn 1.0000 -0.0000 0.0000
vn 0.0000 1.0000 0.0000
vn -1.0000 -0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 0.0000 -0.0000 1.0000
usemtl m_7.001
s 1
f 1/1/1 2/2/1 3/3/1 4/4/1
f 5/5/2 1/6/2 4/7/2 6/8/2
f 7/9/3 5/10/3 6/11/3 8/12/3
f 2/13/4 7/14/4 8/15/4 3/16/4
f 8/17/5 6/18/5 4/19/5 3/20/5
f 2/21/6 1/1/6 5/22/6 7/23/6
o cube.003
v 0.500000 -0.500000 -1.312500
v -0.500000 -0.500000 -1.312500
v -0.500000 -0.500000 -1.500000
v 0.500000 -0.500000 -1.500000
v 0.500000 0.500000 -1.312500
v 0.500000 0.500000 -1.500000
v -0.500000 0.500000 -1.312500
v -0.500000 0.500000 -1.500000
vt 0.666667 0.937500
vt 1.000000 0.937500
vt 1.000000 1.000000
vt 0.666667 1.000000
vt 0.666667 0.937500
vt 1.000000 0.937500
vt 1.000000 1.000000
vt 0.666667 1.000000
vt 0.666667 0.937500
vt 1.000000 0.937500
vt 1.000000 1.000000
vt 0.666667 1.000000
vt 0.666667 0.937500
vt 1.000000 0.937500
vt 1.000000 1.000000
vt 0.666667 1.000000
vt 0.666667 0.000000
vt 1.000000 0.000000
vt 1.000000 0.333333
vt 0.666667 0.333333
vt 0.666667 0.333333
vt 1.000000 0.333333
vt 1.000000 0.666667
vt 0.666667 0.666667
vn 0.0000 -1.0000 0.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 1.0000 0.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 0.0000 0.0000 1.0000
usemtl m_7.001
s 1
f 9/24/7 10/25/7 11/26/7 12/27/7
f 13/28/8 9/29/8 12/30/8 14/31/8
f 15/32/9 13/33/9 14/34/9 16/35/9
f 10/36/10 15/37/10 16/38/10 11/39/10
f 16/40/11 14/41/11 12/42/11 11/43/11
f 10/44/12 9/45/12 13/46/12 15/47/12
o cube.004
v 0.125000 -0.125000 0.375000
v -0.125000 -0.125000 0.375000
v -0.125000 -0.125000 -1.375000
v 0.125000 -0.125000 -1.375000
v 0.125000 0.125000 0.375000
v 0.125000 0.125000 -1.375000
v -0.125000 0.125000 0.375000
v -0.125000 0.125000 -1.375000
vt 0.125000 0.354167
vt 0.208333 0.354167
vt 0.208333 0.979167
vt 0.125000 0.979167
vt 0.125000 0.354167
vt 0.208333 0.354167
vt 0.208333 0.979167
vt 0.125000 0.979167
vt 0.125000 0.354167
vt 0.208333 0.354167
vt 0.208333 0.979167
vt 0.125000 0.979167
vt 0.125000 0.354167
vt 0.208333 0.354167
vt 0.208333 0.979167
vt 0.125000 0.979167
vt 0.458333 0.130208
vt 0.541667 0.130208
vt 0.541667 0.213542
vt 0.458333 0.213542
vt 0.791667 0.463542
vt 0.875000 0.463542
vt 0.875000 0.546875
vt 0.791667 0.546875
vn 0.0000 -1.0000 -0.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 1.0000 0.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 0.0000 0.0000 1.0000
usemtl m_7.001
s 1
f 17/48/13 18/49/13 19/50/13 20/51/13
f 21/52/14 17/53/14 20/54/14 22/55/14
f 23/56/15 21/57/15 22/58/15 24/59/15
f 18/60/16 23/61/16 24/62/16 19/63/16
f 24/64/17 22/65/17 20/66/17 19/67/17
f 18/68/18 17/69/18 21/70/18 23/71/18

143
models/piston_sticky_2.obj Normal file
View File

@@ -0,0 +1,143 @@
# Blender v2.82 (sub 7) OBJ File: ''
# www.blender.org
mtllib piston_sticky_2.mtl
o cube.008
v 0.500000 -0.500000 0.500000
v -0.500000 -0.500000 0.500000
v -0.500000 -0.500000 -0.312500
v 0.500000 -0.500000 -0.312500
v 0.500000 0.500000 0.500000
v 0.500000 0.500000 -0.312500
v -0.500000 0.500000 0.500000
v -0.500000 0.500000 -0.312500
vt 0.666667 0.666667
vt 1.000000 0.666667
vt 1.000000 0.937500
vt 0.666667 0.937500
vt 0.666667 0.666667
vt 1.000000 0.666667
vt 1.000000 0.937500
vt 0.666667 0.937500
vt 0.666667 0.666667
vt 1.000000 0.666667
vt 1.000000 0.937500
vt 0.666667 0.937500
vt 0.666667 0.666667
vt 1.000000 0.666667
vt 1.000000 0.937500
vt 0.666667 0.937500
vt 0.333333 0.333333
vt 0.666667 0.333333
vt 0.666667 0.666667
vt 0.333333 0.666667
vt 0.333333 0.666667
vt 0.666667 1.000000
vt 0.333333 1.000000
vn 0.0000 -1.0000 0.0000
vn 1.0000 -0.0000 0.0000
vn 0.0000 1.0000 0.0000
vn -1.0000 -0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 0.0000 -0.0000 1.0000
usemtl m_0
s 1
f 1/1/1 2/2/1 3/3/1 4/4/1
f 5/5/2 1/6/2 4/7/2 6/8/2
f 7/9/3 5/10/3 6/11/3 8/12/3
f 2/13/4 7/14/4 8/15/4 3/16/4
f 8/17/5 6/18/5 4/19/5 3/20/5
f 2/21/6 1/1/6 5/22/6 7/23/6
o cube.009
v 0.500000 -0.500000 -2.312500
v -0.500000 -0.500000 -2.312500
v -0.500000 -0.500000 -2.500000
v 0.500000 -0.500000 -2.500000
v 0.500000 0.500000 -2.312500
v 0.500000 0.500000 -2.500000
v -0.500000 0.500000 -2.312500
v -0.500000 0.500000 -2.500000
vt 0.666667 0.937500
vt 1.000000 0.937500
vt 1.000000 1.000000
vt 0.666667 1.000000
vt 0.666667 0.937500
vt 1.000000 0.937500
vt 1.000000 1.000000
vt 0.666667 1.000000
vt 0.666667 0.937500
vt 1.000000 0.937500
vt 1.000000 1.000000
vt 0.666667 1.000000
vt 0.666667 0.937500
vt 1.000000 0.937500
vt 1.000000 1.000000
vt 0.666667 1.000000
vt 0.666667 0.000000
vt 1.000000 0.000000
vt 1.000000 0.333333
vt 0.666667 0.333333
vt 0.666667 0.333333
vt 1.000000 0.333333
vt 1.000000 0.666667
vt 0.666667 0.666667
vn 0.0000 -1.0000 -0.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 1.0000 0.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 0.0000 0.0000 1.0000
usemtl m_0
s 1
f 9/24/7 10/25/7 11/26/7 12/27/7
f 13/28/8 9/29/8 12/30/8 14/31/8
f 15/32/9 13/33/9 14/34/9 16/35/9
f 10/36/10 15/37/10 16/38/10 11/39/10
f 16/40/11 14/41/11 12/42/11 11/43/11
f 10/44/12 9/45/12 13/46/12 15/47/12
o cube.010
v 0.125000 -0.125000 0.375000
v -0.125000 -0.125000 0.375000
v -0.125000 -0.125000 -2.375000
v 0.125000 -0.125000 -2.375000
v 0.125000 0.125000 0.375000
v 0.125000 0.125000 -2.375000
v -0.125000 0.125000 0.375000
v -0.125000 0.125000 -2.375000
vt 0.125000 0.020833
vt 0.208333 0.020833
vt 0.208333 0.979167
vt 0.125000 0.979167
vt 0.125000 0.020833
vt 0.208333 0.020833
vt 0.208333 0.979167
vt 0.125000 0.979167
vt 0.125000 0.020833
vt 0.208333 0.020833
vt 0.208333 0.979167
vt 0.125000 0.979167
vt 0.125000 0.020833
vt 0.208333 0.020833
vt 0.208333 0.979167
vt 0.125000 0.979167
vt 0.562500 0.229167
vt 0.458333 0.229167
vt 0.458333 0.125000
vt 0.562500 0.125000
vt 0.875000 0.458333
vt 0.791667 0.458333
vt 0.791667 0.541667
vt 0.875000 0.541667
vn 0.0000 -1.0000 -0.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 1.0000 0.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 0.0000 0.0000 1.0000
usemtl m_0
s 1
f 17/48/13 18/49/13 19/50/13 20/51/13
f 21/52/14 17/53/14 20/54/14 22/55/14
f 23/56/15 21/57/15 22/58/15 24/59/15
f 18/60/16 23/61/16 24/62/16 19/63/16
f 24/64/17 22/65/17 20/66/17 19/67/17
f 18/68/18 17/69/18 21/70/18 23/71/18

View File

@@ -3,7 +3,7 @@ local S = utils.S
if utils.mesecon_supported and mesecon.mvps_push then
if utils.mesecon_supported then
@@ -21,14 +21,10 @@ local mesecon_rules =
-- use mesecons movestone settings
local timer_interval = 1 / mesecon.setting ("movestone_speed", 3)
local max_push = 3
local max_pull = 3
-- helper functions:
local function get_movefloor_direction (rulename)
if rulename.y > 0 then
return { x = 0, y = 1, z = 0 }
@@ -38,6 +34,7 @@ local function get_movefloor_direction (rulename)
end
local function add_movefloor_list (pos, list)
for i = 1, #list do
if list[i].x == pos.x and
@@ -76,10 +73,289 @@ end
-- copied from mesecons movestone
local function movefloor_move (pos, node, rulename, is_sticky)
local function get_node_height (node)
local height = 0
local def = minetest.registered_nodes[node.name]
if def and type (def.collision_box) == "table" then
if def.collision_box.type and def.collision_box.type == "regular" then
height = 1
else
for _, box in pairs (def.collision_box) do
if type (box) == "table" then
if type (box[5]) == "number" then
height = box[5]
else
for _, b in ipairs (box) do
if type (b[5]) == "number" and b[5] > height then
height = b[5]
end
end
end
end
end
end
end
return height
end
local function get_affected_nodes (floor_list)
local list = { }
local max_height = 0
local protected = false
for _, fpos in ipairs (floor_list) do
for y = 0, max_push, 1 do
local npos = vector.add (fpos, { x = 0, y = y, z = 0 })
local node = utils.get_far_node (npos)
if node and node.name ~= "air" then
local meta = minetest.get_meta (npos)
local timer = minetest.get_node_timer (npos)
local h = get_node_height (node) + npos.y - fpos.y - 0.5
list[#list + 1] =
{
pos = npos,
node = node,
meta = (meta and meta:to_table ()),
timeout = (timer and timer:get_timeout ()) or 0,
elapsed = (timer and timer:get_elapsed ()) or 0
}
if h > max_height then
max_height = h
end
if utils.is_protected (npos, nil) then
protected = true
end
end
end
end
return list, math.ceil (max_height), protected
end
local function get_entity_height (obj, base)
local height = 0
if obj.get_pos then
local pos = obj:get_pos ()
if obj.get_luaentity then
local entity = obj:get_luaentity ()
if entity and entity.name then
local def = minetest.registered_entities[entity.name]
if def and type (def.collisionbox) == "table" and
type (def.collisionbox[5]) == "number" then
height = def.collisionbox[5] + pos.y - base
end
end
end
local props = obj:get_properties ()
if props and props.collisionbox and type (props.collisionbox) == "table" and
type (props.collisionbox[5]) == "number" then
if props.collisionbox[5] > height then
height = props.collisionbox[5] + pos.y - base
end
end
end
return height
end
local function get_affected_entities (floor_list)
local list = { }
local max_height = 0
for _, fpos in pairs (floor_list) do
local min_pos = vector.subtract (fpos, { x = 0.4999, y = 0.4999, z = 0.4999 })
local max_pos = vector.add (fpos, { x = 0.4999, y = max_push + 0.4999, z = 0.4999 })
local objects = minetest.get_objects_in_area (min_pos, max_pos)
for _, obj in ipairs (objects) do
local h = get_entity_height (obj, fpos.y + 0.5)
list[#list + 1] =
{
pos = obj:get_pos (),
obj = obj
}
if h > max_height then
max_height = h
end
end
end
return list, math.ceil (max_height)
end
local function is_obstructed (floor_list, height)
for _, fpos in pairs (floor_list) do
local npos = vector.add (fpos, { x = 0, y = height, z = 0 })
if utils.is_protected (npos, nil) then
return true
end
local node = utils.get_far_node (npos)
if node and node.name ~= "air" then
local def = minetest.registered_nodes[node.name]
if not def or not def.buildable_to then
return true
end
end
end
return false
end
local function move_entities (list, move, players)
for _, entry in ipairs (list) do
if entry.obj then
if players or not entry.obj:is_player () then
local pos = nil
if entry.obj:is_player () then
pos = vector.add (entry.pos, { x = move.x, y = move.y + 0.1, z = move.z })
else
pos = vector.add (entry.pos, move)
end
if entry.obj.move_to then
entry.obj:move_to (pos)
elseif entry.set_pos then
entry.obj:set_pos (pos)
end
end
end
end
end
local function update_player_position (list)
for _, entry in ipairs (list) do
local player = minetest.get_player_by_name (entry.name)
if player then
local pos = player:get_pos ()
if pos.y < entry.pos.y then
pos.y = entry.pos.y + 0.1
player:set_pos (pos)
end
end
end
end
local function queue_player_update (list, move)
local players = { }
for _, entry in ipairs (list) do
if entry.obj and entry.obj:is_player () then
players[#players + 1] =
{
pos = vector.add (entry.pos, move),
name = entry.obj:get_player_name ()
}
end
end
if #players > 0 then
minetest.after(0.1, update_player_position, players)
end
end
local function move_nodes (list, move)
if move.y > 0 then
for i = #list, 1, -1 do
local pos = vector.add (list[i].pos, move)
minetest.remove_node (list[i].pos)
minetest.set_node (pos, list[i].node)
if list[i].meta then
local meta = minetest.get_meta (pos)
if meta then
meta:from_table (list[i].meta)
end
end
if list[i].timeout > 0 then
timer = minetest.get_node_timer (pos)
if timer then
timer:set (list[i].timeout, list[i].elapsed)
end
end
end
else
for i = 1, #list, 1 do
local pos = vector.add (list[i].pos, move)
minetest.remove_node (list[i].pos)
minetest.set_node (pos, list[i].node)
if list[i].meta then
local meta = minetest.get_meta (pos)
if meta then
meta:from_table (list[i].meta)
end
end
if list[i].timeout > 0 then
timer = minetest.get_node_timer (pos)
if timer then
timer:set (list[i].timeout, list[i].elapsed)
end
end
end
end
end
local function check_for_falling (list)
for _, pos in ipairs (list) do
minetest.check_for_falling (vector.add (pos, { x = 0, y = max_push + 1, z = 0 }))
end
end
local function movefloor_move (pos, node, rulename)
local direction = get_movefloor_direction (rulename)
local play_sound = false
local list =
{
@@ -88,68 +364,34 @@ local function movefloor_move (pos, node, rulename, is_sticky)
find_adjoining_movefloor (pos, list)
for i = 1, #list do
local frontpos = vector.add (list[i], direction)
local meta = minetest.get_meta (list[i])
local owner = meta:get_string ("owner")
local continue = true
local nodes, height, protected = get_affected_nodes (list)
-- ### Step 1: Push nodes in front ###
local success, stack, oldstack = mesecon.mvps_push (frontpos, direction, max_push, owner)
if not success then
if stack == "protected" then
meta:set_string ("infotext", "Can't move: protected area on the way")
else
minetest.get_node_timer (list[i]):start (timer_interval)
continue = false
end
end
if continue then
mesecon.mvps_move_objects (frontpos, direction, oldstack)
-- ### Step 2: Move the movestone ###
minetest.set_node (frontpos, node)
local meta2 = minetest.get_meta (frontpos)
meta2:set_string ("owner", owner)
minetest.remove_node (list[i])
mesecon.on_dignode (list[i], node)
mesecon.on_placenode (frontpos, node)
minetest.get_node_timer (frontpos):start (timer_interval)
play_sound = true
-- ### Step 3: If sticky, pull stack behind ###
if is_sticky and direction.y < 0 then
local backpos = vector.subtract (list[i], direction)
success, stack, oldstack = mesecon.mvps_pull_all (backpos, direction, max_pull, owner)
if success then
mesecon.mvps_move_objects (backpos, vector.multiply (direction, -1), oldstack, -1)
end
end
-- ### Step 4: Let things fall ###
minetest.check_for_falling (vector.add (list[i], { x = 0, y = 1, z = 0 }))
end
end
if play_sound then
minetest.sound_play("movestone", { pos = list[i], max_hear_distance = 20, gain = 0.5 }, true)
end
end
local function on_timer (pos, elapsed)
local sourcepos = mesecon.is_powered (pos)
if not sourcepos then
if protected then
return
end
local rulename = vector.subtract (sourcepos[1], pos)
local entities, h = get_affected_entities (list)
mesecon.activate (pos, minetest.get_node (pos), rulename, 0)
if h > height then
height = h
end
if is_obstructed (list, (direction.y > 0 and height + 1) or -1) then
return
end
if direction.y > 0 then
move_entities (entities, direction, true)
move_nodes (nodes, direction)
queue_player_update (entities, direction)
else
move_nodes (nodes, direction)
move_entities (entities, direction, false)
check_for_falling (list)
queue_player_update (entities, direction)
end
minetest.sound_play ("lwmovefloor", { pos = pos, max_hear_distance = 10, gain = 1.0 }, true)
end
@@ -164,8 +406,8 @@ local function mesecon_support ()
action_on = function (pos, node, rulename)
-- do something to turn the effector on
if rulename and not minetest.get_node_timer (pos):is_started () then
movefloor_move (pos, node, rulename, true)
if rulename then
movefloor_move (pos, node, rulename)
end
end
}
@@ -190,8 +432,6 @@ minetest.register_node("lwcomponents:movefloor", {
groups = { cracky = 2 },
sounds = default.node_sound_wood_defaults (),
mesecons = mesecon_support (),
on_timer = on_timer,
})

959
pistons.lua Normal file
View File

@@ -0,0 +1,959 @@
local utils = ...
local S = utils.S
if utils.digilines_supported or utils.mesecon_supported then
local piston_interval = 0.2
local function direction_vector (node)
local axis = math.floor (node.param2 / 4)
local rotate = node.param2 % 4
local vec = { x = 0, y = 0, z = 0 }
if rotate == 0 then
vec = { x = 0, y = 0, z = -1 }
elseif rotate == 1 then
vec = { x = -1, y = 0, z = 0 }
elseif rotate == 2 then
vec = { x = 0, y = 0, z = 1 }
elseif rotate == 3 then
vec = { x = 1, y = 0, z = 0 }
end
if axis == 1 then
vec = vector.rotate (vec, { x = math.pi / -2, y = 0, z = 0 })
elseif axis == 2 then
vec = vector.rotate (vec, { x = math.pi / 2, y = 0, z = 0 })
elseif axis == 3 then
vec = vector.rotate (vec, { x = 0, y = 0, z = math.pi / 2 })
elseif axis == 4 then
vec = vector.rotate (vec, { x = 0, y = 0, z = math.pi / -2 })
elseif axis == 5 then
vec = vector.rotate (vec, { x = math.pi, y = 0, z = 0 })
end
return vec
end
local function push_entities (pos, vec)
local tpos = vector.add (pos, vec)
local tnode = utils.get_far_node (tpos)
local can_move = false
if tnode then
if tnode.name == "air" then
can_move = true
else
local tdef = utils.find_item_def (tnode.name)
can_move = tdef and not tdef.walkable
end
end
if can_move then
local object = minetest.get_objects_inside_radius (pos, 1.5)
for j = 1, #object do
if object[j].get_pos then
local opos = object[j]:get_pos ()
if opos.x > (pos.x - 0.5) and opos.x < (pos.x + 0.5) and
opos.z > (pos.z - 0.5) and opos.z < (pos.z + 0.5) and
opos.y > (pos.y - 0.5) and opos.y < (pos.y + 0.5) then
object[j]:set_pos (vector.add (opos, vec))
end
end
end
end
end
local function push_nodes (pos, extent)
local node = utils.get_far_node (pos)
if node then
local vec = direction_vector (node)
local last = vector.add (pos, vector.multiply (vec, extent))
local maxnodes = utils.settings.max_piston_nodes + 1
local count = 0
for i = 1, maxnodes do
local tnode = utils.get_far_node (last)
if not tnode then
return false
end
local tdef = utils.find_item_def (tnode.name)
if tnode.name == "air" or (tdef and not tdef.walkable) then
count = i - 1
break
end
if i == maxnodes then
return false
end
last = vector.add (last, vec)
end
push_entities (last, vec)
for i = 1, count, 1 do
local cpos = vector.subtract (last, vec)
local cnode = utils.get_far_node (cpos)
local cmeta = minetest.get_meta (cpos)
if not cnode or not cmeta then
return false
end
local tmeta = cmeta:to_table ()
local ctimer = minetest.get_node_timer (cpos)
local ctimeout = (ctimer and ctimer:get_timeout ()) or 0
local celapsed = (ctimer and ctimer:get_elapsed ()) or 0
push_entities (cpos, vec)
minetest.remove_node (cpos)
minetest.set_node (last, cnode)
if tmeta then
cmeta = minetest.get_meta (last)
if not cmeta then
return false
end
cmeta:from_table (tmeta)
end
if ctimeout > 0 then
ctimer = minetest.get_node_timer (last)
if ctimer then
ctimer:set (ctimeout, celapsed)
end
end
last = cpos
end
end
return true
end
local function pull_node (pos, extent)
local node = utils.get_far_node (pos)
if node then
local vec = direction_vector (node)
local cpos = vector.add (pos, vector.multiply (vec, extent))
local cnode = utils.get_far_node (cpos)
local cdef = cnode and utils.find_item_def (cnode.name)
if cnode and cnode.name ~= "air" and cdef and cdef.walkable then
local cmeta = minetest.get_meta (cpos)
if cmeta then
local tpos = vector.subtract (cpos, vec)
local tmeta = cmeta:to_table ()
local ctimer = minetest.get_node_timer (cpos)
local ctimeout = (ctimer and ctimer:get_timeout ()) or 0
local celapsed = (ctimer and ctimer:get_elapsed ()) or 0
minetest.remove_node (cpos)
minetest.set_node (tpos, cnode)
if tmeta then
cmeta = minetest.get_meta (tpos)
if cmeta then
cmeta:from_table (tmeta)
end
end
if ctimeout > 0 then
ctimer = minetest.get_node_timer (tpos)
if ctimer then
ctimer:set (ctimeout, celapsed)
end
end
end
end
end
end
local function place_blank (pos, extent)
local node = utils.get_far_node (pos)
if node then
local vec = direction_vector (node)
local blank_pos = vector.add (pos, vector.multiply (vec, extent))
local blank_node = utils.get_far_node (blank_pos)
local blank_def = blank_node and utils.find_item_def (blank_node.name)
if blank_node and blank_node.name == "air" or
(blank_def and not blank_def.walkable) then
minetest.set_node (blank_pos,
{
name = "lwcomponents:piston_blank_"..tostring (extent),
param2 = node.param2
})
end
end
end
local function remove_blank (pos, extent)
local node = utils.get_far_node (pos)
if node then
local vec = direction_vector (node)
local blank_pos = vector.add (pos, vector.multiply (vec, extent))
local blank_node = utils.get_far_node (blank_pos)
if blank_node and
blank_node.name == "lwcomponents:piston_blank_"..tostring (extent) then
minetest.remove_node (blank_pos)
end
end
end
local function extend_piston (pos, extent)
local node = utils.get_far_node (pos)
local meta = minetest.get_meta (pos)
if node and meta then
extent = math.max (math.min (tonumber (extent or 2), meta:get_int ("max_extent")), 0)
if node.name == "lwcomponents:piston" then
if extent ~= 0 then
if push_nodes (pos, 1) then
node.name = "lwcomponents:piston_1"
minetest.swap_node (pos, node)
place_blank (pos, 1)
minetest.sound_play ("lwpiston_extend",
{
pos = pos,
max_hear_distance = 20,
gain = 0.3
},
true)
if extent == 2 then
meta:set_int ("extent", 2)
minetest.get_node_timer (pos):start (piston_interval)
return true
end
end
end
elseif node.name == "lwcomponents:piston_1" then
if extent == 0 then
remove_blank (pos, 1)
node.name = "lwcomponents:piston"
minetest.swap_node (pos, node)
minetest.sound_play ("lwpiston_retract",
{
pos = pos,
max_hear_distance = 20,
gain = 0.3
},
true)
elseif extent == 2 then
if push_nodes (pos, 2) then
node.name = "lwcomponents:piston_2"
minetest.swap_node (pos, node)
place_blank (pos, 2)
minetest.sound_play ("lwpiston_extend",
{
pos = pos,
max_hear_distance = 20,
gain = 0.3
},
true)
end
end
elseif node.name == "lwcomponents:piston_2" then
if extent ~= 2 then
remove_blank (pos, 2)
node.name = "lwcomponents:piston_1"
minetest.swap_node (pos, node)
minetest.sound_play ("lwpiston_retract",
{
pos = pos,
max_hear_distance = 20,
gain = 0.3
},
true)
if extent == 0 then
meta:set_int ("extent", 0)
minetest.get_node_timer (pos):start (piston_interval)
return true
end
end
elseif node.name == "lwcomponents:piston_sticky" then
if extent ~= 0 then
if push_nodes (pos, 1) then
node.name = "lwcomponents:piston_sticky_1"
minetest.swap_node (pos, node)
place_blank (pos, 1)
minetest.sound_play ("lwpiston_extend",
{
pos = pos,
max_hear_distance = 20,
gain = 0.3
},
true)
if extent == 2 then
meta:set_int ("extent", 2)
minetest.get_node_timer (pos):start (piston_interval)
return true
end
end
end
elseif node.name == "lwcomponents:piston_sticky_1" then
if extent == 0 then
remove_blank (pos, 1)
node.name = "lwcomponents:piston_sticky"
minetest.swap_node (pos, node)
pull_node (pos, 2)
minetest.sound_play ("lwpiston_retract",
{
pos = pos,
max_hear_distance = 20,
gain = 0.3
},
true)
elseif extent == 2 then
if push_nodes (pos, 2) then
node.name = "lwcomponents:piston_sticky_2"
minetest.swap_node (pos, node)
place_blank (pos, 2)
minetest.sound_play ("lwpiston_extend",
{
pos = pos,
max_hear_distance = 20,
gain = 0.3
},
true)
end
end
elseif node.name == "lwcomponents:piston_sticky_2" then
if extent ~= 2 then
remove_blank (pos, 2)
node.name = "lwcomponents:piston_sticky_1"
minetest.swap_node (pos, node)
pull_node (pos, 3)
minetest.sound_play ("lwpiston_retract",
{
pos = pos,
max_hear_distance = 20,
gain = 0.3
},
true)
if extent == 0 then
meta:set_int ("extent", 0)
minetest.get_node_timer (pos):start (piston_interval)
return true
end
end
end
end
return false
end
local function on_destruct_1 (pos)
remove_blank (pos, 1)
end
local function on_destruct_2 (pos)
remove_blank (pos, 2)
remove_blank (pos, 1)
end
local function on_place (itemstack, placer, pointed_thing)
local param2 = 0
if placer and placer:is_player () then
param2 = minetest.dir_to_facedir (placer:get_look_dir (), true)
elseif pointed_thing and pointed_thing.type == "node" then
param2 = minetest.dir_to_facedir (vector.subtract (pointed_thing.under, pointed_thing.above), true)
end
return minetest.item_place (itemstack, placer, pointed_thing, param2)
end
local function after_place_node (pos, placer, itemstack, pointed_thing)
local meta = minetest.get_meta (pos)
local spec =
"size[7,3.3]"..
"field[1,1;4,2;channel;Channel;${channel}]"..
"button_exit[4.6,1.15;1.5,1;submit;Set]"..
"checkbox[1,2;single;Single move;false]"
meta:set_string ("formspec", spec)
meta:set_int ("max_extent", 2)
-- If return true no item is taken from itemstack
return false
end
local function on_receive_fields (pos, formname, fields, sender)
if not utils.can_interact_with_node (pos, sender) then
return
end
local meta = minetest.get_meta (pos)
if meta then
if fields.submit then
meta:set_string ("channel", fields.channel)
end
if fields.single then
if fields.single == "true" then
local spec =
"size[7,3.3]"..
"field[1,1;4,2;channel;Channel;${channel}]"..
"button_exit[4.6,1.15;1.5,1;submit;Set]"..
"checkbox[1,2;single;Single move;true]"
meta:set_int ("max_extent", 1)
meta:set_string ("formspec", spec)
else
local spec =
"size[7,3.3]"..
"field[1,1;4,2;channel;Channel;${channel}]"..
"button_exit[4.6,1.15;1.5,1;submit;Set]"..
"checkbox[1,2;single;Single move;false]"
meta:set_int ("max_extent", 2)
meta:set_string ("formspec", spec)
end
end
end
end
local function on_blast (pos, intensity)
local meta = minetest.get_meta (pos)
if meta then
if intensity >= 1.0 then
minetest.remove_node (pos)
else -- intensity < 1.0
local node = minetest.get_node_or_nil (pos)
if node then
local items = minetest.get_node_drops (node, nil)
if items and #items > 0 then
local stack = ItemStack (items[1])
if stack then
preserve_metadata (pos, node, meta, { stack })
utils.item_drop (stack, nil, pos)
minetest.remove_node (pos)
end
end
end
end
end
end
local function can_dig (pos, player)
if not utils.can_interact_with_node (pos, player) then
return false
end
return true
end
local function on_rightclick (pos, node, clicker, itemstack, pointed_thing)
if not utils.can_interact_with_node (pos, clicker) then
if clicker and clicker:is_player () then
local owner = "<unknown>"
local meta = minetest.get_meta (pos)
if meta then
owner = meta:get_string ("owner")
end
local spec =
"formspec_version[3]"..
"size[8.0,4.0,false]"..
"label[1.0,1.0;Owned by "..minetest.formspec_escape (owner).."]"..
"button_exit[3.0,2.0;2.0,1.0;close;Close]"
minetest.show_formspec (clicker:get_player_name (),
"lwcomponents:component_privately_owned",
spec)
end
end
return itemstack
end
local function on_timer (pos, elapsed)
local meta = minetest.get_meta (pos)
if meta then
return extend_piston (pos, meta:get_int ("extent"))
end
return false
end
local function digilines_support ()
if utils.digilines_supported then
return
{
wire =
{
rules = utils.digilines_default_rules,
},
effector =
{
action = function (pos, node, channel, msg)
local meta = minetest.get_meta(pos)
if meta then
local this_channel = meta:get_string ("channel")
if this_channel ~= "" and this_channel == channel then
if type (msg) == "string" then
local m = { }
for w in string.gmatch(msg, "[^%s]+") do
m[#m + 1] = w
end
if m[1] == "extend" then
extend_piston (pos, m[2])
elseif m[1] == "retract" then
extend_piston (pos, 0)
elseif m[1] == "single" then
local spec =
"size[7,3.3]"..
"field[1,1;4,2;channel;Channel;${channel}]"..
"button_exit[4.6,1.15;1.5,1;submit;Set]"..
"checkbox[1,2;single;Single move;true]"
meta:set_int ("max_extent", 1)
meta:set_string ("formspec", spec)
elseif m[1] == "double" then
local spec =
"size[7,3.3]"..
"field[1,1;4,2;channel;Channel;${channel}]"..
"button_exit[4.6,1.15;1.5,1;submit;Set]"..
"checkbox[1,2;single;Single move;false]"
meta:set_int ("max_extent", 2)
meta:set_string ("formspec", spec)
end
end
end
end
end,
}
}
end
return nil
end
local function mesecon_support ()
if utils.mesecon_supported then
return
{
effector =
{
rules = utils.mesecon_default_rules,
action_on = function (pos, node)
-- do something to turn the effector on
extend_piston (pos, 2)
end,
action_off = function (pos, node)
-- do something to turn the effector off
extend_piston (pos, 0)
end,
}
}
end
return nil
end
minetest.register_node("lwcomponents:piston_blank_1", {
description = S("Piston blank"),
drawtype = "airlike",
light_source = 0,
sunlight_propagates = true,
walkable = false,
pointable = false,
diggable = false,
climbable = false,
buildable_to = false,
floodable = false,
is_ground_content = false,
drop = "",
groups = { not_in_creative_inventory = 1 },
paramtype = "light",
-- unaffected by explosions
on_blast = function() end,
})
minetest.register_node("lwcomponents:piston_blank_2", {
description = S("Piston blank"),
drawtype = "airlike",
paramtype = "none",
param1 = 0,
paramtype2 = "facedir",
param2 = 0,
collision_box = {
type = "fixed",
fixed = {
{-0.125, -0.125, -0.4, 0.125, 0.125, 0.4},
{-0.5, -0.5, -0.5, 0.5, 0.5, -0.3125},
},
},
light_source = 0,
sunlight_propagates = true,
walkable = true,
pointable = false,
diggable = false,
climbable = false,
buildable_to = false,
floodable = false,
is_ground_content = false,
drop = "",
groups = { not_in_creative_inventory = 1 },
paramtype = "light",
-- unaffected by explosions
on_blast = function() end,
})
minetest.register_node("lwcomponents:piston", {
description = S("Double Piston"),
tiles = { "lwcomponents_piston_top.png", "lwcomponents_piston_bottom.png",
"lwcomponents_piston_right.png", "lwcomponents_piston_left.png",
"lwcomponents_piston_base.png", "lwcomponents_piston_pusher.png" },
is_ground_content = false,
groups = { cracky = 3 },
sounds = default.node_sound_stone_defaults (),
paramtype = "none",
param1 = 0,
paramtype2 = "facedir",
param2 = 0,
floodable = false,
drop = "lwcomponents:piston",
_digistuff_channelcopier_fieldname = "channel",
mesecons = mesecon_support (),
digiline = digilines_support (),
on_place = on_place,
on_receive_fields = on_receive_fields,
can_dig = can_dig,
after_place_node = after_place_node,
on_blast = on_blast,
on_rightclick = on_rightclick,
on_timer = on_timer
})
minetest.register_node("lwcomponents:piston_1", {
description = S("Double Piston"),
drawtype = "mesh",
mesh = "piston_normal_1.obj",
tiles = { "lwcomponents_piston.png" },
visual_scale = 1.0,
selection_box = {
type = "fixed",
fixed = {
{-0.125, -0.125, -1.4, 0.125, 0.125, 0.4},
{-0.5, -0.5, -1.5, 0.5, 0.5, -1.3125},
{-0.5, -0.5, -0.3125, 0.5, 0.5, 0.5},
},
},
collision_box = {
type = "fixed",
fixed = {
{-0.125, -0.125, -1.4, 0.125, 0.125, 0.4},
{-0.5, -0.5, -1.5, 0.5, 0.5, -1.3125},
{-0.5, -0.5, -0.3125, 0.5, 0.5, 0.5},
},
},
is_ground_content = false,
groups = { cracky = 3 , not_in_creative_inventory = 1 },
sounds = default.node_sound_stone_defaults (),
paramtype = "none",
param1 = 0,
paramtype2 = "facedir",
param2 = 0,
floodable = false,
drop = "lwcomponents:piston",
_digistuff_channelcopier_fieldname = "channel",
mesecons = mesecon_support (),
digiline = digilines_support (),
on_destruct = on_destruct_1,
on_receive_fields = on_receive_fields,
can_dig = can_dig,
after_place_node = after_place_node,
on_blast = on_blast,
on_rightclick = on_rightclick,
on_timer = on_timer
})
minetest.register_node("lwcomponents:piston_2", {
description = S("Double Piston"),
drawtype = "mesh",
mesh = "piston_normal_2.obj",
tiles = { "lwcomponents_piston.png" },
visual_scale = 1.0,
selection_box = {
type = "fixed",
fixed = {
{-0.125, -0.125, -2.4, 0.125, 0.125, 0.4},
{-0.5, -0.5, -2.5, 0.5, 0.5, -2.3125},
{-0.5, -0.5, -0.3125, 0.5, 0.5, 0.5},
},
},
collision_box = {
type = "fixed",
fixed = {
{-0.125, -0.125, -2.4, 0.125, 0.125, 0.4},
{-0.5, -0.5, -2.5, 0.5, 0.5, -2.3125},
{-0.5, -0.5, -0.3125, 0.5, 0.5, 0.5},
},
},
is_ground_content = false,
groups = { cracky = 3 , not_in_creative_inventory = 1 },
sounds = default.node_sound_stone_defaults (),
paramtype = "none",
param1 = 0,
paramtype2 = "facedir",
param2 = 0,
floodable = false,
drop = "lwcomponents:piston",
_digistuff_channelcopier_fieldname = "channel",
mesecons = mesecon_support (),
digiline = digilines_support (),
on_destruct = on_destruct_2,
on_receive_fields = on_receive_fields,
can_dig = can_dig,
after_place_node = after_place_node,
on_blast = on_blast,
on_rightclick = on_rightclick,
on_timer = on_timer
})
minetest.register_node("lwcomponents:piston_sticky", {
description = S("Double Sticky Piston"),
tiles = { "lwcomponents_piston_top.png", "lwcomponents_piston_bottom.png",
"lwcomponents_piston_right.png", "lwcomponents_piston_left.png",
"lwcomponents_piston_base.png", "lwcomponents_piston_pusher_sticky.png" },
is_ground_content = false,
groups = { cracky = 3 },
sounds = default.node_sound_stone_defaults (),
paramtype = "none",
param1 = 0,
paramtype2 = "facedir",
param2 = 0,
floodable = false,
drop = "lwcomponents:piston_sticky",
_digistuff_channelcopier_fieldname = "channel",
mesecons = mesecon_support (),
digiline = digilines_support (),
on_place = on_place,
on_receive_fields = on_receive_fields,
can_dig = can_dig,
after_place_node = after_place_node,
on_blast = on_blast,
on_rightclick = on_rightclick,
on_timer = on_timer
})
minetest.register_node("lwcomponents:piston_sticky_1", {
description = S("Double Sticky Piston"),
drawtype = "mesh",
mesh = "piston_sticky_1.obj",
tiles = { "lwcomponents_piston.png" },
visual_scale = 1.0,
selection_box = {
type = "fixed",
fixed = {
{-0.125, -0.125, -1.4, 0.125, 0.125, 0.4},
{-0.5, -0.5, -1.5, 0.5, 0.5, -1.3125},
{-0.5, -0.5, -0.3125, 0.5, 0.5, 0.5},
},
},
collision_box = {
type = "fixed",
fixed = {
{-0.125, -0.125, -1.4, 0.125, 0.125, 0.4},
{-0.5, -0.5, -1.5, 0.5, 0.5, -1.3125},
{-0.5, -0.5, -0.3125, 0.5, 0.5, 0.5},
},
},
is_ground_content = false,
groups = { cracky = 3 , not_in_creative_inventory = 1 },
sounds = default.node_sound_stone_defaults (),
paramtype = "none",
param1 = 0,
paramtype2 = "facedir",
param2 = 0,
floodable = false,
drop = "lwcomponents:piston_sticky",
_digistuff_channelcopier_fieldname = "channel",
mesecons = mesecon_support (),
digiline = digilines_support (),
on_destruct = on_destruct_1,
on_receive_fields = on_receive_fields,
can_dig = can_dig,
after_place_node = after_place_node,
on_blast = on_blast,
on_rightclick = on_rightclick,
on_timer = on_timer
})
minetest.register_node("lwcomponents:piston_sticky_2", {
description = S("Double Sticky Piston"),
drawtype = "mesh",
mesh = "piston_sticky_2.obj",
tiles = { "lwcomponents_piston.png" },
visual_scale = 1.0,
selection_box = {
type = "fixed",
fixed = {
{-0.125, -0.125, -2.4, 0.125, 0.125, 0.4},
{-0.5, -0.5, -2.5, 0.5, 0.5, -2.3125},
{-0.5, -0.5, -0.3125, 0.5, 0.5, 0.5},
},
},
collision_box = {
type = "fixed",
fixed = {
{-0.125, -0.125, -2.4, 0.125, 0.125, 0.4},
{-0.5, -0.5, -2.5, 0.5, 0.5, -2.3125},
{-0.5, -0.5, -0.3125, 0.5, 0.5, 0.5},
},
},
is_ground_content = false,
groups = { cracky = 3 , not_in_creative_inventory = 1 },
sounds = default.node_sound_stone_defaults (),
paramtype = "none",
param1 = 0,
paramtype2 = "facedir",
param2 = 0,
floodable = false,
drop = "lwcomponents:piston_sticky",
_digistuff_channelcopier_fieldname = "channel",
mesecons = mesecon_support (),
digiline = digilines_support (),
on_destruct = on_destruct_2,
on_receive_fields = on_receive_fields,
can_dig = can_dig,
after_place_node = after_place_node,
on_blast = on_blast,
on_rightclick = on_rightclick,
on_timer = on_timer
})
end -- utils.digilines_supported or utils.mesecon_supported

View File

@@ -13,7 +13,7 @@ CC BY-SA 3.0
Version
=======
0.1.12
0.1.21
Minetest Version
@@ -28,7 +28,6 @@ default
Optional Dependencies
=====================
lwdrops
mesecons
digilines
unifieddyes
@@ -64,8 +63,11 @@ Various components for mesecons and digilines.
* Fan, blows any entity, player or drop in front of the fan.
* Conduit, connected in a circuit to move items.
* Cannon, shoots an item on command with directional aiming (plus 3 shells).
* Double (optionally single) reach pistons and sticky pistons.
* Digiswitch, digilines controlled mesecons power.
* Movefloor, similar to vertical mesecons movestone.
* Camera, takes a representative image.
* Mesecons Through Wire, transmits through 1 to 2 solid blocks.
* Solid color conductor blocks, same as Solid Color Block but also mesecons
and digilines conductor.
@@ -93,6 +95,9 @@ Alert handler errors
Issue errors when handler's of other mods fail.
Default: true
Maximum piston nodes
Maximum nodes a piston can push.
Default: 15
------------------------------------------------------------------------

View File

@@ -9,6 +9,9 @@ utils.settings.spawn_mobs =
utils.settings.alert_handler_errors =
minetest.settings:get_bool ("lwcomponents_alert_handler_errors", true)
utils.settings.max_piston_nodes =
tonumber(minetest.settings:get("lwcomponents_max_piston_nodes") or 15)
--

View File

@@ -3,3 +3,6 @@ lwcomponents_spawn_mobs (Spawn mobs) bool true
# Issue errors when handler's of other mods fail.
lwcomponents_alert_handler_errors (Alert handler errors) bool true
# Maximum nodes a piston can push.
lwcomponents_max_piston_nodes (Maximum piston nodes) int 15

BIN
sounds/lwmovefloor.ogg Normal file

Binary file not shown.

BIN
sounds/lwpiston_extend.ogg Normal file

Binary file not shown.

BIN
sounds/lwpiston_retract.ogg Normal file

Binary file not shown.

BIN
textures/lwcamera.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 495 B

BIN
textures/lwcamera_lens.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 723 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 873 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 857 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 719 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 698 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 864 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 860 B

80
through_wire.lua Normal file
View File

@@ -0,0 +1,80 @@
local utils = ...
local S = utils.S
if utils.mesecon_supported then
local through_wire_get_rules = function (node)
local rules = { {x = -1, y = 0, z = 0},
{x = 2, y = 0, z = 0},
{x = 3, y = 0, z = 0} }
if node.param2 == 2 then
rules = mesecon.rotate_rules_left(rules)
elseif node.param2 == 3 then
rules = mesecon.rotate_rules_right(mesecon.rotate_rules_right(rules))
elseif node.param2 == 0 then
rules = mesecon.rotate_rules_right(rules)
end
return rules
end
mesecon.register_node ("lwcomponents:through_wire", {
description = S("Mesecons Through Wire"),
drawtype = "nodebox",
paramtype = "light",
paramtype2 = "facedir",
is_ground_content = false,
sunlight_propagates = true,
walkable = false,
on_rotate = false,
selection_box = {
type = "fixed",
fixed = { -3/16, -8/16, -8/16, 3/16, 3/16, 8/16 }
},
node_box = {
type = "fixed",
fixed = {
{ -3/16, -3/16, 13/32 , 3/16, 3/16 , 8/16 }, -- the smaller bump
{ -1/32, -1/32, 1/2 , 1/32, 1/32 , 3/2 }, -- the wire through the block
{ -2/32, -1/2 , 0.5002-3/32 , 2/32, 0 , 0.5 }, -- the vertical wire bit
{ -2/32, -1/2 , -16/32+0.001 , 2/32, -14/32, 7/16+0.002 } -- the horizontal wire
}
},
drop = "lwcomponents:through_wire_off",
sounds = default.node_sound_defaults(),
}, {
tiles = { "mesecons_wire_off.png" },
groups = { dig_immediate = 3 },
mesecons = {
conductor = {
state = mesecon.state.off,
rules = through_wire_get_rules,
onstate = "lwcomponents:through_wire_on"
}
}
}, {
tiles = { "mesecons_wire_on.png" },
groups = { dig_immediate = 3, not_in_creative_inventory = 1 },
mesecons = {
conductor = {
state = mesecon.state.on,
rules = through_wire_get_rules,
offstate = "lwcomponents:through_wire_off"
}
}
})
end -- utils.mesecon_supported
--

View File

@@ -67,43 +67,6 @@ end
-- check for lwdrops
if minetest.global_exists ("lwdrops") then
utils.lwdrops_supported = true
utils.on_destroy = lwdrops.on_destroy
utils.item_pickup = lwdrops.item_pickup
utils.item_drop = lwdrops.item_drop
else
utils.lwdrops_supported = false
-- dummy
utils.on_destroy = function (itemstack)
end
utils.item_pickup = function (entity, cleanup)
local stack = nil
if entity and entity.name and entity.name == "__builtin:item" and
entity.itemstring and entity.itemstring ~= "" then
stack = ItemStack (entity.itemstring)
if cleanup ~= false then
entity.itemstring = ""
entity.object:remove ()
end
end
return stack
end
utils.item_drop = function (itemstack, dropper, pos)
return minetest.item_drop (itemstack, dropper, pos)
end
end
-- check for unifieddyes
if minetest.global_exists ("unifieddyes") then
utils.unifieddyes_supported = true
@@ -138,6 +101,53 @@ end
function utils.on_destroy (itemstack)
local stack = ItemStack (itemstack)
if stack and stack:get_count () > 0 then
local def = utils.find_item_def (stack:get_name ())
if def and def.on_destroy then
def.on_destroy (stack)
end
end
end
function utils.item_pickup (entity, cleanup)
local stack = nil
if entity and entity.name and entity.name == "__builtin:item" and
entity.itemstring and entity.itemstring ~= "" then
stack = ItemStack (entity.itemstring)
if cleanup ~= false then
entity.itemstring = ""
entity.object:remove ()
end
end
return stack
end
function utils.item_drop (itemstack, dropper, pos)
if itemstack then
local def = utils.find_item_def (itemstack:get_name ())
if def and def.on_drop then
return def.on_drop (itemstack, dropper, pos)
end
end
return minetest.item_drop (itemstack, dropper, pos)
end
function utils.can_interact_with_node (pos, player)
if not player or not player:is_player () then
return false