diff options
47 files changed, 3218 insertions, 714 deletions
diff --git a/.luacheckrc b/.luacheckrc index 8ce3cc6..427b2d9 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -14,4 +14,5 @@ read_globals = { "laptop", "mesecon", "digilines", + "xcompat", } @@ -0,0 +1,54 @@ +celevator +Fully functional realistic elevators for Luanti/Minetest (5.7+) +=============================================================== + +Description +----------- + +Adds fully functional, realistic elevators capable of moving players between multiple floors in a building. + +Features include: + + 2 to 100 floors with customizable names + Travel speed adjustable for each elevator independently, up to 20m/s (more than 7.5m/s not recommended in multiplayer) + Can travel through loaded or unloaded mapblocks + Full selective-collective operation + Group dispatching with up to 16 cars in a group and true ETA dispatching + Optional destination-based dispatching + Swing car operation + Animated doors, hoist machine, and tapehead + Controller interface with diagnostic LEDs, display, and GUI configuration + Optional car call security settings (require area access to place a car call, or disallow car calls to a specific floor entirely) + Functional independent service and fire service phase I and II (approximately following ASME A17.1 codes) modes + Car top and machine room inspection operation with adjustable speed + Adjustable door dwell and nudging timers + mView remote monitoring software (optional, available if "laptop" mod is installed) + Mesecons input and output modules (optional, available if "mesecons" mod is installed) + Communication with Luacontrollers via digilines input/output modules (optional, available if "digilines" mod is installed) + +Documentation +------------- + +Documentation is located in the "docs" subdirectory. +See "docs/celevator_controller_manual.pdf" for full installation and setup instructions. + +Contributing +------------ + +If you would like to contribute code, the easiest way is to publish your changes somewhere and request that I pull them. +I can be reached on Libera.Chat in #luanti as "cheapie", or you can contact me via ContentDB or the Luanti forums (same username). +If you don't have anywhere to publish your changes, I can also accept patches. + +Reporting Issues +---------------- + +See the previous "Contributing" section for contact information. +You are encouraged to report any issues you have to me using any of those contact methods. +If you just have a question or you're not sure if something is a bug, IRC is probably the easiest method. + +License +------- + +This software is offered under The Unlicense. +See the LICENSE file for the full license text. +If you do use this code for something I'd love to hear what it is, but you're not required to tell me. diff --git a/callbuttons.lua b/callbuttons.lua index 58cd40d..7e19de6 100644 --- a/callbuttons.lua +++ b/callbuttons.lua @@ -239,3 +239,35 @@ for _,state in ipairs(validstates) do end, }) end + +minetest.register_abm({ + label = "Check call buttons for missing/replaced controllers", + nodenames = {"group:_celevator_callbutton",}, + interval = 15, + chance = 1, + action = function(pos) + local meta = minetest.get_meta(pos) + local carid = meta:get_int("carid") + if not (carid and carid > 0) then return end --Not set up yet + local carinfo = minetest.deserialize(celevator.storage:get_string("car"..carid)) + if not carinfo then + meta:set_string("infotext","Error reading car information!\nPlease remove and replace this node.") + return + end + local iscontroller = (carinfo.controllerpos and celevator.controller.iscontroller(carinfo.controllerpos)) + local isdispatcher = (carinfo.dispatcherpos and celevator.dispatcher.isdispatcher(carinfo.dispatcherpos)) + if not (iscontroller or isdispatcher) then + meta:set_string("infotext","Controller/dispatcher is missing!\nPlease remove and replace this node.") + return + end + local metacarid = 0 + if iscontroller then + metacarid = celevator.get_meta(carinfo.controllerpos):get_int("carid") + elseif isdispatcher then + metacarid = celevator.get_meta(carinfo.dispatcherpos):get_int("carid") + end + if metacarid ~= carid then + meta:set_string("infotext","Controller/dispatcher found but with incorrect ID!\nPlease remove and replace this node.") + end + end, +}) @@ -1,6 +1,6 @@ celevator.car = {} -local function disambiguatebutton(pos,facedir,player) +local function disambiguatecartopbutton(pos,facedir,player) if player and not player.is_fake_player then local eyepos = vector.add(player:get_pos(),vector.add(player:get_eye_offset(),vector.new(0,1.5,0))) local lookdir = player:get_look_dir() @@ -12,7 +12,8 @@ local function disambiguatebutton(pos,facedir,player) pointed = ray:next() if pointed and pointed.type == "node" then local node = minetest.get_node(pointed.under) - if node.name == "celevator:car_021" then + local ndef = minetest.registered_nodes[node.name] or {} + if ndef._cartopbox then button = pointed.under hitpos = vector.subtract(pointed.intersection_point,button) end @@ -68,507 +69,216 @@ minetest.register_globalstep(function() end end) -local pieces = { - { - _position = "000", - node_box = { - type = "fixed", - fixed = { - {-0.5,-0.6,-0.5,0.5,-0.5,0.5}, - {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, - {-0.5,-1.5,-0.5,0.5,-0.6,-0.45}, - }, - }, - tiles = { - "celevator_car_floor.png^celevator_door_sill_single.png", - "celevator_car_bottom.png", - "celevator_car_wallpaper.png^celevator_car_wall_bottom.png^celevator_car_switch_panel.png", - "celevator_cabinet_sides.png^celevator_car_side_overlay.png^[transformR90", - "celevator_cabinet_sides.png", - }, - on_timer = function(pos) - local carid = minetest.get_meta(pos):get_int("carid") - local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid))) - if not (carinfo and carinfo.controllerpos) then return end - local yaw = minetest.dir_to_yaw(minetest.fourdir_to_dir(minetest.get_node(pos).param2)) - local positions = { - vector.new(-0.25,-0.1,-0.5), - vector.new(0.25,-0.1,-0.5), - vector.new(0.75,-0.1,-0.5), - vector.new(1.25,-0.1,-0.5), - } - local playerseen = false - for _,searchpos in ipairs(positions) do - local rotatedpos = vector.rotate_around_axis(searchpos,vector.new(0,1,0),yaw) - local erefs = minetest.get_objects_inside_radius(vector.add(pos,rotatedpos),0.5) - for _,ref in pairs(erefs) do - if ref:is_player() then - playerseen = true - break - end - end - if playerseen then break end - end - if playerseen then - celevator.controller.run(carinfo.controllerpos,{ - type = "lightcurtain", - }) +celevator.car.types = {} + +function celevator.car.register(name,defs,size) + celevator.car.types[name] = { + size = size, + } + for _,def in ipairs(defs) do + def._celevator_car_type = name + def.groups = { + not_in_creative_inventory = 1, + _celevator_car = 1, + } + local xp = tonumber(string.sub(def._position,1,1)) + local yp = tonumber(string.sub(def._position,2,2)) + local zp = tonumber(string.sub(def._position,3,3)) + if xp > 0 then + def.groups._connects_xm = 1 + end + if xp < size.x-1 then + def.groups._connects_xp = 1 + end + if yp > 0 then + def.groups._connects_ym = 1 + end + if yp < size.y-1 then + def.groups._connects_yp = 1 + end + if zp > 0 then + def.groups._connects_zm = 1 + end + if zp < size.z-1 then + def.groups._connects_zp = 1 + end + def.paramtype = "light" + def.paramtype2 = "4dir" + def.drawtype = "nodebox" + def.description = "Car "..def._position.." (you hacker you!)" + def.light_source = 9 + def.drop = "" + if def._cop then + def.on_receive_fields = function(pos,_,fields,player) + local meta = minetest.get_meta(pos) + local carid = meta:get_int("carid") + if carid == 0 then return end + local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid))) + if not carinfo then return end + local playername = player:get_player_name() + local protected = minetest.is_protected(pos,playername) and not minetest.check_player_privs(playername,{protection_bypass=true}) + local event = { + type = "cop", + fields = fields, + player = playername, + protected = protected, + } + celevator.controller.run(carinfo.controllerpos,event) end - return true - end, - }, - { - _position = "001", - node_box = { - type = "fixed", - fixed = { - {-0.5,-0.6,-0.5,0.5,-0.5,0.5}, - {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, - }, - }, - tiles = { - "celevator_car_floor.png", - "celevator_car_bottom_center.png", - "celevator_car_wallpaper.png^celevator_car_wall_bottom.png^celevator_car_wall_vent.png", - "celevator_cabinet_sides.png^celevator_car_side_center_overlay.png", - "celevator_cabinet_sides.png", - }, - }, - { - _position = "002", - node_box = { - type = "fixed", - fixed = { - {-0.5,-0.6,-0.5,0.5,-0.5,0.5}, - {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, - {-0.45,-0.5,0.45,0.5,0.5,0.5}, - }, - }, - tiles = { - "celevator_car_floor.png", - "celevator_car_bottom.png", - "celevator_car_wallpaper.png^celevator_car_wall_bottom.png", - "celevator_cabinet_sides.png^celevator_car_side_overlay.png", - "celevator_cabinet_sides.png", - "celevator_car_wallpaper.png^celevator_car_wall_bottom.png", - }, - }, - { - _position = "100", - node_box = { - type = "fixed", - fixed = { - {-0.5,-0.6,-0.5,0.5,-0.5,0.5}, - {0.45,-0.5,-0.5,0.5,0.5,0.5}, - {-0.5,-1.5,-0.5,0.5,-0.6,-0.45}, - }, - }, - tiles = { - "celevator_car_floor.png^celevator_door_sill_double.png", - "celevator_car_bottom.png", - "celevator_cabinet_sides.png^celevator_car_side_overlay.png", - "celevator_car_wallpaper.png^celevator_car_wall_bottom.png", - "celevator_cabinet_sides.png", - }, - }, - { - _position = "101", - node_box = { - type = "fixed", - fixed = { - {-0.5,-0.6,-0.5,0.5,-0.5,0.5}, - {0.45,-0.5,-0.5,0.5,0.5,0.5}, - }, - }, - tiles = { - "celevator_car_floor.png", - "celevator_car_bottom_center.png^[transformFX", - "celevator_cabinet_sides.png^celevator_car_side_center_overlay.png", - "celevator_car_wallpaper.png^celevator_car_wall_bottom.png^celevator_car_wall_vent.png", - "celevator_cabinet_sides.png", - }, - }, - { - _position = "102", - node_box = { - type = "fixed", - fixed = { - {-0.5,-0.6,-0.5,0.5,-0.5,0.5}, - {0.45,-0.5,-0.5,0.5,0.5,0.5}, - {-0.5,-0.5,0.45,0.45,0.5,0.5}, - }, - }, - tiles = { - "celevator_car_floor.png", - "celevator_car_bottom.png", - "celevator_cabinet_sides.png^celevator_car_side_overlay.png^[transformR90", - "celevator_car_wallpaper.png^celevator_car_wall_bottom.png", - "celevator_cabinet_sides.png", - "celevator_car_wallpaper.png^celevator_car_wall_bottom.png", - }, - }, - { - _position = "010", - node_box = { - type = "fixed", - fixed = { - {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, - }, - }, - tiles = { - "celevator_cabinet_sides.png", - "celevator_cabinet_sides.png", - "celevator_car_wallpaper_2x.png^celevator_cop.png", - "celevator_cabinet_sides.png", - }, - }, - { - _position = "011", - node_box = { - type = "fixed", - fixed = { - {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, - }, - }, - tiles = { - "celevator_cabinet_sides.png", - "celevator_cabinet_sides.png", - "celevator_car_wallpaper.png^celevator_car_handrail_end.png", - "celevator_cabinet_sides.png^celevator_car_side_center2_overlay.png", - "celevator_cabinet_sides.png", - }, - }, - { - _position = "012", - node_box = { - type = "fixed", - fixed = { - {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, - {-0.45,-0.5,0.45,0.5,0.5,0.5}, - }, - }, - tiles = { - "celevator_cabinet_sides.png", - "celevator_cabinet_sides.png", - "celevator_car_wallpaper.png^(celevator_car_handrail_end.png^[transformFX)", - "celevator_cabinet_sides.png", - "celevator_cabinet_sides.png", - "celevator_car_wallpaper.png^celevator_car_handrail_end.png", - }, - }, - { - _position = "110", - node_box = { - type = "fixed", - fixed = { - {0.45,-0.5,-0.5,0.5,0.5,0.5}, - }, - }, - tiles = { - "celevator_cabinet_sides.png", - "celevator_cabinet_sides.png", - "celevator_cabinet_sides.png", - "celevator_car_wallpaper.png^(celevator_car_handrail_end.png^[transformFX)", - "celevator_cabinet_sides.png", - }, - }, - { - _position = "111", - node_box = { - type = "fixed", - fixed = { - {0.45,-0.5,-0.5,0.5,0.5,0.5}, - }, - }, - tiles = { - "celevator_cabinet_sides.png", - "celevator_cabinet_sides.png", - "celevator_cabinet_sides.png^celevator_car_side_center2_overlay.png", - "celevator_car_wallpaper.png^celevator_car_handrail_center.png", - "celevator_cabinet_sides.png", - }, - }, - { - _position = "112", - node_box = { - type = "fixed", - fixed = { - {0.45,-0.5,-0.5,0.5,0.5,0.5}, - {-0.5,-0.5,0.45,0.45,0.5,0.5}, - }, - }, - tiles = { - "celevator_cabinet_sides.png", - "celevator_cabinet_sides.png", - "celevator_cabinet_sides.png", - "celevator_car_wallpaper.png^celevator_car_handrail_end.png", - "celevator_cabinet_sides.png", - "celevator_car_wallpaper.png^(celevator_car_handrail_end.png^[transformFX)", - }, - }, - { - _position = "020", - node_box = { - type = "fixed", - fixed = { - {-0.5,0.5,-0.5,0.5,0.6,0.5}, - {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, - {-0.5,0.6,-0.4,0.5,1,-0.1}, - }, - }, - tiles = { - "celevator_cabinet_sides.png", - "celevator_car_ceiling.png", - "celevator_car_wallpaper.png", - "celevator_cabinet_sides.png", - "celevator_cabinet_sides.png", - "celevator_dooroperator_left.png", - }, - }, - { - _position = "021", - node_box = { - type = "fixed", - fixed = { - {-0.5,0.5,-0.5,0.5,0.6,0.5}, - {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, - }, - }, - tiles = { - "celevator_cabinet_sides.png^celevator_car_top_center_overlay.png", - "celevator_car_ceiling.png", - "celevator_car_wallpaper.png", - "celevator_cabinet_sides.png^celevator_car_side_center_overlay.png", - "celevator_cabinet_sides.png", - }, - on_rightclick = function(pos,node,clicker) - local name = clicker:get_player_name() - for _,v in ipairs(held) do - if name == v.name then return end + elseif def._keyswitches then + def.on_receive_fields = function(pos,_,fields,player) + if fields.quit then return end + local meta = minetest.get_meta(pos) + local carid = meta:get_int("carid") + if carid == 0 then return end + local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid))) + if not carinfo then return end + local playername = player:get_player_name() + if minetest.is_protected(pos,playername) and not minetest.check_player_privs(playername,{protection_bypass=true}) then + minetest.chat_send_player(playername,"You don't have access to these switches.") + minetest.record_protection_violation(pos,playername) + return + end + local event = { + type = "copswitches", + fields = fields, + player = name, + } + celevator.controller.run(carinfo.controllerpos,event) end - local fdir = minetest.fourdir_to_dir(node.param2) - local control = disambiguatebutton(pos,fdir,clicker) - if not control then return end - local meta = minetest.get_meta(pos) - local carid = meta:get_int("carid") - if carid == 0 then return end - local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid))) - if not (carinfo and carinfo.controllerpos) then return end - if control == "inspectswitch" then - local boxpos = vector.add(pos,vector.new(0,1,0)) - local erefs = minetest.get_objects_inside_radius(boxpos,0.5) - for _,ref in pairs(erefs) do - if ref:get_luaentity() and ref:get_luaentity().name == "celevator:car_top_box" then - local state = ref:get_properties().wield_item - if state == "celevator:car_top_box_off" then - state = "celevator:car_top_box_on" - elseif state == "celevator:car_top_box_on" then - state = "celevator:car_top_box_off" + end + if def._cartopbox then + def.groups._celevator_car_spawnstopbox = 1 + def.on_rightclick = function(pos,node,clicker) + local playername = clicker:get_player_name() + for _,v in ipairs(held) do + if playername == v.name then return end + end + local fdir = minetest.fourdir_to_dir(node.param2) + local control = disambiguatecartopbutton(pos,fdir,clicker) + if not control then return end + local meta = minetest.get_meta(pos) + local carid = meta:get_int("carid") + if carid == 0 then return end + local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid))) + if not (carinfo and carinfo.controllerpos) then return end + if control == "inspectswitch" then + local boxpos = vector.add(pos,vector.new(0,1,0)) + local erefs = minetest.get_objects_inside_radius(boxpos,0.5) + for _,ref in pairs(erefs) do + if ref:get_luaentity() and ref:get_luaentity().name == "celevator:car_top_box" then + local state = ref:get_properties().wield_item + if state == "celevator:car_top_box_off" then + state = "celevator:car_top_box_on" + elseif state == "celevator:car_top_box_on" then + state = "celevator:car_top_box_off" + end + ref:set_properties({wield_item = state}) end - ref:set_properties({wield_item = state}) end end + celevator.controller.handlecartopbox(carinfo.controllerpos,control) + table.insert(held,{ + pos = carinfo.controllerpos, + name = playername, + button = "place", + control = control, + }) end - celevator.controller.handlecartopbox(carinfo.controllerpos,control) - table.insert(held,{ - pos = carinfo.controllerpos, - name = name, - button = "place", - control = control, - }) - end, - after_dig_node = function(pos) - local toppos = vector.add(pos,vector.new(0,1.1,0)) - local entitiesnearby = minetest.get_objects_inside_radius(toppos,0.5) - for _,i in pairs(entitiesnearby) do - if i:get_luaentity() and i:get_luaentity().name == "celevator:car_top_box" then - i:remove() + def.after_dig_node = function(pos) + local toppos = vector.add(pos,vector.new(0,1.1,0)) + local entitiesnearby = minetest.get_objects_inside_radius(toppos,0.5) + for _,i in pairs(entitiesnearby) do + if i:get_luaentity() and i:get_luaentity().name == "celevator:car_top_box" then + i:remove() + end end end - end, - }, - { - _position = "022", - node_box = { - type = "fixed", - fixed = { - {-0.5,0.5,-0.5,0.5,0.6,0.5}, - {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, - {-0.45,-0.5,0.45,0.5,0.5,0.5}, - }, - }, - tiles = { - "celevator_cabinet_sides.png^celevator_car_top_hatch.png", - "celevator_car_ceiling.png", - "celevator_car_wallpaper.png", - "celevator_cabinet_sides.png", - "celevator_cabinet_sides.png", - "celevator_car_wallpaper.png", - }, - }, - { - _position = "120", - node_box = { - type = "fixed", - fixed = { - {-0.5,0.5,-0.5,0.5,0.6,0.5}, - {0.45,-0.5,-0.5,0.5,0.5,0.5}, - {-0.5,0.6,-0.4,0.5,1,-0.1}, - }, - }, - tiles = { - "celevator_cabinet_sides.png", - "celevator_car_ceiling.png", - "celevator_cabinet_sides.png", - "celevator_car_wallpaper.png", - "celevator_cabinet_sides.png", - "celevator_dooroperator_right.png", - }, - }, - { - _position = "121", - node_box = { - type = "fixed", - fixed = { - {-0.5,0.5,-0.5,0.5,0.6,0.5}, - {0.45,-0.5,-0.5,0.5,0.5,0.5}, - }, - }, - tiles = { - "celevator_cabinet_sides.png^celevator_car_top_center_overlay.png^[transformFX", - "celevator_car_ceiling.png", - "celevator_cabinet_sides.png^celevator_car_side_center_overlay.png", - "celevator_car_wallpaper.png", - "celevator_cabinet_sides.png", - }, - }, - { - _position = "122", - node_box = { - type = "fixed", - fixed = { - {-0.5,0.5,-0.5,0.5,0.6,0.5}, - {0.45,-0.5,-0.5,0.5,0.5,0.5}, - {-0.5,-0.5,0.45,0.45,0.5,0.5}, - }, - }, - tiles = { - "celevator_cabinet_sides.png^celevator_car_top_misc.png", - "celevator_car_ceiling.png", - "celevator_cabinet_sides.png", - "celevator_car_wallpaper.png", - "celevator_cabinet_sides.png", - "celevator_car_wallpaper.png", - }, - }, -} - -for _,def in ipairs(pieces) do - def.groups = { - not_in_creative_inventory = 1, - _celevator_car = 1, - } - local xp = tonumber(string.sub(def._position,1,1)) - local yp = tonumber(string.sub(def._position,2,2)) - local zp = tonumber(string.sub(def._position,3,3)) - if xp > 0 then - def.groups._connects_xm = 1 - end - if xp < 1 then - def.groups._connects_xp = 1 - end - if yp > 0 then - def.groups._connects_ym = 1 - end - if yp < 2 then - def.groups._connects_yp = 1 - end - if zp > 0 then - def.groups._connects_zm = 1 - end - if zp < 2 then - def.groups._connects_zp = 1 - end - def.paramtype = "light" - def.paramtype2 = "4dir" - def.drawtype = "nodebox" - def.description = "Car "..def._position.." (you hacker you!)" - def.light_source = 9 - def.drop = "" - def.on_receive_fields = function(pos,_,fields,player) - local meta = minetest.get_meta(pos) - local carid = meta:get_int("carid") - if carid == 0 then return end - local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid))) - if not carinfo then return end - local nname = minetest.get_node(pos).name - if nname == "celevator:car_010" then - local name = player:get_player_name() - local protected = minetest.is_protected(pos,name) and not minetest.check_player_privs(name,{protection_bypass=true}) - local event = { - type = "cop", - fields = fields, - player = player:get_player_name(), - protected = protected, - } - celevator.controller.run(carinfo.controllerpos,event) - elseif nname == "celevator:car_000" then - if fields.quit then return end - local name = player:get_player_name() - if minetest.is_protected(pos,name) and not minetest.check_player_privs(name,{protection_bypass=true}) then - minetest.chat_send_player(name,"You don't have access to these switches.") - minetest.record_protection_violation(pos,name) - return - end - local event = { - type = "copswitches", - fields = fields, - player = name, - } - celevator.controller.run(carinfo.controllerpos,event) end - end - if def._position == "000" then - def.on_construct = function(pos) - minetest.get_meta(pos):set_string("doorstate","closed") + if def._pi then + def.groups._celevator_car_spawnspi = 1 end - def.on_punch = function(pos,_,player) - if player.is_fake_player then return end - local name = player:get_player_name() - local sneak = player:get_player_control().sneak - if not sneak then return end - if minetest.is_protected(pos,name) and not minetest.check_player_privs(name,{protection_bypass=true}) then - minetest.record_protection_violation(pos,name) - return + if def._tapehead then + def.groups._celevator_car_spawnstapehead = 1 + end + if def._position == "000" then + def.groups._celevator_car_root = 1 + def._root = true + def.on_construct = function(pos) + minetest.get_meta(pos):set_string("doorstate","closed") + end + def.on_punch = function(pos,_,player) + if player.is_fake_player then return end + local playername = player:get_player_name() + local sneak = player:get_player_control().sneak + if not sneak then return end + if minetest.is_protected(pos,playername) and not minetest.check_player_privs(playername,{protection_bypass=true}) then + minetest.record_protection_violation(pos,playername) + return + end + local hash = minetest.hash_node_position(pos) + local fs = "formspec_version[7]size[6,4]" + fs = fs.."label[0.5,1;Really remove this car?]" + fs = fs.."button_exit[0.5,2;2,1;yes;Yes]" + fs = fs.."button_exit[3,2;2,1;no;No]" + minetest.show_formspec(playername,string.format("celevator:remove_car_%d",hash),fs) + end + def.on_timer = function(pos) + local carid = minetest.get_meta(pos):get_int("carid") + local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid))) + if not (carinfo and carinfo.controllerpos) then return end + local yaw = minetest.dir_to_yaw(minetest.fourdir_to_dir(minetest.get_node(pos).param2)) + local positions = { + vector.new(-0.25,-0.1,-0.5), + vector.new(0.25,-0.1,-0.5), + vector.new(0.75,-0.1,-0.5), + vector.new(1.25,-0.1,-0.5), + } + local playerseen = false + for _,searchpos in ipairs(positions) do + local rotatedpos = vector.rotate_around_axis(searchpos,vector.new(0,1,0),yaw) + local erefs = minetest.get_objects_inside_radius(vector.add(pos,rotatedpos),0.5) + for _,ref in pairs(erefs) do + if ref:is_player() then + playerseen = true + break + end + end + if playerseen then break end + end + if playerseen then + celevator.controller.run(carinfo.controllerpos,{ + type = "lightcurtain", + }) + end + return true end - local hash = minetest.hash_node_position(pos) - local fs = "formspec_version[7]size[6,4]" - fs = fs.."label[0.5,1;Really remove this car?]" - fs = fs.."button_exit[0.5,2;2,1;yes;Yes]" - fs = fs.."button_exit[3,2;2,1;no;No]" - minetest.show_formspec(name,string.format("celevator:remove_car_%d",hash),fs) end + minetest.register_node("celevator:car_"..name.."_"..def._position,def) end - minetest.register_node("celevator:car_"..def._position,def) end -function celevator.car.spawncar(origin,yaw,carid) +function celevator.car.spawncar(origin,yaw,carid,name,doortype) + if (not name) or name == "" then name = "standard" end + local size = celevator.car.types[name].size local right = vector.rotate_around_axis(vector.new(1,0,0),vector.new(0,1,0),yaw) local back = vector.rotate_around_axis(vector.new(0,0,1),vector.new(0,1,0),yaw) local up = vector.new(0,1,0) - for x=0,1,1 do - for y=0,2,1 do - for z=0,2,1 do + for x=0,(size.x-1),1 do + for y=0,(size.y-1),1 do + for z=0,(size.z-1),1 do local pos = vector.copy(origin) pos = vector.add(pos,vector.multiply(right,x)) pos = vector.add(pos,vector.multiply(back,z)) pos = vector.add(pos,vector.multiply(up,y)) local node = { - name = string.format("celevator:car_%d%d%d",x,y,z), + name = string.format("celevator:car_%s_%d%d%d",name,x,y,z), param2 = minetest.dir_to_fourdir(minetest.yaw_to_dir(yaw)), } minetest.set_node(pos,node) - if carid then minetest.get_meta(pos):set_int("carid",carid) end + local meta = minetest.get_meta(pos) + if carid then meta:set_int("carid",carid) end + meta:set_string("doortype",doortype or "glass") end end end @@ -576,7 +286,7 @@ end minetest.register_abm({ label = "Respawn in-car PI displays", - nodenames = {"celevator:car_020"}, + nodenames = {"group:_celevator_car_spawnspi"}, interval = 1, chance = 1, action = function(pos) @@ -650,97 +360,22 @@ minetest.register_entity("celevator:car_top_box",{ minetest.register_abm({ label = "Respawn car-top inspection boxes", - nodenames = {"celevator:car_021"}, + nodenames = {"group:_celevator_car_spawnstopbox"}, interval = 1, chance = 1, action = updatecartopbox, }) -minetest.register_node("celevator:car",{ - description = "Elevator Car", - paramtype2 = "4dir", - buildable_to = true, - inventory_image = "celevator_car_inventory.png", - wield_image = "celevator_car_wield.png", - wield_scale = vector.new(1,1,10), - tiles = {"celevator_transparent.png"}, - after_place_node = function(pos,player) - if not player:is_player() then - minetest.remove_node(pos) - return true - end - local name = player:get_player_name() - local newnode = minetest.get_node(pos) - local facedir = minetest.dir_to_yaw(minetest.fourdir_to_dir(newnode.param2)) - for x=0,1,1 do - for y=0,2,1 do - for z=0,2,1 do - local offsetdesc = string.format("%dm to the right, %dm up, and %dm back",x,y,z) - local placeoffset = vector.new(x,y,z) - local placepos = vector.add(pos,vector.rotate_around_axis(placeoffset,vector.new(0,1,0),facedir)) - local replaces = minetest.get_node(placepos).name - if not (minetest.registered_nodes[replaces] and minetest.registered_nodes[replaces].buildable_to) then - minetest.chat_send_player(name,string.format("Can't place car here - position %s is blocked!",offsetdesc)) - minetest.remove_node(pos) - return true - end - if minetest.is_protected(placepos,name) and not minetest.check_player_privs(name,{protection_bypass=true}) then - minetest.chat_send_player(name,string.format("Can't place car here - position %s is protected!",offsetdesc)) - minetest.record_protection_violation(placepos,name) - minetest.remove_node(pos) - return true - end - end - end - end - for x=0,1,1 do - for y=0,2,1 do - for z=0,2,1 do - local piecename = string.format("celevator:car_%d%d%d",x,y,z) - local placeoffset = vector.new(x,y,z) - local placepos = vector.add(pos,vector.rotate_around_axis(placeoffset,vector.new(0,1,0),facedir)) - minetest.set_node(placepos,{name=piecename,param2=newnode.param2}) - end - end - end - end, -}) - minetest.register_on_player_receive_fields(function(_,formname,fields) if string.sub(formname,1,21) ~= "celevator:remove_car_" then return false end if not fields.yes then return true end local hash = tonumber(string.sub(formname,22,-1)) if not hash then return true end local rootpos = minetest.get_position_from_hash(hash) - local rootdir = minetest.dir_to_yaw(minetest.fourdir_to_dir(minetest.get_node(rootpos).param2)) - local toberemoved = { - ["celevator:car_top_box"] = true, - ["celevator:incar_pi_entity"] = true, - ["celevator:car_door"] = true, - } - for x=0,1,1 do - for y=0,2,1 do - for z=0,2,1 do - local piecename = string.format("celevator:car_%d%d%d",x,y,z) - local pieceoffset = vector.new(x,y,z) - local piecepos = vector.add(rootpos,vector.rotate_around_axis(pieceoffset,vector.new(0,1,0),rootdir)) - if minetest.get_node(piecepos).name == piecename then - minetest.remove_node(piecepos) - local erefs = minetest.get_objects_inside_radius(piecepos,0.5) - for _,ref in pairs(erefs) do - if ref:get_luaentity() and toberemoved[ref:get_luaentity().name] then - ref:remove() - end - end - end - end - end - end - local cartopboxpos = vector.add(rootpos,vector.rotate_around_axis(vector.new(0,3,1),vector.new(0,1,0),rootdir)) - local erefs = minetest.get_objects_inside_radius(cartopboxpos,0.5) - for _,ref in pairs(erefs) do - if ref:get_luaentity() and toberemoved[ref:get_luaentity().name] then - ref:remove() - end + local rootdef = minetest.registered_nodes[celevator.get_node(rootpos).name] or {} + local cartype = rootdef._celevator_car_type + if cartype and celevator.car.types[cartype] then + local rootdir = minetest.dir_to_yaw(minetest.fourdir_to_dir(minetest.get_node(rootpos).param2)) + celevator.car.types[cartype].remove(rootpos,rootdir) end end) diff --git a/car_glassback.lua b/car_glassback.lua new file mode 100644 index 0000000..58d4c7a --- /dev/null +++ b/car_glassback.lua @@ -0,0 +1,416 @@ +local pieces = { + { + _position = "000", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.6,-0.5,0.5,-0.5,0.5}, + {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, + {-0.5,-1.5,-0.5,0.5,-0.6,-0.45}, + }, + }, + tiles = { + "celevator_car_floor.png^celevator_door_sill_single.png", + "celevator_car_bottom.png", + "celevator_car_wallpaper.png^celevator_car_wall_bottom.png^celevator_car_switch_panel.png", + "celevator_cabinet_sides.png^celevator_car_side_overlay.png^[transformR90", + "celevator_cabinet_sides.png", + }, + _keyswitches = true, + }, + { + _position = "001", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.6,-0.5,0.5,-0.5,0.5}, + {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, + }, + }, + tiles = { + "celevator_car_floor.png", + "celevator_car_bottom_center.png", + "celevator_car_wallpaper.png^celevator_car_wall_bottom.png^celevator_car_wall_vent.png", + "celevator_cabinet_sides.png^celevator_car_side_center_overlay.png", + "celevator_cabinet_sides.png", + }, + }, + { + _position = "002", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.6,-0.5,0.5,-0.5,0.5}, + {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, + {-0.45,-0.5,0.45,0.5,0.5,0.5}, + }, + }, + use_texture_alpha = "clip", + tiles = { + "celevator_car_floor.png", + "celevator_car_bottom.png", + "celevator_car_wallpaper.png^celevator_car_wall_bottom.png", + "celevator_cabinet_sides.png^celevator_car_side_overlay.png", + "celevator_car_glass.png", + "celevator_car_glass.png^celevator_car_wall_bottom.png", + }, + }, + { + _position = "100", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.6,-0.5,0.5,-0.5,0.5}, + {0.45,-0.5,-0.5,0.5,0.5,0.5}, + {-0.5,-1.5,-0.5,0.5,-0.6,-0.45}, + }, + }, + tiles = { + "celevator_car_floor.png^celevator_door_sill_double.png", + "celevator_car_bottom.png", + "celevator_cabinet_sides.png^celevator_car_side_overlay.png", + "celevator_car_wallpaper.png^celevator_car_wall_bottom.png", + "celevator_cabinet_sides.png", + }, + }, + { + _position = "101", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.6,-0.5,0.5,-0.5,0.5}, + {0.45,-0.5,-0.5,0.5,0.5,0.5}, + }, + }, + tiles = { + "celevator_car_floor.png", + "celevator_car_bottom_center.png^[transformFX", + "celevator_cabinet_sides.png^celevator_car_side_center_overlay.png", + "celevator_car_wallpaper.png^celevator_car_wall_bottom.png^celevator_car_wall_vent.png", + "celevator_cabinet_sides.png", + }, + }, + { + _position = "102", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.6,-0.5,0.5,-0.5,0.5}, + {0.45,-0.5,-0.5,0.5,0.5,0.5}, + {-0.5,-0.5,0.45,0.45,0.5,0.5}, + }, + }, + use_texture_alpha = "clip", + tiles = { + "celevator_car_floor.png", + "celevator_car_bottom.png", + "celevator_cabinet_sides.png^celevator_car_side_overlay.png^[transformR90", + "celevator_car_wallpaper.png^celevator_car_wall_bottom.png", + "celevator_car_glass.png", + "celevator_car_glass.png^celevator_car_wall_bottom.png", + }, + }, + { + _position = "010", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, + }, + }, + tiles = { + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_car_wallpaper_2x.png^celevator_cop.png", + "celevator_cabinet_sides.png", + }, + _cop = true, + }, + { + _position = "011", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, + }, + }, + tiles = { + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_car_wallpaper.png^celevator_car_handrail_end.png", + "celevator_cabinet_sides.png^celevator_car_side_center2_overlay.png", + "celevator_cabinet_sides.png", + }, + }, + { + _position = "012", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, + {-0.45,-0.5,0.45,0.5,0.5,0.5}, + }, + }, + use_texture_alpha = "clip", + tiles = { + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_car_wallpaper.png^(celevator_car_handrail_end.png^[transformFX)", + "celevator_cabinet_sides.png", + "celevator_car_glass.png", + "celevator_car_glass.png", + }, + }, + { + _position = "110", + node_box = { + type = "fixed", + fixed = { + {0.45,-0.5,-0.5,0.5,0.5,0.5}, + }, + }, + tiles = { + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_car_wallpaper.png^(celevator_car_handrail_end.png^[transformFX)", + "celevator_cabinet_sides.png", + }, + }, + { + _position = "111", + node_box = { + type = "fixed", + fixed = { + {0.45,-0.5,-0.5,0.5,0.5,0.5}, + }, + }, + tiles = { + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png^celevator_car_side_center2_overlay.png", + "celevator_car_wallpaper.png^celevator_car_handrail_center.png", + "celevator_cabinet_sides.png", + }, + }, + { + _position = "112", + node_box = { + type = "fixed", + fixed = { + {0.45,-0.5,-0.5,0.5,0.5,0.5}, + {-0.5,-0.5,0.45,0.45,0.5,0.5}, + }, + }, + use_texture_alpha = "clip", + tiles = { + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_car_wallpaper.png^celevator_car_handrail_end.png", + "celevator_car_glass.png", + "celevator_car_glass.png", + }, + }, + { + _position = "020", + node_box = { + type = "fixed", + fixed = { + {-0.5,0.5,-0.5,0.5,0.6,0.5}, + {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, + {-0.5,0.6,-0.4,0.5,1,-0.1}, + }, + }, + tiles = { + "celevator_cabinet_sides.png", + "celevator_car_ceiling.png", + "celevator_car_wallpaper.png", + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_dooroperator_left.png", + }, + _pi = true, + }, + { + _position = "021", + node_box = { + type = "fixed", + fixed = { + {-0.5,0.5,-0.5,0.5,0.6,0.5}, + {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, + }, + }, + tiles = { + "celevator_cabinet_sides.png^celevator_car_top_center_overlay.png", + "celevator_car_ceiling.png", + "celevator_car_wallpaper.png", + "celevator_cabinet_sides.png^celevator_car_side_center_overlay.png", + "celevator_cabinet_sides.png", + }, + _cartopbox = true, + }, + { + _position = "022", + node_box = { + type = "fixed", + fixed = { + {-0.5,0.5,-0.5,0.5,0.6,0.5}, + {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, + {-0.45,-0.5,0.45,0.5,0.5,0.5}, + }, + }, + use_texture_alpha = "clip", + tiles = { + "celevator_cabinet_sides.png^celevator_car_top_hatch.png", + "celevator_car_ceiling.png", + "celevator_car_wallpaper.png", + "celevator_cabinet_sides.png", + "celevator_car_glass.png", + "celevator_car_glass.png", + }, + }, + { + _position = "120", + node_box = { + type = "fixed", + fixed = { + {-0.5,0.5,-0.5,0.5,0.6,0.5}, + {0.45,-0.5,-0.5,0.5,0.5,0.5}, + {-0.5,0.6,-0.4,0.5,1,-0.1}, + }, + }, + tiles = { + "celevator_cabinet_sides.png", + "celevator_car_ceiling.png", + "celevator_cabinet_sides.png", + "celevator_car_wallpaper.png", + "celevator_cabinet_sides.png", + "celevator_dooroperator_right.png", + }, + }, + { + _position = "121", + node_box = { + type = "fixed", + fixed = { + {-0.5,0.5,-0.5,0.5,0.6,0.5}, + {0.45,-0.5,-0.5,0.5,0.5,0.5}, + }, + }, + tiles = { + "celevator_cabinet_sides.png^celevator_car_top_center_overlay.png^[transformFX", + "celevator_car_ceiling.png", + "celevator_cabinet_sides.png^celevator_car_side_center_overlay.png", + "celevator_car_wallpaper.png", + "celevator_cabinet_sides.png", + }, + }, + { + _position = "122", + node_box = { + type = "fixed", + fixed = { + {-0.5,0.5,-0.5,0.5,0.6,0.5}, + {0.45,-0.5,-0.5,0.5,0.5,0.5}, + {-0.5,-0.5,0.45,0.45,0.5,0.5}, + }, + }, + use_texture_alpha = "clip", + tiles = { + "celevator_cabinet_sides.png^celevator_car_top_misc.png", + "celevator_car_ceiling.png", + "celevator_cabinet_sides.png", + "celevator_car_wallpaper.png", + "celevator_car_glass.png", + "celevator_car_glass.png", + }, + _tapehead = true, + }, +} + +celevator.car.register("glassback",pieces,vector.new(2,3,3)) + + +minetest.register_node("celevator:car_glassback",{ + description = "Glass-Back Elevator Car", + paramtype2 = "4dir", + buildable_to = true, + inventory_image = "celevator_car_glassback_inventory.png", + wield_image = "celevator_car_glassback_wield.png", + wield_scale = vector.new(1,1,10), + tiles = {"celevator_transparent.png"}, + after_place_node = function(pos,player) + if not player:is_player() then + minetest.remove_node(pos) + return true + end + local name = player:get_player_name() + local newnode = minetest.get_node(pos) + local facedir = minetest.dir_to_yaw(minetest.fourdir_to_dir(newnode.param2)) + for x=0,1,1 do + for y=0,2,1 do + for z=0,2,1 do + local offsetdesc = string.format("%dm to the right, %dm up, and %dm back",x,y,z) + local placeoffset = vector.new(x,y,z) + local placepos = vector.add(pos,vector.rotate_around_axis(placeoffset,vector.new(0,1,0),facedir)) + local replaces = minetest.get_node(placepos).name + if not (minetest.registered_nodes[replaces] and minetest.registered_nodes[replaces].buildable_to) then + minetest.chat_send_player(name,string.format("Can't place car here - position %s is blocked!",offsetdesc)) + minetest.remove_node(pos) + return true + end + if minetest.is_protected(placepos,name) and not minetest.check_player_privs(name,{protection_bypass=true}) then + minetest.chat_send_player(name,string.format("Can't place car here - position %s is protected!",offsetdesc)) + minetest.record_protection_violation(placepos,name) + minetest.remove_node(pos) + return true + end + end + end + end + for x=0,1,1 do + for y=0,2,1 do + for z=0,2,1 do + local piecename = string.format("celevator:car_glassback_%d%d%d",x,y,z) + local placeoffset = vector.new(x,y,z) + local placepos = vector.add(pos,vector.rotate_around_axis(placeoffset,vector.new(0,1,0),facedir)) + minetest.set_node(placepos,{name=piecename,param2=newnode.param2}) + end + end + end + end, +}) + +celevator.car.types.glassback.remove = function(rootpos,rootdir) + local toberemoved = { + ["celevator:car_top_box"] = true, + ["celevator:incar_pi_entity"] = true, + ["celevator:car_door"] = true, + } + for x=0,1,1 do + for y=0,2,1 do + for z=0,2,1 do + local piecename = string.format("celevator:car_glassback_%d%d%d",x,y,z) + local pieceoffset = vector.new(x,y,z) + local piecepos = vector.add(rootpos,vector.rotate_around_axis(pieceoffset,vector.new(0,1,0),rootdir)) + if minetest.get_node(piecepos).name == piecename then + minetest.remove_node(piecepos) + local erefs = minetest.get_objects_inside_radius(piecepos,0.5) + for _,ref in pairs(erefs) do + if ref:get_luaentity() and toberemoved[ref:get_luaentity().name] then + ref:remove() + end + end + end + end + end + end + local cartopboxpos = vector.add(rootpos,vector.rotate_around_axis(vector.new(0,3,1),vector.new(0,1,0),rootdir)) + local erefs = minetest.get_objects_inside_radius(cartopboxpos,0.5) + for _,ref in pairs(erefs) do + if ref:get_luaentity() and toberemoved[ref:get_luaentity().name] then + ref:remove() + end + end +end diff --git a/car_metal.lua b/car_metal.lua new file mode 100644 index 0000000..1b18ced --- /dev/null +++ b/car_metal.lua @@ -0,0 +1,410 @@ +local pieces = { + { + _position = "000", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.6,-0.5,0.5,-0.5,0.5}, + {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, + {-0.5,-1.5,-0.5,0.5,-0.6,-0.45}, + }, + }, + tiles = { + "celevator_car_metal_floor.png^celevator_door_sill_single.png", + "celevator_car_bottom.png", + "celevator_car_metal.png^celevator_car_wall_bottom.png^celevator_car_switch_panel.png", + "celevator_cabinet_sides.png^celevator_car_side_overlay.png^[transformR90", + "celevator_cabinet_sides.png", + }, + _keyswitches = true, + }, + { + _position = "001", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.6,-0.5,0.5,-0.5,0.5}, + {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, + }, + }, + tiles = { + "celevator_car_metal_floor.png", + "celevator_car_bottom_center.png", + "celevator_car_metal.png^celevator_car_wall_bottom.png^celevator_car_wall_vent.png", + "celevator_cabinet_sides.png^celevator_car_side_center_overlay.png", + "celevator_cabinet_sides.png", + }, + }, + { + _position = "002", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.6,-0.5,0.5,-0.5,0.5}, + {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, + {-0.45,-0.5,0.45,0.5,0.5,0.5}, + }, + }, + tiles = { + "celevator_car_metal_floor.png", + "celevator_car_bottom.png", + "celevator_car_metal.png^celevator_car_wall_bottom.png", + "celevator_cabinet_sides.png^celevator_car_side_overlay.png", + "celevator_cabinet_sides.png", + "celevator_car_metal.png^celevator_car_wall_bottom.png", + }, + }, + { + _position = "100", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.6,-0.5,0.5,-0.5,0.5}, + {0.45,-0.5,-0.5,0.5,0.5,0.5}, + {-0.5,-1.5,-0.5,0.5,-0.6,-0.45}, + }, + }, + tiles = { + "celevator_car_metal_floor.png^celevator_door_sill_double.png", + "celevator_car_bottom.png", + "celevator_cabinet_sides.png^celevator_car_side_overlay.png", + "celevator_car_metal.png^celevator_car_wall_bottom.png", + "celevator_cabinet_sides.png", + }, + }, + { + _position = "101", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.6,-0.5,0.5,-0.5,0.5}, + {0.45,-0.5,-0.5,0.5,0.5,0.5}, + }, + }, + tiles = { + "celevator_car_metal_floor.png", + "celevator_car_bottom_center.png^[transformFX", + "celevator_cabinet_sides.png^celevator_car_side_center_overlay.png", + "celevator_car_metal.png^celevator_car_wall_bottom.png^celevator_car_wall_vent.png", + "celevator_cabinet_sides.png", + }, + }, + { + _position = "102", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.6,-0.5,0.5,-0.5,0.5}, + {0.45,-0.5,-0.5,0.5,0.5,0.5}, + {-0.5,-0.5,0.45,0.45,0.5,0.5}, + }, + }, + tiles = { + "celevator_car_metal_floor.png", + "celevator_car_bottom.png", + "celevator_cabinet_sides.png^celevator_car_side_overlay.png^[transformR90", + "celevator_car_metal.png^celevator_car_wall_bottom.png", + "celevator_cabinet_sides.png", + "celevator_car_metal.png^celevator_car_wall_bottom.png", + }, + }, + { + _position = "010", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, + }, + }, + tiles = { + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_car_metal_2x.png^celevator_cop.png", + "celevator_cabinet_sides.png", + }, + _cop = true, + }, + { + _position = "011", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, + }, + }, + tiles = { + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_car_metal.png^celevator_car_handrail_end.png", + "celevator_cabinet_sides.png^celevator_car_side_center2_overlay.png", + "celevator_cabinet_sides.png", + }, + }, + { + _position = "012", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, + {-0.45,-0.5,0.45,0.5,0.5,0.5}, + }, + }, + tiles = { + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_car_metal.png^(celevator_car_handrail_end.png^[transformFX)", + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_car_metal.png", + }, + }, + { + _position = "110", + node_box = { + type = "fixed", + fixed = { + {0.45,-0.5,-0.5,0.5,0.5,0.5}, + }, + }, + tiles = { + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_car_metal.png^(celevator_car_handrail_end.png^[transformFX)", + "celevator_cabinet_sides.png", + }, + }, + { + _position = "111", + node_box = { + type = "fixed", + fixed = { + {0.45,-0.5,-0.5,0.5,0.5,0.5}, + }, + }, + tiles = { + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png^celevator_car_side_center2_overlay.png", + "celevator_car_metal.png^celevator_car_handrail_center.png", + "celevator_cabinet_sides.png", + }, + }, + { + _position = "112", + node_box = { + type = "fixed", + fixed = { + {0.45,-0.5,-0.5,0.5,0.5,0.5}, + {-0.5,-0.5,0.45,0.45,0.5,0.5}, + }, + }, + tiles = { + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_car_metal.png^celevator_car_handrail_end.png", + "celevator_cabinet_sides.png", + "celevator_car_metal.png", + }, + }, + { + _position = "020", + node_box = { + type = "fixed", + fixed = { + {-0.5,0.5,-0.5,0.5,0.6,0.5}, + {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, + {-0.5,0.6,-0.4,0.5,1,-0.1}, + }, + }, + tiles = { + "celevator_cabinet_sides.png", + "celevator_car_metal_ceiling.png", + "celevator_car_metal_top.png", + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_dooroperator_left.png", + }, + _pi = true, + }, + { + _position = "021", + node_box = { + type = "fixed", + fixed = { + {-0.5,0.5,-0.5,0.5,0.6,0.5}, + {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, + }, + }, + tiles = { + "celevator_cabinet_sides.png^celevator_car_top_center_overlay.png", + "celevator_car_metal_ceiling.png", + "celevator_car_metal_top.png", + "celevator_cabinet_sides.png^celevator_car_side_center_overlay.png", + "celevator_cabinet_sides.png", + }, + _cartopbox = true, + }, + { + _position = "022", + node_box = { + type = "fixed", + fixed = { + {-0.5,0.5,-0.5,0.5,0.6,0.5}, + {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, + {-0.45,-0.5,0.45,0.5,0.5,0.5}, + }, + }, + tiles = { + "celevator_cabinet_sides.png^celevator_car_top_hatch.png", + "celevator_car_metal_ceiling.png", + "celevator_car_metal_top.png", + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_car_metal_top.png", + }, + }, + { + _position = "120", + node_box = { + type = "fixed", + fixed = { + {-0.5,0.5,-0.5,0.5,0.6,0.5}, + {0.45,-0.5,-0.5,0.5,0.5,0.5}, + {-0.5,0.6,-0.4,0.5,1,-0.1}, + }, + }, + tiles = { + "celevator_cabinet_sides.png", + "celevator_car_metal_ceiling.png", + "celevator_cabinet_sides.png", + "celevator_car_metal_top.png", + "celevator_cabinet_sides.png", + "celevator_dooroperator_right.png", + }, + }, + { + _position = "121", + node_box = { + type = "fixed", + fixed = { + {-0.5,0.5,-0.5,0.5,0.6,0.5}, + {0.45,-0.5,-0.5,0.5,0.5,0.5}, + }, + }, + tiles = { + "celevator_cabinet_sides.png^celevator_car_top_center_overlay.png^[transformFX", + "celevator_car_metal_ceiling.png", + "celevator_cabinet_sides.png^celevator_car_side_center_overlay.png", + "celevator_car_metal_top.png", + "celevator_cabinet_sides.png", + }, + }, + { + _position = "122", + node_box = { + type = "fixed", + fixed = { + {-0.5,0.5,-0.5,0.5,0.6,0.5}, + {0.45,-0.5,-0.5,0.5,0.5,0.5}, + {-0.5,-0.5,0.45,0.45,0.5,0.5}, + }, + }, + tiles = { + "celevator_cabinet_sides.png^celevator_car_top_misc.png", + "celevator_car_metal_ceiling.png", + "celevator_cabinet_sides.png", + "celevator_car_metal_top.png", + "celevator_cabinet_sides.png", + "celevator_car_metal_top.png", + }, + _tapehead = true, + }, +} + +celevator.car.register("metal",pieces,vector.new(2,3,3)) + + +minetest.register_node("celevator:car_metal",{ + description = "Metal Elevator Car", + paramtype2 = "4dir", + buildable_to = true, + inventory_image = "celevator_car_metal_inventory.png", + wield_image = "celevator_car_metal_wield.png", + wield_scale = vector.new(1,1,10), + tiles = {"celevator_transparent.png"}, + after_place_node = function(pos,player) + if not player:is_player() then + minetest.remove_node(pos) + return true + end + local name = player:get_player_name() + local newnode = minetest.get_node(pos) + local facedir = minetest.dir_to_yaw(minetest.fourdir_to_dir(newnode.param2)) + for x=0,1,1 do + for y=0,2,1 do + for z=0,2,1 do + local offsetdesc = string.format("%dm to the right, %dm up, and %dm back",x,y,z) + local placeoffset = vector.new(x,y,z) + local placepos = vector.add(pos,vector.rotate_around_axis(placeoffset,vector.new(0,1,0),facedir)) + local replaces = minetest.get_node(placepos).name + if not (minetest.registered_nodes[replaces] and minetest.registered_nodes[replaces].buildable_to) then + minetest.chat_send_player(name,string.format("Can't place car here - position %s is blocked!",offsetdesc)) + minetest.remove_node(pos) + return true + end + if minetest.is_protected(placepos,name) and not minetest.check_player_privs(name,{protection_bypass=true}) then + minetest.chat_send_player(name,string.format("Can't place car here - position %s is protected!",offsetdesc)) + minetest.record_protection_violation(placepos,name) + minetest.remove_node(pos) + return true + end + end + end + end + for x=0,1,1 do + for y=0,2,1 do + for z=0,2,1 do + local piecename = string.format("celevator:car_metal_%d%d%d",x,y,z) + local placeoffset = vector.new(x,y,z) + local placepos = vector.add(pos,vector.rotate_around_axis(placeoffset,vector.new(0,1,0),facedir)) + minetest.set_node(placepos,{name=piecename,param2=newnode.param2}) + end + end + end + end, +}) + +celevator.car.types.metal.remove = function(rootpos,rootdir) + local toberemoved = { + ["celevator:car_top_box"] = true, + ["celevator:incar_pi_entity"] = true, + ["celevator:car_door"] = true, + } + for x=0,1,1 do + for y=0,2,1 do + for z=0,2,1 do + local piecename = string.format("celevator:car_metal_%d%d%d",x,y,z) + local pieceoffset = vector.new(x,y,z) + local piecepos = vector.add(rootpos,vector.rotate_around_axis(pieceoffset,vector.new(0,1,0),rootdir)) + if minetest.get_node(piecepos).name == piecename then + minetest.remove_node(piecepos) + local erefs = minetest.get_objects_inside_radius(piecepos,0.5) + for _,ref in pairs(erefs) do + if ref:get_luaentity() and toberemoved[ref:get_luaentity().name] then + ref:remove() + end + end + end + end + end + end + local cartopboxpos = vector.add(rootpos,vector.rotate_around_axis(vector.new(0,3,1),vector.new(0,1,0),rootdir)) + local erefs = minetest.get_objects_inside_radius(cartopboxpos,0.5) + for _,ref in pairs(erefs) do + if ref:get_luaentity() and toberemoved[ref:get_luaentity().name] then + ref:remove() + end + end +end diff --git a/car_metalglass.lua b/car_metalglass.lua new file mode 100644 index 0000000..432babf --- /dev/null +++ b/car_metalglass.lua @@ -0,0 +1,416 @@ +local pieces = { + { + _position = "000", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.6,-0.5,0.5,-0.5,0.5}, + {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, + {-0.5,-1.5,-0.5,0.5,-0.6,-0.45}, + }, + }, + tiles = { + "celevator_car_metal_floor.png^celevator_door_sill_single.png", + "celevator_car_bottom.png", + "celevator_car_metal.png^celevator_car_wall_bottom.png^celevator_car_switch_panel.png", + "celevator_cabinet_sides.png^celevator_car_side_overlay.png^[transformR90", + "celevator_cabinet_sides.png", + }, + _keyswitches = true, + }, + { + _position = "001", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.6,-0.5,0.5,-0.5,0.5}, + {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, + }, + }, + tiles = { + "celevator_car_metal_floor.png", + "celevator_car_bottom_center.png", + "celevator_car_metal.png^celevator_car_wall_bottom.png^celevator_car_wall_vent.png", + "celevator_cabinet_sides.png^celevator_car_side_center_overlay.png", + "celevator_cabinet_sides.png", + }, + }, + { + _position = "002", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.6,-0.5,0.5,-0.5,0.5}, + {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, + {-0.45,-0.5,0.45,0.5,0.5,0.5}, + }, + }, + use_texture_alpha = "clip", + tiles = { + "celevator_car_metal_floor.png", + "celevator_car_bottom.png", + "celevator_car_metal.png^celevator_car_wall_bottom.png", + "celevator_cabinet_sides.png^celevator_car_side_overlay.png", + "celevator_car_glass.png", + "celevator_car_glass.png^celevator_car_wall_bottom.png", + }, + }, + { + _position = "100", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.6,-0.5,0.5,-0.5,0.5}, + {0.45,-0.5,-0.5,0.5,0.5,0.5}, + {-0.5,-1.5,-0.5,0.5,-0.6,-0.45}, + }, + }, + tiles = { + "celevator_car_metal_floor.png^celevator_door_sill_double.png", + "celevator_car_bottom.png", + "celevator_cabinet_sides.png^celevator_car_side_overlay.png", + "celevator_car_metal.png^celevator_car_wall_bottom.png", + "celevator_cabinet_sides.png", + }, + }, + { + _position = "101", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.6,-0.5,0.5,-0.5,0.5}, + {0.45,-0.5,-0.5,0.5,0.5,0.5}, + }, + }, + tiles = { + "celevator_car_metal_floor.png", + "celevator_car_bottom_center.png^[transformFX", + "celevator_cabinet_sides.png^celevator_car_side_center_overlay.png", + "celevator_car_metal.png^celevator_car_wall_bottom.png^celevator_car_wall_vent.png", + "celevator_cabinet_sides.png", + }, + }, + { + _position = "102", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.6,-0.5,0.5,-0.5,0.5}, + {0.45,-0.5,-0.5,0.5,0.5,0.5}, + {-0.5,-0.5,0.45,0.45,0.5,0.5}, + }, + }, + use_texture_alpha = "clip", + tiles = { + "celevator_car_metal_floor.png", + "celevator_car_bottom.png", + "celevator_cabinet_sides.png^celevator_car_side_overlay.png^[transformR90", + "celevator_car_metal.png^celevator_car_wall_bottom.png", + "celevator_car_glass.png", + "celevator_car_glass.png^celevator_car_wall_bottom.png", + }, + }, + { + _position = "010", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, + }, + }, + tiles = { + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_car_metal_2x.png^celevator_cop.png", + "celevator_cabinet_sides.png", + }, + _cop = true, + }, + { + _position = "011", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, + }, + }, + tiles = { + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_car_metal.png^celevator_car_handrail_end.png", + "celevator_cabinet_sides.png^celevator_car_side_center2_overlay.png", + "celevator_cabinet_sides.png", + }, + }, + { + _position = "012", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, + {-0.45,-0.5,0.45,0.5,0.5,0.5}, + }, + }, + use_texture_alpha = "clip", + tiles = { + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_car_metal.png^(celevator_car_handrail_end.png^[transformFX)", + "celevator_cabinet_sides.png", + "celevator_car_glass.png", + "celevator_car_glass.png", + }, + }, + { + _position = "110", + node_box = { + type = "fixed", + fixed = { + {0.45,-0.5,-0.5,0.5,0.5,0.5}, + }, + }, + tiles = { + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_car_metal.png^(celevator_car_handrail_end.png^[transformFX)", + "celevator_cabinet_sides.png", + }, + }, + { + _position = "111", + node_box = { + type = "fixed", + fixed = { + {0.45,-0.5,-0.5,0.5,0.5,0.5}, + }, + }, + tiles = { + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png^celevator_car_side_center2_overlay.png", + "celevator_car_metal.png^celevator_car_handrail_center.png", + "celevator_cabinet_sides.png", + }, + }, + { + _position = "112", + node_box = { + type = "fixed", + fixed = { + {0.45,-0.5,-0.5,0.5,0.5,0.5}, + {-0.5,-0.5,0.45,0.45,0.5,0.5}, + }, + }, + use_texture_alpha = "clip", + tiles = { + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_car_metal.png^celevator_car_handrail_end.png", + "celevator_car_glass.png", + "celevator_car_glass.png", + }, + }, + { + _position = "020", + node_box = { + type = "fixed", + fixed = { + {-0.5,0.5,-0.5,0.5,0.6,0.5}, + {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, + {-0.5,0.6,-0.4,0.5,1,-0.1}, + }, + }, + tiles = { + "celevator_cabinet_sides.png", + "celevator_car_metal_ceiling.png", + "celevator_car_metal_top.png", + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_dooroperator_left.png", + }, + _pi = true, + }, + { + _position = "021", + node_box = { + type = "fixed", + fixed = { + {-0.5,0.5,-0.5,0.5,0.6,0.5}, + {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, + }, + }, + tiles = { + "celevator_cabinet_sides.png^celevator_car_top_center_overlay.png", + "celevator_car_metal_ceiling.png", + "celevator_car_metal_top.png", + "celevator_cabinet_sides.png^celevator_car_side_center_overlay.png", + "celevator_cabinet_sides.png", + }, + _cartopbox = true, + }, + { + _position = "022", + node_box = { + type = "fixed", + fixed = { + {-0.5,0.5,-0.5,0.5,0.6,0.5}, + {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, + {-0.45,-0.5,0.45,0.5,0.5,0.5}, + }, + }, + use_texture_alpha = "clip", + tiles = { + "celevator_cabinet_sides.png^celevator_car_top_hatch.png", + "celevator_car_metal_ceiling.png", + "celevator_car_metal_top.png", + "celevator_cabinet_sides.png", + "celevator_car_glass.png", + "celevator_car_glass.png", + }, + }, + { + _position = "120", + node_box = { + type = "fixed", + fixed = { + {-0.5,0.5,-0.5,0.5,0.6,0.5}, + {0.45,-0.5,-0.5,0.5,0.5,0.5}, + {-0.5,0.6,-0.4,0.5,1,-0.1}, + }, + }, + tiles = { + "celevator_cabinet_sides.png", + "celevator_car_metal_ceiling.png", + "celevator_cabinet_sides.png", + "celevator_car_metal_top.png", + "celevator_cabinet_sides.png", + "celevator_dooroperator_right.png", + }, + }, + { + _position = "121", + node_box = { + type = "fixed", + fixed = { + {-0.5,0.5,-0.5,0.5,0.6,0.5}, + {0.45,-0.5,-0.5,0.5,0.5,0.5}, + }, + }, + tiles = { + "celevator_cabinet_sides.png^celevator_car_top_center_overlay.png^[transformFX", + "celevator_car_metal_ceiling.png", + "celevator_cabinet_sides.png^celevator_car_side_center_overlay.png", + "celevator_car_metal_top.png", + "celevator_cabinet_sides.png", + }, + }, + { + _position = "122", + node_box = { + type = "fixed", + fixed = { + {-0.5,0.5,-0.5,0.5,0.6,0.5}, + {0.45,-0.5,-0.5,0.5,0.5,0.5}, + {-0.5,-0.5,0.45,0.45,0.5,0.5}, + }, + }, + use_texture_alpha = "clip", + tiles = { + "celevator_cabinet_sides.png^celevator_car_top_misc.png", + "celevator_car_metal_ceiling.png", + "celevator_cabinet_sides.png", + "celevator_car_metal_top.png", + "celevator_car_glass.png", + "celevator_car_glass.png", + }, + _tapehead = true, + }, +} + +celevator.car.register("metal_glassback",pieces,vector.new(2,3,3)) + + +minetest.register_node("celevator:car_metal_glassback",{ + description = "Metal Glass-Back Elevator Car", + paramtype2 = "4dir", + buildable_to = true, + inventory_image = "celevator_car_metal_glassback_inventory.png", + wield_image = "celevator_car_metal_glassback_wield.png", + wield_scale = vector.new(1,1,10), + tiles = {"celevator_transparent.png"}, + after_place_node = function(pos,player) + if not player:is_player() then + minetest.remove_node(pos) + return true + end + local name = player:get_player_name() + local newnode = minetest.get_node(pos) + local facedir = minetest.dir_to_yaw(minetest.fourdir_to_dir(newnode.param2)) + for x=0,1,1 do + for y=0,2,1 do + for z=0,2,1 do + local offsetdesc = string.format("%dm to the right, %dm up, and %dm back",x,y,z) + local placeoffset = vector.new(x,y,z) + local placepos = vector.add(pos,vector.rotate_around_axis(placeoffset,vector.new(0,1,0),facedir)) + local replaces = minetest.get_node(placepos).name + if not (minetest.registered_nodes[replaces] and minetest.registered_nodes[replaces].buildable_to) then + minetest.chat_send_player(name,string.format("Can't place car here - position %s is blocked!",offsetdesc)) + minetest.remove_node(pos) + return true + end + if minetest.is_protected(placepos,name) and not minetest.check_player_privs(name,{protection_bypass=true}) then + minetest.chat_send_player(name,string.format("Can't place car here - position %s is protected!",offsetdesc)) + minetest.record_protection_violation(placepos,name) + minetest.remove_node(pos) + return true + end + end + end + end + for x=0,1,1 do + for y=0,2,1 do + for z=0,2,1 do + local piecename = string.format("celevator:car_metal_glassback_%d%d%d",x,y,z) + local placeoffset = vector.new(x,y,z) + local placepos = vector.add(pos,vector.rotate_around_axis(placeoffset,vector.new(0,1,0),facedir)) + minetest.set_node(placepos,{name=piecename,param2=newnode.param2}) + end + end + end + end, +}) + +celevator.car.types.metal_glassback.remove = function(rootpos,rootdir) + local toberemoved = { + ["celevator:car_top_box"] = true, + ["celevator:incar_pi_entity"] = true, + ["celevator:car_door"] = true, + } + for x=0,1,1 do + for y=0,2,1 do + for z=0,2,1 do + local piecename = string.format("celevator:car_metal_glassback_%d%d%d",x,y,z) + local pieceoffset = vector.new(x,y,z) + local piecepos = vector.add(rootpos,vector.rotate_around_axis(pieceoffset,vector.new(0,1,0),rootdir)) + if minetest.get_node(piecepos).name == piecename then + minetest.remove_node(piecepos) + local erefs = minetest.get_objects_inside_radius(piecepos,0.5) + for _,ref in pairs(erefs) do + if ref:get_luaentity() and toberemoved[ref:get_luaentity().name] then + ref:remove() + end + end + end + end + end + end + local cartopboxpos = vector.add(rootpos,vector.rotate_around_axis(vector.new(0,3,1),vector.new(0,1,0),rootdir)) + local erefs = minetest.get_objects_inside_radius(cartopboxpos,0.5) + for _,ref in pairs(erefs) do + if ref:get_luaentity() and toberemoved[ref:get_luaentity().name] then + ref:remove() + end + end +end diff --git a/car_standard.lua b/car_standard.lua new file mode 100644 index 0000000..70cb91f --- /dev/null +++ b/car_standard.lua @@ -0,0 +1,419 @@ +local pieces = { + { + _position = "000", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.6,-0.5,0.5,-0.5,0.5}, + {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, + {-0.5,-1.5,-0.5,0.5,-0.6,-0.45}, + }, + }, + tiles = { + "celevator_car_floor.png^celevator_door_sill_single.png", + "celevator_car_bottom.png", + "celevator_car_wallpaper.png^celevator_car_wall_bottom.png^celevator_car_switch_panel.png", + "celevator_cabinet_sides.png^celevator_car_side_overlay.png^[transformR90", + "celevator_cabinet_sides.png", + }, + _keyswitches = true, + }, + { + _position = "001", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.6,-0.5,0.5,-0.5,0.5}, + {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, + }, + }, + tiles = { + "celevator_car_floor.png", + "celevator_car_bottom_center.png", + "celevator_car_wallpaper.png^celevator_car_wall_bottom.png^celevator_car_wall_vent.png", + "celevator_cabinet_sides.png^celevator_car_side_center_overlay.png", + "celevator_cabinet_sides.png", + }, + }, + { + _position = "002", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.6,-0.5,0.5,-0.5,0.5}, + {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, + {-0.45,-0.5,0.45,0.5,0.5,0.5}, + }, + }, + tiles = { + "celevator_car_floor.png", + "celevator_car_bottom.png", + "celevator_car_wallpaper.png^celevator_car_wall_bottom.png", + "celevator_cabinet_sides.png^celevator_car_side_overlay.png", + "celevator_cabinet_sides.png", + "celevator_car_wallpaper.png^celevator_car_wall_bottom.png", + }, + }, + { + _position = "100", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.6,-0.5,0.5,-0.5,0.5}, + {0.45,-0.5,-0.5,0.5,0.5,0.5}, + {-0.5,-1.5,-0.5,0.5,-0.6,-0.45}, + }, + }, + tiles = { + "celevator_car_floor.png^celevator_door_sill_double.png", + "celevator_car_bottom.png", + "celevator_cabinet_sides.png^celevator_car_side_overlay.png", + "celevator_car_wallpaper.png^celevator_car_wall_bottom.png", + "celevator_cabinet_sides.png", + }, + }, + { + _position = "101", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.6,-0.5,0.5,-0.5,0.5}, + {0.45,-0.5,-0.5,0.5,0.5,0.5}, + }, + }, + tiles = { + "celevator_car_floor.png", + "celevator_car_bottom_center.png^[transformFX", + "celevator_cabinet_sides.png^celevator_car_side_center_overlay.png", + "celevator_car_wallpaper.png^celevator_car_wall_bottom.png^celevator_car_wall_vent.png", + "celevator_cabinet_sides.png", + }, + }, + { + _position = "102", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.6,-0.5,0.5,-0.5,0.5}, + {0.45,-0.5,-0.5,0.5,0.5,0.5}, + {-0.5,-0.5,0.45,0.45,0.5,0.5}, + }, + }, + tiles = { + "celevator_car_floor.png", + "celevator_car_bottom.png", + "celevator_cabinet_sides.png^celevator_car_side_overlay.png^[transformR90", + "celevator_car_wallpaper.png^celevator_car_wall_bottom.png", + "celevator_cabinet_sides.png", + "celevator_car_wallpaper.png^celevator_car_wall_bottom.png", + }, + }, + { + _position = "010", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, + }, + }, + tiles = { + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_car_wallpaper_2x.png^celevator_cop.png", + "celevator_cabinet_sides.png", + }, + _cop = true, + }, + { + _position = "011", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, + }, + }, + tiles = { + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_car_wallpaper.png^celevator_car_handrail_end.png", + "celevator_cabinet_sides.png^celevator_car_side_center2_overlay.png", + "celevator_cabinet_sides.png", + }, + }, + { + _position = "012", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, + {-0.45,-0.5,0.45,0.5,0.5,0.5}, + }, + }, + tiles = { + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_car_wallpaper.png^(celevator_car_handrail_end.png^[transformFX)", + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_car_wallpaper.png^celevator_car_handrail_end.png", + }, + }, + { + _position = "110", + node_box = { + type = "fixed", + fixed = { + {0.45,-0.5,-0.5,0.5,0.5,0.5}, + }, + }, + tiles = { + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_car_wallpaper.png^(celevator_car_handrail_end.png^[transformFX)", + "celevator_cabinet_sides.png", + }, + }, + { + _position = "111", + node_box = { + type = "fixed", + fixed = { + {0.45,-0.5,-0.5,0.5,0.5,0.5}, + }, + }, + tiles = { + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png^celevator_car_side_center2_overlay.png", + "celevator_car_wallpaper.png^celevator_car_handrail_center.png", + "celevator_cabinet_sides.png", + }, + }, + { + _position = "112", + node_box = { + type = "fixed", + fixed = { + {0.45,-0.5,-0.5,0.5,0.5,0.5}, + {-0.5,-0.5,0.45,0.45,0.5,0.5}, + }, + }, + tiles = { + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_car_wallpaper.png^celevator_car_handrail_end.png", + "celevator_cabinet_sides.png", + "celevator_car_wallpaper.png^(celevator_car_handrail_end.png^[transformFX)", + }, + }, + { + _position = "020", + node_box = { + type = "fixed", + fixed = { + {-0.5,0.5,-0.5,0.5,0.6,0.5}, + {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, + {-0.5,0.6,-0.4,0.5,1,-0.1}, + }, + }, + tiles = { + "celevator_cabinet_sides.png", + "celevator_car_ceiling.png", + "celevator_car_wallpaper.png", + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_dooroperator_left.png", + }, + _pi = true, + }, + { + _position = "021", + node_box = { + type = "fixed", + fixed = { + {-0.5,0.5,-0.5,0.5,0.6,0.5}, + {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, + }, + }, + tiles = { + "celevator_cabinet_sides.png^celevator_car_top_center_overlay.png", + "celevator_car_ceiling.png", + "celevator_car_wallpaper.png", + "celevator_cabinet_sides.png^celevator_car_side_center_overlay.png", + "celevator_cabinet_sides.png", + }, + _cartopbox = true, + }, + { + _position = "022", + node_box = { + type = "fixed", + fixed = { + {-0.5,0.5,-0.5,0.5,0.6,0.5}, + {-0.5,-0.5,-0.5,-0.45,0.5,0.5}, + {-0.45,-0.5,0.45,0.5,0.5,0.5}, + }, + }, + tiles = { + "celevator_cabinet_sides.png^celevator_car_top_hatch.png", + "celevator_car_ceiling.png", + "celevator_car_wallpaper.png", + "celevator_cabinet_sides.png", + "celevator_cabinet_sides.png", + "celevator_car_wallpaper.png", + }, + }, + { + _position = "120", + node_box = { + type = "fixed", + fixed = { + {-0.5,0.5,-0.5,0.5,0.6,0.5}, + {0.45,-0.5,-0.5,0.5,0.5,0.5}, + {-0.5,0.6,-0.4,0.5,1,-0.1}, + }, + }, + tiles = { + "celevator_cabinet_sides.png", + "celevator_car_ceiling.png", + "celevator_cabinet_sides.png", + "celevator_car_wallpaper.png", + "celevator_cabinet_sides.png", + "celevator_dooroperator_right.png", + }, + }, + { + _position = "121", + node_box = { + type = "fixed", + fixed = { + {-0.5,0.5,-0.5,0.5,0.6,0.5}, + {0.45,-0.5,-0.5,0.5,0.5,0.5}, + }, + }, + tiles = { + "celevator_cabinet_sides.png^celevator_car_top_center_overlay.png^[transformFX", + "celevator_car_ceiling.png", + "celevator_cabinet_sides.png^celevator_car_side_center_overlay.png", + "celevator_car_wallpaper.png", + "celevator_cabinet_sides.png", + }, + }, + { + _position = "122", + node_box = { + type = "fixed", + fixed = { + {-0.5,0.5,-0.5,0.5,0.6,0.5}, + {0.45,-0.5,-0.5,0.5,0.5,0.5}, + {-0.5,-0.5,0.45,0.45,0.5,0.5}, + }, + }, + tiles = { + "celevator_cabinet_sides.png^celevator_car_top_misc.png", + "celevator_car_ceiling.png", + "celevator_cabinet_sides.png", + "celevator_car_wallpaper.png", + "celevator_cabinet_sides.png", + "celevator_car_wallpaper.png", + }, + _tapehead = true, + }, +} + +celevator.car.register("standard",pieces,vector.new(2,3,3)) + +for x=0,1,1 do + for y=0,2,1 do + for z=0,2,1 do + minetest.register_alias(string.format("celevator:car_%d%d%d",x,y,z),string.format("celevator:car_standard_%d%d%d",x,y,z)) + end + end +end + +minetest.register_node("celevator:car_standard",{ + description = "Basic Elevator Car", + paramtype2 = "4dir", + buildable_to = true, + inventory_image = "celevator_car_inventory.png", + wield_image = "celevator_car_wield.png", + wield_scale = vector.new(1,1,10), + tiles = {"celevator_transparent.png"}, + after_place_node = function(pos,player) + if not player:is_player() then + minetest.remove_node(pos) + return true + end + local name = player:get_player_name() + local newnode = minetest.get_node(pos) + local facedir = minetest.dir_to_yaw(minetest.fourdir_to_dir(newnode.param2)) + for x=0,1,1 do + for y=0,2,1 do + for z=0,2,1 do + local offsetdesc = string.format("%dm to the right, %dm up, and %dm back",x,y,z) + local placeoffset = vector.new(x,y,z) + local placepos = vector.add(pos,vector.rotate_around_axis(placeoffset,vector.new(0,1,0),facedir)) + local replaces = minetest.get_node(placepos).name + if not (minetest.registered_nodes[replaces] and minetest.registered_nodes[replaces].buildable_to) then + minetest.chat_send_player(name,string.format("Can't place car here - position %s is blocked!",offsetdesc)) + minetest.remove_node(pos) + return true + end + if minetest.is_protected(placepos,name) and not minetest.check_player_privs(name,{protection_bypass=true}) then + minetest.chat_send_player(name,string.format("Can't place car here - position %s is protected!",offsetdesc)) + minetest.record_protection_violation(placepos,name) + minetest.remove_node(pos) + return true + end + end + end + end + for x=0,1,1 do + for y=0,2,1 do + for z=0,2,1 do + local piecename = string.format("celevator:car_standard_%d%d%d",x,y,z) + local placeoffset = vector.new(x,y,z) + local placepos = vector.add(pos,vector.rotate_around_axis(placeoffset,vector.new(0,1,0),facedir)) + minetest.set_node(placepos,{name=piecename,param2=newnode.param2}) + end + end + end + end, +}) + +minetest.register_alias("celevator:car","celevator:car_standard") + +celevator.car.types.standard.remove = function(rootpos,rootdir) + local toberemoved = { + ["celevator:car_top_box"] = true, + ["celevator:incar_pi_entity"] = true, + ["celevator:car_door"] = true, + } + for x=0,1,1 do + for y=0,2,1 do + for z=0,2,1 do + local piecename = string.format("celevator:car_standard_%d%d%d",x,y,z) + local pieceoffset = vector.new(x,y,z) + local piecepos = vector.add(rootpos,vector.rotate_around_axis(pieceoffset,vector.new(0,1,0),rootdir)) + if minetest.get_node(piecepos).name == piecename then + minetest.remove_node(piecepos) + local erefs = minetest.get_objects_inside_radius(piecepos,0.5) + for _,ref in pairs(erefs) do + if ref:get_luaentity() and toberemoved[ref:get_luaentity().name] then + ref:remove() + end + end + end + end + end + end + local cartopboxpos = vector.add(rootpos,vector.rotate_around_axis(vector.new(0,3,1),vector.new(0,1,0),rootdir)) + local erefs = minetest.get_objects_inside_radius(cartopboxpos,0.5) + for _,ref in pairs(erefs) do + if ref:get_luaentity() and toberemoved[ref:get_luaentity().name] then + ref:remove() + end + end +end diff --git a/chatcommands.lua b/chatcommands.lua new file mode 100644 index 0000000..bfd79c7 --- /dev/null +++ b/chatcommands.lua @@ -0,0 +1,181 @@ +minetest.register_chatcommand("carcall",{ + description = "Places a car call at the specified landing on the specified elevator", + params = "<car ID> <landing number>", + func = function(name,param) + local carid,landing = string.match(param,"(%d+) (%d+)") + if not (carid and tonumber(carid)) then + return false,"Invalid car ID" + end + if not (landing and tonumber(landing)) then + return false,"Invalid landing number" + end + local carinfo = minetest.deserialize(celevator.storage:get_string("car"..carid)) + if not (carinfo and carinfo.controllerpos) then + return false,"No such car or car info is missing" + end + if not celevator.controller.iscontroller(carinfo.controllerpos) then + return false,"Controller is missing" + end + if celevator.get_meta(carinfo.controllerpos):get_int("carid") ~= tonumber(carid) then + return false,"Controller found but with wrong ID" + end + if minetest.is_protected(carinfo.controllerpos,name) then + minetest.record_protection_violation(carinfo.controllerpos,name) + return false,"Controller is protected" + end + celevator.controller.run(carinfo.controllerpos,{ + type = "remotemsg", + channel = "carcall", + msg = tonumber(landing), + }) + return true,"Command sent" + end, +}) + +minetest.register_chatcommand("upcall",{ + description = "Places an up hall call at the specified landing on the specified elevator or dispatcher", + params = "<car ID> <landing number>", + func = function(name,param) + local carid,landing = string.match(param,"(%d+) (%d+)") + if not (carid and tonumber(carid)) then + return false,"Invalid car ID" + end + if not (landing and tonumber(landing)) then + return false,"Invalid landing number" + end + local carinfo = minetest.deserialize(celevator.storage:get_string("car"..carid)) + if not (carinfo and (carinfo.controllerpos or carinfo.dispatcherpos)) then + return false,"No such car or car info is missing" + end + if carinfo.controllerpos then + if not celevator.controller.iscontroller(carinfo.controllerpos) then + return false,"Controller is missing" + end + if celevator.get_meta(carinfo.controllerpos):get_int("carid") ~= tonumber(carid) then + return false,"Controller found but with wrong ID" + end + if minetest.is_protected(carinfo.controllerpos,name) then + minetest.record_protection_violation(carinfo.controllerpos,name) + return false,"Controller is protected" + end + --One of these will work depending on the mode, the other will be ignored + celevator.controller.run(carinfo.controllerpos,{ + type = "remotemsg", + channel = "upcall", + msg = tonumber(landing), + }) + celevator.controller.run(carinfo.controllerpos,{ + type = "remotemsg", + channel = "swingupcall", + msg = tonumber(landing), + }) + return true,"Command sent" + elseif carinfo.dispatcherpos then + if not celevator.dispatcher.isdispatcher(carinfo.dispatcherpos) then + return false,"Dispatcher is missing" + end + if celevator.get_meta(carinfo.dispatcherpos):get_int("carid") ~= tonumber(carid) then + return false,"Dispatcher found but with wrong ID" + end + if minetest.is_protected(carinfo.dispatcherpos,name) then + minetest.record_protection_violation(carinfo.dispatcherpos,name) + return false,"Dispatcher is protected" + end + celevator.dispatcher.run(carinfo.dispatcherpos,{ + type = "remotemsg", + channel = "upcall", + msg = tonumber(landing), + }) + return true,"Command sent" + end + end, +}) + +minetest.register_chatcommand("downcall",{ + description = "Places a down hall call at the specified landing on the specified elevator or dispatcher", + params = "<car ID> <landing number>", + func = function(name,param) + local carid,landing = string.match(param,"(%d+) (%d+)") + if not (carid and tonumber(carid)) then + return false,"Invalid car ID" + end + if not (landing and tonumber(landing)) then + return false,"Invalid landing number" + end + local carinfo = minetest.deserialize(celevator.storage:get_string("car"..carid)) + if not (carinfo and (carinfo.controllerpos or carinfo.dispatcherpos)) then + return false,"No such car or car info is missing" + end + if carinfo.controllerpos then + if not celevator.controller.iscontroller(carinfo.controllerpos) then + return false,"Controller is missing" + end + if celevator.get_meta(carinfo.controllerpos):get_int("carid") ~= tonumber(carid) then + return false,"Controller found but with wrong ID" + end + if minetest.is_protected(carinfo.controllerpos,name) then + minetest.record_protection_violation(carinfo.controllerpos,name) + return false,"Controller is protected" + end + --One of these will work depending on the mode, the other will be ignored + celevator.controller.run(carinfo.controllerpos,{ + type = "remotemsg", + channel = "dncall", + msg = tonumber(landing), + }) + celevator.controller.run(carinfo.controllerpos,{ + type = "remotemsg", + channel = "swingdncall", + msg = tonumber(landing), + }) + return true,"Command sent" + elseif carinfo.dispatcherpos then + if not celevator.dispatcher.isdispatcher(carinfo.dispatcherpos) then + return false,"Dispatcher is missing" + end + if celevator.get_meta(carinfo.dispatcherpos):get_int("carid") ~= tonumber(carid) then + return false,"Dispatcher found but with wrong ID" + end + if minetest.is_protected(carinfo.dispatcherpos,name) then + minetest.record_protection_violation(carinfo.dispatcherpos,name) + return false,"Dispatcher is protected" + end + celevator.dispatcher.run(carinfo.dispatcherpos,{ + type = "remotemsg", + channel = "dncall", + msg = tonumber(landing), + }) + return true,"Command sent" + end + end, +}) + +minetest.register_chatcommand("elevstatus",{ + description = "View the status of the specified elevator", + params = "<car ID>", + func = function(_,param) + if not (param and tonumber(param)) then + return false,"Invalid car ID" + end + local carinfo = minetest.deserialize(celevator.storage:get_string("car"..param)) + if not (carinfo and carinfo.controllerpos) then + return false,"No such car or car info is missing" + end + if not celevator.controller.iscontroller(carinfo.controllerpos) then + return false,"Controller is missing" + end + local controllermeta = celevator.get_meta(carinfo.controllerpos) + if controllermeta:get_int("carid") ~= tonumber(param) then + return false,"Controller found but with wrong ID" + end + local mem = minetest.deserialize(controllermeta:get_string("mem")) + if not mem then + return false,"Failed to load controller memory" + end + local infotext = controllermeta:get_string("infotext") + if mem.drive and mem.drive.status and mem.drive.status.vel and mem.drive.status.apos then + infotext = infotext..string.format(" - %0.02fm - %+0.02fm/s",mem.drive.status.apos,mem.drive.status.vel) + end + return true,infotext + end, +}) diff --git a/controller.lua b/controller.lua index 365cf73..2921f81 100644 --- a/controller.lua +++ b/controller.lua @@ -444,6 +444,9 @@ function celevator.controller.finish(pos,mem,changedinterrupts) celevator.drives[drivetype].pibeep(drivepos) end end + if type(mem.drive.status) == "table" then + meta:set_string("vel",tostring(mem.drive.status.vel)) + end end local node = celevator.get_node(pos) local oldmem = minetest.deserialize(meta:get_string("mem")) or {} @@ -451,6 +454,12 @@ function celevator.controller.finish(pos,mem,changedinterrupts) local olddownbuttonlights = oldmem.dncalls or {} local newupbuttonlights = mem.upcalls or {} local newdownbuttonlights = mem.dncalls or {} + if mem.params and mem.params.groupmode == "group" then + oldupbuttonlights = oldmem.swingupcalls + olddownbuttonlights = oldmem.swingdncalls + newupbuttonlights = mem.swingupcalls + newdownbuttonlights = mem.swingdncalls + end local callbuttons = carinfo.callbuttons for _,button in pairs(callbuttons) do if oldupbuttonlights[button.landing] ~= newupbuttonlights[button.landing] then @@ -636,7 +645,9 @@ end function celevator.controller.checkiqueue(dtime) for hash,iqueue in pairs(celevator.controller.iqueue) do local pos = minetest.get_position_from_hash(hash) + local noneleft = true for iid,time in pairs(iqueue) do + noneleft = false iqueue[iid] = time-dtime if iqueue[iid] < 0 then iqueue[iid] = nil @@ -646,6 +657,10 @@ function celevator.controller.checkiqueue(dtime) celevator.controller.run(pos,event) end end + if noneleft then + celevator.controller.iqueue[hash] = nil + celevator.storage:set_string("controller_iqueue",minetest.serialize(celevator.controller.iqueue)) + end end end diff --git a/controllerfw.lua b/controllerfw.lua index eeb8814..1850a1e 100644 --- a/controllerfw.lua +++ b/controllerfw.lua @@ -48,13 +48,14 @@ local modenames = { stop = "Emergency Stop", mrinspect = "Machine Room Inspection", carinspect = "Car Top Inspection", - inspconflict = "Inspection Conflict", + inspconflict = "Inspection Conflict", --No longer used but some controllers may be in it at update time fs1 = "Fire Service - Phase 1", fs2 = "Fire Service - Phase 2", fs2hold = "Fire Service - Phase 2 Hold", indep = "Independent Service", capture = "Captured", test = "Test Mode", + swing = "Swing Operation", } local doorstates = { @@ -74,6 +75,9 @@ local faultnames = { drivebadorigin = "Drive Origin Invalid", drivedoorinterlock = "Attempted to Move Doors With Car in Motion", driveoutofbounds = "Target Position Out of Bounds", + drivenomachine = "Hoist Machine Missing", + drivemachinemismatch = "Drive<->Machine ID Mismatch", + drivecontrollermismatch = "Controller<->Drive ID Mismatch", } local function drivecmd(command) @@ -93,7 +97,7 @@ local function getpos(pioffset) ret = ret+v if ret > searchpos then return k end end - return mem.params.floorheights[#mem.params.floorheights] + return #mem.params.floorheights end local function gettarget(floor) @@ -195,7 +199,7 @@ local function open() interrupt(10,"opentimeout") interrupt(nil,"closetimeout") if mem.nudging then - if mem.carstate == "normal" then + if (mem.carstate == "normal" or mem.carstate == "swing") then interrupt(0,"nudge") else mem.nudging = false @@ -228,8 +232,27 @@ if mem.params and not mem.recallto then mem.recallto = mem.params.mainlanding or if mem.params and not mem.params.inspectionspeed then mem.params.inspectionspeed = 0.2 end if mem.params and not mem.params.indepunlock then mem.params.indepunlock = {} end if mem.params and not mem.params.secoverrideusers then mem.params.secoverrideusers = {} end +if mem.params and mem.params.swingcallwhennotswing == nil then mem.params.swingcallwhennotswing = true end if not mem.editinguser then mem.editinguser = 1 end +if mem.params and #mem.params.floornames < 2 then + mem.params.floornames = {"1","2","3"} + mem.params.floorheights = {5,5,5} + mem.carstate = "bfdemand" + if mem.doorstate == "closed" then + drivecmd({ + command = "setmaxvel", + maxvel = mem.params.contractspeed, + }) + drivecmd({command = "resetpos"}) + interrupt(0.1,"checkdrive") + mem.carmotion = true + juststarted = true + else + close() + end +end + if event.type == "program" then mem.carstate = "uninit" mem.editingfloor = 1 @@ -275,6 +298,7 @@ if event.type == "program" then inspectionspeed = 0.2, indepunlock = {}, secoverrideusers = {}, + swingcallwhennotswing = true, } end elseif event.type == "ui" then @@ -338,7 +362,7 @@ elseif event.type == "ui" then elseif event.fields.add then table.insert(mem.params.floorheights,5) table.insert(mem.params.floornames,tostring(#mem.params.floornames+1)) - elseif event.fields.remove then + elseif event.fields.remove and #mem.params.floornames > 2 then table.remove(mem.params.floorheights,mem.editingfloor) table.remove(mem.params.floornames,mem.editingfloor) mem.editingfloor = math.max(1,mem.editingfloor-1) @@ -428,16 +452,17 @@ elseif event.type == "ui" then and (mem.carstate == "normal" or mem.carstate == "test" or mem.carstate == "capture" - or mem.carstate == "indep") + or mem.carstate == "indep" + or mem.carstate == "swing") then mem.carcalls[i] = true - elseif event.fields[string.format("upcall%d",i)] and mem.carstate == "normal" and not mem.capturesw then + elseif event.fields[string.format("upcall%d",i)] and (mem.carstate == "normal" or mem.carstate == "swing") and not mem.capturesw then if mem.params.groupmode == "group" then mem.swingupcalls[i] = true else mem.upcalls[i] = true end - elseif event.fields[string.format("downcall%d",i)] and mem.carstate == "normal" and not mem.capturesw then + elseif event.fields[string.format("downcall%d",i)] and (mem.carstate == "normal" or mem.carstate == "swing") and not mem.capturesw then if mem.params.groupmode == "group" then mem.swingdncalls[i] = true else @@ -503,6 +528,9 @@ elseif event.type == "ui" then if event.fields.indepunlock then mem.params.indepunlock[mem.editingfloor] = (event.fields.indepunlock == "true") end + if event.fields.swingcallwhennotswing then + mem.params.swingcallwhennotswing = (event.fields.swingcallwhennotswing == "true") + end if event.fields.save then mem.screenstate = "parameters" elseif event.fields.floor then @@ -556,7 +584,7 @@ elseif event.type == "ui" then end elseif event.iid == "opened" and mem.doorstate == "opening" then mem.doorstate = "open" - if mem.carstate == "normal" then + if (mem.carstate == "normal" or mem.carstate == "swing") then interrupt(mem.params.doortimer,"close") end elseif event.iid == "close" and mem.doorstate == "open" then @@ -578,9 +606,9 @@ elseif event.iid == "closed" and (mem.doorstate == "closing" or mem.doorstate == mem.carmotion = true juststarted = true end -elseif event.type == "callbutton" and mem.carstate == "normal" then +elseif event.type == "callbutton" and (mem.carstate == "normal" or mem.carstate == "swing") then if mem.doorstate == "closed" or mem.direction ~= event.dir or getpos() ~= event.landing then - if mem.params.groupmode == "group" then + if mem.params.groupmode == "group" and not (mem.carstate == "normal" and not mem.params.swingcallwhennotswing) then if event.dir == "up" and event.landing >= 1 and event.landing < #mem.params.floornames then mem.swingupcalls[event.landing] = true elseif event.dir == "down" and event.landing > 1 and event.landing <= #mem.params.floornames then @@ -601,10 +629,15 @@ elseif event.type == "callbutton" and mem.carstate == "normal" then elseif event.iid == "checkopen" then if mem.drive.status.doorstate == "open" then interrupt(0,"opened") - if mem.carstate == "normal" or mem.carstate == "indep" or mem.carstate == "fs1" or mem.carstate == "fs2" or mem.carstate == "fs2hold" then + if mem.carstate == "normal" + or mem.carstate == "indep" + or mem.carstate == "fs1" + or mem.carstate == "fs2" + or mem.carstate == "fs2hold" + or mem.carstate == "swing" then interrupt(nil,"opentimeout") end - if mem.carstate == "normal" and not mem.interrupts.nudge and mem.params.nudgetimer > 0 then + if (mem.carstate == "normal" or mem.carstate == "swing") and not mem.interrupts.nudge and mem.params.nudgetimer > 0 then interrupt(mem.params.nudgetimer,"nudge") end else @@ -625,7 +658,7 @@ elseif event.iid == "closetimeout" then fault("closetimeout",true) elseif event.type == "cop" then local fields = event.fields - if mem.carstate == "normal" or mem.carstate == "indep" or mem.carstate == "fs2" then + if mem.carstate == "normal" or mem.carstate == "indep" or mem.carstate == "fs2" or mem.carstate == "swing" then for k,v in pairs(fields) do if string.sub(k,1,7) == "carcall" then local landing = tonumber(string.sub(k,8,-1)) @@ -649,7 +682,7 @@ elseif event.type == "cop" then end if v and landing and landing >= 1 and landing <= #mem.params.floorheights and secok then if getpos() == landing then - if mem.carstate == "normal" or mem.carstate == "indep" then + if mem.carstate == "normal" or mem.carstate == "indep" or mem.carstate == "swing" then if mem.doorstate == "closing" and not mem.nudging then open() elseif mem.doorstate == "open" then @@ -745,6 +778,12 @@ elseif event.type == "cartopbox" then }) end elseif event.type == "dispatchermsg" then + local swingstateok = false + if mem.carstate == "normal" then + swingstateok = mem.params.swingcallwhennotswing + elseif mem.carstate == "swing" then + swingstateok = true + end if event.channel == "pairrequest" and mem.screenstate == "oobe_dispatcherconnect" then mem.params.floornames = event.msg.floornames mem.params.floorheights = event.msg.floorheights @@ -794,11 +833,11 @@ elseif event.type == "dispatchermsg" then mem.groupupcalls[event.msg] = nil elseif event.channel == "groupdncancel" then mem.groupdncalls[event.msg] = nil - elseif event.channel == "swingupcall" and mem.carstate == "normal" then + elseif event.channel == "swingupcall" and swingstateok then mem.swingupcalls[event.msg] = true - elseif event.channel == "swingdncall" and mem.carstate == "normal" then + elseif event.channel == "swingdncall" and swingstateok then mem.swingdncalls[event.msg] = true - elseif event.channel == "carcall" and mem.carstate == "normal" then + elseif event.channel == "carcall" and (mem.carstate == "normal" or mem.carstate == "swing") then mem.carcalls[event.msg] = true send(event.source,"status",mem) elseif event.channel == "fs1switch" then @@ -810,38 +849,51 @@ elseif event.type == "dispatchermsg" then if not event.msg then mem.flashfirehat = false end end elseif event.type == "remotemsg" then + local swingstateok = false + if mem.carstate == "normal" then + swingstateok = mem.params.swingcallwhennotswing + elseif mem.carstate == "swing" then + swingstateok = true + end if event.channel == "groupupcall" and mem.carstate == "normal" then mem.groupupcalls[event.msg] = true elseif event.channel == "groupdncall" and mem.carstate == "normal" then mem.groupdncalls[event.msg] = true - elseif event.channel == "swingupcall" and mem.carstate == "normal" then + elseif event.channel == "swingupcall" and swingstateok then mem.swingupcalls[event.msg] = true - elseif event.channel == "swingdncall" and mem.carstate == "normal" then + elseif event.channel == "swingdncall" and swingstateok then mem.swingdncalls[event.msg] = true - elseif event.channel == "upcall" and mem.carstate == "normal" then + elseif event.channel == "upcall" and (mem.carstate == "normal" or mem.carstate == "swing") then mem.upcalls[event.msg] = true - elseif event.channel == "dncall" and mem.carstate == "normal" then + elseif event.channel == "dncall" and (mem.carstate == "normal" or mem.carstate == "swing") then mem.dncalls[event.msg] = true elseif event.channel == "groupupcancel" then mem.groupupcalls[event.msg] = nil elseif event.channel == "groupdncancel" then mem.groupdncalls[event.msg] = nil - elseif event.channel == "carcall" and mem.carstate == "normal" then + elseif event.channel == "carcall" and (mem.carstate == "normal" or mem.carstate == "swing") then mem.carcalls[event.msg] = true elseif event.channel == "security" and type(event.msg.floor) == "number" then if mem.params.floornames[event.msg.floor] and event.msg.floor ~= (mem.params.mainlanding or 1) then mem.params.carcallsecurity[event.msg.floor] = event.msg.mode end + elseif event.channel == "swing" then + mem.swing = event.msg + if mem.carstate == "normal" and event.msg then + mem.carstate = "swing" + elseif mem.carstate == "swing" and not event.msg then + mem.carstate = "normal" + end end elseif event.type == "lightcurtain" and not mem.nudging then - if mem.carstate == "normal" or mem.carstate == "indep" then + if mem.carstate == "normal" or mem.carstate == "indep" or mem.carstate == "swing" then if mem.doorstate == "closing" then open() - elseif mem.doorstate == "open" and mem.carstate == "normal" then + elseif mem.doorstate == "open" and (mem.carstate == "normal" or mem.carstate == "swing") then interrupt(mem.params.doortimer,"close") end end -elseif event.iid == "nudge" and mem.carstate == "normal" then +elseif event.iid == "nudge" and (mem.carstate == "normal" or mem.carstate == "swing") then mem.nudging = true if mem.doorstate == "open" then close(true) @@ -901,19 +953,6 @@ elseif mem.controllerstopsw or mem.screenstate == "floortable" or mem.screenstat mem.direction = nil interrupt(nil,"opentimeout") interrupt(nil,"closetimeout") -elseif mem.controllerinspectsw and mem.cartopinspectsw then - mem.carstate = "inspconflict" - mem.carcalls = {} - mem.upcalls = {} - mem.dncalls = {} - mem.swingupcalls = {} - mem.swingdncalls = {} - mem.groupupcalls = {} - mem.groupdncalls = {} - mem.direction = nil - drivecmd({command="estop"}) - interrupt(nil,"opentimeout") - interrupt(nil,"closetimeout") elseif mem.controllerinspectsw and not mem.cartopinspectsw then mem.carstate = "mrinspect" mem.carcalls = {} @@ -927,7 +966,7 @@ elseif mem.controllerinspectsw and not mem.cartopinspectsw then interrupt(nil,"opentimeout") interrupt(nil,"closetimeout") if oldstate ~= "mrinspect" then drivecmd({command="estop"}) end -elseif mem.cartopinspectsw and not mem.controllerinspectsw then +elseif mem.cartopinspectsw then mem.carstate = "carinspect" mem.carcalls = {} mem.upcalls = {} @@ -1022,9 +1061,9 @@ elseif mem.indsw then if oldstate == "stop" or oldstate == "mrinspect" or oldstate == "fault" then mem.carstate = "resync" gotofloor(getpos()) - elseif oldstate == "normal" and (mem.doorstate == "closed" or mem.doorstate == "closing") and not (mem.carmotion or juststarted) then + elseif (oldstate == "normal" or oldstate == "swing") and (mem.doorstate == "closed" or mem.doorstate == "closing") and not (mem.carmotion or juststarted) then open() - elseif oldstate == "normal" and mem.doorstate == "open" then + elseif (oldstate == "normal" or oldstate == "swing") and mem.doorstate == "open" then interrupt(nil,"close") end elseif mem.testsw then @@ -1060,14 +1099,18 @@ else if (oldstate == "fs1" or oldstate == "fs2" or oldstate == "fs2hold") and mem.doorstate == "open" then interrupt(mem.params.doortimer,"close") end - mem.carstate = "normal" + mem.carstate = (mem.swing and "swing" or "normal") elseif oldstate == "indep" then - mem.carstate = "normal" + mem.carstate = (mem.swing and "swing" or "normal") if mem.doorstate == "open" then interrupt(mem.params.doortimer,"close") end end end -if mem.carstate == "normal" and oldstate ~= "normal" and mem.doorstate ~= "closed" and mem.params.nudgetimer > 0 and not mem.interrupts.nudge then +if (mem.carstate == "normal" or mem.carstate == "swing") + and oldstate ~= "normal" and oldstate ~= "swing" + and mem.doorstate ~= "closed" + and mem.params.nudgetimer > 0 + and not mem.interrupts.nudge then interrupt(mem.params.nudgetimer,"nudge") elseif mem.carstate ~= "normal" and oldstate == "normal" then interrupt(nil,"nudge") @@ -1079,7 +1122,7 @@ if mem.carmotion then interrupt(0.1,"checkdrive") else local hallcall = mem.upcalls[getpos()] or mem.dncalls[getpos()] - if mem.carstate == "normal" or mem.carstate == "indep" or mem.carstate == "fs1" or mem.carstate == "fs2" then + if mem.carstate == "normal" or mem.carstate == "indep" or mem.carstate == "fs1" or mem.carstate == "fs2" or mem.carstate == "swing" then mem.carcalls[getpos()] = nil if mem.direction == "up" then mem.upcalls[getpos()] = nil @@ -1141,7 +1184,7 @@ if mem.carmotion then elseif mem.capturesw then mem.carstate = "capture" else - mem.carstate = "normal" + mem.carstate = (mem.swing and "swing" or "normal") end end end @@ -1164,6 +1207,7 @@ local canprocesscalls = { test = true, indep = true, fs2 = true, + swing = true, } if canprocesscalls[mem.carstate] and mem.doorstate == "closed" then @@ -1212,14 +1256,14 @@ if canprocesscalls[mem.carstate] and mem.doorstate == "closed" then gotofloor(gethighestdowncall()) end end - if mem.carstate == "normal" and mem.capturesw and not mem.direction then + if (mem.carstate == "normal" or mem.carstate == "swing") and mem.capturesw and not mem.direction then mem.upcalls = {} mem.dncalls = {} mem.carstate = "capture" elseif mem.carstate == "capture" and mem.direction then - mem.carstate = "normal" + mem.carstate = (mem.swing and "swing" or "normal") end - elseif (mem.carstate == "normal" or mem.carstate == "capture" or mem.carstate == "test") and mem.carmotion then + elseif (mem.carstate == "normal" or mem.carstate == "capture" or mem.carstate == "test" or mem.carstate == "swing") and mem.carmotion then if mem.drive.status.vel > 0 then local nextup = getnextcallabove("up") if nextup then @@ -1471,6 +1515,7 @@ elseif mem.screenstate == "carcallsecurity" then fs(minetest.formspec_escape(string.format("%s - %s",mem.params.floornames[i],secmode))..(i==1 and "" or ",")) end fs(";"..tostring(#mem.params.floornames-mem.editingfloor+1)..";false]") + fs("checkbox[1,9.5;swingcallwhennotswing;Allow Swing Calls When Not In Swing Operation;"..tostring(mem.params.swingcallwhennotswing).."]") if mem.editingfloor ~= (mem.params.mainlanding or 1) then fs("dropdown[8,2;4,1;secmode;Security Disabled,Authorized Users Only,Locked;") if mem.params.carcallsecurity[mem.editingfloor] == "auth" then @@ -1533,7 +1578,7 @@ local hidepi = { } if hidepi[mem.carstate] then mem.pifloor = "--" end -if mem.pifloor ~= oldpifloor and mem.carstate == "normal" then +if mem.pifloor ~= oldpifloor and (mem.carstate == "normal" or mem.carstate == "swing") then drivecmd({command="pibeep"}) end @@ -1544,6 +1589,7 @@ local arrowenabled = { indep = true, capture = true, test = true, + swing = true, } mem.piuparrow = mem.drive.status.vel > 0 and arrowenabled[mem.carstate] mem.pidownarrow = mem.drive.status.vel < 0 and arrowenabled[mem.carstate] @@ -1553,9 +1599,9 @@ mem.flash_is = mem.carstate == "indep" mem.flash_blank = mem.nudging mem.lanterns = {} -if mem.carstate == "normal" and (mem.doorstate == "open" or mem.doorstate == "opening") then +if (mem.carstate == "normal" or mem.carstate == "swing") and (mem.doorstate == "open" or mem.doorstate == "opening") then mem.lanterns[getpos()] = mem.direction -elseif mem.carstate == "normal" and mem.doorstate == "closed" and mem.drive.status then +elseif (mem.carstate == "normal" or mem.carstate == "swing") and mem.doorstate == "closed" and mem.drive.status then local ring = false if mem.drive.status.vel > 0 and mem.drive.status.neareststop > mem.drive.status.dpos then ring = true @@ -1,81 +1,235 @@ +local xcompat_available = minetest.global_exists("xcompat") +local m = xcompat_available and table.copy(xcompat.materials) or {} + +-- provide required materials if xcompat is missing +if not xcompat_available then + if minetest.get_modpath("default") then + m.empty_bucket = "bucket:bucket_empty" + m.iron_lump = "default:iron_lump" + m.steel_ingot = "default:steel_ingot" + m.glass = "default:glass" + m.sandstone = "default:sandstone" + m.copper_ingot = "default:copper_ingot" + m.copper_block = "default:copperblock" + m.gold_block = "default:goldblock" + m.tin_block = "default:tinblock" + m.mese = "default:mese" + m.pick_steel = "default:pick_steel" + m.torch = "default:torch" + elseif minetest.get_modpath("mcl_core") then + m.empty_bucket = "mcl_buckets:bucket_empty" + m.iron_lump = "mcl_raw_ores:raw_iron" + m.steel_ingot = "mcl_core:iron_ingot" + m.glass = "mcl_core:glass" + m.sandstone = "mcl_core:sandstone" + m.copper_ingot = "mcl_copper:copper_ingot" + m.copper_block = "mcl_copper:block" + m.gold_block = "mcl_core:goldblock" + m.tin_block = "mcl_core:ironblock" + m.mese = "mesecons_torch:redstoneblock" -- mcla still carries this as an alias + m.pick_steel = "mcl_core:pick_steel" + m.torch = "mcl_torches:torch" + else + minetest.log("warning","[celevator] Unsupported game and xcompat not found, not registering craft recipes") + return + end + if minetest.get_modpath("dye") then + m.dye_black = "dye:black" + m.dye_blue = "dye:blue" + m.dye_red = "dye:red" + m.dye_green = "dye:green" + elseif minetest.get_modpath("mcl_dyes") then + m.dye_black = "mcl_dyes:black" + m.dye_blue = "mcl_dyes:blue" + m.dye_red = "mcl_dyes:red" + m.dye_green = "mcl_dyes:green" + elseif minetest.get_modpath("mcl_dye") then + m.dye_black = "mcl_dye:black" + m.dye_blue = "mcl_dye:blue" + m.dye_red = "mcl_dye:red" + m.dye_green = "mcl_dye:green" + end +end + +if minetest.get_modpath("basic_materials") then + m.steel_bar = "basic_materials:steel_bar" + m.steel_strip = "basic_materials:steel_strip" + m.steel_gear = "basic_materials:gear_steel" + m.plastic_sheet = "basic_materials:plastic_sheet" + m.silicon = "basic_materials:silicon" + m.copper_wire = "basic_materials:copper_wire" + m.ic = "basic_materials:ic" + m.motor = "basic_materials:motor" +else + m.steel_bar = m.gold_block + m.steel_strip = m.gold_block + m.steel_gear = m.gold_block + m.plastic_sheet = m.tin_block + m.silicon = m.sandstone + m.copper_wire = m.copper_ingot + m.ic = m.copper_block + m.motor = m.pick_steel +end + +-- vl mesecons has colored lightstone with different naming scheme +local mc_lightstone = minetest.registered_nodes["mesecons_lightstone:lightstone_blue_off"] +local vl_lightstone = minetest.registered_nodes["mesecons_lightstone:lightstone_off_blue"] +if mc_lightstone then + -- real mesecons_lightstone + m.lightstone_blue = "mesecons_lightstone:lightstone_blue_off" + m.lightstone_green = "mesecons_lightstone:lightstone_green_off" + m.lightstone_red = "mesecons_lightstone:lightstone_red_off" + m.lightstone_white = "mesecons_lightstone:lightstone_white_off" + m.lightstone_extra = "" +elseif vl_lightstone then + -- vl mesecons_lightstone + m.lightstone_blue = "mesecons_lightstone:lightstone_off_blue" + m.lightstone_green = "mesecons_lightstone:lightstone_off_green" + m.lightstone_red = "mesecons_lightstone:lightstone_off_red" + m.lightstone_white = "mesecons_lightstone:lightstone_off_white" + m.lightstone_extra = "" +else + m.lightstone_blue = m.dye_blue + m.lightstone_green = m.dye_green + m.lightstone_red = m.dye_red + m.lightstone_white = m.torch + m.lightstone_extra = m.torch +end + +local mesecons_button = minetest.registered_nodes["mesecons_button:button_off"] +if mesecons_button then + -- real mesecons + m.button = mesecons_button.name +elseif minetest.get_modpath("mcl_core") then + m.button = "group:button" +else + m.button = m.mese +end + +if minetest.get_modpath("mesecons_switch") then + -- real mesecons + m.switch = "mesecons_switch:mesecon_switch_off" +elseif minetest.get_modpath("mcl_lever") then + -- mcla + m.switch = "mcl_lever:lever_off" +elseif minetest.get_modpath("mesecons_walllever") then + -- other mcl + m.switch = "mesecons_walllever:wall_lever_off" +else + m.switch = m.mese +end + +if minetest.get_modpath("digilines") then + m.lcd = "digilines:lcd" +else + m.lcd = m.mese +end + minetest.register_craft({ output = "celevator:buffer_oil", recipe = { - {"","basic_materials:steel_bar",""}, - {"default:steel_ingot","bucket:bucket_empty","default:steel_ingot"}, - {"default:steel_ingot","default:steel_ingot","default:steel_ingot"}, + {"",m.steel_bar,""}, + {m.steel_ingot,m.empty_bucket,m.steel_ingot}, + {m.steel_ingot,m.steel_ingot,m.steel_ingot}, }, }) minetest.register_craft({ output = "celevator:buffer_rubber", recipe = { - {"basic_materials:plastic_sheet","dye:black","basic_materials:plastic_sheet"}, - {"","default:steel_ingot",""}, - {"default:steel_ingot","default:steel_ingot","default:steel_ingot"}, + {m.plastic_sheet,m.dye_black,m.plastic_sheet}, + {"",m.steel_ingot,""}, + {m.steel_ingot,m.steel_ingot,m.steel_ingot}, }, }) minetest.register_craft({ output = "celevator:callbutton_both", recipe = { - {"basic_materials:steel_strip","mesecons_lightstone:lightstone_blue_off","mesecons_button:button_off"}, - {"basic_materials:steel_strip","",""}, - {"basic_materials:steel_strip","mesecons_lightstone:lightstone_blue_off","mesecons_button:button_off"}, + {m.steel_strip,m.lightstone_blue,m.button}, + {m.steel_strip,m.lightstone_extra,""}, + {m.steel_strip,m.lightstone_blue,m.button}, }, }) minetest.register_craft({ output = "celevator:callbutton_up", recipe = { - {"basic_materials:steel_strip","mesecons_lightstone:lightstone_blue_off","mesecons_button:button_off"}, - {"basic_materials:steel_strip","",""}, - {"basic_materials:steel_strip","",""}, + {m.steel_strip,m.lightstone_blue,m.button}, + {m.steel_strip,m.lightstone_extra,""}, + {m.steel_strip,"",""}, }, }) minetest.register_craft({ output = "celevator:callbutton_down", recipe = { - {"basic_materials:steel_strip","",""}, - {"basic_materials:steel_strip","",""}, - {"basic_materials:steel_strip","mesecons_lightstone:lightstone_blue_off","mesecons_button:button_off"}, + {m.steel_strip,"",""}, + {m.steel_strip,m.lightstone_extra,""}, + {m.steel_strip,m.lightstone_blue,m.button}, + }, +}) + +minetest.register_craft({ + output = "celevator:car_standard", + recipe = { + {m.steel_ingot,m.steel_ingot,m.steel_ingot}, + {m.button,"celevator:hwdoor_glass",m.steel_ingot}, + {m.switch,m.steel_ingot,m.steel_ingot}, + }, +}) + +minetest.register_craft({ + output = "celevator:car_glassback", + recipe = { + {m.steel_ingot,m.steel_ingot,m.steel_ingot}, + {m.button,"celevator:hwdoor_glass",m.glass}, + {m.switch,m.steel_ingot,m.steel_ingot}, + }, +}) + +minetest.register_craft({ + output = "celevator:car_metal", + recipe = { + {"",m.steel_strip,""}, + {m.steel_strip,"celevator:car_standard",m.steel_strip}, + {"",m.steel_strip,""}, }, }) minetest.register_craft({ - output = "celevator:car", + output = "celevator:car_metal_glassback", recipe = { - {"default:steel_ingot","default:steel_ingot","default:steel_ingot"}, - {"mesecons_button:button_off","celevator:hwdoor_glass","default:steel_ingot"}, - {"mesecons_switch:mesecon_switch_off","default:steel_ingot","default:steel_ingot"}, + {"",m.steel_strip,""}, + {m.steel_strip,"celevator:car_glassback",m.steel_strip}, + {"",m.steel_strip,""}, }, }) minetest.register_craft({ output = "celevator:controller", recipe = { - {"basic_materials:steel_strip","basic_materials:ic","basic_materials:steel_strip"}, - {"basic_materials:steel_strip","basic_materials:ic","basic_materials:steel_strip"}, - {"basic_materials:steel_strip","default:steel_ingot","basic_materials:steel_strip"}, + {m.steel_strip,m.ic,m.steel_strip}, + {m.steel_strip,m.ic,m.steel_strip}, + {m.steel_strip,m.steel_ingot,m.steel_strip}, }, }) minetest.register_craft({ output = "celevator:dispatcher", recipe = { - {"basic_materials:steel_strip","basic_materials:ic","basic_materials:steel_strip"}, - {"basic_materials:steel_strip","basic_materials:ic","basic_materials:steel_strip"}, - {"basic_materials:steel_strip","basic_materials:steel_strip","basic_materials:steel_strip"}, + {m.steel_strip,m.ic,m.steel_strip}, + {m.steel_strip,m.ic,m.steel_strip}, + {m.steel_strip,m.steel_strip,m.steel_strip}, }, }) minetest.register_craft({ output = "celevator:drive", recipe = { - {"basic_materials:silicon","basic_materials:steel_strip","basic_materials:silicon"}, - {"basic_materials:silicon","basic_materials:ic","basic_materials:silicon"}, - {"basic_materials:silicon","basic_materials:steel_strip","basic_materials:silicon"}, + {m.silicon,m.steel_strip,m.silicon}, + {m.silicon,m.ic,m.silicon}, + {m.silicon,m.steel_strip,m.silicon}, }, }) @@ -83,8 +237,8 @@ minetest.register_craft({ output = "celevator:digilines_io", recipe = { {"","",""}, - {"","basic_materials:ic",""}, - {"digilines:wire_std_00000000","basic_materials:steel_strip","digilines:wire_std_00000000"}, + {"",m.ic,""}, + {"digilines:wire_std_00000000",m.steel_strip,"digilines:wire_std_00000000"}, }, }) @@ -92,8 +246,8 @@ minetest.register_craft({ output = "celevator:mesecons_input_off", recipe = { {"","",""}, - {"","basic_materials:ic",""}, - {"mesecons:wire_00000000_off","basic_materials:steel_strip","basic_materials:steel_strip"}, + {"",m.ic,""}, + {"mesecons:wire_00000000_off",m.steel_strip,m.steel_strip}, }, }) @@ -101,69 +255,78 @@ minetest.register_craft({ output = "celevator:mesecons_output_off", recipe = { {"","",""}, - {"","basic_materials:ic",""}, - {"basic_materials:steel_strip","basic_materials:steel_strip","mesecons:wire_00000000_off"}, + {"",m.ic,""}, + {m.steel_strip,m.steel_strip,"mesecons:wire_00000000_off"}, }, }) minetest.register_craft({ output = "celevator:fs1switch_off", recipe = { - {"basic_materials:steel_strip","mesecons_lightstone:lightstone_red_off",""}, - {"basic_materials:steel_strip","mesecons_switch:mesecon_switch_off","dye:red"}, - {"basic_materials:steel_strip","",""}, + {m.steel_strip,m.lightstone_red,m.lightstone_extra}, + {m.steel_strip,m.switch,m.dye_red}, + {m.steel_strip,"",""}, }, }) minetest.register_craft({ output = "celevator:guide_rail 10", recipe = { - {"basic_materials:steel_strip","default:steel_ingot","basic_materials:steel_strip"}, - {"basic_materials:steel_strip","default:steel_ingot","basic_materials:steel_strip"}, - {"basic_materials:steel_strip","default:steel_ingot","basic_materials:steel_strip"}, + {m.steel_strip,m.steel_ingot,m.steel_strip}, + {m.steel_strip,m.steel_ingot,m.steel_strip}, + {m.steel_strip,m.steel_ingot,m.steel_strip}, }, }) minetest.register_craft({ output = "celevator:guide_rail_bracket", recipe = { - {"basic_materials:steel_strip","celevator:guide_rail","basic_materials:steel_strip"}, + {m.steel_strip,"celevator:guide_rail",m.steel_strip}, }, }) minetest.register_craft({ output = "celevator:hwdoor_glass", recipe = { - {"basic_materials:steel_bar","basic_materials:steel_bar","basic_materials:steel_bar"}, - {"default:glass","basic_materials:steel_bar","default:glass"}, - {"basic_materials:steel_bar","basic_materials:steel_bar","basic_materials:steel_bar"}, + {m.steel_bar,m.steel_bar,m.steel_bar}, + {m.glass,m.steel_bar,m.glass}, + {m.steel_bar,m.steel_bar,m.steel_bar}, + }, +}) + +minetest.register_craft({ + output = "celevator:hwdoor_steel", + recipe = { + {m.steel_bar,m.steel_bar,m.steel_bar}, + {m.steel_strip,m.steel_bar,m.steel_strip}, + {m.steel_bar,m.steel_bar,m.steel_bar}, }, }) minetest.register_craft({ output = "celevator:lantern_up", recipe = { - {"basic_materials:steel_strip",""}, - {"basic_materials:steel_strip","mesecons_lightstone:lightstone_green_off"}, - {"basic_materials:steel_strip",""}, + {m.steel_strip,m.lightstone_green}, + {m.steel_strip,m.lightstone_extra}, + {m.steel_strip,""}, }, }) minetest.register_craft({ output = "celevator:lantern_down", recipe = { - {"basic_materials:steel_strip",""}, - {"basic_materials:steel_strip","mesecons_lightstone:lightstone_red_off"}, - {"basic_materials:steel_strip",""}, + {m.steel_strip,""}, + {m.steel_strip,m.lightstone_extra}, + {m.steel_strip,m.lightstone_red}, }, }) minetest.register_craft({ output = "celevator:lantern_both", recipe = { - {"basic_materials:steel_strip","mesecons_lightstone:lightstone_green_off"}, - {"basic_materials:steel_strip",""}, - {"basic_materials:steel_strip","mesecons_lightstone:lightstone_red_off"}, + {m.steel_strip,m.lightstone_green}, + {m.steel_strip,m.lightstone_extra}, + {m.steel_strip,m.lightstone_red}, }, }) @@ -218,18 +381,18 @@ minetest.register_craft({ minetest.register_craft({ output = "celevator:machine", recipe = { - {"basic_materials:gear_steel","basic_materials:copper_wire",""}, - {"basic_materials:steel_bar","basic_materials:steel_bar","basic_materials:motor"}, - {"default:steel_ingot","default:steel_ingot","default:steel_ingot"}, + {m.steel_gear,m.copper_wire,""}, + {m.steel_bar,m.steel_bar,m.motor}, + {m.steel_ingot,m.steel_ingot,m.steel_ingot}, }, }) minetest.register_craft({ output = "celevator:pi", recipe = { - {"basic_materials:steel_strip",""}, - {"mesecons_lightstone:lightstone_red_off","digilines:lcd"}, - {"basic_materials:steel_strip",""}, + {m.steel_strip,m.lightstone_extra}, + {m.lightstone_red,m.lcd}, + {m.steel_strip,m.lightstone_extra}, }, }) @@ -263,9 +426,9 @@ minetest.register_craft({ minetest.register_craft({ output = "celevator:tape 15", recipe = { - {"basic_materials:steel_strip","","basic_materials:steel_strip"}, - {"basic_materials:steel_strip","basic_materials:steel_strip","basic_materials:steel_strip"}, - {"basic_materials:steel_strip","","basic_materials:steel_strip"}, + {m.steel_strip,"",m.steel_strip}, + {m.steel_strip,m.steel_strip,m.steel_strip}, + {m.steel_strip,"",m.steel_strip}, }, }) @@ -274,8 +437,8 @@ minetest.register_craft({ type = "shapeless", recipe = { "celevator:tape", - "default:iron_lump", - "basic_materials:plastic_sheet", + m.iron_lump, + m.plastic_sheet, }, }) @@ -284,15 +447,32 @@ minetest.register_craft({ type = "shapeless", recipe = { "celevator:tape", - "basic_materials:steel_strip", + m.steel_strip, }, }) minetest.register_craft({ output = "celevator:dbdkiosk", recipe = { - {"basic_materials:steel_strip","basic_materials:ic","default:glass"}, - {"basic_materials:steel_strip","mesecons_lightstone:lightstone_white_off","default:glass"}, - {"basic_materials:steel_strip","","default:glass"}, + {m.steel_strip,m.ic,m.glass}, + {m.steel_strip,m.lightstone_white,m.glass}, + {m.steel_strip,"",m.glass}, + }, +}) + +minetest.register_craft({ + output = "celevator:genericswitch", + recipe = { + {m.steel_strip,"",""}, + {m.steel_strip,m.switch,m.dye_black}, + {m.steel_strip,"",""}, + }, +}) + +minetest.register_craft({ + output = "celevator:governor", + recipe = { + {m.steel_strip,m.steel_bar,m.button}, + {m.steel_strip,m.steel_gear,m.steel_strip}, }, }) diff --git a/decorations.lua b/decorations.lua index 847c06a..7c408e4 100644 --- a/decorations.lua +++ b/decorations.lua @@ -304,7 +304,7 @@ end minetest.register_abm({ label = "Spawn tapeheads", - nodenames = {"celevator:car_122"}, + nodenames = {"group:_celevator_car_spawnstapehead"}, neighbors = {"celevator:tape","celevator:tape_magnets","celevator:tape_bracket"}, interval = 1, chance = 1, diff --git a/digilines.lua b/digilines.lua index 4b30345..8f5c220 100644 --- a/digilines.lua +++ b/digilines.lua @@ -158,6 +158,18 @@ local function handledigilines(pos,node,channel,msg) celevator.controller.run(carinfo.controllerpos,{ type = "mrsmoke", }) + elseif msg.command == "swingon" then + celevator.controller.run(carinfo.controllerpos,{ + type = "remotemsg", + channel = "swing", + msg = true, + }) + elseif msg.command == "swingoff" then + celevator.controller.run(carinfo.controllerpos,{ + type = "remotemsg", + channel = "swing", + msg = false, + }) end end end diff --git a/dispatcher.lua b/dispatcher.lua index a8bcf1c..02533ff 100644 --- a/dispatcher.lua +++ b/dispatcher.lua @@ -422,7 +422,9 @@ end function celevator.dispatcher.checkiqueue(dtime) for hash,iqueue in pairs(celevator.dispatcher.iqueue) do local pos = minetest.get_position_from_hash(hash) + local noneleft = true for iid,time in pairs(iqueue) do + noneleft = false iqueue[iid] = time-dtime if iqueue[iid] < 0 then iqueue[iid] = nil @@ -432,6 +434,10 @@ function celevator.dispatcher.checkiqueue(dtime) celevator.dispatcher.run(pos,event) end end + if noneleft then + celevator.dispatcher.iqueue[hash] = nil + celevator.storage:set_string("dispatcher_iqueue",minetest.serialize(celevator.dispatcher.iqueue)) + end end end diff --git a/dispatcherfw.lua b/dispatcherfw.lua index 25ad4f8..9b0a23b 100644 --- a/dispatcherfw.lua +++ b/dispatcherfw.lua @@ -300,6 +300,27 @@ local function fs(element) mem.formspec = mem.formspec..element end +if mem.params and #mem.params.floornames < 2 then + mem.params.floorheights = {5,5,5} + mem.params.floornames = {"1","2","3"} + for _,carid in ipairs(mem.params.carids) do + local floornames = {} + local floorheights = {} + for i=1,#mem.params.floornames,1 do + if mem.params.floorsserved[carid][i] then + table.insert(floornames,mem.params.floornames[i]) + table.insert(floorheights,mem.params.floorheights[i]) + elseif #floornames > 0 then + floorheights[#floorheights] = floorheights[#floorheights]+mem.params.floorheights[i] + end + end + send(carid,"newfloortable",{ + floornames = floornames, + floorheights = floorheights, + }) + end +end + if event.type == "program" then mem.carstatus = {} mem.screenstate = "oobe_welcome" @@ -367,7 +388,7 @@ elseif event.type == "ui" then elseif event.fields.add then table.insert(mem.params.floorheights,5) table.insert(mem.params.floornames,tostring(#mem.params.floornames+1)) - elseif event.fields.remove then + elseif event.fields.remove and #mem.params.floornames > 2 then table.remove(mem.params.floorheights,mem.editingfloor) table.remove(mem.params.floornames,mem.editingfloor) mem.editingfloor = math.max(1,mem.editingfloor-1) diff --git a/docs/README b/docs/README index 4928bef..a53637c 100644 --- a/docs/README +++ b/docs/README @@ -1,2 +1,4 @@ Source for celevator_controller_manual.pdf is not included in this repository due to its large size. If desired, the file can be downloaded from: https://cheapiesystems.com/media/celevator_controller_manual.odt + +This isn't the README for the whole project, go up one folder for that. diff --git a/docs/celevator_controller_manual.pdf b/docs/celevator_controller_manual.pdf Binary files differindex 2a1fec0..0bca94b 100644 --- a/docs/celevator_controller_manual.pdf +++ b/docs/celevator_controller_manual.pdf diff --git a/docs/file_sources b/docs/file_sources index 4bf263d..9de4fc7 100644 --- a/docs/file_sources +++ b/docs/file_sources @@ -1,4 +1,6 @@ -All code: Written by cheapie +Code: Written by the following contributors: +* cheapie +* j-r (Jürgen Rühle) All textures: Hand-drawn by cheapie using GIMP @@ -9,7 +9,7 @@ local function placesill(pos,node) end local yaw = minetest.dir_to_yaw(minetest.fourdir_to_dir(node.param2)) local entity = minetest.add_entity(pos,"celevator:door_sill") - if node.name == "celevator:hwdoor_slow_glass_bottom" then + if node.name == "celevator:hwdoor_slow_glass_bottom" or node.name == "celevator:hwdoor_slow_steel_bottom" then entity:set_properties({ wield_item = "celevator:door_sill_double", }) @@ -199,6 +199,182 @@ minetest.register_node("celevator:hwdoor_slow_glass_top",{ }, }) +minetest.register_node("celevator:hwdoor_fast_steel_bottom",{ + description = "Steel Hoistway Door (fast, bottom - you hacker you!)", + tiles = { + "celevator_transparent.png", + "celevator_door_glass_edge.png", + "celevator_door_glass_edge.png", + "celevator_door_glass_edge.png", + "celevator_door_metal.png", + "celevator_door_metal.png", + }, + groups = { + not_in_creative_inventory = 1, + _celevator_hwdoor_root = 1, + oddly_breakable_by_hand = 2, + }, + drop = "celevator:hwdoor_steel", + paramtype = "light", + paramtype2 = "4dir", + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.5,0.4,0.5,0.5,0.5}, + }, + }, + after_dig_node = function(pos,node) + local erefs = minetest.get_objects_inside_radius(pos,1.5) + for _,ref in pairs(erefs) do + if ref:get_luaentity() and ref:get_luaentity().name == "celevator:door_sill" then ref:remove() end + end + local facedir = minetest.dir_to_yaw(minetest.fourdir_to_dir(node.param2)) + local xnames = { + [0] = "fast", + [1] = "slow", + } + local ynames = { + [0] = "bottom", + [1] = "middle", + [2] = "top", + } + for x=0,1,1 do + for y=0,2,1 do + local piecename = string.format("celevator:hwdoor_%s_steel_%s",xnames[x],ynames[y]) + local pieceoffset = vector.new(x,y,0) + local piecepos = vector.add(pos,vector.rotate_around_axis(pieceoffset,vector.new(0,1,0),facedir)) + if minetest.get_node(piecepos).name == piecename then minetest.remove_node(piecepos) end + end + end + end, +}) + +minetest.register_node("celevator:hwdoor_fast_steel_middle",{ + description = "Steel Hoistway Door (fast, middle - you hacker you!)", + tiles = { + "celevator_transparent.png", + "celevator_transparent.png", + "celevator_door_glass_edge.png", + "celevator_door_glass_edge.png", + "celevator_door_metal.png", + "celevator_door_metal.png", + }, + groups = { + not_in_creative_inventory = 1, + }, + drop = "", + paramtype = "light", + paramtype2 = "4dir", + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.5,0.4,0.5,0.5,0.5}, + }, + }, +}) + +minetest.register_node("celevator:hwdoor_fast_steel_top",{ + description = "Steel Hoistway Door (fast, top - you hacker you!)", + tiles = { + "celevator_door_glass_edge.png", + "celevator_transparent.png", + "celevator_door_glass_edge.png", + "celevator_door_glass_edge.png", + "celevator_door_metal.png", + "celevator_door_metal.png", + }, + groups = { + not_in_creative_inventory = 1, + }, + drop = "", + paramtype = "light", + paramtype2 = "4dir", + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.5,0.4,0.5,0.5,0.5}, + }, + }, +}) + +minetest.register_node("celevator:hwdoor_slow_steel_bottom",{ + description = "Steel Hoistway Door (slow, bottom - you hacker you!)", + tiles = { + "celevator_transparent.png", + "celevator_door_glass_edge.png", + "celevator_door_glass_edge.png", + "celevator_door_glass_edge.png", + "celevator_door_metal.png", + "celevator_door_metal.png", + }, + groups = { + not_in_creative_inventory = 1, + }, + drop = "", + paramtype = "light", + paramtype2 = "4dir", + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.5,0.3,0.5,0.5,0.4}, + }, + }, +}) + +minetest.register_node("celevator:hwdoor_slow_steel_middle",{ + description = "Steel Hoistway Door (slow, middle - you hacker you!)", + tiles = { + "celevator_transparent.png", + "celevator_transparent.png", + "celevator_door_glass_edge.png", + "celevator_door_glass_edge.png", + "celevator_door_metal.png", + "celevator_door_metal.png", + }, + groups = { + not_in_creative_inventory = 1, + }, + drop = "", + paramtype = "light", + paramtype2 = "4dir", + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.5,0.3,0.5,0.5,0.4}, + }, + }, +}) + +minetest.register_node("celevator:hwdoor_slow_steel_top",{ + description = "Steel Hoistway Door (slow, top - you hacker you!)", + tiles = { + "celevator_door_glass_edge.png", + "celevator_transparent.png", + "celevator_door_glass_edge.png", + "celevator_door_glass_edge.png", + "celevator_door_metal.png", + "celevator_door_metal.png", + }, + groups = { + not_in_creative_inventory = 1, + }, + drop = "", + paramtype = "light", + paramtype2 = "4dir", + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.5,0.3,0.5,0.5,0.4}, + }, + }, +}) + minetest.register_node("celevator:hwdoor_placeholder",{ description = "Hoistway Door Open-State Placeholder (you hacker you!)", groups = { @@ -255,6 +431,10 @@ function celevator.doors.hwopen(pos,drivepos) oldnodes[i] = celevator.get_node(position) end local erefs = celevator.drives.entity.nodestoentities(positions,"celevator:hwdoor_moving") + local doortype = "glass" + if oldnodes[1].name == "celevator:hwdoor_slow_steel_bottom" then + doortype = "steel" + end hwdoors_moving[hash] = { direction = "open", positions = positions, @@ -263,6 +443,7 @@ function celevator.doors.hwopen(pos,drivepos) opendir = vector.rotate_around_axis(fdir,vector.new(0,1,0),-math.pi/2), drivepos = drivepos, param2 = param2, + doortype = doortype, } celevator.doors.erefs[hash] = erefs celevator.storage:set_string("hwdoors_moving",minetest.serialize(hwdoors_moving)) @@ -270,8 +451,10 @@ function celevator.doors.hwopen(pos,drivepos) local pmeta = celevator.get_meta(pos) pmeta:set_string("data",minetest.serialize(hwdoors_moving[hash])) pmeta:set_string("state","opening") + pmeta:set_string("doortype",doortype) local carpos = vector.add(pos,fdir) - if celevator.get_node(carpos).name == "celevator:car_000" then + local carndef = minetest.registered_nodes[celevator.get_node(carpos).name] or {} + if carndef._root then celevator.doors.caropen(carpos) end elseif hwdoors_moving[hash].direction == "close" then @@ -280,7 +463,8 @@ function celevator.doors.hwopen(pos,drivepos) celevator.storage:set_string("hwdoors_moving",minetest.serialize(hwdoors_moving)) local fdir = minetest.fourdir_to_dir(hwdoors_moving[hash].param2) local carpos = vector.add(pos,fdir) - if celevator.get_node(carpos).name == "celevator:car_000" then + local carndef = minetest.registered_nodes[celevator.get_node(carpos).name] or {} + if carndef._root then celevator.doors.caropen(carpos) end minetest.set_node(pos,{name="celevator:hwdoor_placeholder",param2=hwdoors_moving[hash].param2}) @@ -301,7 +485,8 @@ function celevator.doors.hwclose(pos,drivepos,nudge) if state ~= "open" then return end local fdir = minetest.fourdir_to_dir(celevator.get_node(pos).param2) local carpos = vector.add(pos,fdir) - if celevator.get_node(carpos).name == "celevator:car_000" then + local carndef = minetest.registered_nodes[celevator.get_node(carpos).name] or {} + if carndef._root then celevator.doors.carclose(carpos,nudge) end local data = minetest.deserialize(pmeta:get_string("data")) @@ -493,7 +678,8 @@ minetest.register_entity("celevator:car_door",{ }, }) -function celevator.doors.spawncardoors(pos,dir) +function celevator.doors.spawncardoors(pos,dir,doortype,replace) + if not doortype then doortype = "glass" end local refs = {} for x=2,1,-1 do for y=1,3,1 do @@ -501,7 +687,15 @@ function celevator.doors.spawncardoors(pos,dir) local doorpos = vector.add(pos,vector.rotate_around_axis(vector.new(x-2,y-1,0),vector.new(0,1,0),yaw)) local xnames = {"slow","fast"} local ynames = {"bottom","middle","top"} - local nname = string.format("celevator:hwdoor_%s_glass_%s",xnames[x],ynames[y]) + local nname = string.format("celevator:hwdoor_%s_%s_%s",xnames[x],doortype,ynames[y]) + if replace then + local oldrefs = minetest.get_objects_inside_radius(doorpos,0.1) + for _,i in pairs(oldrefs) do + if i:get_luaentity() and i:get_luaentity().name == "celevator:car_door" then + i:remove() + end + end + end local ref = minetest.add_entity(doorpos,"celevator:car_door") ref:set_yaw(yaw) ref:set_properties({ @@ -589,7 +783,9 @@ function celevator.doors.carclose(pos,nudge) local dir = minetest.fourdir_to_dir(celevator.get_node(pos).param2) data.direction = "close" data.time = 0 - local erefs = celevator.doors.spawncardoors(pos,dir) + local doortype = meta:get_string("doortype") + if (not doortype) or doortype == "" then doortype = "glass" end + local erefs = celevator.doors.spawncardoors(pos,dir,doortype) local soffset = data.opendir local foffset = vector.multiply(soffset,2) for i=1,3,1 do @@ -619,7 +815,7 @@ end minetest.register_abm({ label = "Respawn car doors", - nodenames = {"celevator:car_000"}, + nodenames = {"group:_celevator_car_root"}, interval = 1, chance = 1, action = function(pos) @@ -631,7 +827,10 @@ minetest.register_abm({ end end local fdir = minetest.facedir_to_dir(minetest.get_node(pos).param2) - celevator.doors.spawncardoors(pos,fdir) + local carmeta = minetest.get_meta(pos) + local doortype = carmeta:get_string("doortype") + if (not doortype) or doortype == "" then doortype = "glass" end + celevator.doors.spawncardoors(pos,fdir,doortype) end, }) @@ -667,12 +866,12 @@ minetest.register_node("celevator:hwdoor_glass",{ local placepos = vector.add(pos,vector.rotate_around_axis(placeoffset,vector.new(0,1,0),facedir)) local replaces = minetest.get_node(placepos).name if not (minetest.registered_nodes[replaces] and minetest.registered_nodes[replaces].buildable_to) then - minetest.chat_send_player(name,string.format("Can't place car here - position %s is blocked!",offsetdesc)) + minetest.chat_send_player(name,string.format("Can't place door here - position %s is blocked!",offsetdesc)) minetest.remove_node(pos) return true end if minetest.is_protected(placepos,name) and not minetest.check_player_privs(name,{protection_bypass=true}) then - minetest.chat_send_player(name,string.format("Can't place car here - position %s is protected!",offsetdesc)) + minetest.chat_send_player(name,string.format("Can't place door here - position %s is protected!",offsetdesc)) minetest.record_protection_violation(placepos,name) minetest.remove_node(pos) return true @@ -690,6 +889,76 @@ minetest.register_node("celevator:hwdoor_glass",{ end end end + local carpos = vector.add(pos,vector.rotate_around_axis(vector.new(0,0,1),vector.new(0,1,0),facedir)) + local carndef = minetest.registered_nodes[celevator.get_node(carpos).name] or {} + if carndef._root then + celevator.get_meta(carpos):set_string("doortype","glass") + celevator.doors.spawncardoors(carpos,minetest.fourdir_to_dir(newnode.param2),"glass",true) + end + end, +}) + +minetest.register_node("celevator:hwdoor_steel",{ + description = "Steel Elevator Hoistway Door", + paramtype2 = "4dir", + buildable_to = true, + inventory_image = "celevator_door_metal_inventory.png", + wield_image = "celevator_door_metal_inventory.png", + wield_scale = vector.new(1,3,1), + tiles = {"celevator_transparent.png"}, + after_place_node = function(pos,player) + if not player:is_player() then + minetest.remove_node(pos) + return true + end + local name = player:get_player_name() + local newnode = minetest.get_node(pos) + local facedir = minetest.dir_to_yaw(minetest.fourdir_to_dir(newnode.param2)) + local xnames = { + [0] = "fast", + [1] = "slow", + } + local ynames = { + [0] = "bottom", + [1] = "middle", + [2] = "top", + } + for x=0,1,1 do + for y=0,2,1 do + local offsetdesc = string.format("%dm to the right and %dm up",x,y) + local placeoffset = vector.new(x,y,0) + local placepos = vector.add(pos,vector.rotate_around_axis(placeoffset,vector.new(0,1,0),facedir)) + local replaces = minetest.get_node(placepos).name + if not (minetest.registered_nodes[replaces] and minetest.registered_nodes[replaces].buildable_to) then + minetest.chat_send_player(name,string.format("Can't place door here - position %s is blocked!",offsetdesc)) + minetest.remove_node(pos) + return true + end + if minetest.is_protected(placepos,name) and not minetest.check_player_privs(name,{protection_bypass=true}) then + minetest.chat_send_player(name,string.format("Can't place door here - position %s is protected!",offsetdesc)) + minetest.record_protection_violation(placepos,name) + minetest.remove_node(pos) + return true + end + end + end + for x=0,1,1 do + for y=0,2,1 do + local piecename = string.format("celevator:hwdoor_%s_steel_%s",xnames[x],ynames[y]) + local placeoffset = vector.new(x,y,0) + local placepos = vector.add(pos,vector.rotate_around_axis(placeoffset,vector.new(0,1,0),facedir)) + minetest.set_node(placepos,{name=piecename,param2=newnode.param2}) + if y==0 then + placesill(placepos,{name=piecename,param2=newnode.param2}) + end + end + end + local carpos = vector.add(pos,vector.rotate_around_axis(vector.new(0,0,1),vector.new(0,1,0),facedir)) + local carndef = minetest.registered_nodes[celevator.get_node(carpos).name] or {} + if carndef._root then + celevator.get_meta(carpos):set_string("doortype","steel") + celevator.doors.spawncardoors(carpos,minetest.fourdir_to_dir(newnode.param2),"steel",true) + end end, }) @@ -747,7 +1016,12 @@ minetest.register_entity("celevator:door_sill",{ minetest.register_lbm({ label = "Respawn hoistway door sills", name = "celevator:spawn_sill", - nodenames = {"celevator:hwdoor_fast_glass_bottom","celevator:hwdoor_slow_glass_bottom"}, + nodenames = { + "celevator:hwdoor_fast_glass_bottom", + "celevator:hwdoor_slow_glass_bottom", + "celevator:hwdoor_fast_steel_bottom", + "celevator:hwdoor_slow_steel_bottom", + }, run_at_every_load = true, action = placesill, }) diff --git a/drive_entity.lua b/drive_entity.lua index ae72bca..0ddd4c4 100644 --- a/drive_entity.lua +++ b/drive_entity.lua @@ -11,6 +11,8 @@ celevator.drives.entity = { sheaverefs = {}, } +local playerposlimits = {} + local function update_ui(pos) local meta = minetest.get_meta(pos) local apos = tonumber(meta:get_string("apos")) or 0 @@ -231,6 +233,80 @@ minetest.register_entity("celevator:car_moving",{ }, }) +minetest.register_entity("celevator:player_holder",{ + initial_properties = { + visual = "cube", + textures = { + "blank.png", + "blank.png", + "blank.png", + "blank.png", + "blank.png", + "blank.png", + }, + --I have no idea where this magic number comes from, but it seems about right and that's good enough + visual_size = vector.new(3,3,3), + static_save = false, + pointable = false, + }, + on_step = function(self,dtime) + local obj = self.object + local car,_,attachoffset = obj:get_attach() + if not car then + obj:remove() + return + end + local children = obj:get_children() + local player + for _,i in pairs(children) do + if i:is_player() then + player = i + end + end + if not player then return end + local caryaw = car:get_yaw() + local playeryaw = player:get_look_horizontal() + local attachrot = vector.new(0,(caryaw-playeryaw)*57.296,0) + local control = player:get_player_control() + if (control.up or control.down or control.left or control.right) then + local walkspeed = 120 + local walkamount = walkspeed*dtime + local displacement = vector.new(0,0,0) + if control.up then + displacement = vector.add(displacement,vector.new(0,0,walkamount)) + end + if control.down then + displacement = vector.add(displacement,vector.new(0,0,0-walkamount)) + end + if control.left then + displacement = vector.add(displacement,vector.new(0-walkamount,0,0)) + end + if control.right then + displacement = vector.add(displacement,vector.new(walkamount,0,0)) + end + displacement = vector.rotate_around_axis(displacement,vector.new(0,1,0),playeryaw) + displacement = vector.rotate_around_axis(displacement,vector.new(0,-1,0),caryaw) + local oldattachoffset = vector.copy(attachoffset) + attachoffset = vector.add(attachoffset,displacement) + local realattachoffset = vector.rotate_around_axis(vector.multiply(attachoffset,1/30),vector.new(0,1,0),caryaw) + local newpos = vector.add(car:get_pos(),realattachoffset) + local limits = playerposlimits[player:get_player_name()] or {} + if limits.xmin and limits.xmax and limits.xmin < limits.xmax then + if newpos.x > limits.xmax or newpos.x < limits.xmin then + attachoffset = oldattachoffset + end + end + if limits.zmin and limits.zmax and limits.zmin < limits.zmax then + if newpos.z > limits.zmax or newpos.z < limits.zmin then + attachoffset = oldattachoffset + end + end + end + obj:set_attach(car,"",attachoffset,vector.new(0,0,0)) + player:set_attach(obj,"",vector.new(0,0,0),attachrot) + end, +}) + function celevator.drives.entity.gathercar(pos,yaw,nodes) if not nodes then nodes = {} end local hash = minetest.hash_node_position(pos) @@ -259,6 +335,16 @@ end function celevator.drives.entity.nodestoentities(nodes,ename) local refs = {} + local xmin = 32000 + local xmax = -32000 + local zmin = 32000 + local zmax = -32000 + for _,pos in ipairs(nodes) do + if pos.x < xmin then xmin = pos.x end + if pos.x > xmax then xmax = pos.x end + if pos.z < zmin then zmin = pos.z end + if pos.z > zmax then zmax = pos.z end + end for _,pos in ipairs(nodes) do local node = celevator.get_node(pos) local attach = minetest.get_objects_inside_radius(pos,0.9) @@ -268,7 +354,8 @@ function celevator.drives.entity.nodestoentities(nodes,ename) }) eref:set_yaw(minetest.dir_to_yaw(minetest.fourdir_to_dir(node.param2))) table.insert(refs,eref) - if node.name == "celevator:car_021" or node.name == "celevator:car_122" then + local ndef = minetest.registered_nodes[node.name] or {} + if ndef._cartopbox or ndef._tapehead then local toppos = vector.add(pos,vector.new(0,1,0)) local topattach = minetest.get_objects_inside_radius(toppos,0.75) for _,ref in pairs(topattach) do @@ -285,12 +372,27 @@ function celevator.drives.entity.nodestoentities(nodes,ename) } if attachref:get_luaentity() and included[attachref:get_luaentity().name] then table.insert(refs,attachref) + elseif attachref:is_player() then + local attachpos = attachref:get_pos() + local basepos = eref:get_pos() + local attachoffset = vector.subtract(attachpos,basepos) + attachoffset = vector.rotate_around_axis(attachoffset,vector.new(0,-1,0),eref:get_yaw()) + local holder = minetest.add_entity(attachpos,"celevator:player_holder") + holder:set_attach(eref,"",vector.multiply(attachoffset,30),vector.new(0,0,0)) + attachref:set_attach(holder,"") + local extra = 0.25 --To allow getting closer to walls + playerposlimits[attachref:get_player_name()] = { + xmin = xmin-extra, + xmax = xmax+extra, + zmin = zmin-extra, + zmax = zmax+extra, + } else local attachpos = attachref:get_pos() local basepos = eref:get_pos() - local attachoffset = vector.multiply(vector.subtract(attachpos,basepos),30) + local attachoffset = vector.subtract(attachpos,basepos) attachoffset = vector.rotate_around_axis(attachoffset,vector.new(0,-1,0),eref:get_yaw()) - attachref:set_attach(eref,"",attachoffset) + attachref:set_attach(eref,"",vector.multiply(attachoffset,30),vector.new(0,0,0)) end end end @@ -333,10 +435,15 @@ function celevator.drives.entity.entitiestonodes(refs,carid) i:set_velocity(vector.new(0,0,0)) if i:is_player() then local ppos = i:get_pos() - ppos.y=ppos.y-0.4 - if top then ppos.y = ppos.y+1.1 end + ppos.y=ppos.y-0.48 + if top then ppos.y = ppos.y+1.02 end i:set_pos(ppos) - minetest.after(0.5,i.set_pos,i,ppos) + minetest.after(0.5,function() + if not i:is_player() then return end + local newpos = i:get_pos() + newpos.y = math.max(newpos.y,ppos.y) + i:set_pos(newpos) + end) elseif i:get_luaentity() and rounded[i:get_luaentity().name] then local epos = i:get_pos() epos.y = math.floor(epos.y+0.5) @@ -373,6 +480,7 @@ function celevator.drives.entity.step(dtime) local dpos = tonumber(meta:get_string("dpos")) or 0 local maxvel = tonumber(meta:get_string("maxvel")) or 0.2 local startpos = tonumber(meta:get_string("startpos")) or 0 + local oldvel = tonumber(meta:get_string("vel")) or 0 local inspection = meta:get_int("inspection") == 1 local origin = minetest.string_to_pos(meta:get_string("origin")) if not origin then @@ -402,7 +510,12 @@ function celevator.drives.entity.step(dtime) end end local carparam2 = celevator.get_node(nodes[1]).param2 + local cardef = minetest.registered_nodes[celevator.get_node(nodes[1]).name] or {} + local cartype = cardef._celevator_car_type or "standard" + local carmeta = celevator.get_meta(startv) meta:set_int("carparam2",carparam2) + meta:set_string("cartype",cartype) + meta:set_string("doortype",carmeta:get_string("doortype")) local handles = celevator.drives.entity.nodestoentities(nodes) celevator.drives.entity.entityinfo[hash] = { handles = handles, @@ -432,20 +545,28 @@ function celevator.drives.entity.step(dtime) local dremain = math.abs(dpos-apos) local dmoved = math.abs(apos-startpos) local vel - if dremain < 0.01 then + local relevel = (dpos < apos and oldvel > 0) or (dpos > apos and oldvel < 0) + if dremain < 0.01 or (inspection and relevel) then vel = 0 meta:set_string("state","stopped") motorsound(pos,"idle") celevator.drives.entity.sheavetonode(carid) local ok = celevator.drives.entity.entitiestonodes(handles,carid) + local doortype = meta:get_string("doortype") + if (not doortype) or doortype == "" then doortype = "glass" end + local spawnpos = vector.round(vector.add(origin,vector.new(0,apos,0))) if not ok then local carparam2 = meta:get_int("carparam2") - celevator.car.spawncar(vector.round(vector.add(origin,vector.new(0,apos,0))),minetest.dir_to_yaw(minetest.fourdir_to_dir(carparam2)),carid) + local cartype = meta:get_string("cartype") + celevator.car.spawncar(spawnpos,minetest.dir_to_yaw(minetest.fourdir_to_dir(carparam2)),carid,cartype,doortype) + else + celevator.get_meta(spawnpos):set_string("doortype",doortype) end apos = math.floor(apos+0.5) minetest.after(0.25,celevator.drives.entity.updatecopformspec,pos) - elseif dremain < 0.2 and not inspection then - vel = 0.2 + table.remove(entitydrives_running,i) + elseif dremain < 0.1 and not inspection then + vel = 0.1 elseif dremain < 2*maxvel and dremain < dmoved and not inspection then vel = math.min(dremain,maxvel) if celevator.drives.entity.movementsoundstate[hash] == "fast" or celevator.drives.entity.movementsoundstate[hash] == "accel" then @@ -478,17 +599,23 @@ function celevator.drives.entity.step(dtime) local dremain = math.abs(dpos-apos) local dmoved = math.abs(apos-startpos) local vel - if dremain < 0.01 then + local relevel = (dpos < apos and oldvel > 0) or (dpos > apos and oldvel < 0) + if dremain < 0.01 or (relevel and inspection) then vel = 0 meta:set_string("state","stopped") motorsound(pos,"idle") celevator.drives.entity.sheavetonode(carid) local carparam2 = meta:get_int("carparam2") - celevator.car.spawncar(vector.round(vector.add(origin,vector.new(0,apos,0))),minetest.dir_to_yaw(minetest.fourdir_to_dir(carparam2)),carid) + local cartype = meta:get_string("cartype") + local doortype = meta:get_string("doortype") + if (not doortype) or doortype == "" then doortype = "glass" end + local spawnpos = vector.round(vector.add(origin,vector.new(0,apos,0))) + celevator.car.spawncar(spawnpos,minetest.dir_to_yaw(minetest.fourdir_to_dir(carparam2)),carid,cartype,doortype) apos = math.floor(apos+0.5) minetest.after(0.25,celevator.drives.entity.updatecopformspec,pos) - elseif dremain < 0.2 and not inspection then - vel = 0.2 + table.remove(entitydrives_running,i) + elseif dremain < 0.1 and not inspection then + vel = 0.1 elseif dremain < 2*maxvel and dremain < dmoved and not inspection then vel = math.min(dremain,maxvel) if celevator.drives.entity.movementsoundstate[hash] == "fast" or celevator.drives.entity.movementsoundstate[hash] == "accel" then @@ -526,7 +653,21 @@ function celevator.drives.entity.moveto(pos,target,inspection) meta:mark_as_private({"apos","dpos","vel","maxvel","state","startpos","doorstate"}) local carid = celevator.get_meta(pos):get_int("carid") local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid))) - if not (carinfo and carinfo.machinepos) then return end + if not (carinfo and carinfo.machinepos and celevator.get_node(carinfo.machinepos).name == "celevator:machine") then + meta:set_string("fault","nomachine") + return + end + if not carinfo.controllerpos then return end + local controllermeta = celevator.get_meta(carinfo.controllerpos) + if controllermeta:get_int("carid") ~= carid then + meta:set_string("fault","controllermismatch") + return + end + local machinemeta = celevator.get_meta(carinfo.machinepos) + if machinemeta:get_int("carid") ~= carid then + meta:set_string("fault","machinemismatch") + return + end local origin = minetest.string_to_pos(meta:get_string("origin")) if not origin then minetest.log("error","[celevator] [entity drive] Invalid origin for drive at "..minetest.pos_to_string(pos)) @@ -1025,9 +1166,10 @@ function celevator.drives.entity.updatecopformspec(drivepos) for hash in pairs(carnodes) do local piecepos = minetest.get_position_from_hash(hash) local piece = celevator.get_node(piecepos) - if piece.name == "celevator:car_010" then + local ndef = minetest.registered_nodes[piece.name] or {} + if ndef._cop then celevator.get_meta(piecepos):set_string("formspec",copformspec) - elseif piece.name == "celevator:car_000" then + elseif ndef._keyswitches then celevator.get_meta(piecepos):set_string("formspec",switchformspec) end end diff --git a/genericswitch.lua b/genericswitch.lua index d52e9c9..9cdf31c 100644 --- a/genericswitch.lua +++ b/genericswitch.lua @@ -154,6 +154,30 @@ local inputoptions = { end, needsfloor = true, }, + { + id = "swingon", + desc = "Activate Swing Operation", + func_on = function(controllerpos) + celevator.controller.run(controllerpos,{ + type = "remotemsg", + channel = "swing", + msg = true, + }) + end, + needsfloor = false, + }, + { + id = "swingoff", + desc = "Deactivate Swing Operation", + func_on = function(controllerpos) + celevator.controller.run(controllerpos,{ + type = "remotemsg", + channel = "swing", + msg = false, + }) + end, + needsfloor = false, + }, } local dinputoptions = { diff --git a/governor.lua b/governor.lua new file mode 100644 index 0000000..4333c92 --- /dev/null +++ b/governor.lua @@ -0,0 +1,131 @@ +local function spawngovsheave(pos) + local entitiesnearby = minetest.get_objects_inside_radius(pos,0.5) + for _,i in pairs(entitiesnearby) do + if i:get_luaentity() and i:get_luaentity().name == "celevator:governor_sheave" then + return + end + end + local entity = minetest.add_entity(pos,"celevator:governor_sheave") + local fdir = minetest.fourdir_to_dir(minetest.get_node(pos).param2) + local yaw = minetest.dir_to_yaw(fdir) + local offset = vector.rotate_around_axis(vector.new(0,-0.05,-0.143),vector.new(0,1,0),yaw) + entity:set_yaw(yaw) + entity:set_pos(vector.add(pos,offset)) +end + +minetest.register_node("celevator:governor",{ + description = "Elevator Governor", + groups = { + cracky = 1, + }, + paramtype = "light", + paramtype2 = "4dir", + tiles = { + "celevator_machine_top.png", + "celevator_machine_top.png", + "celevator_machine_top.png", + "celevator_machine_top.png", + "celevator_governor_back.png", + "celevator_governor_front.png", + }, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-0.2,-0.5,-0.1,0.2,0.1,-0.07}, + {-0.2,-0.5,0.07,0.2,0.1,0.1}, + {-0.2,-0.5,-0.25,0.2,-0.45,-0.1}, + {-0.2,-0.5,0.1,0.2,-0.45,0.25}, + }, + }, + on_construct = function(pos) + minetest.get_meta(pos):set_string("formspec","field[carid;Car ID;]") + spawngovsheave(pos) + end, + after_dig_node = function(pos) + local entitiesnearby = minetest.get_objects_inside_radius(pos,0.5) + for _,i in pairs(entitiesnearby) do + if i:get_luaentity() and i:get_luaentity().name == "celevator:governor_sheave" then + i:remove() + end + end + end, + on_receive_fields = function(pos,_,fields) + if not (fields.carid and tonumber(fields.carid)) then return end + local carid = tonumber(fields.carid) + local carinfo = minetest.deserialize(celevator.storage:get_string("car"..carid)) + if not (carinfo and carinfo.controllerpos) then return end + if not celevator.controller.iscontroller(carinfo.controllerpos) then return end + local meta = minetest.get_meta(pos) + meta:set_string("controllerpos",minetest.pos_to_string(carinfo.controllerpos)) + meta:set_string("formspec","") + end, +}) + +minetest.register_node("celevator:governor_sheave",{ + description = "Governor Sheave (you hacker you!)", + groups = { + not_in_creative_inventory = 1, + }, + drop = "", + paramtype = "light", + paramtype2 = "4dir", + tiles = { + "celevator_governor_sheave_sides.png^[transformR90", + "celevator_governor_sheave_sides.png^[transformR270", + "celevator_governor_sheave_sides.png", + "celevator_governor_sheave_sides.png^[transformR180", + "celevator_sheave_front_centered.png", + "celevator_sheave_front_centered.png", + }, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-0.3,-0.3,0.2,0.3,0.3,0.5}, + {-0.4,-0.2,0.2,-0.3,0.2,0.5}, + {0.3,-0.2,0.2,0.4,0.2,0.5}, + {-0.2,0.3,0.2,0.2,0.4,0.5}, + {-0.2,-0.4,0.2,0.2,-0.3,0.5}, + }, + }, + selection_box = { + type = "fixed", + fixed = {}, + }, +}) + +minetest.register_entity("celevator:governor_sheave",{ + initial_properties = { + visual = "wielditem", + visual_size = vector.new(0.4,0.4,0.27), + wield_item = "celevator:governor_sheave", + static_save = false, + pointable = false, + }, + on_step = function(self) + local sheave = self.object + if not sheave then return end + local governorpos = vector.round(sheave:get_pos()) + local governormeta = celevator.get_meta(governorpos) + local controllerpos = minetest.string_to_pos(governormeta:get_string("controllerpos")) + if not controllerpos then return end + local controllermeta = celevator.get_meta(controllerpos) + local vel = tonumber(controllermeta:get_string("vel")) or 0 + if vel == 0 then return end + local drivepos = celevator.controller.finddrive(controllerpos) + local drivemeta = celevator.get_meta(drivepos) + local apos = tonumber(drivemeta:get_string("apos")) or 0 + local rotation = sheave:get_rotation() + rotation.z = apos*2*math.pi + sheave:set_rotation(rotation) + end, +}) + +minetest.register_lbm({ + name = "celevator:spawngovsheave", + label = "Spawn governor sheaves", + nodenames = {"celevator:governor"}, + run_at_every_load = true, + action = spawngovsheave, +}) @@ -1,6 +1,10 @@ local components = { "framework", "car", + "car_standard", + "car_glassback", + "car_metal", + "car_metalglass", "doors", "drive_null", "drive_entity", @@ -12,7 +16,9 @@ local components = { "dbdkiosk", "genericswitch", "decorations", + "governor", "crafts", + "chatcommands", } local integrations = { @@ -61,6 +61,10 @@ laptop.register_app("celevator",{ fs = fs..mtos.theme:get_label("0.5,1","Could not find a controller or dispatcher with the given ID.") fs = fs..mtos.theme:get_label("0.5,1.3","Please check the ID number and try again.") fs = fs..mtos.theme:get_button("0.5,3;2,1","major","ok","OK") + elseif ram.screenstate == "protected" then + fs = fs..mtos.theme:get_label("0.5,0.5","Error") + fs = fs..mtos.theme:get_label("0.5,1","Controller or dispatcher is protected.") + fs = fs..mtos.theme:get_button("0.5,3;2,1","major","ok","OK") elseif ram.screenstate == "dispatcherstatus" then local connection = mem.connections[mem.selectedconnection] local pos = connection.pos @@ -201,6 +205,7 @@ laptop.register_app("celevator",{ indep = "Independent Service", capture = "Captured", test = "Test Mode", + swing = "Swing Operation", } local doorstates = { open = "Open", @@ -331,10 +336,16 @@ laptop.register_app("celevator",{ mem.screenpage = 1 if exp.type == "DCL" then mem.selectedconnection = #mem.connections-exp.index+1 end local connection = mem.connections[mem.selectedconnection] - if connection.itemtype == "controller" and celevator.controller.iscontroller(connection.pos) then + local cpos = connection.pos + if minetest.is_protected(cpos,mtos.sysram.current_player) and not minetest.check_player_privs(mtos.sysram.current_player,{protection_bypass=true}) then + minetest.record_protection_violation(cpos,mtos.sysram.current_player) + ram.screenstate = "protected" + return + end + if connection.itemtype == "controller" and celevator.controller.iscontroller(cpos) then ram.screenstate = "controllerstatus" app:get_timer():start(0.2) - elseif connection.itemtype == "dispatcher" and celevator.dispatcher.isdispatcher(connection.pos) then + elseif connection.itemtype == "dispatcher" and celevator.dispatcher.isdispatcher(cpos) then ram.screenstate = "dispatcherstatus" app:get_timer():start(0.2) else @@ -365,6 +376,11 @@ laptop.register_app("celevator",{ ram.screenstate = "notfound" return end + if minetest.is_protected(pos,mtos.sysram.current_player) and not minetest.check_player_privs(mtos.sysram.current_player,{protection_bypass=true}) then + minetest.record_protection_violation(pos,mtos.sysram.current_player) + ram.screenstate = "protected" + return + end local connection = { name = fields.name, carid = carid, @@ -381,6 +397,10 @@ laptop.register_app("celevator",{ if fields.ok then ram.screenstate = "newconnection" end + elseif ram.screenstate == "protected" then + if fields.ok then + ram.screenstate = #mem.connections > 0 and "connections" or "newconnection" + end elseif ram.screenstate == "dispatcherstatus" then if fields.disconnect then ram.screenstate = "connections" diff --git a/mesecons.lua b/mesecons.lua index 7064821..f505649 100644 --- a/mesecons.lua +++ b/mesecons.lua @@ -83,6 +83,14 @@ local outputoptions = { needsfloor = false, }, { + id = "swing", + desc = "Swing Operation", + func = function(mem) + return (mem.carstate == "swing") + end, + needsfloor = false, + }, + { id = "opening", desc = "Doors Opening", func = function(mem) @@ -393,6 +401,30 @@ local inputoptions = { end, needsfloor = true, }, + { + id = "swingon", + desc = "Activate Swing Operation", + func_on = function(controllerpos) + celevator.controller.run(controllerpos,{ + type = "remotemsg", + channel = "swing", + msg = true, + }) + end, + needsfloor = false, + }, + { + id = "swingoff", + desc = "Deactivate Swing Operation", + func_on = function(controllerpos) + celevator.controller.run(controllerpos,{ + type = "remotemsg", + channel = "swing", + msg = false, + }) + end, + needsfloor = false, + }, } local dinputoptions = { @@ -1,5 +1,5 @@ name = celevator description = Realistic Elevators -optional_depends = laptop,mesecons,digilines +optional_depends = laptop,mesecons,digilines,xcompat,mesecons_lightstone,mesecons_button author = cheapie min_minetest_version = 5.7 diff --git a/pilantern.lua b/pilantern.lua index 7dda0a5..29f3cf7 100644 --- a/pilantern.lua +++ b/pilantern.lua @@ -578,3 +578,30 @@ minetest.register_abm({ celevator.pi.updatedisplay(pos) end, }) + +minetest.register_abm({ + label = "Check PIs/lanterns for missing/replaced controllers", + nodenames = {"group:_celevator_pi","group:_celevator_lantern"}, + interval = 15, + chance = 1, + action = function(pos) + local meta = minetest.get_meta(pos) + local carid = meta:get_int("carid") + if not (carid and carid > 0) then return end --Not set up yet + local carinfo = minetest.deserialize(celevator.storage:get_string("car"..carid)) + if not carinfo then + celevator.pi.settext(pos," --") + meta:set_string("infotext","Error reading car information!\nPlease remove and replace this node.") + return + end + if not (carinfo.controllerpos and celevator.controller.iscontroller(carinfo.controllerpos)) then + celevator.pi.settext(pos," --") + meta:set_string("infotext","Controller is missing!\nPlease remove and replace this node.") + return + end + if celevator.get_meta(carinfo.controllerpos):get_int("carid") ~= carid then + celevator.pi.settext(pos," --") + meta:set_string("infotext","Controller found but with incorrect ID!\nPlease remove and replace this node.") + end + end, +}) diff --git a/screenshot.png b/screenshot.png Binary files differnew file mode 100644 index 0000000..907df06 --- /dev/null +++ b/screenshot.png diff --git a/textures/celevator_car_glass.png b/textures/celevator_car_glass.png Binary files differnew file mode 100644 index 0000000..025c1ec --- /dev/null +++ b/textures/celevator_car_glass.png diff --git a/textures/celevator_car_glassback_inventory.png b/textures/celevator_car_glassback_inventory.png Binary files differnew file mode 100644 index 0000000..77dc082 --- /dev/null +++ b/textures/celevator_car_glassback_inventory.png diff --git a/textures/celevator_car_glassback_wield.png b/textures/celevator_car_glassback_wield.png Binary files differnew file mode 100644 index 0000000..152bbcf --- /dev/null +++ b/textures/celevator_car_glassback_wield.png diff --git a/textures/celevator_car_metal.png b/textures/celevator_car_metal.png Binary files differnew file mode 100644 index 0000000..f9fdee6 --- /dev/null +++ b/textures/celevator_car_metal.png diff --git a/textures/celevator_car_metal_2x.png b/textures/celevator_car_metal_2x.png Binary files differnew file mode 100644 index 0000000..fdbb229 --- /dev/null +++ b/textures/celevator_car_metal_2x.png diff --git a/textures/celevator_car_metal_ceiling.png b/textures/celevator_car_metal_ceiling.png Binary files differnew file mode 100644 index 0000000..5023c7e --- /dev/null +++ b/textures/celevator_car_metal_ceiling.png diff --git a/textures/celevator_car_metal_floor.png b/textures/celevator_car_metal_floor.png Binary files differnew file mode 100644 index 0000000..d944936 --- /dev/null +++ b/textures/celevator_car_metal_floor.png diff --git a/textures/celevator_car_metal_glassback_inventory.png b/textures/celevator_car_metal_glassback_inventory.png Binary files differnew file mode 100644 index 0000000..5c7cc22 --- /dev/null +++ b/textures/celevator_car_metal_glassback_inventory.png diff --git a/textures/celevator_car_metal_glassback_wield.png b/textures/celevator_car_metal_glassback_wield.png Binary files differnew file mode 100644 index 0000000..a072b41 --- /dev/null +++ b/textures/celevator_car_metal_glassback_wield.png diff --git a/textures/celevator_car_metal_inventory.png b/textures/celevator_car_metal_inventory.png Binary files differnew file mode 100644 index 0000000..e969f08 --- /dev/null +++ b/textures/celevator_car_metal_inventory.png diff --git a/textures/celevator_car_metal_top.png b/textures/celevator_car_metal_top.png Binary files differnew file mode 100644 index 0000000..c9d400a --- /dev/null +++ b/textures/celevator_car_metal_top.png diff --git a/textures/celevator_car_metal_wield.png b/textures/celevator_car_metal_wield.png Binary files differnew file mode 100644 index 0000000..2c76aa4 --- /dev/null +++ b/textures/celevator_car_metal_wield.png diff --git a/textures/celevator_door_glass_inventory.png b/textures/celevator_door_glass_inventory.png Binary files differindex 4ebf6f9..2538465 100644 --- a/textures/celevator_door_glass_inventory.png +++ b/textures/celevator_door_glass_inventory.png diff --git a/textures/celevator_door_metal.png b/textures/celevator_door_metal.png Binary files differnew file mode 100644 index 0000000..b14be20 --- /dev/null +++ b/textures/celevator_door_metal.png diff --git a/textures/celevator_door_metal_inventory.png b/textures/celevator_door_metal_inventory.png Binary files differnew file mode 100644 index 0000000..d5f858a --- /dev/null +++ b/textures/celevator_door_metal_inventory.png diff --git a/textures/celevator_governor_back.png b/textures/celevator_governor_back.png Binary files differnew file mode 100644 index 0000000..3bf1cc6 --- /dev/null +++ b/textures/celevator_governor_back.png diff --git a/textures/celevator_governor_front.png b/textures/celevator_governor_front.png Binary files differnew file mode 100644 index 0000000..52a4c23 --- /dev/null +++ b/textures/celevator_governor_front.png diff --git a/textures/celevator_governor_sheave_sides.png b/textures/celevator_governor_sheave_sides.png Binary files differnew file mode 100644 index 0000000..43e3a12 --- /dev/null +++ b/textures/celevator_governor_sheave_sides.png |