diff options
75 files changed, 8693 insertions, 2671 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ffc8a2e --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +i18n.py +locale/*.old diff --git a/.luacheckrc b/.luacheckrc index 8ce3cc6..0a45878 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -5,13 +5,14 @@ globals = { } read_globals = { - "DIR_DELIM", "vector", "screwdriver", - "minetest", + "core", "table.copy", "VoxelManip", "laptop", "mesecon", "digilines", + "xcompat", + "digistuff", } @@ -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..432ef19 100644 --- a/callbuttons.lua +++ b/callbuttons.lua @@ -1,5 +1,54 @@ celevator.callbutton = {} +local fscontext = {} + +local S = core.get_translator("celevator") + +local function showfs(pos,name) + local nname = celevator.get_node(pos).name + fscontext[name] = pos + + local fs = "formspec_version[10]size[4,6]" + fs = fs.."background[0,0;4,6;celevator_callbutton_panel.png;true]" + + local uplit = core.get_item_group(nname,"_celevator_callbutton_up_lit") == 1 + local uptex = "celevator_callbutton_up.png" + local uplittex = "[combine:17x9:0,0="..uptex..":9,1=celevator_callbutton_light.png" + if uplit then uptex = uplittex end + fs = fs.."image_button[0.75,1;2.5,1.25;"..uptex..";up;;false;false;"..uplittex.."]" + + local downlit = core.get_item_group(nname,"_celevator_callbutton_down_lit") == 1 + local downtex = "celevator_callbutton_down.png" + local downlittex = "[combine:17x9:0,0="..downtex..":9,1=celevator_callbutton_light.png" + if downlit then downtex = downlittex end + fs = fs.."image_button[0.75,3.5;2.5,1.25;"..downtex..";down;;false;false;"..downlittex.."]" + + core.show_formspec(name,"celevator:call_button",fs) +end + +core.register_on_player_receive_fields(function(player,formname,fields) + if formname ~= "celevator:call_button" then + return false + end + local name = player:get_player_name() + local pos = fscontext[name] + if not pos then return true end + if fields.quit then + fscontext[name] = nil + elseif fields.up then + local nname = celevator.get_node(pos).name + if core.get_item_group(nname,"_celevator_callbutton_has_up") == 1 then + core.registered_nodes["celevator:callbutton_up"].on_rightclick(pos) + end + elseif fields.down then + local nname = celevator.get_node(pos).name + if core.get_item_group(nname,"_celevator_callbutton_has_down") == 1 then + core.registered_nodes["celevator:callbutton_down"].on_rightclick(pos) + end + end + return true +end) + local function makebuttontex(dir,upon,downon,inventory) local tex = "[combine:64x64".. ":0,0=celevator_cabinet_sides.png".. @@ -42,77 +91,93 @@ local function makebuttontex(dir,upon,downon,inventory) return(tex) end +local upname = S("Elevator Up Call Button") +local dnname = S("Elevator Down Call Button") +local bothname = S("Elevator Up and Down Call Buttons") +local onname = S("Elevator Call Button (on state - you hacker you!)") + local validstates = { - {"up",false,false,"Up"}, - {"up",true,false,"Up"}, - {"down",false,false,"Down"}, - {"down",false,true,"Down"}, - {"both",false,false,"Up and Down"}, - {"both",true,false,"Up and Down"}, - {"both",false,true,"Up and Down"}, - {"both",true,true,"Up and Down"}, + {"up",false,false,upname}, + {"up",true,false,onname}, + {"down",false,false,dnname}, + {"down",false,true,onname}, + {"both",false,false,bothname}, + {"both",true,false,onname}, + {"both",false,true,onname}, + {"both",true,true,onname}, } function celevator.callbutton.setlight(pos,dir,newstate) local node = celevator.get_node(pos) - if minetest.get_item_group(node.name,"_celevator_callbutton") ~= 1 then return end + if core.get_item_group(node.name,"_celevator_callbutton") ~= 1 then return end if dir == "up" then - if minetest.get_item_group(node.name,"_celevator_callbutton_has_up") ~= 1 then return end - local lit = minetest.get_item_group(node.name,"_celevator_callbutton_up_lit") == 1 + if core.get_item_group(node.name,"_celevator_callbutton_has_up") ~= 1 then return end + local lit = core.get_item_group(node.name,"_celevator_callbutton_up_lit") == 1 if lit == newstate then return end local newname = "celevator:callbutton_" - if minetest.get_item_group(node.name,"_celevator_callbutton_has_down") == 1 then + if core.get_item_group(node.name,"_celevator_callbutton_has_down") == 1 then newname = newname.."both" else newname = newname.."up" end if newstate then newname = newname.."_upon" end - if minetest.get_item_group(node.name,"_celevator_callbutton_down_lit") == 1 then + if core.get_item_group(node.name,"_celevator_callbutton_down_lit") == 1 then newname = newname.."_downon" end node.name = newname - minetest.swap_node(pos,node) + core.swap_node(pos,node) elseif dir == "down" then - if minetest.get_item_group(node.name,"_celevator_callbutton_has_down") ~= 1 then return end - local lit = minetest.get_item_group(node.name,"_celevator_callbutton_down_lit") == 1 + if core.get_item_group(node.name,"_celevator_callbutton_has_down") ~= 1 then return end + local lit = core.get_item_group(node.name,"_celevator_callbutton_down_lit") == 1 if lit == newstate then return end local newname = "celevator:callbutton_" - if minetest.get_item_group(node.name,"_celevator_callbutton_has_up") == 1 then + if core.get_item_group(node.name,"_celevator_callbutton_has_up") == 1 then newname = newname.."both" else newname = newname.."down" end - if minetest.get_item_group(node.name,"_celevator_callbutton_up_lit") == 1 then + if core.get_item_group(node.name,"_celevator_callbutton_up_lit") == 1 then newname = newname.."_upon" end if newstate then newname = newname.."_downon" end node.name = newname - minetest.swap_node(pos,node) + core.swap_node(pos,node) + end + for name,contextpos in pairs(fscontext) do + if vector.equals(pos,contextpos) then + showfs(pos,name) + end end end local function disambiguatedir(pos,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() - local distance = vector.distance(eyepos,pos) - local endpos = vector.add(eyepos,vector.multiply(lookdir,distance+1)) - local ray = minetest.raycast(eyepos,endpos,true,false) - local pointed,button,hitpos - repeat - pointed = ray:next() - if pointed and pointed.type == "node" then - local node = minetest.get_node(pointed.under) - if node.name and (minetest.get_item_group(node.name,"_celevator_callbutton") == 1) then - button = pointed.under - hitpos = vector.subtract(pointed.intersection_point,button) + local name = player:get_player_name() + local windowinfo = core.get_player_window_information(name) + if windowinfo and windowinfo.touch_controls then + showfs(pos,name) + else + 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() + local distance = vector.distance(eyepos,pos) + local endpos = vector.add(eyepos,vector.multiply(lookdir,distance+1)) + local ray = core.raycast(eyepos,endpos,true,false) + local pointed,button,hitpos + repeat + pointed = ray:next() + if pointed and pointed.type == "node" then + local node = core.get_node(pointed.under) + if node.name and (core.get_item_group(node.name,"_celevator_callbutton") == 1) then + button = pointed.under + hitpos = vector.subtract(pointed.intersection_point,button) + end end - end - until button or not pointed - if not hitpos then return end - hitpos.y = -1*hitpos.y - hitpos.y = math.floor((hitpos.y+0.5)*64+0.5)+1 - return hitpos.y >= 40 and "down" or "up" + until button or not pointed + if not hitpos then return end + hitpos.y = -1*hitpos.y + hitpos.y = math.floor((hitpos.y+0.5)*64+0.5)+1 + return hitpos.y >= 40 and "down" or "up" + end end end @@ -134,8 +199,8 @@ for _,state in ipairs(validstates) do light = light + 5 end local idle = not (state[2] or state[3]) - local description = string.format("Elevator %s Call Button%s%s",state[4],(state[1] == "both" and "s" or ""),(idle and "" or " (on state, you hacker you!)")) - minetest.register_node(nname,{ + local description = state[4] + core.register_node(nname,{ description = description, groups = { dig_immediate = 2, @@ -167,45 +232,63 @@ for _,state in ipairs(validstates) do }, }, after_place_node = function(pos) - local meta = minetest.get_meta(pos) - meta:set_string("formspec","formspec_version[7]size[8,5]field[0.5,0.5;7,1;carid;Car ID;]field[0.5,2;7,1;landing;Landing Number;]button[3,3.5;2,1;save;Save]") + local meta = core.get_meta(pos) + local idmsg = S("Car ID") + local landingmsg = S("Landing Number") + local savemsg = S("Save") + local fs = "formspec_version[7]size[8,5]" + fs = fs.."field[0.5,0.5;7,1;carid;"..idmsg..";]" + fs = fs.."field[0.5,2;7,1;landing;"..landingmsg..";]" + fs = fs.."button[3,3.5;2,1;save;"..savemsg.."]" + meta:set_string("formspec",fs) end, - on_receive_fields = function(pos,_,fields) + on_receive_fields = function(pos,_,fields,player) if tonumber(fields.carid) and tonumber(fields.landing) then local carid = tonumber(fields.carid) - local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid))) + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) if not carinfo then return end + local controllerpos = carinfo.controllerpos or carinfo.dispatcherpos + local playername = player and player:get_player_name() or "" + if core.is_protected(controllerpos,playername) and not core.check_player_privs(playername,{protection_bypass=true}) then + core.record_protection_violation(controllerpos,playername) + if carinfo.controllerpos then + core.chat_send_player(playername,S("Can't connect to a controller you don't have access to.")) + else + core.chat_send_player(playername,S("Can't connect to a dispatcher you don't have access to.")) + end + return + end table.insert(carinfo.callbuttons,{pos=pos,landing=tonumber(fields.landing)}) - celevator.storage:set_string(string.format("car%d",carid),minetest.serialize(carinfo)) - local meta = minetest.get_meta(pos) + celevator.storage:set_string(string.format("car%d",carid),core.serialize(carinfo)) + local meta = core.get_meta(pos) meta:set_int("carid",carid) meta:set_int("landing",tonumber(fields.landing)) meta:set_string("formspec","") end end, on_destruct = function(pos) - local meta = minetest.get_meta(pos) + local meta = core.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))) + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) if not carinfo then return end for i,button in pairs(carinfo.callbuttons) do if vector.equals(pos,button.pos) then table.remove(carinfo.callbuttons,i) - celevator.storage:set_string(string.format("car%d",carid),minetest.serialize(carinfo)) + celevator.storage:set_string(string.format("car%d",carid),core.serialize(carinfo)) end end end, on_rightclick = function(pos,_,clicker) - local meta = minetest.get_meta(pos) + local meta = core.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))) + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) if not carinfo then return end local controllerpos = carinfo.controllerpos or carinfo.dispatcherpos local isdispatcher = carinfo.dispatcherpos if not controllerpos then return end - local controllermeta = minetest.get_meta(controllerpos) + local controllermeta = core.get_meta(controllerpos) if controllermeta:get_int("carid") ~= carid then return end local landing = meta:get_int("landing") if state[1] == "up" then @@ -239,3 +322,35 @@ for _,state in ipairs(validstates) do end, }) end + +core.register_abm({ + label = "Check call buttons for missing/replaced controllers", + nodenames = {"group:_celevator_callbutton",}, + interval = 15, + chance = 1, + action = function(pos) + local meta = core.get_meta(pos) + local carid = meta:get_int("carid") + if not (carid and carid > 0) then return end --Not set up yet + local carinfo = core.deserialize(celevator.storage:get_string("car"..carid)) + if not carinfo then + meta:set_string("infotext",S("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",S("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",S("Controller/dispatcher found but with incorrect ID!\nPlease remove and replace this node.")) + end + end, +}) @@ -1,25 +1,35 @@ celevator.car = {} -local function disambiguatebutton(pos,facedir,player) +local S = core.get_translator("celevator") + +local function disambiguatecartopbutton(pos,facedir,player) if player and not player.is_fake_player then + local playername = player:get_player_name() + if core.settings:get_bool("celevator.cartop_protected",false) then + if core.is_protected(pos,playername) and not core.check_player_privs(playername,{protection_bypass=true}) then + core.record_protection_violation(pos,playername) + return + end + end 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() local distance = vector.distance(eyepos,pos) local endpos = vector.add(eyepos,vector.multiply(lookdir,distance+1)) - local ray = minetest.raycast(eyepos,endpos,true,false) + local ray = core.raycast(eyepos,endpos,true,false) local pointed,button,hitpos repeat 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 node = core.get_node(pointed.under) + local ndef = core.registered_nodes[node.name] or {} + if ndef._cartopbox then button = pointed.under hitpos = vector.subtract(pointed.intersection_point,button) end end until button or not pointed if not hitpos then return end - hitpos = vector.rotate_around_axis(hitpos,vector.new(0,-1,0),minetest.dir_to_yaw(facedir)+(math.pi/2)) + hitpos = vector.rotate_around_axis(hitpos,vector.new(0,-1,0),core.dir_to_yaw(facedir)+(math.pi/2)) if hitpos.y < 0.55 then return end if hitpos.z > 0.36 or hitpos.z < 0.09 then return end if hitpos.x >= -0.36 and hitpos.x <= -0.16 then @@ -34,33 +44,33 @@ end local function updatecartopbox(pos) local toppos = vector.add(pos,vector.new(0,1.1,0)) - local entitiesnearby = minetest.get_objects_inside_radius(toppos,0.5) + local entitiesnearby = core.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 - local carmeta = minetest.get_meta(pos) + local carmeta = core.get_meta(pos) local carid = carmeta:get_int("carid") if carid == 0 then return end - local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid))) + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) if not carinfo then return end - local entity = minetest.add_entity(pos,"celevator:car_top_box") + local entity = core.add_entity(pos,"celevator:car_top_box") local inspon = carinfo.cartopinspect entity:set_properties({ wield_item = inspon and "celevator:car_top_box_on" or "celevator:car_top_box_off", }) - local fdir = minetest.fourdir_to_dir(minetest.get_node(pos).param2) + local fdir = core.fourdir_to_dir(core.get_node(pos).param2) fdir = vector.rotate_around_axis(fdir,vector.new(0,1,0),math.pi/2) - entity:set_yaw(minetest.dir_to_yaw(fdir)) + entity:set_yaw(core.dir_to_yaw(fdir)) entity:set_pos(toppos) end local held = {} -minetest.register_globalstep(function() +core.register_globalstep(function() for k,v in ipairs(held) do - local player = minetest.get_player_by_name(v.name) + local player = core.get_player_by_name(v.name) if not (player and player:get_player_control()[v.button]) then table.remove(held,k) celevator.controller.handlecartopbox(v.pos,v.control.."_release") @@ -68,539 +78,226 @@ 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 = S("Car (part @1 - you hacker you!)",def._position) + def.light_source = 9 + def.drop = "" + if def._cop then + def.groups._has_cop = 1 + def.on_rightclick = function(pos,_,player) + local meta = core.get_meta(pos) + local carid = meta:get_int("carid") + if carid ~= 0 then celevator.drives.entity.coprightclick(carid,player,pos) end 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.groups._has_keyswitches = 1 + def.on_rightclick = function(pos,_,player) + local meta = core.get_meta(pos) + local carid = meta:get_int("carid") + if carid ~= 0 then celevator.drives.entity.keyswitchrightclick(carid,player,pos) end 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 = core.fourdir_to_dir(node.param2) + local control = disambiguatecartopbutton(pos,fdir,clicker) + if not control then return end + local meta = core.get_meta(pos) + local carid = meta:get_int("carid") + if carid == 0 then return end + local carinfo = core.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 = core.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 = core.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) + core.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 core.is_protected(pos,playername) and not core.check_player_privs(playername,{protection_bypass=true}) then + core.record_protection_violation(pos,playername) + return + end + local hash = core.hash_node_position(pos) + local fs = "formspec_version[7]size[6,4]" + fs = fs.."label[0.5,1;"..S("Really remove this car?").."]" + fs = fs.."button_exit[0.5,2;2,1;yes;"..S("Yes").."]" + fs = fs.."button_exit[3,2;2,1;no;"..S("No").."]" + core.show_formspec(playername,string.format("celevator:remove_car_%d",hash),fs) + end + def.on_timer = function(pos) + local carid = core.get_meta(pos):get_int("carid") + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) + if not (carinfo and carinfo.controllerpos) then return end + local yaw = core.dir_to_yaw(core.fourdir_to_dir(core.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 = core.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 + core.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), - param2 = minetest.dir_to_fourdir(minetest.yaw_to_dir(yaw)), + name = string.format("celevator:car_%s_%d%d%d",name,x,y,z), + param2 = core.dir_to_fourdir(core.yaw_to_dir(yaw)), } - minetest.set_node(pos,node) - if carid then minetest.get_meta(pos):set_int("carid",carid) end + core.set_node(pos,node) + local meta = core.get_meta(pos) + if carid then meta:set_int("carid",carid) end + meta:set_string("doortype",doortype or "glass") end end end end -minetest.register_abm({ +core.register_abm({ label = "Respawn in-car PI displays", - nodenames = {"celevator:car_020"}, + nodenames = {"group:_celevator_car_spawnspi"}, interval = 1, chance = 1, action = function(pos) - local entitiesnearby = minetest.get_objects_inside_radius(pos,0.5) + local entitiesnearby = core.get_objects_inside_radius(pos,0.5) for _,i in pairs(entitiesnearby) do if i:get_luaentity() and i:get_luaentity().name == "celevator:incar_pi_entity" then return end end - local entity = minetest.add_entity(pos,"celevator:incar_pi_entity") - local fdir = vector.rotate_around_axis(minetest.facedir_to_dir(minetest.get_node(pos).param2),vector.new(0,1,0),math.pi/2) + local entity = core.add_entity(pos,"celevator:incar_pi_entity") + local fdir = vector.rotate_around_axis(core.facedir_to_dir(core.get_node(pos).param2),vector.new(0,1,0),math.pi/2) local etex = celevator.pi.generatetexture(" --",false,false,false,true) entity:set_properties({ textures = {etex}, }) - entity:set_yaw(minetest.dir_to_yaw(fdir)) + entity:set_yaw(core.dir_to_yaw(fdir)) entity:set_pos(vector.add(pos,vector.multiply(fdir,0.44))) end, }) -minetest.register_node("celevator:car_top_box_off",{ - description = "Car-top Inspection Box, Off State (you hacker you!)", +core.register_node("celevator:car_top_box_off",{ + description = S("Car-top Inspection Box, Off State (you hacker you!)"), drop = "", groups = { + cracky = 3, + oddly_breakable_by_hand = 1, not_in_creative_inventory = 1, }, paramtype = "light", @@ -617,10 +314,12 @@ minetest.register_node("celevator:car_top_box_off",{ }, }) -minetest.register_node("celevator:car_top_box_on",{ - description = "Car-top Inspection Box, On State (you hacker you!)", +core.register_node("celevator:car_top_box_on",{ + description = S("Car-top Inspection Box, On State (you hacker you!)"), drop = "", groups = { + cracky = 3, + oddly_breakable_by_hand = 1, not_in_creative_inventory = 1, }, paramtype = "light", @@ -637,110 +336,35 @@ minetest.register_node("celevator:car_top_box_on",{ }, }) -minetest.register_entity("celevator:car_top_box",{ +core.register_entity("celevator:car_top_box",{ initial_properties = { visual = "wielditem", visual_size = vector.new(0.667,0.667,0.667), wield_item = "celevator:car_top_box_off", static_save = false, pointable = false, - glow = minetest.LIGHT_MAX, + glow = core.LIGHT_MAX, }, }) -minetest.register_abm({ +core.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) +core.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 rootpos = core.get_position_from_hash(hash) + local rootdef = core.registered_nodes[celevator.get_node(rootpos).name] or {} + local cartype = rootdef._celevator_car_type + if cartype and celevator.car.types[cartype] then + local rootdir = core.dir_to_yaw(core.fourdir_to_dir(core.get_node(rootpos).param2)) + celevator.car.types[cartype].remove(rootpos,rootdir) end end) diff --git a/car_fullglass.lua b/car_fullglass.lua new file mode 100644 index 0000000..f934007 --- /dev/null +++ b/car_fullglass.lua @@ -0,0 +1,425 @@ +local S = core.get_translator("celevator") + +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.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}, + }, + }, + use_texture_alpha = "clip", + tiles = { + "celevator_car_metal_floor.png", + "celevator_car_bottom_center.png", + "celevator_car_side_center_overlay.png^celevator_car_glass.png^celevator_car_wall_bottom.png^celevator_car_wall_vent.png", + "celevator_car_wall_bottom.png^celevator_car_wall_vent.png^celevator_car_glass.png^celevator_car_side_center_overlay.png", + "celevator_car_glass.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_side_overlay.png^[transformFX^celevator_car_glass.png^celevator_car_wall_bottom.png", + "celevator_car_wall_bottom.png^celevator_car_glass.png^celevator_car_side_overlay.png", + "celevator_car_wall_bottom.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.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}, + }, + }, + use_texture_alpha = "clip", + tiles = { + "celevator_car_metal_floor.png", + "celevator_car_bottom_center.png^[transformFX", + "celevator_car_wall_bottom.png^celevator_car_wall_vent.png^celevator_car_glass.png^celevator_car_side_center_overlay.png", + "celevator_car_side_center_overlay.png^celevator_car_glass.png^celevator_car_wall_bottom.png^celevator_car_wall_vent.png", + "celevator_car_glass.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_car_wall_bottom.png^[transformR270^celevator_car_glass.png^celevator_car_side_overlay.png^[transformR90", + "celevator_car_side_overlay.png^celevator_car_glass.png^celevator_car_wall_bottom.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}, + }, + }, + use_texture_alpha = "clip", + tiles = { + "celevator_car_glass.png", + "celevator_car_glass.png", + "celevator_car_side_center2_overlay.png^celevator_car_glass.png^celevator_car_handrail_end.png", + "celevator_car_handrail_end.png^[transformFX^celevator_car_glass.png^celevator_car_side_center2_overlay.png", + "celevator_car_glass.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_car_glass.png", + "celevator_car_glass.png", + "celevator_car_glass.png^(celevator_car_handrail_end.png^[transformFX)", + "celevator_car_handrail_end.png^celevator_car_glass.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}, + }, + }, + use_texture_alpha = "clip", + tiles = { + "celevator_car_glass.png", + "celevator_car_glass.png", + "celevator_car_handrail_center.png^celevator_car_glass.png^celevator_car_side_center2_overlay.png", + "celevator_car_side_center2_overlay.png^celevator_car_glass.png^celevator_car_handrail_center.png", + "celevator_car_glass.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_car_glass.png", + "celevator_car_glass.png", + "celevator_car_handrail_end.png^[transformFX^celevator_car_glass.png", + "celevator_car_glass.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}, + }, + }, + use_texture_alpha = "clip", + tiles = { + "celevator_cabinet_sides.png^celevator_car_top_center_overlay.png", + "celevator_car_metal_ceiling.png", + "celevator_car_side_center_overlay.png^celevator_car_glass.png", + "celevator_car_glass.png^celevator_car_side_center_overlay.png", + "celevator_car_glass.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_glass.png", + "celevator_car_glass.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}, + }, + }, + use_texture_alpha = "clip", + tiles = { + "celevator_cabinet_sides.png^celevator_car_top_center_overlay.png^[transformFX", + "celevator_car_metal_ceiling.png", + "celevator_car_glass.png^celevator_car_side_center_overlay.png", + "celevator_car_side_center_overlay.png^celevator_car_glass.png", + "celevator_car_glass.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_car_glass.png", + "celevator_car_glass.png", + "celevator_car_glass.png", + "celevator_car_glass.png", + }, + _tapehead = true, + }, +} + +celevator.car.register("fullglass",pieces,vector.new(2,3,3)) + + +core.register_node("celevator:car_fullglass",{ + description = S("Full-Glass Elevator Car"), + paramtype2 = "4dir", + buildable_to = true, + inventory_image = "celevator_car_fullglass_inventory.png", + wield_image = "celevator_car_fullglass_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 + core.remove_node(pos) + return true + end + local name = player:get_player_name() + local newnode = core.get_node(pos) + local facedir = core.dir_to_yaw(core.fourdir_to_dir(newnode.param2)) + for x=0,1,1 do + for y=0,2,1 do + for z=0,2,1 do + 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 = core.get_node(placepos).name + if not (core.registered_nodes[replaces] and core.registered_nodes[replaces].buildable_to) then + local message = S("Can't place car here - position @1m to the right, @2m up, and @3m back is blocked!",x,y,z) + core.chat_send_player(name,message) + core.remove_node(pos) + return true + end + if core.is_protected(placepos,name) and not core.check_player_privs(name,{protection_bypass=true}) then + local message = S("Can't place car here - position @1m to the right, @2m up, and @3m back is protected!",x,y,z) + core.chat_send_player(name,message) + core.record_protection_violation(placepos,name) + core.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_fullglass_%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)) + core.set_node(placepos,{name=piecename,param2=newnode.param2}) + end + end + end + end, +}) + +celevator.car.types.fullglass.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_fullglass_%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 core.get_node(piecepos).name == piecename then + core.remove_node(piecepos) + local erefs = core.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 = core.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_glassback.lua b/car_glassback.lua new file mode 100644 index 0000000..1c7163e --- /dev/null +++ b/car_glassback.lua @@ -0,0 +1,419 @@ +local S = core.get_translator("celevator") + +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.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.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)) + + +core.register_node("celevator:car_glassback",{ + description = S("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 + core.remove_node(pos) + return true + end + local name = player:get_player_name() + local newnode = core.get_node(pos) + local facedir = core.dir_to_yaw(core.fourdir_to_dir(newnode.param2)) + for x=0,1,1 do + for y=0,2,1 do + for z=0,2,1 do + 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 = core.get_node(placepos).name + if not (core.registered_nodes[replaces] and core.registered_nodes[replaces].buildable_to) then + local message = S("Can't place car here - position @1m to the right, @2m up, and @3m back is blocked!",x,y,z) + core.chat_send_player(name,message) + core.remove_node(pos) + return true + end + if core.is_protected(placepos,name) and not core.check_player_privs(name,{protection_bypass=true}) then + local message = S("Can't place car here - position @1m to the right, @2m up, and @3m back is protected!",x,y,z) + core.chat_send_player(name,message) + core.record_protection_violation(placepos,name) + core.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)) + core.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 core.get_node(piecepos).name == piecename then + core.remove_node(piecepos) + local erefs = core.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 = core.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..c3d1a44 --- /dev/null +++ b/car_metal.lua @@ -0,0 +1,413 @@ +local S = core.get_translator("celevator") + +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.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.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)) + + +core.register_node("celevator:car_metal",{ + description = S("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 + core.remove_node(pos) + return true + end + local name = player:get_player_name() + local newnode = core.get_node(pos) + local facedir = core.dir_to_yaw(core.fourdir_to_dir(newnode.param2)) + for x=0,1,1 do + for y=0,2,1 do + for z=0,2,1 do + 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 = core.get_node(placepos).name + if not (core.registered_nodes[replaces] and core.registered_nodes[replaces].buildable_to) then + local message = S("Can't place car here - position @1m to the right, @2m up, and @3m back is blocked!",x,y,z) + core.chat_send_player(name,message) + core.remove_node(pos) + return true + end + if core.is_protected(placepos,name) and not core.check_player_privs(name,{protection_bypass=true}) then + local message = S("Can't place car here - position @1m to the right, @2m up, and @3m back is protected!",x,y,z) + core.chat_send_player(name,message) + core.record_protection_violation(placepos,name) + core.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)) + core.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 core.get_node(piecepos).name == piecename then + core.remove_node(piecepos) + local erefs = core.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 = core.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..7ca944e --- /dev/null +++ b/car_metalglass.lua @@ -0,0 +1,419 @@ +local S = core.get_translator("celevator") + +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.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.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)) + + +core.register_node("celevator:car_metal_glassback",{ + description = S("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 + core.remove_node(pos) + return true + end + local name = player:get_player_name() + local newnode = core.get_node(pos) + local facedir = core.dir_to_yaw(core.fourdir_to_dir(newnode.param2)) + for x=0,1,1 do + for y=0,2,1 do + for z=0,2,1 do + 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 = core.get_node(placepos).name + if not (core.registered_nodes[replaces] and core.registered_nodes[replaces].buildable_to) then + local message = S("Can't place car here - position @1m to the right, @2m up, and @3m back is blocked!",x,y,z) + core.chat_send_player(name,message) + core.remove_node(pos) + return true + end + if core.is_protected(placepos,name) and not core.check_player_privs(name,{protection_bypass=true}) then + local message = S("Can't place car here - position @1m to the right, @2m up, and @3m back is protected!",x,y,z) + core.chat_send_player(name,message) + core.record_protection_violation(placepos,name) + core.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)) + core.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 core.get_node(piecepos).name == piecename then + core.remove_node(piecepos) + local erefs = core.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 = core.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..44f74bb --- /dev/null +++ b/car_standard.lua @@ -0,0 +1,422 @@ +local S = core.get_translator("celevator") + +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.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.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 + core.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 + +core.register_node("celevator:car_standard",{ + description = S("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 + core.remove_node(pos) + return true + end + local name = player:get_player_name() + local newnode = core.get_node(pos) + local facedir = core.dir_to_yaw(core.fourdir_to_dir(newnode.param2)) + for x=0,1,1 do + for y=0,2,1 do + for z=0,2,1 do + 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 = core.get_node(placepos).name + if not (core.registered_nodes[replaces] and core.registered_nodes[replaces].buildable_to) then + local message = S("Can't place car here - position @1m to the right, @2m up, and @3m back is blocked!",x,y,z) + core.chat_send_player(name,message) + core.remove_node(pos) + return true + end + if core.is_protected(placepos,name) and not core.check_player_privs(name,{protection_bypass=true}) then + local message = S("Can't place car here - position @1m to the right, @2m up, and @3m back is protected!",x,y,z) + core.chat_send_player(name,message) + core.record_protection_violation(placepos,name) + core.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)) + core.set_node(placepos,{name=piecename,param2=newnode.param2}) + end + end + end + end, +}) + +core.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 core.get_node(piecepos).name == piecename then + core.remove_node(piecepos) + local erefs = core.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 = core.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..eacb4f0 --- /dev/null +++ b/chatcommands.lua @@ -0,0 +1,183 @@ +local S = core.get_translator("celevator") + +core.register_chatcommand("carcall",{ + description = S("Places a car call at the specified landing on the specified elevator"), + params = S("<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,S("Invalid car ID") + end + if not (landing and tonumber(landing)) then + return false,S("Invalid landing number") + end + local carinfo = core.deserialize(celevator.storage:get_string("car"..carid)) + if not (carinfo and carinfo.controllerpos) then + return false,S("No such car or car info is missing") + end + if not celevator.controller.iscontroller(carinfo.controllerpos) then + return false,S("Controller is missing") + end + if celevator.get_meta(carinfo.controllerpos):get_int("carid") ~= tonumber(carid) then + return false,S("Controller found but with wrong ID") + end + if core.is_protected(carinfo.controllerpos,name) then + core.record_protection_violation(carinfo.controllerpos,name) + return false,S("Controller is protected") + end + celevator.controller.run(carinfo.controllerpos,{ + type = "remotemsg", + channel = "carcall", + msg = tonumber(landing), + }) + return true,S("Command sent") + end, +}) + +core.register_chatcommand("upcall",{ + description = S("Places an up hall call at the specified landing on the specified elevator or dispatcher"), + params = S("<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,S("Invalid car ID") + end + if not (landing and tonumber(landing)) then + return false,S("Invalid landing number") + end + local carinfo = core.deserialize(celevator.storage:get_string("car"..carid)) + if not (carinfo and (carinfo.controllerpos or carinfo.dispatcherpos)) then + return false,S("No such car or car info is missing") + end + if carinfo.controllerpos then + if not celevator.controller.iscontroller(carinfo.controllerpos) then + return false,S("Controller is missing") + end + if celevator.get_meta(carinfo.controllerpos):get_int("carid") ~= tonumber(carid) then + return false,S("Controller found but with wrong ID") + end + if core.is_protected(carinfo.controllerpos,name) then + core.record_protection_violation(carinfo.controllerpos,name) + return false,S("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,S("Command sent") + elseif carinfo.dispatcherpos then + if not celevator.dispatcher.isdispatcher(carinfo.dispatcherpos) then + return false,S("Dispatcher is missing") + end + if celevator.get_meta(carinfo.dispatcherpos):get_int("carid") ~= tonumber(carid) then + return false,S("Dispatcher found but with wrong ID") + end + if core.is_protected(carinfo.dispatcherpos,name) then + core.record_protection_violation(carinfo.dispatcherpos,name) + return false,S("Dispatcher is protected") + end + celevator.dispatcher.run(carinfo.dispatcherpos,{ + type = "remotemsg", + channel = "upcall", + msg = tonumber(landing), + }) + return true,S("Command sent") + end + end, +}) + +core.register_chatcommand("downcall",{ + description = S("Places a down hall call at the specified landing on the specified elevator or dispatcher"), + params = S("<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,S("Invalid car ID") + end + if not (landing and tonumber(landing)) then + return false,S("Invalid landing number") + end + local carinfo = core.deserialize(celevator.storage:get_string("car"..carid)) + if not (carinfo and (carinfo.controllerpos or carinfo.dispatcherpos)) then + return false,S("No such car or car info is missing") + end + if carinfo.controllerpos then + if not celevator.controller.iscontroller(carinfo.controllerpos) then + return false,S("Controller is missing") + end + if celevator.get_meta(carinfo.controllerpos):get_int("carid") ~= tonumber(carid) then + return false,S("Controller found but with wrong ID") + end + if core.is_protected(carinfo.controllerpos,name) then + core.record_protection_violation(carinfo.controllerpos,name) + return false,S("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,S("Command sent") + elseif carinfo.dispatcherpos then + if not celevator.dispatcher.isdispatcher(carinfo.dispatcherpos) then + return false,S("Dispatcher is missing") + end + if celevator.get_meta(carinfo.dispatcherpos):get_int("carid") ~= tonumber(carid) then + return false,S("Dispatcher found but with wrong ID") + end + if core.is_protected(carinfo.dispatcherpos,name) then + core.record_protection_violation(carinfo.dispatcherpos,name) + return false,S("Dispatcher is protected") + end + celevator.dispatcher.run(carinfo.dispatcherpos,{ + type = "remotemsg", + channel = "dncall", + msg = tonumber(landing), + }) + return true,S("Command sent") + end + end, +}) + +core.register_chatcommand("elevstatus",{ + description = S("View the status of the specified elevator"), + params = S("<car ID>"), + func = function(_,param) + if not (param and tonumber(param)) then + return false,S("Invalid car ID") + end + local carinfo = core.deserialize(celevator.storage:get_string("car"..param)) + if not (carinfo and carinfo.controllerpos) then + return false,S("No such car or car info is missing") + end + if not celevator.controller.iscontroller(carinfo.controllerpos) then + return false,S("Controller is missing") + end + local controllermeta = celevator.get_meta(carinfo.controllerpos) + if controllermeta:get_int("carid") ~= tonumber(param) then + return false,S("Controller found but with wrong ID") + end + local mem = core.deserialize(controllermeta:get_string("mem")) + if not mem then + return false,S("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..d6c4ee9 100644 --- a/controller.lua +++ b/controller.lua @@ -1,23 +1,25 @@ celevator.controller = {} -celevator.controller.iqueue = minetest.deserialize(celevator.storage:get_string("controller_iqueue")) or {} +local S = core.get_translator("celevator") -celevator.controller.equeue = minetest.deserialize(celevator.storage:get_string("controller_equeue")) or {} +celevator.controller.iqueue = core.deserialize(celevator.storage:get_string("controller_iqueue")) or {} + +celevator.controller.equeue = core.deserialize(celevator.storage:get_string("controller_equeue")) or {} celevator.controller.running = {} -local fw,err = loadfile(minetest.get_modpath("celevator")..DIR_DELIM.."controllerfw.lua") +local fw,err = loadfile(core.get_modpath("celevator").."/controllerfw.lua") if not fw then error(err) end -minetest.register_chatcommand("celevator_reloadcontroller",{ +core.register_chatcommand("celevator_reloadcontroller",{ params = "", - description = "Reload celevator controller firmware from disk", + description = S("Reload celevator controller firmware from disk"), privs = {server = true}, func = function() - local newfw,loaderr = loadfile(minetest.get_modpath("celevator")..DIR_DELIM.."controllerfw.lua") + local newfw,loaderr = loadfile(core.get_modpath("celevator").."/controllerfw.lua") if newfw then fw = newfw - return true,"Firmware reloaded successfully" + return true,S("Firmware reloaded successfully") else return false,loaderr end @@ -25,32 +27,32 @@ minetest.register_chatcommand("celevator_reloadcontroller",{ }) local function after_place(pos,placer) - local node = minetest.get_node(pos) + local node = core.get_node(pos) local toppos = {x=pos.x,y=pos.y + 1,z=pos.z} - local topnode = minetest.get_node(toppos) + local topnode = core.get_node(toppos) local placername = placer:get_player_name() if topnode.name ~= "air" then if placer:is_player() then - minetest.chat_send_player(placername,"Can't place cabinet - no room for the top half!") + core.chat_send_player(placername,S("Can't place cabinet - no room for the top half!")) end - minetest.set_node(pos,{name="air"}) + core.set_node(pos,{name="air"}) return true end - if minetest.is_protected(toppos,placername) and not minetest.check_player_privs(placername,{protection_bypass=true}) then + if core.is_protected(toppos,placername) and not core.check_player_privs(placername,{protection_bypass=true}) then if placer:is_player() then - minetest.chat_send_player(placername,"Can't place cabinet - top half is protected!") - minetest.record_protection_violation(toppos,placername) + core.chat_send_player(placername,S("Can't place cabinet - top half is protected!")) + core.record_protection_violation(toppos,placername) end - minetest.set_node(pos,{name="air"}) + core.set_node(pos,{name="air"}) return true end node.name = "celevator:controller_top" - minetest.set_node(toppos,node) + core.set_node(toppos,node) end local function ondestruct(pos) pos.y = pos.y + 1 - local topnode = minetest.get_node(pos) + local topnode = core.get_node(pos) local controllertops = { ["celevator:controller_top"] = true, ["celevator:controller_top_running"] = true, @@ -58,32 +60,38 @@ local function ondestruct(pos) ["celevator:controller_top_open_running"] = true, } if controllertops[topnode.name] then - minetest.set_node(pos,{name="air"}) + core.set_node(pos,{name="air"}) end - celevator.controller.equeue[minetest.hash_node_position(pos)] = nil - celevator.storage:set_string("controller_equeue",minetest.serialize(celevator.controller.equeue)) - local carid = minetest.get_meta(pos):get_int("carid") + celevator.controller.equeue[core.hash_node_position(pos)] = nil + celevator.storage:set_string("controller_equeue",core.serialize(celevator.controller.equeue)) + local carid = core.get_meta(pos):get_int("carid") if carid ~= 0 then celevator.storage:set_string(string.format("car%d",carid),"") end end local function onrotate(controllerpos,node,user,mode,new_param2) - if not minetest.global_exists("screwdriver") then + if not core.global_exists("screwdriver") then return false end local ret = screwdriver.rotate_simple(controllerpos,node,user,mode,new_param2) - minetest.after(0,function(pos) - local newnode = minetest.get_node(pos) + core.after(0,function(pos) + local newnode = core.get_node(pos) local param2 = newnode.param2 pos.y = pos.y + 1 - local topnode = minetest.get_node(pos) + local topnode = core.get_node(pos) topnode.param2 = param2 - minetest.set_node(pos,topnode) + core.set_node(pos,topnode) end,controllerpos) return ret end local function handlefields(pos,_,fields,sender) local playername = sender and sender:get_player_name() or "" + if core.settings:get_bool("celevator.controller_screen_protected",false) then + if core.is_protected(pos,playername) and not core.check_player_privs(playername,{protection_bypass=true}) then + core.record_protection_violation(pos,playername) + return + end + end local event = {} event.type = "ui" event.fields = fields @@ -99,20 +107,20 @@ local function controllerleds(pos,running) } if node.name == "celevator:controller_top_open" and running then node.name = "celevator:controller_top_open_running" - minetest.swap_node(toppos,node) - minetest.sound_play("celevator_controller_start",sparams,true) + core.swap_node(toppos,node) + core.sound_play("celevator_controller_start",sparams,true) elseif node.name == "celevator:controller_top" and running then node.name = "celevator:controller_top_running" - minetest.swap_node(toppos,node) - minetest.sound_play("celevator_controller_start",sparams,true) + core.swap_node(toppos,node) + core.sound_play("celevator_controller_start",sparams,true) elseif node.name == "celevator:controller_top_open_running" and not running then node.name = "celevator:controller_top_open" - minetest.swap_node(toppos,node) - minetest.sound_play("celevator_controller_stop",sparams,true) + core.swap_node(toppos,node) + core.sound_play("celevator_controller_stop",sparams,true) elseif node.name == "celevator:controller_top_running" and not running then node.name = "celevator:controller_top" - minetest.swap_node(toppos,node) - minetest.sound_play("celevator_controller_stop",sparams,true) + core.swap_node(toppos,node) + core.sound_play("celevator_controller_stop",sparams,true) end end @@ -121,15 +129,16 @@ local function candig(_,player) if controls.sneak then return true else - minetest.chat_send_player(player:get_player_name(),"Hold the sneak button while digging to remove.") + core.chat_send_player(player:get_player_name(),S("Hold the sneak button while digging to remove.")) return false end end -minetest.register_node("celevator:controller",{ - description = "Elevator Controller", +core.register_node("celevator:controller",{ + description = S("Elevator Controller"), groups = { - cracky = 1, + cracky = 3, + oddly_breakable_by_hand = 1, }, paramtype = "light", paramtype2 = "facedir", @@ -160,15 +169,15 @@ minetest.register_node("celevator:controller",{ on_receive_fields = handlefields, can_dig = candig, on_construct = function(pos) - local meta = minetest.get_meta(pos) - meta:set_string("mem",minetest.serialize({})) + local meta = core.get_meta(pos) + meta:set_string("mem",core.serialize({})) meta:mark_as_private("mem") local event = {} event.type = "program" local carid = celevator.storage:get_int("maxcarid")+1 meta:set_int("carid",carid) celevator.storage:set_int("maxcarid",carid) - celevator.storage:set_string(string.format("car%d",carid),minetest.serialize({controllerpos=pos,pis={},lanterns={},callbuttons={},fs1switches={}})) + celevator.storage:set_string(string.format("car%d",carid),core.serialize({controllerpos=pos,pis={},lanterns={},callbuttons={},fs1switches={}})) celevator.controller.run(pos,event) end, on_punch = function(pos,node,puncher) @@ -176,24 +185,26 @@ minetest.register_node("celevator:controller",{ return end local name = puncher: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,"Can't open cabinet - cabinet is locked.") - minetest.record_protection_violation(pos,name) - return + if core.settings:get_bool("celevator.controller_cabinet_protected",true) then + if core.is_protected(pos,name) and not core.check_player_privs(name,{protection_bypass=true}) then + core.chat_send_player(name,S("Can't open cabinet - cabinet is locked.")) + core.record_protection_violation(pos,name) + return + end end node.name = "celevator:controller_open" - minetest.swap_node(pos,node) - local meta = minetest.get_meta(pos) + core.swap_node(pos,node) + local meta = core.get_meta(pos) meta:set_string("formspec",meta:get_string("formspec_hidden")) pos.y = pos.y + 1 - node = minetest.get_node(pos) + node = core.get_node(pos) if node.name == "celevator:controller_top_running" then node.name = "celevator:controller_top_open_running" else node.name = "celevator:controller_top_open" end - minetest.swap_node(pos,node) - minetest.sound_play("celevator_cabinet_open",{ + core.swap_node(pos,node) + core.sound_play("celevator_cabinet_open",{ pos = pos, gain = 0.5, max_hear_distance = 10 @@ -201,10 +212,11 @@ minetest.register_node("celevator:controller",{ end, }) -minetest.register_node("celevator:controller_open",{ - description = "Controller (door open - you hacker you!)", +core.register_node("celevator:controller_open",{ + description = S("Controller (door open - you hacker you!)"), groups = { - cracky = 1, + cracky = 3, + oddly_breakable_by_hand = 1, not_in_creative_inventory = 1, }, paramtype = "light", @@ -243,18 +255,18 @@ minetest.register_node("celevator:controller_open",{ return end node.name = "celevator:controller" - minetest.swap_node(pos,node) - local meta = minetest.get_meta(pos) + core.swap_node(pos,node) + local meta = core.get_meta(pos) meta:set_string("formspec","") pos.y = pos.y + 1 - node = minetest.get_node(pos) + node = core.get_node(pos) if node.name == "celevator:controller_top_open_running" then node.name = "celevator:controller_top_running" else node.name = "celevator:controller_top" end - minetest.swap_node(pos,node) - minetest.sound_play("celevator_cabinet_close",{ + core.swap_node(pos,node) + core.sound_play("celevator_cabinet_close",{ pos = pos, gain = 0.5, max_hear_distance = 10 @@ -262,9 +274,11 @@ minetest.register_node("celevator:controller_open",{ end, }) -minetest.register_node("celevator:controller_top",{ - description = "Controller (top section - you hacker you!)", +core.register_node("celevator:controller_top",{ + description = S("Controller (top section - you hacker you!)"), groups = { + cracky = 3, + oddly_breakable_by_hand = 1, not_in_creative_inventory = 1, }, drop = "", @@ -293,9 +307,11 @@ minetest.register_node("celevator:controller_top",{ }, }) -minetest.register_node("celevator:controller_top_running",{ - description = "Controller (top section, car in motion - you hacker you!)", +core.register_node("celevator:controller_top_running",{ + description = S("Controller (top section, car in motion - you hacker you!)"), groups = { + cracky = 3, + oddly_breakable_by_hand = 1, not_in_creative_inventory = 1, }, drop = "", @@ -324,9 +340,11 @@ minetest.register_node("celevator:controller_top_running",{ }, }) -minetest.register_node("celevator:controller_top_open",{ - description = "Controller (top section, open - you hacker you!)", +core.register_node("celevator:controller_top_open",{ + description = S("Controller (top section, open - you hacker you!)"), groups = { + cracky = 3, + oddly_breakable_by_hand = 1, not_in_creative_inventory = 1, }, drop = "", @@ -360,9 +378,11 @@ minetest.register_node("celevator:controller_top_open",{ }, }) -minetest.register_node("celevator:controller_top_open_running",{ - description = "Controller (top section, open, car in motion - you hacker you!)", +core.register_node("celevator:controller_top_open_running",{ + description = S("Controller (top section, open, car in motion - you hacker you!)"), groups = { + cracky = 3, + oddly_breakable_by_hand = 1, not_in_creative_inventory = 1, }, drop = "", @@ -403,24 +423,24 @@ end function celevator.controller.finddrive(pos) local node = celevator.get_node(pos) - local dir = minetest.facedir_to_dir(node.param2) + local dir = core.facedir_to_dir(node.param2) local drivepos = vector.add(pos,vector.new(0,1,0)) drivepos = vector.add(drivepos,vector.rotate_around_axis(dir,vector.new(0,-1,0),math.pi/2)) drivepos = vector.round(drivepos) local drivename = celevator.get_node(drivepos).name - return drivepos,minetest.registered_nodes[drivename]._celevator_drive_type + return drivepos,core.registered_nodes[drivename]._celevator_drive_type end function celevator.controller.finish(pos,mem,changedinterrupts) if not celevator.controller.iscontroller(pos) then return else - local meta = minetest.get_meta(pos) + local meta = core.get_meta(pos) local carid = meta:get_int("carid") - local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid))) + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) local carinfodirty = false if not carinfo then - minetest.log("error","[celevator] [controller] Bad car info for controller at "..minetest.pos_to_string(pos)) + core.log("error",string.format("[celevator] [controller] Bad car info for controller at %s",core.pos_to_string(pos))) return end local drivepos,drivetype = celevator.controller.finddrive(pos) @@ -435,7 +455,7 @@ function celevator.controller.finish(pos,mem,changedinterrupts) elseif command.command == "estop" then celevator.drives[drivetype].estop(drivepos) elseif command.command == "open" then - minetest.after(0.25,celevator.drives[drivetype].movedoors,drivepos,"open") + core.after(0.25,celevator.drives[drivetype].movedoors,drivepos,"open") elseif command.command == "close" then celevator.drives[drivetype].movedoors(drivepos,"close",command.nudge) elseif command.command == "resetfault" then @@ -444,13 +464,22 @@ 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 {} + local oldmem = core.deserialize(meta:get_string("mem")) or {} local oldupbuttonlights = oldmem.upcalls or {} 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 @@ -533,10 +562,10 @@ function celevator.controller.finish(pos,mem,changedinterrupts) meta:set_string("copformspec",mem.copformspec) meta:set_string("switchformspec",mem.switchformspec) if (mem.copformspec ~= oldmem.copformspec or mem.switchformspec ~= oldmem.switchformspec) and drivetype then - minetest.after(0.25,celevator.drives[drivetype].updatecopformspec,drivepos) + core.after(0.25,celevator.drives[drivetype].updatecopformspec,drivepos) end for _,message in ipairs(mem.messages) do - local destinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",message.carid))) + local destinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",message.carid))) if destinfo and destinfo.dispatcherpos then celevator.dispatcher.run(destinfo.dispatcherpos,{ type = "controllermsg", @@ -546,26 +575,26 @@ function celevator.controller.finish(pos,mem,changedinterrupts) }) end end - meta:set_string("mem",minetest.serialize(mem)) + meta:set_string("mem",core.serialize(mem)) if node.name == "celevator:controller_open" then meta:set_string("formspec",mem.formspec or "") end meta:set_string("formspec_hidden",mem.formspec or "") meta:set_string("infotext",mem.infotext or "") - local hash = minetest.hash_node_position(pos) + local hash = core.hash_node_position(pos) if not celevator.controller.iqueue[hash] then celevator.controller.iqueue[hash] = mem.interrupts end for iid in pairs(changedinterrupts) do celevator.controller.iqueue[hash][iid] = mem.interrupts[iid] end - celevator.storage:set_string("controller_iqueue",minetest.serialize(celevator.controller.iqueue)) + celevator.storage:set_string("controller_iqueue",core.serialize(celevator.controller.iqueue)) controllerleds(pos,mem.showrunning) celevator.controller.running[hash] = nil if #celevator.controller.equeue[hash] > 0 then local event = celevator.controller.equeue[hash][1] table.remove(celevator.controller.equeue[hash],1) - celevator.storage:set_string("controller_equeue",minetest.serialize(celevator.controller.equeue)) + celevator.storage:set_string("controller_equeue",core.serialize(celevator.controller.equeue)) celevator.controller.run(pos,event) end if carinfodirty then - celevator.storage:set_string(string.format("car%d",carid),minetest.serialize(carinfo)) + celevator.storage:set_string(string.format("car%d",carid),core.serialize(carinfo)) end end end @@ -574,25 +603,27 @@ function celevator.controller.run(pos,event) if not celevator.controller.iscontroller(pos) then return else - local hash = minetest.hash_node_position(pos) + local hash = core.hash_node_position(pos) if not celevator.controller.equeue[hash] then celevator.controller.equeue[hash] = {} - celevator.storage:set_string("controller_equeue",minetest.serialize(celevator.controller.equeue)) + celevator.storage:set_string("controller_equeue",core.serialize(celevator.controller.equeue)) end if celevator.controller.running[hash] then table.insert(celevator.controller.equeue[hash],event) - celevator.storage:set_string("controller_equeue",minetest.serialize(celevator.controller.equeue)) + celevator.storage:set_string("controller_equeue",core.serialize(celevator.controller.equeue)) if #celevator.controller.equeue[hash] > 5 then - local message = "[celevator] [controller] Async process for controller at %s is falling behind, %d events in queue" - minetest.log("warning",string.format(message,minetest.pos_to_string(pos),#celevator.controller.equeue[hash])) + local pstring = core.pos_to_string(pos) + local queuelen = #celevator.controller.equeue[hash] + local message = string.format("[celevator] [controller] Async process for controller at %s is falling behind, %d events in queue",pstring,queuelen) + core.log("warning",message) end return end celevator.controller.running[hash] = true - local meta = minetest.get_meta(pos) - local mem = minetest.deserialize(meta:get_string("mem")) + local meta = core.get_meta(pos) + local mem = core.deserialize(meta:get_string("mem")) if not mem then - minetest.log("error","[celevator] [controller] Failed to load controller memory at "..minetest.pos_to_string(pos)) + core.log("error",string.format("[celevator] [controller] Failed to load controller memory at %s",core.pos_to_string(pos))) return end mem.drive = {} @@ -602,9 +633,9 @@ function celevator.controller.run(pos,event) mem.drive.type = drivetype mem.drive.status = celevator.drives[drivetype].getstatus(drivepos) end - mem.interrupts = celevator.controller.iqueue[minetest.hash_node_position(pos)] or {} + mem.interrupts = celevator.controller.iqueue[core.hash_node_position(pos)] or {} mem.carid = meta:get_int("carid") - minetest.handle_async(fw,celevator.controller.finish,pos,event,mem) + core.handle_async(fw,celevator.controller.finish,pos,event,mem) end end @@ -635,8 +666,10 @@ end function celevator.controller.checkiqueue(dtime) for hash,iqueue in pairs(celevator.controller.iqueue) do - local pos = minetest.get_position_from_hash(hash) + local pos = core.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,7 +679,11 @@ 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",core.serialize(celevator.controller.iqueue)) + end end end -minetest.register_globalstep(celevator.controller.checkiqueue) +core.register_globalstep(celevator.controller.checkiqueue) diff --git a/controllerfw.lua b/controllerfw.lua index eeb8814..fe23066 100644 --- a/controllerfw.lua +++ b/controllerfw.lua @@ -1,5 +1,7 @@ local pos,event,mem = ... +local S = core.get_translator("celevator") + local changedinterrupts = {} mem.messages = {} @@ -40,40 +42,44 @@ end local juststarted = false local modenames = { - normal = "Normal Operation", - uninit = "Uninitialized", - resync = "Position Sync - Floor", - bfdemand = "Position Sync - Terminal", - fault = "Fault", - stop = "Emergency Stop", - mrinspect = "Machine Room Inspection", - carinspect = "Car Top Inspection", - inspconflict = "Inspection Conflict", - fs1 = "Fire Service - Phase 1", - fs2 = "Fire Service - Phase 2", - fs2hold = "Fire Service - Phase 2 Hold", - indep = "Independent Service", - capture = "Captured", - test = "Test Mode", + normal = S("Normal Operation"), + uninit = S("Uninitialized"), + resync = S("Position Sync - Floor"), + bfdemand = S("Position Sync - Terminal"), + fault = S("Fault"), + stop = S("Emergency Stop"), + mrinspect = S("Machine Room Inspection"), + carinspect = S("Car Top Inspection"), + inspconflict = "Inspection Conflict", --No longer used but some controllers may be in it at update time + fs1 = S("Fire Service - Phase 1"), + fs2 = S("Fire Service - Phase 2"), + fs2hold = S("Fire Service - Phase 2 Hold"), + indep = S("Independent Service"), + capture = S("Captured"), + test = S("Test Mode"), + swing = S("Swing Operation"), } local doorstates = { - open = "Open", - opening = "Opening", - closing = "Closing", - closed = "Closed", - testtiming = "Closed", + open = S("Doors Open"), + opening = S("Doors Opening"), + closing = S("Doors Closing"), + closed = S("Doors Closed"), + testtiming = S("Doors Closed"), } local faultnames = { - opentimeout = "Door Open Timeout", - closetimeout = "Door Close Timeout", - drivecomm = "Lost Communication With Drive", - driveuninit = "Drive Not Configured", - drivemetaload = "Drive Metadata Load Failure", - drivebadorigin = "Drive Origin Invalid", - drivedoorinterlock = "Attempted to Move Doors With Car in Motion", - driveoutofbounds = "Target Position Out of Bounds", + opentimeout = S("Door Open Timeout"), + closetimeout = S("Door Close Timeout"), + drivecomm = S("Lost Communication With Drive"), + driveuninit = S("Drive Not Configured"), + drivemetaload = S("Drive Metadata Load Failure"), + drivebadorigin = S("Drive Origin Invalid"), + drivedoorinterlock = S("Attempted to Move Doors With Car in Motion"), + driveoutofbounds = S("Target Position Out of Bounds"), + drivenomachine = S("Hoist Machine Missing"), + drivemachinemismatch = S("Drive<->Machine ID Mismatch"), + drivecontrollermismatch = S("Controller<->Drive ID Mismatch"), } local function drivecmd(command) @@ -93,7 +99,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 +201,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 +234,30 @@ 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 mem.params and not mem.params.suppressbeep then mem.params.suppressbeep = {} end +if mem.params and not mem.params.hiddenbuttons then mem.params.hiddenbuttons = {} end +if mem.params and not mem.params.alwayshiddenbuttons then mem.params.alwayshiddenbuttons = {} 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 +303,10 @@ if event.type == "program" then inspectionspeed = 0.2, indepunlock = {}, secoverrideusers = {}, + swingcallwhennotswing = true, + suppressbeep = {}, + hiddenbuttons = {}, + alwayshiddenbuttons = {}, } end elseif event.type == "ui" then @@ -303,7 +335,8 @@ elseif event.type == "ui" then mem.screenstate = "oobe_groupmode" end elseif mem.screenstate == "oobe_floortable" or mem.screenstate == "floortable" then - local exp = event.fields.floor and minetest.explode_textlist_event(event.fields.floor) or {} + local exp = event.fields.floor and core.explode_textlist_event(event.fields.floor) or {} + local maxfloors = tonumber(core.settings:get("celevator.max_landings")) or 100 if event.fields.back then mem.screenstate = "oobe_groupmode" elseif event.fields.next then @@ -335,14 +368,15 @@ elseif event.type == "ui" then mem.screenstate = (mem.screenstate == "oobe_floortable" and "oobe_floortable_edit" or "floortable_edit") elseif event.fields.edit then mem.screenstate = (mem.screenstate == "oobe_floortable" and "oobe_floortable_edit" or "floortable_edit") - 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.add and #mem.params.floornames < maxfloors then + table.insert(mem.params.floorheights,mem.params.floorheights[#mem.params.floorheights] or 5) + local previous = tonumber(mem.params.floornames[#mem.params.floornames]) or #mem.params.floornames + table.insert(mem.params.floornames,tostring(math.floor(previous)+1)) + 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) - elseif event.fields.moveup then + elseif event.fields.moveup and mem.editingfloor < #mem.params.floornames then local height = mem.params.floorheights[mem.editingfloor] local name = mem.params.floornames[mem.editingfloor] table.remove(mem.params.floorheights,mem.editingfloor) @@ -350,7 +384,7 @@ elseif event.type == "ui" then table.insert(mem.params.floorheights,mem.editingfloor+1,height) table.insert(mem.params.floornames,mem.editingfloor+1,name) mem.editingfloor = mem.editingfloor + 1 - elseif event.fields.movedown then + elseif event.fields.movedown and mem.editingfloor > 1 then local height = mem.params.floorheights[mem.editingfloor] local name = mem.params.floornames[mem.editingfloor] table.remove(mem.params.floorheights,mem.editingfloor) @@ -363,7 +397,7 @@ elseif event.type == "ui" then if event.fields.back or event.fields.save then mem.screenstate = (mem.screenstate == "oobe_floortable_edit" and "oobe_floortable" or "floortable") local height = tonumber(event.fields.height) - if height then + if height and height < (tonumber(core.settings:get("celevator.max_height")) or 100) then height = math.floor(height+0.5) mem.params.floorheights[mem.editingfloor] = math.max(1,height) end @@ -377,7 +411,8 @@ elseif event.type == "ui" then mem.params.doortimer = doortimer end local contractspeed = tonumber(event.fields.contractspeed) - if contractspeed and contractspeed >= 0.1 and contractspeed <= 20 then + local maxspeed = tonumber(core.settings:get("celevator.max_speed")) or 20 + if contractspeed and contractspeed >= 0.1 and contractspeed <= maxspeed then mem.params.contractspeed = contractspeed end local nudgetimer = tonumber(event.fields.nudgetimer) @@ -428,16 +463,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 @@ -445,10 +481,10 @@ elseif event.type == "ui" then end end end - if event.fields.scrollup then + if event.fields.scrollup and (mem.screenpage-1)*10+1 < #mem.params.floornames then mem.screenpage = mem.screenpage + 1 mem.scrollfollowscar = false - elseif event.fields.scrolldown then + elseif event.fields.scrolldown and mem.screenpage > 1 then mem.screenpage = mem.screenpage - 1 mem.scrollfollowscar = false elseif event.fields.scrollfollowscar then @@ -494,19 +530,47 @@ elseif event.type == "ui" then if event.fields.back then mem.screenstate = "status" elseif event.fields.clear then + local wasfatalfaulted = mem.fatalfault mem.faultlog = {} mem.activefaults = {} mem.fatalfault = false drivecmd({command = "resetfault"}) + if wasfatalfaulted then + 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 end elseif mem.screenstate == "carcallsecurity" then if event.fields.indepunlock then mem.params.indepunlock[mem.editingfloor] = (event.fields.indepunlock == "true") end + if event.fields.suppressbeep then + mem.params.suppressbeep[mem.editingfloor] = (event.fields.suppressbeep == "true") + end + if event.fields.hidebutton then + mem.params.hiddenbuttons[mem.editingfloor] = (event.fields.hidebutton == "true") + end + if event.fields.alwayshidebutton then + mem.params.alwayshiddenbuttons[mem.editingfloor] = (event.fields.alwayshidebutton == "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 - local exp = minetest.explode_textlist_event(event.fields.floor) or {} + local exp = core.explode_textlist_event(event.fields.floor) or {} if exp.type == "CHG" then mem.editingfloor = #mem.params.floornames-exp.index+1 elseif exp.type == "DCL" then @@ -533,7 +597,7 @@ elseif event.type == "ui" then if not mem.params.secoverrideusers[mem.editingfloor] then mem.params.secoverrideusers[mem.editingfloor] = {} end - local exp = minetest.explode_textlist_event(event.fields.user) or {} + local exp = core.explode_textlist_event(event.fields.user) or {} if exp.type == "CHG" then mem.editinguser = exp.index elseif exp.type == "DCL" then @@ -556,7 +620,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 +642,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 +665,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 +694,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 +718,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 @@ -670,6 +739,24 @@ elseif event.type == "cop" then open() elseif fields.callcancel and (mem.carstate == "indep" or mem.carstate == "fs2") then mem.carcalls = {} + if mem.drive.status.vel > 0 then + for i=getpos(),#mem.params.floornames,1 do + if mem.drive.status.neareststop < gettarget(i) and mem.drive.status.dpos > gettarget(i) then + gotofloor(i) + break + end + end + elseif mem.drive.status.vel < 0 then + for i=getpos(),1,-1 do + if mem.drive.status.neareststop > gettarget(i) and mem.drive.status.dpos < gettarget(i) then + gotofloor(i) + break + end + end + end + elseif fields.phone then + mem.phoneactive = true + interrupt(15,"phonedone") end end elseif event.type == "copswitches" then @@ -745,6 +832,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 @@ -786,19 +879,19 @@ elseif event.type == "dispatchermsg" then end elseif event.channel == "getstatus" then send(event.source,"status",mem) - elseif event.channel == "groupupcall" and mem.carstate == "normal" then + elseif event.channel == "groupupcall" and mem.carstate == "normal" and event.msg then mem.groupupcalls[event.msg] = true - elseif event.channel == "groupdncall" and mem.carstate == "normal" then + elseif event.channel == "groupdncall" and mem.carstate == "normal" and event.msg then mem.groupdncalls[event.msg] = true - elseif event.channel == "groupupcancel" then + elseif event.channel == "groupupcancel" and event.msg then mem.groupupcalls[event.msg] = nil - elseif event.channel == "groupdncancel" then + elseif event.channel == "groupdncancel" and event.msg then mem.groupdncalls[event.msg] = nil - elseif event.channel == "swingupcall" and mem.carstate == "normal" then + elseif event.channel == "swingupcall" and swingstateok and event.msg then mem.swingupcalls[event.msg] = true - elseif event.channel == "swingdncall" and mem.carstate == "normal" then + elseif event.channel == "swingdncall" and swingstateok and event.msg 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") and event.msg then mem.carcalls[event.msg] = true send(event.source,"status",mem) elseif event.channel == "fs1switch" then @@ -810,38 +903,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) @@ -871,6 +977,8 @@ elseif event.type == "mrsmoke" then end if not mem.recallto then mem.recallto = getpos() end end +elseif event.iid == "phonedone" then + mem.phoneactive = false end local oldstate = mem.carstate @@ -901,19 +1009,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 +1022,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 +1117,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 +1155,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,8 +1178,9 @@ 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.carstate == "fs2" then mem.carcalls = {} end if mem.direction == "up" then mem.upcalls[getpos()] = nil mem.swingupcalls[getpos()] = nil @@ -1141,7 +1241,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 +1264,7 @@ local canprocesscalls = { test = true, indep = true, fs2 = true, + swing = true, } if canprocesscalls[mem.carstate] and mem.doorstate == "closed" then @@ -1212,14 +1313,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 @@ -1252,75 +1353,101 @@ fs("no_prepend[]") fs("background9[0,0;16,12;celevator_fs_bg.png;true;3]") if mem.screenstate == "oobe_welcome" then fs("image[6,1;4,2;celevator_logo.png]") - fs("label[1,4;Welcome to your new MTronic XT elevator controller!]") - fs("label[1,4.5;This setup wizard is designed to get your elevator up and running as quickly as possible.]") - fs("label[1,5.5;Press Next to begin.]") - fs("button[1,10;2,1;license;License Info]") - fs("button[13,10;2,1;next;Next >]") + local welcomemsg = S("Welcome to your new MTronic XT elevator controller!") + local wizardmsg = S("This setup wizard is designed to get your elevator up and running as quickly as possible.") + local pressnextmsg = S("Press Next to begin.") + local licensemsg = S("License Info") + local nextbuttonmsg = S("Next >") + fs("label[1,4;"..welcomemsg.."]") + fs("label[1,4.5;"..wizardmsg.."]") + fs("label[1,5.5;"..pressnextmsg.."]") + fs("button[1,10;3,1;license;"..licensemsg.."]") + fs("button[13,10;2,1;next;"..nextbuttonmsg.."]") elseif mem.screenstate == "oobe_license" then - local licensefile = io.open(minetest.get_modpath("celevator")..DIR_DELIM.."LICENSE") - local license = minetest.formspec_escape(licensefile:read("*all")) + local licensefile = io.open(core.get_modpath("celevator").."/LICENSE") + local license = core.formspec_escape(licensefile:read("*all")) licensefile:close() - fs("textarea[1,1;14,8;license;This applies to the whole celevator mod\\, not just this controller:;"..license.."]") - fs("button[7,10.5;2,1;back;OK]") + local licenseinfo = core.formspec_escape(S("This applies to the whole celevator mod, not just this controller:")) + fs("textarea[1,1;14,8;license;"..licenseinfo..";"..license.."]") + local okmsg = S("OK") + fs("button[7,10.5;2,1;back;"..okmsg.."]") elseif mem.screenstate == "oobe_groupmode" then - fs("button[1,10;2,1;back;< Back]") - fs("label[1,1;Select a group operation mode:]") - fs("button[1,3;2,1;simplex;Simplex]") - fs("label[1,4.5;This will be the only elevator in the group. Hall calls will be handled by this controller.]") - fs("button[1,6;2,1;group;Group]") - fs("label[1,7.5;This elevator will participate in a group with others. Hall calls will be handled by a dispatcher.]") + local backmsg = S("< Back") + fs("button[1,10;2,1;back;"..backmsg.."]") + local modeselectmsg = S("Select a group operation mode:") + fs("label[1,1;"..modeselectmsg.."]") + local simplexmsg = S("Simplex") + fs("button[1,3;2,1;simplex;"..simplexmsg.."]") + local simplexlongmsg = S("This will be the only elevator in the group. Hall calls will be handled by this controller.") + fs("label[1,4.5;"..simplexlongmsg.."]") + local groupmsg = S("Group") + fs("button[1,6;2,1;group;"..groupmsg.."]") + local grouplongmsg = S("This elevator will participate in a group with others. Hall calls will be handled by a dispatcher.") + fs("label[1,7.5;"..grouplongmsg.."]") elseif mem.screenstate == "oobe_dispatcherconnect" then - fs("button[1,10;2,1;back;< Cancel]") - fs("label[1,1;Waiting for connection from dispatcher...]") - fs(string.format("label[1,1.5;This controller's car ID is: %d]",mem.carid)) + local cancelmsg = S("Cancel") + fs("button[1,10;2,1;back;"..cancelmsg.."]") + local waitingmsg = S("Waiting for connection from dispatcher...") + fs("label[1,1;"..waitingmsg.."]") + local idmsg = S("This controller's car ID is: @1",mem.carid) + fs("label[1,1.5;"..idmsg.."]") elseif mem.screenstate == "oobe_floortable" or mem.screenstate == "floortable" then if mem.screenstate == "oobe_floortable" then - fs("label[1,1;Enter details of all floors this elevator will serve, then press Done.]") - fs("button[1,10;2,1;back;< Back]") - fs("button[13,10;2,1;next;Done >]") + local helpmsg = S("Enter details of all floors this elevator will serve, then press Done.") + fs("label[1,1;"..helpmsg.."]") + local backmsg = S("< Back") + fs("button[1,10;2,1;back;"..backmsg.."]") + local donemsg = S("Done") + fs("button[13,10;2,1;next;"..donemsg.."]") else - fs("label[1,1;EDIT FLOOR TABLE]") - fs("button[1,10;2,1;next;Done]") + local titlemsg = S("EDIT FLOOR TABLE") + fs("label[1,1;"..titlemsg.."]") + local donemsg = S("Done") + fs("button[1,10;2,1;next;"..donemsg.."]") end fs("textlist[1,2;6,7;floor;") for i=#mem.params.floornames,1,-1 do - fs(minetest.formspec_escape(string.format("%d - Height: %d - PI: %s",i,mem.params.floorheights[i],mem.params.floornames[i]))..(i==1 and "" or ",")) + local floortext = S("@1 - Height: @2 - PI: @3",i,mem.params.floorheights[i],mem.params.floornames[i]) + fs(core.formspec_escape(floortext)..(i==1 and "" or ",")) end fs(";"..tostring(#mem.params.floornames-mem.editingfloor+1)..";false]") - if #mem.params.floornames < 100 then fs("button[8,2;2,1;add;New Floor]") end - fs("button[8,3.5;2,1;edit;Edit Floor]") - if #mem.params.floornames > 2 then fs("button[8,5;2,1;remove;Remove Floor]") end - if mem.editingfloor < #mem.params.floornames then fs("button[8,6.5;2,1;moveup;Move Up]") end - if mem.editingfloor > 1 then fs("button[8,8;2,1;movedown;Move Down") end + local maxfloors = tonumber(core.settings:get("celevator.max_landings")) or 100 + if #mem.params.floornames < maxfloors then fs("button[8,2;2,1;add;"..S("New Floor").."]") end + fs("button[8,3.5;2,1;edit;"..S("Edit Floor").."]") + if #mem.params.floornames > 2 then fs("button[8,5;2,1;remove;"..S("Remove Floor").."]") end + if mem.editingfloor < #mem.params.floornames then fs("button[8,6.5;2,1;moveup;"..S("Move Up").."]") end + if mem.editingfloor > 1 then fs("button[8,8;2,1;movedown;"..S("Move Down").."]") end elseif mem.screenstate == "oobe_floortable_edit" or mem.screenstate == "floortable_edit" then if mem.screenstate == "oobe_floortable_edit" then - fs("button[7,10.5;2,1;back;OK]") - fs("label[1,5;The Floor Height is the distance (in meters/nodes) from the floor level of this floor to the floor level of the next floor.]") - fs("label[1,5.5;(not used at the highest floor)]") - fs("label[1,6.5;The Floor Name is how the floor will be displayed on the position indicators.]") + fs("button[7,10.5;2,1;back;"..S("OK").."]") + local help1 = S("The Floor Height is the distance (in meters/nodes) from the floor level of this floor to the floor level of the next floor.") + local help2 = S("(not used at the highest floor)") + local help3 = S("The Floor Name is how the floor will be displayed on the position indicators.") + fs("label[1,5;"..help1.."]") + fs("label[1,5.5;"..help2.."]") + fs("label[1,6.5;"..help3.."]") else - fs("button[7,10.5;2,1;save;Save]") + fs("button[7,10.5;2,1;save;"..S("Save").."]") end - fs("label[1,1;Editing floor "..tostring(mem.editingfloor).."]") - fs("field[1,3;3,1;height;Floor Height;"..tostring(mem.params.floorheights[mem.editingfloor]).."]") - fs("field[5,3;3,1;name;Floor Name;"..minetest.formspec_escape(mem.params.floornames[mem.editingfloor]).."]") + fs("label[1,1;"..S("Editing Floor @1",tostring(mem.editingfloor)).."]") + fs("field[1,3;3,1;height;"..S("Floor Height")..";"..tostring(mem.params.floorheights[mem.editingfloor]).."]") + fs("field[5,3;3,1;name;"..S("Floor Name")..";"..core.formspec_escape(mem.params.floornames[mem.editingfloor]).."]") elseif mem.screenstate == "status" then fs("style_type[image_button;font=mono;font_size=*0.75]") fs("box[12,2.5;0.1,9;#AAAAAAFF]") fs("box[13.12,2.5;0.05,9;#AAAAAAFF]") fs("box[14.12,2.5;0.05,9;#AAAAAAFF]") fs("box[15.25,2.5;0.1,9;#AAAAAAFF]") - fs("label[12.5,2;UP]") - fs("label[13.38,2;CAR]") - fs("label[14.25,2;DOWN]") + fs("image[12.5,1.9;0.2,0.4;celevator_menu_small_arrow.png]") + fs("label[13.38,2;"..S("CAR").."]") + fs("image[14.6,1.9;0.2,0.4;celevator_menu_small_arrow.png^[transformFY]") local maxfloor = #mem.params.floornames local bottom = (mem.screenpage-1)*10+1 for i=0,9,1 do local ypos = 11-(i*0.9) local floornum = bottom+i if floornum > maxfloor then break end - fs(string.format("label[11.25,%f;%s]",ypos,minetest.formspec_escape(mem.params.floornames[floornum]))) + fs(string.format("label[11.25,%f;%s]",ypos,core.formspec_escape(mem.params.floornames[floornum]))) local ccdot = mem.carcalls[floornum] and "*" or "" if getpos() == floornum then local cargraphics = { @@ -1332,31 +1459,31 @@ elseif mem.screenstate == "status" then } ccdot = cargraphics[mem.doorstate] if mem.direction == "up" then - ccdot = minetest.colorize("#55FF55",ccdot) + ccdot = core.colorize("#55FF55",ccdot) elseif mem.direction == "down" then - ccdot = minetest.colorize("#FF5555",ccdot) + ccdot = core.colorize("#FF5555",ccdot) end end fs(string.format("image_button[13.25,%f;0.75,0.75;celevator_fs_bg.png;carcall%d;%s]",ypos-0.25,floornum,ccdot)) if floornum < maxfloor then - local arrow = mem.upcalls[floornum] and minetest.colorize("#55FF55","^") or "" + local arrow = mem.upcalls[floornum] and core.colorize("#55FF55","^") or "" if mem.params.groupmode == "group" then - arrow = mem.groupupcalls[floornum] and minetest.colorize("#55FF55","^") or "" - arrow = (mem.swingupcalls[floornum] and minetest.colorize("#FFFF55","^") or "")..arrow + arrow = mem.groupupcalls[floornum] and core.colorize("#55FF55","^") or "" + arrow = (mem.swingupcalls[floornum] and core.colorize("#FFFF55","^") or "")..arrow end fs(string.format("image_button[12.25,%f;0.75,0.75;celevator_fs_bg.png;upcall%d;%s]",ypos-0.25,floornum,arrow)) end if floornum > 1 then - local arrow = mem.dncalls[floornum] and minetest.colorize("#FF5555","v") or "" + local arrow = mem.dncalls[floornum] and core.colorize("#FF5555","v") or "" if mem.params.groupmode == "group" then - arrow = mem.swingdncalls[floornum] and minetest.colorize("#FFFF55","v") or "" - arrow = (mem.groupdncalls[floornum] and minetest.colorize("#FF5555","v") or "")..arrow + arrow = mem.swingdncalls[floornum] and core.colorize("#FFFF55","v") or "" + arrow = (mem.groupdncalls[floornum] and core.colorize("#FF5555","v") or "")..arrow end fs(string.format("image_button[14.25,%f;0.75,0.75;celevator_fs_bg.png;downcall%d;%s]",ypos-0.25,floornum,arrow)) end end if maxfloor > 10 then - fs(string.format("checkbox[13,1.25;scrollfollowscar;Follow Car;%s]",tostring(mem.scrollfollowscar))) + fs(string.format("checkbox[13,1.25;scrollfollowscar;"..S("Follow Car")..";%s]",tostring(mem.scrollfollowscar))) if bottom+9 < maxfloor then fs("image_button[12.75,0.25;0.75,0.75;celevator_menu_arrow.png;scrollup;;false;false;celevator_menu_arrow.png]") end @@ -1364,18 +1491,21 @@ elseif mem.screenstate == "status" then fs("image_button[13.87,0.25;0.75,0.75;celevator_menu_arrow.png^\\[transformFY;scrolldown;;false;false;celevator_menu_arrow.png^\\[transformFY]") end end - fs("label[1,1;CAR STATUS]") + fs("label[1,1;"..S("CAR STATUS").."]") fs(string.format("label[1,2;%s]",modenames[mem.carstate])) - fs(string.format("label[1,2.5;Doors %s]",doorstates[mem.doorstate])) - local currentfloor = minetest.formspec_escape(mem.params.floornames[getpos()]) - fs(string.format("label[1,3;Position: %0.02fm Speed: %+0.02fm/s PI: %s]",mem.drive.status.apos,mem.drive.status.vel,currentfloor)) + fs(string.format("label[1,2.5;%s]",doorstates[mem.doorstate])) + local currentfloor = core.formspec_escape(mem.params.floornames[getpos()]) + local posfmt = string.format("%0.02f",mem.drive.status.apos) + local speedfmt = string.format("%+0.02f",mem.drive.status.vel) + local posmsg = S("Position: @1m Speed: @2m/s PI: @3",posfmt,speedfmt,currentfloor) + fs("label[1,3;"..posmsg.."]") if #mem.faultlog > 0 then - fs("label[1,3.5;Fault(s) Active]") + fs("label[1,3.5;"..S("Fault(s) Active").."]") else - fs("label[1,3.5;No Current Faults]") + fs("label[1,3.5;"..S("No Current Faults").."]") end - fs("button[1,10;3,1;faults;Fault History]") - fs("button[4.5,10;3,1;parameters;Edit Parameters]") + fs("button[1,10;3,1;faults;"..S("Fault History").."]") + fs("button[4.5,10;3,1;parameters;"..S("Edit Parameters").."]") local redon = "celevator_led_red_on.png" local redoff = "celevator_led_red_off.png" local yellowon = "celevator_led_yellow_on.png" @@ -1383,64 +1513,64 @@ elseif mem.screenstate == "status" then local greenon = "celevator_led_green_on.png" local greenoff = "celevator_led_green_off.png" fs(string.format("image[7,1;0.7,0.7;%s]",mem.carstate == "fault" and redon or redoff)) - fs("label[8,1.35;FAULT]") + fs("label[8,1.35;"..S("FAULT").."]") local inspectionstates = { mrinspect = true, carinspect = true, inspconflict = true, } fs(string.format("image[7,1.9;0.7,0.7;%s]",inspectionstates[mem.carstate] and yellowon or yellowoff)) - fs("label[8,2.25;INSP/ACCESS]") + fs("label[8,2.25;"..S("INSP/ACCESS").."]") fs(string.format("image[7,2.8;0.7,0.7;%s]",mem.carstate == "normal" and greenon or greenoff)) - fs("label[8,3.15;NORMAL OPERATION]") + fs("label[8,3.15;"..S("NORMAL OPERATION").."]") fs(string.format("image[7,3.7;0.7,0.7;%s]",mem.drive.status.vel > 0.01 and yellowon or yellowoff)) - fs("label[8,4.05;UP]") + fs("label[8,4.05;"..S("UP").."]") fs(string.format("image[7,4.6;0.7,0.7;%s]",math.abs(mem.drive.status.vel) > 0.01 and yellowon or yellowoff)) - fs("label[8,4.95;DRIVE CMD]") + fs("label[8,4.95;"..S("DRIVE CMD").."]") fs(string.format("image[7,5.5;0.7,0.7;%s]",mem.drive.status.vel < -0.01 and yellowon or yellowoff)) - fs("label[8,5.85;DOWN]") + fs("label[8,5.85;"..S("DOWN").."]") fs(string.format("image[7,6.4;0.7,0.7;%s]",math.abs(mem.drive.status.vel) > math.min(0.4,mem.params.contractspeed/2) and yellowon or yellowoff)) - fs("label[8,6.75;HIGH SPEED]") + fs("label[8,6.75;"..S("HIGH SPEED").."]") fs(string.format("image[7,7.3;0.7,0.7;%s]",math.abs(gettarget(getpos(true))-mem.drive.status.apos) < 0.5 and greenon or greenoff)) - fs("label[8,7.65;DOOR ZONE]") + fs("label[8,7.65;"..S("DOOR ZONE").."]") fs(string.format("image[7,8.2;0.7,0.7;%s]",mem.doorstate == "closed" and greenon or greenoff)) - fs("label[8,8.55;DOORS LOCKED]") + fs("label[8,8.55;"..S("DOORS LOCKED").."]") fs("style[*;font=mono]") local stopswimg = "celevator_toggle_switch.png"..(mem.controllerstopsw and "^\\[transformFY" or "") fs(string.format("image_button[1,5;1,1.33;%s;stopsw;;false;false;%s]",stopswimg,stopswimg)) - fs("label[1.3,4.75;RUN]") - fs("label[1.2,6.6;STOP]") + fs("label[1.3,4.75;"..S("RUN").."]") + fs("label[1.2,6.6;"..S("STOP").."]") local captureswimg = "celevator_toggle_switch.png"..(mem.capturesw and "" or "^\\[transformFY") fs(string.format("image_button[3,5;1,1.33;%s;capturesw;;false;false;%s]",captureswimg,captureswimg)) - fs("label[3,4.75;CAPTURE]") + fs("label[3,4.75;"..S("CAPTURE").."]") local testswimg = "celevator_toggle_switch.png"..(mem.testsw and "" or "^\\[transformFY") fs(string.format("image_button[5,5;1,1.33;%s;testsw;;false;false;%s]",testswimg,testswimg)) - fs("label[5.23,4.75;TEST]") + fs("label[5.23,4.75;"..S("TEST").."]") local inspectswimg = "celevator_toggle_switch.png"..(mem.controllerinspectsw and "" or "^\\[transformFY") fs(string.format("image_button[1,8;1,1.33;%s;inspectsw;;false;false;%s]",inspectswimg,inspectswimg)) - fs("label[1.05,7.75;INSPECT]") - fs("label[1.1,9.6;NORMAL]") + fs("label[1.05,7.75;"..S("INSPECT").."]") + fs("label[1.1,9.6;"..S("NORMAL").."]") fs(string.format("image_button[3,8.25;1,1;%s;inspectup;;false;false;%s]","celevator_button_black.png","celevator_button_black.png")) - fs("label[3.4,7.75;UP]") + fs("label[3.4,7.75;"..S("UP ").."]") fs(string.format("image_button[5,8.25;1,1;%s;inspectdown;;false;false;%s]","celevator_button_black.png","celevator_button_black.png")) - fs("label[5.25,7.75;DOWN]") + fs("label[5.25,7.75;"..S("DOWN ").."]") elseif mem.screenstate == "parameters" then - fs("label[1,1;EDIT PARAMETERS]") - fs("button[1,10;3,1;save;Save]") - fs("button[4.5,10;3,1;cancel;Cancel]") - if mem.params.groupmode == "simplex" then fs("button[8,10;3,1;floortable;Edit Floor Table]") end - fs(string.format("field[1,3;3,1;doortimer;Door Dwell Timer;%0.1f]",mem.params.doortimer)) - fs(string.format("field[1,5;3,1;contractspeed;Contract Speed (m/s);%0.1f]",mem.params.contractspeed)) - fs(string.format("field[4.5,5;3,1;inspectionspeed;Inspection Speed (m/s);%0.1f]",mem.params.inspectionspeed)) - fs(string.format("field[1,7;3,1;mainlanding;Main Egress Landing;%d]",mem.params.mainlanding or 1)) - fs(string.format("field[4.5,3;3,1;nudgetimer;Nudging Timer (0 = None);%0.1f]",mem.params.nudgetimer)) - fs(string.format("field[4.5,7;3,1;altrecalllanding;Alternate Recall Landing;%d]",mem.params.altrecalllanding)) + fs("label[1,1;"..S("EDIT PARAMETERS").."]") + fs("button[1,10;3,1;save;"..S("Save").."]") + fs("button[4.5,10;3,1;cancel;"..S("Cancel").."]") + if mem.params.groupmode == "simplex" then fs("button[8,10;3,1;floortable;"..S("Edit Floor Table").."]") end + fs(string.format("field[1,3;3,1;doortimer;"..S("Door Dwell Timer")..";%0.1f]",mem.params.doortimer)) + fs(string.format("field[1,5;3,1;contractspeed;"..S("Contract Speed (m/s)")..";%0.1f]",mem.params.contractspeed)) + fs(string.format("field[4.5,5;3,1;inspectionspeed;"..S("Inspection Speed (m/s)")..";%0.1f]",mem.params.inspectionspeed)) + fs(string.format("field[1,7;3,1;mainlanding;"..S("Main Egress Landing")..";%d]",mem.params.mainlanding or 1)) + fs(string.format("field[4.5,3;3,1;nudgetimer;"..S("Nudging Timer")..";%0.1f]",mem.params.nudgetimer)) + fs(string.format("field[4.5,7;3,1;altrecalllanding;"..S("Alternate Recall Landing")..";%d]",mem.params.altrecalllanding)) fs("style[resetdoors,resetcontroller;bgcolor=#DD3333]") - fs("button[12,1;3,1;resetdoors;Reset Doors]") - fs("button[12,2.5;3,1;resetcontroller;Reset Controller]") - fs("button[1,8.5;3,1;carcallsecurity;Car Call Security]") + fs("button[12,1;3,1;resetdoors;"..S("Reset Doors").."]") + fs("button[12,2.5;3,1;resetcontroller;"..S("Reset Controller").."]") + fs("button[1,8.5;3,1;carcallsecurity;"..S("Car Call Security").."]") elseif mem.screenstate == "faults" then - fs("label[1,1;FAULT HISTORY]") + fs("label[1,1;"..S("FAULT HISTORY").."]") if #mem.faultlog > 0 then for i=0,9,1 do if #mem.faultlog-i >= 1 then @@ -1451,28 +1581,30 @@ elseif mem.screenstate == "faults" then end end else - fs("label[1,2;No Current Faults]") + fs("label[1,2;"..S("No Current Faults").."]") end - fs("button[1,10;3,1;back;Back]") - fs("button[4.5,10;3,1;clear;Clear]") + fs("button[1,10;3,1;back;"..S("Back").."]") + fs("button[4.5,10;3,1;clear;"..S("Clear").."]") elseif mem.screenstate == "carcallsecurity" then - fs("label[1,1;CAR CALL SECURITY]") - fs("button[1,10;3,1;save;Done]") + fs("label[1,1;"..S("CAR CALL SECURITY").."]") + fs("button[1,10;3,1;save;"..S("Done").."]") fs("textlist[1,2;6,7;floor;") for i=#mem.params.floornames,1,-1 do local secmode = mem.params.carcallsecurity[i] if secmode == "auth" then - secmode = "Authorized Users Only" + secmode = S("Authorized Users Only") elseif secmode == "deny" then - secmode = "Locked" + secmode = S("Locked") else - secmode = "Security Disabled" + secmode = S("Security Disabled") end - fs(minetest.formspec_escape(string.format("%s - %s",mem.params.floornames[i],secmode))..(i==1 and "" or ",")) + fs(core.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]") + local swingmsg = S("Allow Swing Calls When Not In Swing Operation") + fs("checkbox[1,9.5;swingcallwhennotswing;"..swingmsg..";"..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;") + fs("dropdown[8,2;4,1;secmode;"..S("Security Disabled")..","..S("Authorized Users Only")..","..S("Locked")..";") if mem.params.carcallsecurity[mem.editingfloor] == "auth" then fs("2;true]") elseif mem.params.carcallsecurity[mem.editingfloor] == "deny" then @@ -1481,25 +1613,33 @@ elseif mem.screenstate == "carcallsecurity" then fs("1;true]") end if mem.params.carcallsecurity[mem.editingfloor] then - fs(string.format("checkbox[8,3.5;indepunlock;Unlock in Independent;%s]",(mem.params.indepunlock[mem.editingfloor] and "true" or "false"))) - fs("label[8,4.7;Extra Allowed Users]") + fs(string.format("checkbox[8,5;indepunlock;"..S("Unlock in Independent")..";%s]",(mem.params.indepunlock[mem.editingfloor] and "true" or "false"))) + fs("label[8,5.7;"..S("Extra Allowed Users").."]") if not mem.params.secoverrideusers[mem.editingfloor] then mem.params.secoverrideusers[mem.editingfloor] = {} end if #mem.params.secoverrideusers[mem.editingfloor] > 0 then - fs("textlist[8,6;4,2;user;") + fs("textlist[8,7;4,2;user;") for i=1,#mem.params.secoverrideusers[mem.editingfloor],1 do - fs(minetest.formspec_escape(mem.params.secoverrideusers[mem.editingfloor][i])..(i==#mem.params.secoverrideusers[mem.editingfloor] and "" or ",")) + fs(core.formspec_escape(mem.params.secoverrideusers[mem.editingfloor][i])..(i==#mem.params.secoverrideusers[mem.editingfloor] and "" or ",")) end fs(";"..tostring(mem.editinguser)..";false]") else - fs("label[8,6.25;(none)]") + fs("label[8,7.25;"..S("(none)").."]") end - fs("field[8,5;3,1;username;;]") - fs("button[11.25,5;0.5,1;adduser;+]") - fs("button[12,5;0.5,1;deluser;-]") + fs("field[8,6;3,1;username;;]") + fs("button[11.25,6;0.5,1;adduser;+]") + fs("button[12,6;0.5,1;deluser;-]") end else - fs("label[8,2;Main landing cannot be locked]") + fs("label[8,2;"..S("Main landing cannot be locked").."]") end + local hidden = mem.params.hiddenbuttons[mem.editingfloor] and "true" or "false" + fs("checkbox[8,4;hidebutton;"..S("Hide Button")..";"..hidden.."]") + if hidden == "true" then + local veryhidden = mem.params.alwayshiddenbuttons[mem.editingfloor] and "true" or "false" + fs("checkbox[8,4.5;alwayshidebutton;"..S("Also Hide in Fire/Independent Service")..";"..veryhidden.."]") + end + local suppressed = mem.params.suppressbeep[mem.editingfloor] and "true" or "false" + fs("checkbox[8,3.5;suppressbeep;"..S("Suppress Beep Sound")..";"..suppressed.."]") end local arrow = " " @@ -1511,7 +1651,7 @@ end local floorname = mem.params.floornames[getpos()] local modename = modenames[mem.carstate] local doorstate = doorstates[mem.doorstate] -mem.infotext = string.format("ID %d: Floor %s %s - %s - Doors %s",mem.carid,floorname,arrow,modename,doorstate) +mem.infotext = S("ID @1: Floor @2 - @3 - @4",mem.carid,(floorname.." "..arrow),modename,doorstate) if mem.drive.type then mem.showrunning = mem.drive.status.vel ~= 0 @@ -1533,8 +1673,10 @@ local hidepi = { } if hidepi[mem.carstate] then mem.pifloor = "--" end -if mem.pifloor ~= oldpifloor and mem.carstate == "normal" then - drivecmd({command="pibeep"}) +if mem.pifloor ~= oldpifloor and (mem.carstate == "normal" or mem.carstate == "swing") then + if not mem.params.suppressbeep[getpos(true)] then + drivecmd({command="pibeep"}) + end end local arrowenabled = { @@ -1544,6 +1686,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 +1696,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 @@ -1576,27 +1719,45 @@ elseif mem.carstate == "normal" and mem.doorstate == "closed" and mem.drive.stat end mem.copformspec = "formspec_version[7]" -local floorcount = #mem.params.floornames -local copcols = math.floor((floorcount-1)/10)+1 -local coprows = math.floor((floorcount-1)/copcols)+1 +local displayedfloors = {} +local realfloors = {} +if mem.carstate == "fs2" or mem.carstate == "fs2hold" or mem.carstate == "indep" then + for k,v in pairs(mem.params.floornames) do + if not (mem.params.hiddenbuttons[k] and mem.params.alwayshiddenbuttons[k]) then + table.insert(displayedfloors,v) + realfloors[#displayedfloors] = k + end + end +else + for k,v in pairs(mem.params.floornames) do + if not mem.params.hiddenbuttons[k] then + table.insert(displayedfloors,v) + realfloors[#displayedfloors] = k + end + end +end +local floorcount = #displayedfloors +local copcols = math.max(1,math.floor((floorcount-1)/10)+1) +local coprows = math.max(1,math.floor((floorcount-1)/copcols)+1) local litimg = "celevator_copbutton_lit.png" local unlitimg = "celevator_copbutton_unlit.png" -mem.copformspec = mem.copformspec..string.format("size[%f,%f]",copcols*1.25+2.5,coprows*1.25+5) +mem.copformspec = mem.copformspec..string.format("size[%f,%f]",copcols*1.25+2.5,coprows*1.25+6) mem.copformspec = mem.copformspec.."no_prepend[]" mem.copformspec = mem.copformspec.."background9[0,0;16,12;celevator_fs_bg.png;true;3]" for i=1,floorcount,1 do + local landing = realfloors[i] local row = math.floor((i-1)/copcols)+1 local col = ((i-1)%copcols)+1 local yp = (coprows-row+1)*1.25+1 local xp = col*1.25 - local tex = mem.carcalls[i] and litimg or unlitimg - local star = (i == (mem.params.mainlanding or 1) and "*" or "") - local label = minetest.formspec_escape(star..mem.params.floornames[i]) - mem.copformspec = mem.copformspec..string.format("image_button[%f,%f;1.2,1.2;%s;carcall%d;%s;false;false;%s]",xp,yp,tex,i,label,litimg) + local tex = mem.carcalls[landing] and litimg or unlitimg + local star = (landing == (mem.params.mainlanding or 1) and "*" or "") + local label = core.formspec_escape(star..displayedfloors[i]) + mem.copformspec = mem.copformspec..string.format("image_button[%f,%f;1.2,1.2;%s;carcall%d;%s;false;false;%s]",xp,yp,tex,landing,label,litimg) end local doxp = (copcols == 1) and 0.5 or 1.25 -local openlabel = minetest.formspec_escape("<|>") +local openlabel = core.formspec_escape("<|>") mem.copformspec = mem.copformspec..string.format("image_button[%f,%f;1.2,1.2;%s;open;%s;false;false;%s]",doxp,coprows*1.25+2.5,unlitimg,openlabel,litimg) local dcxp = 3.75 @@ -1605,43 +1766,66 @@ if copcols == 1 then elseif copcols == 2 then dcxp = 2.5 end -local closelabel = minetest.formspec_escape(">|<") +local closelabel = core.formspec_escape(">|<") mem.copformspec = mem.copformspec..string.format("image_button[%f,%f;1.2,1.2;%s;close;%s;false;false;%s]",dcxp,coprows*1.25+2.5,unlitimg,closelabel,litimg) -mem.copformspec = mem.copformspec..string.format("image_button[0.4,0.5;1.4,1.4;%s;callcancel;Call\nCancel;false;false;%s]",unlitimg,litimg) +local alarmunlitimg = unlitimg.."^celevator_copbutton_alarm.png" +local alarmlitimg = litimg.."^celevator_copbutton_alarm.png" +mem.copformspec = mem.copformspec..string.format("image_button[%f,%f;1.2,1.2;%s;alarm;;false;false;%s]",doxp,coprows*1.25+4,alarmunlitimg,alarmlitimg) + +local phoneunlitimg = unlitimg.."^celevator_copbutton_phone.png" +local phonelitimg = litimg.."^celevator_copbutton_phone.png" +if mem.phoneactive then + mem.copformspec = mem.copformspec..string.format("image[%f,%f;1.2,1.2;%s]",dcxp,coprows*1.25+4,phonelitimg) +else + mem.copformspec = mem.copformspec..string.format("image_button[%f,%f;1.2,1.2;%s;phone;;false;false;%s]",dcxp,coprows*1.25+4,phoneunlitimg,phonelitimg) +end + +local hatxp = 1.2 + +if floorcount > 0 then + --If all floors are hidden, this is probably a DBD setup and all of the car call buttons are in a cabinet that is not currently open. + --Call cancel would be in there too, so hide it in that case + local callcancellabel = S("Call\nCancel") + mem.copformspec = mem.copformspec..string.format("image_button[0.4,0.5;1.4,1.4;%s;callcancel;"..callcancellabel..";false;false;%s]",unlitimg,litimg) + --Also center the hat in that case (un-center it here if there are buttons) + hatxp = 2.2 +end if mem.flashfirehat then - mem.copformspec = mem.copformspec.."animated_image[2.2,0.5;1.4,1.4;firehat;celevator_fire_hat_flashing.png;2;750]" + mem.copformspec = mem.copformspec..string.format("animated_image[%f,0.5;1.4,1.4;firehat;celevator_fire_hat_flashing.png;2;750]",hatxp) else local firehat = mem.flash_fs and "celevator_fire_hat_lit.png" or "celevator_fire_hat_unlit.png" - mem.copformspec = mem.copformspec..string.format("image[2.2,0.5;1.4,1.4;%s]",firehat) + mem.copformspec = mem.copformspec..string.format("image[%f,0.5;1.4,1.4;%s]",hatxp,firehat) end +local switchboilerplate = ";false;false;celevator_button_rect_active.png" + mem.switchformspec = "formspec_version[7]size[8,10]no_prepend[]background9[0,0;16,12;celevator_fs_bg.png;true;3]" local fs2ontex = (mem.fs2sw == "on") and "celevator_button_rect_active.png" or "celevator_button_rect.png" local fs2holdtex = (mem.fs2sw == "hold") and "celevator_button_rect_active.png" or "celevator_button_rect.png" local fs2offtex = (mem.fs2sw == "off" or not mem.fs2sw) and "celevator_button_rect_active.png" or "celevator_button_rect.png" -mem.switchformspec = mem.switchformspec..string.format("image_button[1.5,1.5;1.5,1;%s;fs2on;ON;false;false;celevator_button_rect_active.png]",fs2ontex) -mem.switchformspec = mem.switchformspec..string.format("image_button[1.5,2.5;1.5,1;%s;fs2hold;HOLD;false;false;celevator_button_rect_active.png]",fs2holdtex) -mem.switchformspec = mem.switchformspec..string.format("image_button[1.5,3.5;1.5,1;%s;fs2off;OFF;false;false;celevator_button_rect_active.png]",fs2offtex) -mem.switchformspec = mem.switchformspec.."label[1.6,4.75;FIRE SVC]" +mem.switchformspec = mem.switchformspec..string.format("image_button[1.5,1.5;1.5,1;%s;fs2on;"..S("ON")..switchboilerplate.."]",fs2ontex) +mem.switchformspec = mem.switchformspec..string.format("image_button[1.5,2.5;1.5,1;%s;fs2hold;"..S("HOLD")..switchboilerplate.."]",fs2holdtex) +mem.switchformspec = mem.switchformspec..string.format("image_button[1.5,3.5;1.5,1;%s;fs2off;"..S("OFF")..switchboilerplate.."]",fs2offtex) +mem.switchformspec = mem.switchformspec.."label[1.6,4.75;"..S("FIRE SVC").."]" local indontex = mem.indsw and "celevator_button_rect_active.png" or "celevator_button_rect.png" local indofftex = (not mem.indsw) and "celevator_button_rect_active.png" or "celevator_button_rect.png" -mem.switchformspec = mem.switchformspec..string.format("image_button[4.5,1.5;1.5,1;%s;indon;ON;false;false;celevator_button_rect_active.png]",indontex) -mem.switchformspec = mem.switchformspec..string.format("image_button[4.5,3.5;1.5,1;%s;indoff;OFF;false;false;celevator_button_rect_active.png]",indofftex) -mem.switchformspec = mem.switchformspec.."label[4.6,4.75;IND SVC]" +mem.switchformspec = mem.switchformspec..string.format("image_button[4.5,1.5;1.5,1;%s;indon;"..S("ON")..switchboilerplate.."]",indontex) +mem.switchformspec = mem.switchformspec..string.format("image_button[4.5,3.5;1.5,1;%s;indoff;"..S("OFF")..switchboilerplate.."]",indofftex) +mem.switchformspec = mem.switchformspec.."label[4.6,4.75;"..S("IND SVC").."]" local lightontex = mem.lightsw and "celevator_button_rect_active.png" or "celevator_button_rect.png" local lightofftex = (not mem.lightsw) and "celevator_button_rect_active.png" or "celevator_button_rect.png" -mem.switchformspec = mem.switchformspec..string.format("image_button[1.5,5.5;1.5,1;%s;lighton;ON;false;false;celevator_button_rect_active.png]",lightontex) -mem.switchformspec = mem.switchformspec..string.format("image_button[1.5,7.5;1.5,1;%s;lightoff;OFF;false;false;celevator_button_rect_active.png]",lightofftex) -mem.switchformspec = mem.switchformspec.."label[1.6,8.75;CAR LIGHT]" +mem.switchformspec = mem.switchformspec..string.format("image_button[1.5,5.5;1.5,1;%s;lighton;"..S("ON")..switchboilerplate.."]",lightontex) +mem.switchformspec = mem.switchformspec..string.format("image_button[1.5,7.5;1.5,1;%s;lightoff;"..S("OFF")..switchboilerplate.."]",lightofftex) +mem.switchformspec = mem.switchformspec.."label[1.6,8.75;"..S("CAR LIGHT").."]" local fanontex = mem.fansw and "celevator_button_rect_active.png" or "celevator_button_rect.png" local fanofftex = (not mem.fansw) and "celevator_button_rect_active.png" or "celevator_button_rect.png" -mem.switchformspec = mem.switchformspec..string.format("image_button[4.5,5.5;1.5,1;%s;fanon;ON;false;false;celevator_button_rect_active.png]",fanontex) -mem.switchformspec = mem.switchformspec..string.format("image_button[4.5,7.5;1.5,1;%s;fanoff;OFF;false;false;celevator_button_rect_active.png]",fanofftex) -mem.switchformspec = mem.switchformspec.."label[4.6,8.75;CAR FAN]" +mem.switchformspec = mem.switchformspec..string.format("image_button[4.5,5.5;1.5,1;%s;fanon;"..S("ON")..switchboilerplate.."]",fanontex) +mem.switchformspec = mem.switchformspec..string.format("image_button[4.5,7.5;1.5,1;%s;fanoff;"..S("OFF")..switchboilerplate.."]",fanofftex) +mem.switchformspec = mem.switchformspec.."label[4.6,8.75;"..S("CAR FAN").."]" return pos,mem,changedinterrupts @@ -1,173 +1,363 @@ -minetest.register_craft({ +local xcompat_available = core.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 core.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 core.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 + core.log("warning","[celevator] Unsupported game and xcompat not found, not registering craft recipes") + return + end + if core.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 core.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 core.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 core.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 = core.registered_nodes["mesecons_lightstone:lightstone_blue_off"] +local vl_lightstone = core.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 = core.registered_nodes["mesecons_button:button_off"] +if mesecons_button then + -- real mesecons + m.button = mesecons_button.name +elseif core.get_modpath("mcl_core") then + m.button = "group:button" +else + m.button = m.mese +end + +if core.get_modpath("mesecons_switch") then + -- real mesecons + m.switch = "mesecons_switch:mesecon_switch_off" +elseif core.get_modpath("mcl_lever") then + -- mcla + m.switch = "mcl_lever:lever_off" +elseif core.get_modpath("mesecons_walllever") then + -- other mcl + m.switch = "mesecons_walllever:wall_lever_off" +else + m.switch = m.mese +end + +if core.get_modpath("digilines") then + m.lcd = "digilines:lcd" +else + m.lcd = m.mese +end + +core.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({ +core.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({ +core.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({ +core.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({ +core.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", +core.register_craft({ + output = "celevator:car_standard", 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_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({ +core.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}, + }, +}) + +core.register_craft({ + output = "celevator:car_fullglass", + recipe = { + {m.glass,m.glass,m.glass}, + {m.button,"celevator:hwdoor_glass",m.glass}, + {m.switch,m.steel_ingot,m.steel_ingot}, + }, +}) + +core.register_craft({ + output = "celevator:car_metal", + recipe = { + {"",m.steel_strip,""}, + {m.steel_strip,"celevator:car_standard",m.steel_strip}, + {"",m.steel_strip,""}, + }, +}) + +core.register_craft({ + output = "celevator:car_metal_glassback", + recipe = { + {"",m.steel_strip,""}, + {m.steel_strip,"celevator:car_glassback",m.steel_strip}, + {"",m.steel_strip,""}, + }, +}) + +core.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({ +core.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({ +core.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}, }, }) -minetest.register_craft({ +core.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"}, }, }) -minetest.register_craft({ +core.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}, }, }) -minetest.register_craft({ +core.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({ +core.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({ +core.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({ +core.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({ +core.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}, + }, +}) + +core.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}, + }, +}) + +core.register_craft({ + output = "celevator:hwdoor_centerglass", + recipe = { + {m.steel_bar,"",m.steel_bar}, + {m.glass,m.steel_bar,m.glass}, + {m.steel_bar,m.steel_bar,m.steel_bar}, + }, +}) + +core.register_craft({ + output = "celevator:hwdoor_centersteel", + recipe = { + {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({ +core.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({ +core.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({ +core.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}, }, }) -minetest.register_craft({ +core.register_craft({ output = "celevator:lantern_vertical_up", type = "shapeless", recipe = { @@ -175,7 +365,7 @@ minetest.register_craft({ }, }) -minetest.register_craft({ +core.register_craft({ output = "celevator:lantern_vertical_down", type = "shapeless", recipe = { @@ -183,7 +373,7 @@ minetest.register_craft({ }, }) -minetest.register_craft({ +core.register_craft({ output = "celevator:lantern_vertical_both", type = "shapeless", recipe = { @@ -191,7 +381,7 @@ minetest.register_craft({ }, }) -minetest.register_craft({ +core.register_craft({ output = "celevator:lantern_up", type = "shapeless", recipe = { @@ -199,7 +389,7 @@ minetest.register_craft({ }, }) -minetest.register_craft({ +core.register_craft({ output = "celevator:lantern_down", type = "shapeless", recipe = { @@ -207,7 +397,7 @@ minetest.register_craft({ }, }) -minetest.register_craft({ +core.register_craft({ output = "celevator:lantern_both", type = "shapeless", recipe = { @@ -215,25 +405,25 @@ minetest.register_craft({ }, }) -minetest.register_craft({ +core.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({ +core.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}, }, }) -minetest.register_craft({ +core.register_craft({ output = "celevator:pilantern_up", type = "shapeless", recipe = { @@ -242,7 +432,7 @@ minetest.register_craft({ }, }) -minetest.register_craft({ +core.register_craft({ output = "celevator:pilantern_down", type = "shapeless", recipe = { @@ -251,7 +441,7 @@ minetest.register_craft({ }, }) -minetest.register_craft({ +core.register_craft({ output = "celevator:pilantern_both", type = "shapeless", recipe = { @@ -260,39 +450,56 @@ minetest.register_craft({ }, }) -minetest.register_craft({ +core.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}, }, }) -minetest.register_craft({ +core.register_craft({ output = "celevator:tape_magnets", type = "shapeless", recipe = { "celevator:tape", - "default:iron_lump", - "basic_materials:plastic_sheet", + m.iron_lump, + m.plastic_sheet, }, }) -minetest.register_craft({ +core.register_craft({ output = "celevator:tape_bracket", type = "shapeless", recipe = { "celevator:tape", - "basic_materials:steel_strip", + m.steel_strip, }, }) -minetest.register_craft({ +core.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}, + }, +}) + +core.register_craft({ + output = "celevator:genericswitch", + recipe = { + {m.steel_strip,"",""}, + {m.steel_strip,m.switch,m.dye_black}, + {m.steel_strip,"",""}, + }, +}) + +core.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/dbdkiosk.lua b/dbdkiosk.lua index 1250685..1f55b3c 100644 --- a/dbdkiosk.lua +++ b/dbdkiosk.lua @@ -1,32 +1,33 @@ celevator.dbdkiosk = {} +local S = core.get_translator("celevator") + function celevator.dbdkiosk.checkprot(pos,name) - if minetest.is_protected(pos,name) and not minetest.check_player_privs(name,{protection_bypass=true}) then - minetest.chat_send_player(name,"Can't open cabinet - cabinet is locked.") - minetest.record_protection_violation(pos,name) + if core.is_protected(pos,name) and not core.check_player_privs(name,{protection_bypass=true}) then + core.record_protection_violation(pos,name) return false end return true end function celevator.dbdkiosk.updatefields(pos) - if minetest.get_node(pos).name ~= "celevator:dbdkiosk" then return end - local meta = minetest.get_meta(pos) + if core.get_node(pos).name ~= "celevator:dbdkiosk" then return end + local meta = core.get_meta(pos) local screenstate = meta:get_string("screenstate") if screenstate == "connect" then meta:set_string("formspec","formspec_version[7]".. "size[8,5]".. - "field[0.5,0.5;7,1;carid;Dispatcher ID;]".. - "field[0.5,2;7,1;landing;Landing Number;]".. - "button[3,3.5;2,1;save;Save]" + "field[0.5,0.5;7,1;carid;"..S("Dispatcher ID")..";]".. + "field[0.5,2;7,1;landing;"..S("Landing Number")..";]".. + "button[3,3.5;2,1;save;"..S("Save").."]" ) elseif screenstate == "main" then local landing = meta:get_int("landing") local fs = "formspec_version[7]" fs = fs.."size[8,14]" - fs = fs.."label[3,0.5;Please select a floor\\:]" - local floornames = minetest.deserialize(meta:get_string("floornames")) - local floorsavailable = minetest.deserialize(meta:get_string("floorsavailable")) + fs = fs.."label[3,0.5;"..core.formspec_escape(S("Please select a floor:")).."]" + local floornames = core.deserialize(meta:get_string("floornames")) + local floorsavailable = core.deserialize(meta:get_string("floorsavailable")) local showfloors = {} for i=1,#floornames,1 do if floorsavailable[i] then @@ -38,7 +39,7 @@ function celevator.dbdkiosk.updatefields(pos) local floornum = showfloors[startfloor+i-1] local floorname = floornum and floornames[floornum] if floorname and floornum ~= landing then - fs = fs..string.format("button[2,%f;4,1;floor%d;%s]",12-i,floornum,minetest.formspec_escape(floorname)) + fs = fs..string.format("button[2,%f;4,1;floor%d;%s]",12-i,floornum,core.formspec_escape(floorname)) end end if startfloor > 1 then @@ -51,39 +52,45 @@ function celevator.dbdkiosk.updatefields(pos) elseif screenstate == "assignment" then local fs = "formspec_version[7]" fs = fs.."size[8,14]" - fs = fs.."label[3,3;Please use elevator]" + fs = fs.."label[3,3;"..S("Please use elevator").."]" fs = fs.."style_type[label;font_size=*4]" fs = fs.."label[3.5,5;"..meta:get_string("assignedcar").."]" meta:set_string("formspec",fs) elseif screenstate == "error" then local fs = "formspec_version[7]" fs = fs.."size[8,14]" - fs = fs.."label[3.5,0.5;ERROR]" - fs = fs.."label[2.5,3;Could not find a suitable elevator]" - fs = fs.."label[2.5,3.5;Please try again later]" + fs = fs.."label[3.5,0.5;"..S("ERROR").."]" + fs = fs.."label[2.5,3;"..S("Could not find a suitable elevator").."]" + fs = fs.."label[2.5,3.5;"..S("Please try again later").."]" meta:set_string("formspec",fs) end end function celevator.dbdkiosk.handlefields(pos,_,fields,player) local name = player:get_player_name() - local meta = minetest.get_meta(pos) + local meta = core.get_meta(pos) local screenstate = meta:get_string("screenstate") if screenstate == "connect" then if not (fields.save and celevator.dbdkiosk.checkprot(pos,name)) then return end if not (tonumber(fields.carid) and tonumber(fields.landing)) then return end - local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",fields.carid))) + if tonumber(fields.landing) ~= math.floor(tonumber(fields.landing)) then return end + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",fields.carid))) if not carinfo then return end if not (carinfo.dispatcherpos and celevator.dispatcher.isdispatcher(carinfo.dispatcherpos)) then return end - local dmem = minetest.deserialize(minetest.get_meta(carinfo.dispatcherpos):get_string("mem")) + if core.is_protected(carinfo.dispatcherpos,name) and not core.check_player_privs(name,{protection_bypass=true}) then + core.record_protection_violation(carinfo.dispatcherpos,name) + core.chat_send_player(name,S("Can't connect to a dispatcher you don't have access to.")) + return + end + local dmem = core.deserialize(core.get_meta(carinfo.dispatcherpos):get_string("mem")) if not dmem then return end local floornames = dmem.params.floornames local floorsavailable = {} for i=1,#floornames,1 do floorsavailable[i] = true end - meta:set_string("floornames",minetest.serialize(floornames)) - meta:set_string("floorsavailable",minetest.serialize(floorsavailable)) + meta:set_string("floornames",core.serialize(floornames)) + meta:set_string("floorsavailable",core.serialize(floorsavailable)) meta:set_int("screenpage",1) meta:set_string("screenstate","main") meta:set_int("carid",tonumber(fields.carid)) @@ -95,17 +102,17 @@ function celevator.dbdkiosk.handlefields(pos,_,fields,player) local floor = tonumber(string.sub(k,6,-1)) if not floor then return end local carid = meta:get_int("carid") - local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid))) + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) if not carinfo then return end if not (carinfo.dispatcherpos and celevator.dispatcher.isdispatcher(carinfo.dispatcherpos)) then return end - local dmem = minetest.deserialize(minetest.get_meta(carinfo.dispatcherpos):get_string("mem")) + local dmem = core.deserialize(core.get_meta(carinfo.dispatcherpos):get_string("mem")) if dmem then local floornames = dmem.params.floornames - meta:set_string("floornames",minetest.serialize(floornames)) + meta:set_string("floornames",core.serialize(floornames)) end local event = { type = "dbdkiosk", - source = minetest.hash_node_position(pos), + source = core.hash_node_position(pos), player = name, srcfloor = meta:get_int("landing"), destfloor = floor, @@ -128,7 +135,7 @@ function celevator.dbdkiosk.handlefields(pos,_,fields,player) end function celevator.dbdkiosk.showassignment(pos,assignment) - local meta = minetest.get_meta(pos) + local meta = core.get_meta(pos) if meta:get_string("screenstate") == "main" then local carnames = {"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P"} if carnames[assignment] then @@ -138,20 +145,21 @@ function celevator.dbdkiosk.showassignment(pos,assignment) meta:set_string("screenstate","error") end celevator.dbdkiosk.updatefields(pos) - minetest.after(5,function() + core.after(5,function() meta:set_string("screenstate","main") celevator.dbdkiosk.updatefields(pos) end) end end -minetest.register_node("celevator:dbdkiosk",{ - description = "Elevator Destination Entry Kiosk", +core.register_node("celevator:dbdkiosk",{ + description = S("Elevator Destination Entry Kiosk"), drawtype = "nodebox", paramtype = "light", paramtype2 = "4dir", groups = { - cracky = 1, + cracky = 3, + oddly_breakable_by_hand = 1, }, node_box = { type = "fixed", @@ -168,7 +176,7 @@ minetest.register_node("celevator:dbdkiosk",{ "celevator_cabinet_sides.png^celevator_dbdkiosk.png", }, on_construct = function(pos) - local meta = minetest.get_meta(pos) + local meta = core.get_meta(pos) meta:set_string("screenstate","connect") celevator.dbdkiosk.updatefields(pos) end, diff --git a/decorations.lua b/decorations.lua index 847c06a..2822e0d 100644 --- a/decorations.lua +++ b/decorations.lua @@ -1,7 +1,10 @@ -minetest.register_node("celevator:buffer_rubber",{ - description = "Elevator Elastomeric Buffer", +local S = core.get_translator("celevator") + +core.register_node("celevator:buffer_rubber",{ + description = S("Elevator Elastomeric Buffer"), groups = { - choppy = 1, + cracky = 3, + oddly_breakable_by_hand = 1, bouncy = 60, }, paramtype = "light", @@ -39,10 +42,11 @@ minetest.register_node("celevator:buffer_rubber",{ }, }) -minetest.register_node("celevator:buffer_oil",{ - description = "Elevator Oil-Filled Buffer", +core.register_node("celevator:buffer_oil",{ + description = S("Elevator Oil-Filled Buffer"), groups = { - choppy = 1, + cracky = 3, + oddly_breakable_by_hand = 1, }, paramtype = "light", tiles = { @@ -65,41 +69,42 @@ minetest.register_node("celevator:buffer_oil",{ }, }, after_place_node = function(pos,placer) - local node = minetest.get_node(pos) + local node = core.get_node(pos) local toppos = {x=pos.x,y=pos.y + 1,z=pos.z} - local topnode = minetest.get_node(toppos) + local topnode = core.get_node(toppos) local placername = placer:get_player_name() if topnode.name ~= "air" then if placer:is_player() then - minetest.chat_send_player(placername,"Can't place buffer - no room for the top half!") + core.chat_send_player(placername,"Can't place buffer - no room for the top half!") end - minetest.set_node(pos,{name="air"}) + core.set_node(pos,{name="air"}) return true end - if minetest.is_protected(toppos,placername) and not minetest.check_player_privs(placername,{protection_bypass=true}) then + if core.is_protected(toppos,placername) and not core.check_player_privs(placername,{protection_bypass=true}) then if placer:is_player() then - minetest.chat_send_player(placername,"Can't place buffer - top half is protected!") - minetest.record_protection_violation(toppos,placername) + core.chat_send_player(placername,"Can't place buffer - top half is protected!") + core.record_protection_violation(toppos,placername) end - minetest.set_node(pos,{name="air"}) + core.set_node(pos,{name="air"}) return true end node.name = "celevator:buffer_oil_top" - minetest.set_node(toppos,node) + core.set_node(toppos,node) end, on_destruct = function(pos) pos.y = pos.y + 1 - local topnode = minetest.get_node(pos) + local topnode = core.get_node(pos) if topnode.name == "celevator:buffer_oil_top" then - minetest.set_node(pos,{name="air"}) + core.set_node(pos,{name="air"}) end end, }) -minetest.register_node("celevator:buffer_oil_top",{ - description = "Elevator Oil-Filled Buffer (top half - you hacker you!)", +core.register_node("celevator:buffer_oil_top",{ + description = S("Elevator Oil-Filled Buffer (top half - you hacker you!)"), groups = { - choppy = 1, + cracky = 3, + oddly_breakable_by_hand = 1, not_in_creative_inventory = 1, }, drop = "", @@ -116,10 +121,11 @@ minetest.register_node("celevator:buffer_oil_top",{ }, }) -minetest.register_node("celevator:guide_rail",{ - description = "Elevator Guide Rail", +core.register_node("celevator:guide_rail",{ + description = S("Elevator Guide Rail"), groups = { - choppy = 1, + cracky = 3, + oddly_breakable_by_hand = 1, }, paramtype = "light", paramtype2 = "4dir", @@ -140,10 +146,11 @@ minetest.register_node("celevator:guide_rail",{ }, }) -minetest.register_node("celevator:guide_rail_bracket",{ - description = "Elevator Guide Rail with Bracket", +core.register_node("celevator:guide_rail_bracket",{ + description = S("Elevator Guide Rail with Bracket"), groups = { - choppy = 1, + cracky = 3, + oddly_breakable_by_hand = 1, }, paramtype = "light", paramtype2 = "4dir", @@ -169,10 +176,11 @@ minetest.register_node("celevator:guide_rail_bracket",{ }, }) -minetest.register_node("celevator:tape",{ - description = "Elevator Positioning System Tape", +core.register_node("celevator:tape",{ + description = S("Elevator Positioning System Tape"), groups = { - choppy = 1, + cracky = 3, + oddly_breakable_by_hand = 1, }, paramtype = "light", paramtype2 = "4dir", @@ -194,10 +202,11 @@ minetest.register_node("celevator:tape",{ }, }) -minetest.register_node("celevator:tape_magnets",{ - description = "Elevator Positioning System Tape with Magnets", +core.register_node("celevator:tape_magnets",{ + description = S("Elevator Positioning System Tape with Magnets"), groups = { - choppy = 1, + cracky = 3, + oddly_breakable_by_hand = 1, }, paramtype = "light", paramtype2 = "4dir", @@ -219,10 +228,11 @@ minetest.register_node("celevator:tape_magnets",{ }, }) -minetest.register_node("celevator:tape_bracket",{ - description = "Elevator Positioning System Tape with Bracket", +core.register_node("celevator:tape_bracket",{ + description = S("Elevator Positioning System Tape with Bracket"), groups = { - choppy = 1, + cracky = 3, + oddly_breakable_by_hand = 1, }, paramtype = "light", paramtype2 = "4dir", @@ -246,14 +256,14 @@ minetest.register_node("celevator:tape_bracket",{ }, }) -minetest.register_entity("celevator:tapehead",{ +core.register_entity("celevator:tapehead",{ initial_properties = { visual = "wielditem", visual_size = vector.new(0.667,0.667,0.667), wield_item = "celevator:tapehead", static_save = false, pointable = false, - glow = minetest.LIGHT_MAX, + glow = core.LIGHT_MAX, }, on_step = function(self) local obj = self.object @@ -261,9 +271,9 @@ minetest.register_entity("celevator:tapehead",{ local pos = obj:get_pos() if not pos then return end local roundpos = vector.round(pos) - local backdir = minetest.yaw_to_dir(obj:get_yaw()) + local backdir = core.yaw_to_dir(obj:get_yaw()) local tapepos = vector.add(roundpos,backdir) - local tapename = minetest.get_node(tapepos).name + local tapename = core.get_node(tapepos).name if tapename ~= "celevator:tape" and tapename ~= "celevator:tape_magnets" and tapename ~= "celevator:tape_bracket" then obj:remove() return @@ -289,32 +299,34 @@ minetest.register_entity("celevator:tapehead",{ local function spawntapehead(pos) local toppos = vector.add(pos,vector.new(0,1,0)) - local entitiesnearby = minetest.get_objects_inside_radius(toppos,0.5) + local entitiesnearby = core.get_objects_inside_radius(toppos,0.5) for _,i in pairs(entitiesnearby) do if i:get_luaentity() and i:get_luaentity().name == "celevator:tapehead" then return end end - local entity = minetest.add_entity(pos,"celevator:tapehead") - local fdir = minetest.fourdir_to_dir(minetest.get_node(pos).param2) + local entity = core.add_entity(pos,"celevator:tapehead") + local fdir = core.fourdir_to_dir(core.get_node(pos).param2) fdir = vector.rotate_around_axis(fdir,vector.new(0,1,0),-math.pi/2) - entity:set_yaw(minetest.dir_to_yaw(fdir)) + entity:set_yaw(core.dir_to_yaw(fdir)) entity:set_pos(toppos) end -minetest.register_abm({ +core.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, action = spawntapehead, }) -minetest.register_node("celevator:tapehead",{ - description = "Elevator Positioning System Tapehead (off, you hacker you!)", +core.register_node("celevator:tapehead",{ + description = S("Elevator Positioning System Tapehead (off, you hacker you!)"), groups = { not_in_creative_inventory = 1, + cracky = 3, + oddly_breakable_by_hand = 1, }, drop = "", paramtype = "light", @@ -338,10 +350,12 @@ minetest.register_node("celevator:tapehead",{ }, }) -minetest.register_node("celevator:tapehead_ulm",{ - description = "Elevator Positioning System Tapehead (ULM on, you hacker you!)", +core.register_node("celevator:tapehead_ulm",{ + description = S("Elevator Positioning System Tapehead (ULM on, you hacker you!)"), groups = { not_in_creative_inventory = 1, + cracky = 3, + oddly_breakable_by_hand = 1, }, drop = "", paramtype = "light", @@ -365,10 +379,12 @@ minetest.register_node("celevator:tapehead_ulm",{ }, }) -minetest.register_node("celevator:tapehead_ulm_dz",{ - description = "Elevator Positioning System Tapehead (ULM and DZ on, you hacker you!)", +core.register_node("celevator:tapehead_ulm_dz",{ + description = S("Elevator Positioning System Tapehead (ULM and DZ on, you hacker you!)"), groups = { not_in_creative_inventory = 1, + cracky = 3, + oddly_breakable_by_hand = 1, }, drop = "", paramtype = "light", @@ -392,10 +408,12 @@ minetest.register_node("celevator:tapehead_ulm_dz",{ }, }) -minetest.register_node("celevator:tapehead_ulm_dlm_dz",{ - description = "Elevator Positioning System Tapehead (ULM, DLM, and DZ on, you hacker you!)", +core.register_node("celevator:tapehead_ulm_dlm_dz",{ + description = S("Elevator Positioning System Tapehead (ULM, DLM, and DZ on, you hacker you!)"), groups = { not_in_creative_inventory = 1, + cracky = 3, + oddly_breakable_by_hand = 1, }, drop = "", paramtype = "light", @@ -419,10 +437,12 @@ minetest.register_node("celevator:tapehead_ulm_dlm_dz",{ }, }) -minetest.register_node("celevator:tapehead_dlm_dz",{ - description = "Elevator Positioning System Tapehead (DLM and DZ on, you hacker you!)", +core.register_node("celevator:tapehead_dlm_dz",{ + description = S("Elevator Positioning System Tapehead (DLM and DZ on, you hacker you!)"), groups = { not_in_creative_inventory = 1, + cracky = 3, + oddly_breakable_by_hand = 1, }, drop = "", paramtype = "light", @@ -446,10 +466,12 @@ minetest.register_node("celevator:tapehead_dlm_dz",{ }, }) -minetest.register_node("celevator:tapehead_dlm",{ - description = "Elevator Positioning System Tapehead (DLM on, you hacker you!)", +core.register_node("celevator:tapehead_dlm",{ + description = S("Elevator Positioning System Tapehead (DLM on, you hacker you!)"), groups = { not_in_creative_inventory = 1, + cracky = 3, + oddly_breakable_by_hand = 1, }, drop = "", paramtype = "light", diff --git a/digilines.lua b/digilines.lua index 4b30345..60fa469 100644 --- a/digilines.lua +++ b/digilines.lua @@ -1,15 +1,17 @@ +local S = core.get_translator("celevator") + local function handledigilines(pos,node,channel,msg) local multi = node.name == "celevator:digilines_multi_io" if msg == "GET" then msg = {command = "GET"} end if type(msg) ~= "table" or type(msg.command) ~= "string" then return end - local meta = minetest.get_meta(pos) + local meta = core.get_meta(pos) local setchannel = meta:get_string("channel") if setchannel ~= channel then return end if multi and type(msg.carid) ~= "number" then return end local carid = multi and msg.carid or meta:get_int("carid") if carid == 0 then return end local dmode = meta:get_int("dispatcher") == 1 - local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid))) or {} + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) or {} if multi then dmode = carinfo.dispatcherpos end @@ -18,7 +20,7 @@ local function handledigilines(pos,node,channel,msg) if not carinfo.dispatcherpos then return end if not celevator.dispatcher.isdispatcher(carinfo.dispatcherpos) then return end if msg.command == "get" then - local mem = minetest.deserialize(minetest.get_meta(carinfo.dispatcherpos):get_string("mem")) + local mem = core.deserialize(core.get_meta(carinfo.dispatcherpos):get_string("mem")) if not mem then return end local ret = { upcalls = {}, @@ -67,7 +69,7 @@ local function handledigilines(pos,node,channel,msg) if not carinfo.controllerpos then return end if not celevator.controller.iscontroller(carinfo.controllerpos) then return end if msg.command == "get" then - local mem = minetest.deserialize(minetest.get_meta(carinfo.controllerpos):get_string("mem")) + local mem = core.deserialize(core.get_meta(carinfo.controllerpos):get_string("mem")) if not mem then return end local ret = { carstate = mem.carstate, @@ -158,12 +160,24 @@ 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 -minetest.register_node("celevator:digilines_io",{ - description = "Elevator Digilines Input/Output", +core.register_node("celevator:digilines_io",{ + description = S("Elevator Digilines Input/Output"), tiles = { "celevator_digilinesio_top.png", "celevator_cabinet_sides.png", @@ -187,27 +201,27 @@ minetest.register_node("celevator:digilines_io",{ }, }, after_place_node = function(pos) - local meta = minetest.get_meta(pos) + local meta = core.get_meta(pos) local fs = "formspec_version[7]size[8,4.5]" - fs = fs.."field[0.5,0.5;3,1;channel;Channel;${channel}]" - fs = fs.."field[4.5,0.5;3,1;carid;Car ID;${carid}]" - fs = fs.."button_exit[2.5,2;3,1;save;Save]" + fs = fs.."field[0.5,0.5;3,1;channel;"..S("Channel")..";${channel}]" + fs = fs.."field[4.5,0.5;3,1;carid;"..S("Car ID")..";${carid}]" + fs = fs.."button_exit[2.5,2;3,1;save;"..S("Save").."]" meta:set_string("formspec",fs) end, on_receive_fields = function(pos,_,fields,player) - local meta = minetest.get_meta(pos) + local meta = core.get_meta(pos) if not fields.save 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 + if core.is_protected(pos,name) and not core.check_player_privs(name,{protection_bypass=true}) then if player:is_player() then - minetest.record_protection_violation(pos,name) + core.record_protection_violation(pos,name) end return end if not tonumber(fields.carid) then return end meta:set_int("carid",fields.carid) local carid = tonumber(fields.carid) - local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid))) or {} + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) or {} if not (carinfo.controllerpos or carinfo.dispatcherpos) then return end local dmode = false if carinfo.dispatcherpos then @@ -217,31 +231,31 @@ minetest.register_node("celevator:digilines_io",{ if not celevator.controller.iscontroller(carinfo.controllerpos) then return end end if dmode then - if minetest.is_protected(carinfo.dispatcherpos,name) and not minetest.check_player_privs(name,{protection_bypass=true}) then + if core.is_protected(carinfo.dispatcherpos,name) and not core.check_player_privs(name,{protection_bypass=true}) then if player:is_player() then - minetest.chat_send_player(name,"Can't connect to a dispatcher you don't have access to.") - minetest.record_protection_violation(carinfo.dispatcherpos,name) + core.chat_send_player(name,S("Can't connect to a dispatcher you don't have access to.")) + core.record_protection_violation(carinfo.dispatcherpos,name) end return end else - if minetest.is_protected(carinfo.controllerpos,name) and not minetest.check_player_privs(name,{protection_bypass=true}) then + if core.is_protected(carinfo.controllerpos,name) and not core.check_player_privs(name,{protection_bypass=true}) then if player:is_player() then - minetest.chat_send_player(name,"Can't connect to a controller you don't have access to.") - minetest.record_protection_violation(carinfo.controllerpos,name) + core.chat_send_player(name,S("Can't connect to a controller you don't have access to.")) + core.record_protection_violation(carinfo.controllerpos,name) end return end end meta:set_int("dispatcher",dmode and 1 or 0) meta:set_string("channel",fields.channel) - local infotext = "Car: "..carid + local infotext = S("ID: @1",carid) meta:set_string("infotext",infotext) end, }) -minetest.register_node("celevator:digilines_multi_io",{ - description = "Elevator Digilines Multi-Car Input/Output", +core.register_node("celevator:digilines_multi_io",{ + description = S("Elevator Digilines Multi-Car Input/Output"), tiles = { "celevator_digilinesio_multi_top.png", "celevator_cabinet_sides.png", @@ -267,28 +281,28 @@ minetest.register_node("celevator:digilines_multi_io",{ }, after_place_node = function(pos,player) local name = player:get_player_name() - if not (minetest.check_player_privs(name,{protection_bypass=true}) or minetest.check_player_privs(name,{server=true})) then + if not (core.check_player_privs(name,{protection_bypass=true}) or core.check_player_privs(name,{server=true})) then if player:is_player() then - minetest.chat_send_player(name,"You need either the 'protection_bypass' or 'server' privilege to use this.") - minetest.record_protection_violation(pos,name) + core.chat_send_player(name,S("You need either the 'protection_bypass' or 'server' privilege to use this.")) + core.record_protection_violation(pos,name) end - minetest.remove_node(pos) + core.remove_node(pos) return end - local meta = minetest.get_meta(pos) + local meta = core.get_meta(pos) local fs = "formspec_version[7]size[8,4.5]" - fs = fs.."field[0.5,0.5;7,1;channel;Channel;${channel}]" - fs = fs.."button_exit[2.5,2;3,1;save;Save]" + fs = fs.."field[0.5,0.5;7,1;channel;"..S("Channel")..";${channel}]" + fs = fs.."button_exit[2.5,2;3,1;save;"..S("Save").."]" meta:set_string("formspec",fs) end, on_receive_fields = function(pos,_,fields,player) - local meta = minetest.get_meta(pos) + local meta = core.get_meta(pos) if not fields.save then return end local name = player:get_player_name() - if not (minetest.check_player_privs(name,{protection_bypass=true}) or minetest.check_player_privs(name,{server=true})) then + if not (core.check_player_privs(name,{protection_bypass=true}) or core.check_player_privs(name,{server=true})) then if player:is_player() then - minetest.chat_send_player(name,"You need either the 'protection_bypass' or 'server' privilege to use this.") - minetest.record_protection_violation(pos,name) + core.chat_send_player(name,S("You need either the 'protection_bypass' or 'server' privilege to use this.")) + core.record_protection_violation(pos,name) end return end diff --git a/digistuff.lua b/digistuff.lua new file mode 100644 index 0000000..c1382e8 --- /dev/null +++ b/digistuff.lua @@ -0,0 +1,27 @@ +local nbsounds = { + --At the moment this is everything except the nudging buzzer + "celevator_brake_apply", + "celevator_brake_release", + "celevator_cabinet_close", + "celevator_cabinet_open", + "celevator_car_run", + "celevator_car_start", + "celevator_car_stop", + "celevator_chime_down", + "celevator_chime_up", + "celevator_controller_start", + "celevator_controller_stop", + "celevator_door_close", + "celevator_door_open", + "celevator_door_reverse", + "celevator_drive_run", + "celevator_motor_accel", + "celevator_motor_decel", + "celevator_motor_fast", + "celevator_motor_slow", + "celevator_pi_beep", + "celevator_chime2_up", + "celevator_chime2_down", +} + +for _,i in ipairs(nbsounds) do digistuff.register_nb_sound(i,i) end diff --git a/dispatcher.lua b/dispatcher.lua index a8bcf1c..cd091bb 100644 --- a/dispatcher.lua +++ b/dispatcher.lua @@ -1,23 +1,25 @@ celevator.dispatcher = {} -celevator.dispatcher.iqueue = minetest.deserialize(celevator.storage:get_string("dispatcher_iqueue")) or {} +local S = core.get_translator("celevator") -celevator.dispatcher.equeue = minetest.deserialize(celevator.storage:get_string("dispatcher_equeue")) or {} +celevator.dispatcher.iqueue = core.deserialize(celevator.storage:get_string("dispatcher_iqueue")) or {} + +celevator.dispatcher.equeue = core.deserialize(celevator.storage:get_string("dispatcher_equeue")) or {} celevator.dispatcher.running = {} -local fw,err = loadfile(minetest.get_modpath("celevator")..DIR_DELIM.."dispatcherfw.lua") +local fw,err = loadfile(core.get_modpath("celevator").."/dispatcherfw.lua") if not fw then error(err) end -minetest.register_chatcommand("celevator_reloaddispatcher",{ +core.register_chatcommand("celevator_reloaddispatcher",{ params = "", description = "Reload celevator dispatcher firmware from disk", privs = {server = true}, func = function() - local newfw,loaderr = loadfile(minetest.get_modpath("celevator")..DIR_DELIM.."dispatcherfw.lua") + local newfw,loaderr = loadfile(core.get_modpath("celevator").."/dispatcherfw.lua") if newfw then fw = newfw - return true,"Firmware reloaded successfully" + return true,S("Firmware reloaded successfully") else return false,loaderr end @@ -25,63 +27,69 @@ minetest.register_chatcommand("celevator_reloaddispatcher",{ }) local function after_place(pos,placer) - local node = minetest.get_node(pos) + local node = core.get_node(pos) local toppos = {x=pos.x,y=pos.y + 1,z=pos.z} - local topnode = minetest.get_node(toppos) + local topnode = core.get_node(toppos) local placername = placer:get_player_name() if topnode.name ~= "air" then if placer:is_player() then - minetest.chat_send_player(placername,"Can't place cabinet - no room for the top half!") + core.chat_send_player(placername,S("Can't place cabinet - no room for the top half!")) end - minetest.set_node(pos,{name="air"}) + core.set_node(pos,{name="air"}) return true end - if minetest.is_protected(toppos,placername) and not minetest.check_player_privs(placername,{protection_bypass=true}) then + if core.is_protected(toppos,placername) and not core.check_player_privs(placername,{protection_bypass=true}) then if placer:is_player() then - minetest.chat_send_player(placername,"Can't place cabinet - top half is protected!") - minetest.record_protection_violation(toppos,placername) + core.chat_send_player(placername,S("Can't place cabinet - top half is protected!")) + core.record_protection_violation(toppos,placername) end - minetest.set_node(pos,{name="air"}) + core.set_node(pos,{name="air"}) return true end node.name = "celevator:dispatcher_top" - minetest.set_node(toppos,node) + core.set_node(toppos,node) end local function ondestruct(pos) pos.y = pos.y + 1 - local topnode = minetest.get_node(pos) + local topnode = core.get_node(pos) local dispatchertops = { ["celevator:dispatcher_top"] = true, ["celevator:dispatcher_top_open"] = true, } if dispatchertops[topnode.name] then - minetest.set_node(pos,{name="air"}) + core.set_node(pos,{name="air"}) end - celevator.dispatcher.equeue[minetest.hash_node_position(pos)] = nil - celevator.storage:set_string("dispatcher_equeue",minetest.serialize(celevator.dispatcher.equeue)) - local carid = minetest.get_meta(pos):get_int("carid") + celevator.dispatcher.equeue[core.hash_node_position(pos)] = nil + celevator.storage:set_string("dispatcher_equeue",core.serialize(celevator.dispatcher.equeue)) + local carid = core.get_meta(pos):get_int("carid") if carid ~= 0 then celevator.storage:set_string(string.format("car%d",carid),"") end end local function onrotate(controllerpos,node,user,mode,new_param2) - if not minetest.global_exists("screwdriver") then + if not core.global_exists("screwdriver") then return false end local ret = screwdriver.rotate_simple(controllerpos,node,user,mode,new_param2) - minetest.after(0,function(pos) - local newnode = minetest.get_node(pos) + core.after(0,function(pos) + local newnode = core.get_node(pos) local param2 = newnode.param2 pos.y = pos.y + 1 - local topnode = minetest.get_node(pos) + local topnode = core.get_node(pos) topnode.param2 = param2 - minetest.set_node(pos,topnode) + core.set_node(pos,topnode) end,controllerpos) return ret end local function handlefields(pos,_,fields,sender) local playername = sender and sender:get_player_name() or "" + if core.settings:get_bool("celevator.controller_screen_protected",false) then + if core.is_protected(pos,playername) and not core.check_player_privs(playername,{protection_bypass=true}) then + core.record_protection_violation(pos,playername) + return + end + end local event = {} event.type = "ui" event.fields = fields @@ -94,15 +102,16 @@ local function candig(_,player) if controls.sneak then return true else - minetest.chat_send_player(player:get_player_name(),"Hold the sneak button while digging to remove.") + core.chat_send_player(player:get_player_name(),S("Hold the sneak button while digging to remove.")) return false end end -minetest.register_node("celevator:dispatcher",{ - description = "Elevator Dispatcher", +core.register_node("celevator:dispatcher",{ + description = S("Elevator Dispatcher"), groups = { - cracky = 1, + cracky = 3, + oddly_breakable_by_hand = 1, }, paramtype = "light", paramtype2 = "facedir", @@ -133,15 +142,15 @@ minetest.register_node("celevator:dispatcher",{ on_receive_fields = handlefields, can_dig = candig, on_construct = function(pos) - local meta = minetest.get_meta(pos) - meta:set_string("mem",minetest.serialize({})) + local meta = core.get_meta(pos) + meta:set_string("mem",core.serialize({})) meta:mark_as_private("mem") local event = {} event.type = "program" local carid = celevator.storage:get_int("maxcarid")+1 meta:set_int("carid",carid) celevator.storage:set_int("maxcarid",carid) - celevator.storage:set_string(string.format("car%d",carid),minetest.serialize({dispatcherpos=pos,callbuttons={},fs1switches={}})) + celevator.storage:set_string(string.format("car%d",carid),core.serialize({dispatcherpos=pos,callbuttons={},fs1switches={}})) celevator.dispatcher.run(pos,event) end, on_punch = function(pos,node,puncher) @@ -149,20 +158,22 @@ minetest.register_node("celevator:dispatcher",{ return end local name = puncher: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,"Can't open cabinet - cabinet is locked.") - minetest.record_protection_violation(pos,name) - return + if core.settings:get_bool("celevator.controller_cabinet_protected",true) then + if core.is_protected(pos,name) and not core.check_player_privs(name,{protection_bypass=true}) then + core.chat_send_player(name,S("Can't open cabinet - cabinet is locked.")) + core.record_protection_violation(pos,name) + return + end end node.name = "celevator:dispatcher_open" - minetest.swap_node(pos,node) - local meta = minetest.get_meta(pos) + core.swap_node(pos,node) + local meta = core.get_meta(pos) meta:set_string("formspec",meta:get_string("formspec_hidden")) pos.y = pos.y + 1 - node = minetest.get_node(pos) + node = core.get_node(pos) node.name = "celevator:dispatcher_top_open" - minetest.swap_node(pos,node) - minetest.sound_play("celevator_cabinet_open",{ + core.swap_node(pos,node) + core.sound_play("celevator_cabinet_open",{ pos = pos, gain = 0.5, max_hear_distance = 10 @@ -170,10 +181,11 @@ minetest.register_node("celevator:dispatcher",{ end, }) -minetest.register_node("celevator:dispatcher_open",{ - description = "Dispatcher (door open - you hacker you!)", +core.register_node("celevator:dispatcher_open",{ + description = S("Dispatcher (door open - you hacker you!)"), groups = { - cracky = 1, + cracky = 3, + oddly_breakable_by_hand = 1, not_in_creative_inventory = 1, }, paramtype = "light", @@ -215,14 +227,14 @@ minetest.register_node("celevator:dispatcher_open",{ return end node.name = "celevator:dispatcher" - minetest.swap_node(pos,node) - local meta = minetest.get_meta(pos) + core.swap_node(pos,node) + local meta = core.get_meta(pos) meta:set_string("formspec","") pos.y = pos.y + 1 - node = minetest.get_node(pos) + node = core.get_node(pos) node.name = "celevator:dispatcher_top" - minetest.swap_node(pos,node) - minetest.sound_play("celevator_cabinet_close",{ + core.swap_node(pos,node) + core.sound_play("celevator_cabinet_close",{ pos = pos, gain = 0.5, max_hear_distance = 10 @@ -230,9 +242,11 @@ minetest.register_node("celevator:dispatcher_open",{ end, }) -minetest.register_node("celevator:dispatcher_top",{ - description = "Dispatcher (top section - you hacker you!)", +core.register_node("celevator:dispatcher_top",{ + description = S("Dispatcher (top section - you hacker you!)"), groups = { + cracky = 3, + oddly_breakable_by_hand = 1, not_in_creative_inventory = 1, }, drop = "", @@ -261,9 +275,11 @@ minetest.register_node("celevator:dispatcher_top",{ }, }) -minetest.register_node("celevator:dispatcher_top_open",{ - description = "Dispatcher (top section, open - you hacker you!)", +core.register_node("celevator:dispatcher_top_open",{ + description = S("Dispatcher (top section, open - you hacker you!)"), groups = { + cracky = 3, + oddly_breakable_by_hand = 1, not_in_creative_inventory = 1, }, drop = "", @@ -303,16 +319,16 @@ function celevator.dispatcher.finish(pos,mem,changedinterrupts) if not celevator.dispatcher.isdispatcher(pos) then return else - local meta = minetest.get_meta(pos) + local meta = core.get_meta(pos) local carid = meta:get_int("carid") - local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid))) + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) local carinfodirty = false if not carinfo then - minetest.log("error","[celevator] [controller] Bad car info for dispatcher at "..minetest.pos_to_string(pos)) + core.log("error",string.format("[celevator] [dispatcher] Bad car info for dispatcher at %s",core.pos_to_string(pos))) return end local node = celevator.get_node(pos) - local oldmem = minetest.deserialize(meta:get_string("mem")) or {} + local oldmem = core.deserialize(meta:get_string("mem")) or {} local oldupbuttonlights = oldmem.upcalls or {} local olddownbuttonlights = oldmem.dncalls or {} local newupbuttonlights = mem.upcalls or {} @@ -335,7 +351,7 @@ function celevator.dispatcher.finish(pos,mem,changedinterrupts) end end for _,message in ipairs(mem.messages) do - local destinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",message.carid))) + local destinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",message.carid))) if destinfo and destinfo.controllerpos then celevator.controller.run(destinfo.controllerpos,{ type = "dispatchermsg", @@ -346,27 +362,27 @@ function celevator.dispatcher.finish(pos,mem,changedinterrupts) end end for _,message in ipairs(mem.kioskmessages) do - celevator.dbdkiosk.showassignment(minetest.get_position_from_hash(message.pos),message.car) + celevator.dbdkiosk.showassignment(core.get_position_from_hash(message.pos),message.car) end - meta:set_string("mem",minetest.serialize(mem)) + meta:set_string("mem",core.serialize(mem)) if node.name == "celevator:dispatcher_open" then meta:set_string("formspec",mem.formspec or "") end meta:set_string("formspec_hidden",mem.formspec or "") meta:set_string("infotext",mem.infotext or "") - local hash = minetest.hash_node_position(pos) + local hash = core.hash_node_position(pos) if not celevator.dispatcher.iqueue[hash] then celevator.dispatcher.iqueue[hash] = mem.interrupts end for iid in pairs(changedinterrupts) do celevator.dispatcher.iqueue[hash][iid] = mem.interrupts[iid] end - celevator.storage:set_string("dispatcher_iqueue",minetest.serialize(celevator.dispatcher.iqueue)) + celevator.storage:set_string("dispatcher_iqueue",core.serialize(celevator.dispatcher.iqueue)) celevator.dispatcher.running[hash] = nil if #celevator.dispatcher.equeue[hash] > 0 then local event = celevator.dispatcher.equeue[hash][1] table.remove(celevator.dispatcher.equeue[hash],1) - celevator.storage:set_string("dispatcher_equeue",minetest.serialize(celevator.dispatcher.equeue)) + celevator.storage:set_string("dispatcher_equeue",core.serialize(celevator.dispatcher.equeue)) celevator.dispatcher.run(pos,event) end if carinfodirty then - celevator.storage:set_string(string.format("car%d",carid),minetest.serialize(carinfo)) + celevator.storage:set_string(string.format("car%d",carid),core.serialize(carinfo)) end end end @@ -375,30 +391,32 @@ function celevator.dispatcher.run(pos,event) if not celevator.dispatcher.isdispatcher(pos) then return else - local hash = minetest.hash_node_position(pos) + local hash = core.hash_node_position(pos) if not celevator.dispatcher.equeue[hash] then celevator.dispatcher.equeue[hash] = {} - celevator.storage:set_string("dispatcher_equeue",minetest.serialize(celevator.dispatcher.equeue)) + celevator.storage:set_string("dispatcher_equeue",core.serialize(celevator.dispatcher.equeue)) end if celevator.dispatcher.running[hash] then table.insert(celevator.dispatcher.equeue[hash],event) - celevator.storage:set_string("dispatcher_equeue",minetest.serialize(celevator.dispatcher.equeue)) + celevator.storage:set_string("dispatcher_equeue",core.serialize(celevator.dispatcher.equeue)) if #celevator.dispatcher.equeue[hash] > 20 then - local message = "[celevator] [dispatcher] Async process for dispatcher at %s is falling behind, %d events in queue" - minetest.log("warning",string.format(message,minetest.pos_to_string(pos),#celevator.dispatcher.equeue[hash])) + local pstring = core.pos_to_string(pos) + local queuelen = #celevator.dispatcher.equeue[hash] + local message = string.format("[celevator] [dispatcher] Async process for dispatcher at %s is falling behind, %d events in queue",pstring,queuelen) + core.log("warning",message) end return end celevator.dispatcher.running[hash] = true - local meta = minetest.get_meta(pos) - local mem = minetest.deserialize(meta:get_string("mem")) + local meta = core.get_meta(pos) + local mem = core.deserialize(meta:get_string("mem")) if not mem then - minetest.log("error","[celevator] [controller] Failed to load dispatcher memory at "..minetest.pos_to_string(pos)) + core.log("error",string.format("[celevator] [dispatcher] Failed to load dispatcher memory at %s",core.pos_to_string(pos))) return end - mem.interrupts = celevator.dispatcher.iqueue[minetest.hash_node_position(pos)] or {} + mem.interrupts = celevator.dispatcher.iqueue[core.hash_node_position(pos)] or {} mem.carid = meta:get_int("carid") - minetest.handle_async(fw,celevator.dispatcher.finish,pos,event,mem) + core.handle_async(fw,celevator.dispatcher.finish,pos,event,mem) end end @@ -421,8 +439,10 @@ end function celevator.dispatcher.checkiqueue(dtime) for hash,iqueue in pairs(celevator.dispatcher.iqueue) do - local pos = minetest.get_position_from_hash(hash) + local pos = core.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,12 +452,16 @@ 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",core.serialize(celevator.dispatcher.iqueue)) + end end end -minetest.register_globalstep(celevator.dispatcher.checkiqueue) +core.register_globalstep(celevator.dispatcher.checkiqueue) -minetest.register_abm({ +core.register_abm({ label = "Run otherwise idle dispatchers if a user is nearby", nodenames = {"celevator:dispatcher","celevator:dispatcher_open"}, interval = 1, diff --git a/dispatcherfw.lua b/dispatcherfw.lua index 25ad4f8..7793091 100644 --- a/dispatcherfw.lua +++ b/dispatcherfw.lua @@ -1,5 +1,7 @@ local pos,event,mem = ... +local S = core.get_translator("celevator") + local changedinterrupts = {} local function interrupt(time,iid) @@ -240,6 +242,7 @@ local function estimatetraveltime(carid,src,dest) end local function buildstopsequence(carid,startfloor,direction,target,targetdir,leaving) + if not startfloor then return {} end local carcalls = cartorealfloor(carid,mem.carstatus[carid].carcalls) local upcalls = cartorealfloor(carid,mem.carstatus[carid].upcalls) local dncalls = cartorealfloor(carid,mem.carstatus[carid].dncalls) @@ -258,7 +261,9 @@ local function buildstopsequence(carid,startfloor,direction,target,targetdir,lea end repeat local src = carpos + if not src then return sequence end carpos,direction = predictnextstop(carid,carpos,direction,carcalls,upcalls,dncalls,leaving) + if not carpos then return sequence end carcalls[carpos] = nil if direction == "up" then upcalls[carpos] = nil @@ -300,6 +305,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" @@ -335,7 +361,8 @@ elseif event.type == "ui" then mem.screenstate = "oobe_welcome" end elseif mem.screenstate == "oobe_floortable" or mem.screenstate == "floortable" then - local exp = event.fields.floor and minetest.explode_textlist_event(event.fields.floor) or {} + local exp = event.fields.floor and core.explode_textlist_event(event.fields.floor) or {} + local maxfloors = tonumber(core.settings:get("celevator.max_landings")) or 100 if event.fields.back then mem.screenstate = "oobe_welcome" elseif event.fields.next then @@ -364,14 +391,15 @@ elseif event.type == "ui" then mem.screenstate = (mem.screenstate == "oobe_floortable" and "oobe_floortable_edit" or "floortable_edit") elseif event.fields.edit then mem.screenstate = (mem.screenstate == "oobe_floortable" and "oobe_floortable_edit" or "floortable_edit") - 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.add and #mem.params.floornames < maxfloors then + table.insert(mem.params.floorheights,mem.params.floorheights[#mem.params.floorheights] or 5) + local previous = tonumber(mem.params.floornames[#mem.params.floornames]) or #mem.params.floornames + table.insert(mem.params.floornames,tostring(math.floor(previous)+1)) + 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) - elseif event.fields.moveup then + elseif event.fields.moveup and mem.editingfloor < #mem.params.floornames then local height = mem.params.floorheights[mem.editingfloor] local name = mem.params.floornames[mem.editingfloor] table.remove(mem.params.floorheights,mem.editingfloor) @@ -379,7 +407,7 @@ elseif event.type == "ui" then table.insert(mem.params.floorheights,mem.editingfloor+1,height) table.insert(mem.params.floornames,mem.editingfloor+1,name) mem.editingfloor = mem.editingfloor + 1 - elseif event.fields.movedown then + elseif event.fields.movedown and mem.editingfloor > 1 then local height = mem.params.floorheights[mem.editingfloor] local name = mem.params.floornames[mem.editingfloor] table.remove(mem.params.floorheights,mem.editingfloor) @@ -392,14 +420,15 @@ elseif event.type == "ui" then if event.fields.back or event.fields.save then mem.screenstate = (mem.screenstate == "oobe_floortable_edit" and "oobe_floortable" or "floortable") local height = tonumber(event.fields.height) - if height then + if height and height < (tonumber(core.settings:get("celevator.max_height")) or 100) then height = math.floor(height+0.5) mem.params.floorheights[mem.editingfloor] = math.max(1,height) end mem.params.floornames[mem.editingfloor] = string.sub(event.fields.name,1,256) end elseif mem.screenstate == "oobe_connections" or mem.screenstate == "connections" then - local exp = event.fields.connection and minetest.explode_textlist_event(event.fields.connection) or {} + local exp = event.fields.connection and core.explode_textlist_event(event.fields.connection) or {} + local maxcars = tonumber(core.settings:get("celevator.max_group")) or 16 if event.fields.back then mem.screenstate = "oobe_floortable" elseif event.fields.next and #mem.params.carids > 0 then @@ -410,10 +439,11 @@ elseif event.type == "ui" then elseif exp.type == "DCL" then mem.editingconnection = #mem.params.carids-exp.index+1 mem.screenstate = (mem.screenstate == "oobe_connections" and "oobe_connection" or "connection") + mem.newconnfloors = mem.params.floorsserved[mem.params.carids[mem.editingconnection]] elseif event.fields.edit then mem.screenstate = (mem.screenstate == "oobe_connections" and "oobe_connection" or "connection") mem.newconnfloors = mem.params.floorsserved[mem.params.carids[mem.editingconnection]] - elseif event.fields.add then + elseif event.fields.add and #mem.params.carids < maxcars then mem.newconnfloors = {} for i in ipairs(mem.params.floornames) do mem.newconnfloors[i] = true @@ -425,7 +455,7 @@ elseif event.type == "ui" then mem.editingconnection = math.max(1,mem.editingconnection-1) end elseif mem.screenstate == "oobe_newconnection" or mem.screenstate == "newconnection" then - local exp = event.fields.floors and minetest.explode_textlist_event(event.fields.floors) or {} + local exp = event.fields.floors and core.explode_textlist_event(event.fields.floors) or {} if event.fields.back then mem.screenstate = (mem.screenstate == "oobe_newconnection" and "oobe_connections" or "connections") elseif event.fields.connect and fields.carid and tonumber(fields.carid) then @@ -450,7 +480,7 @@ elseif event.type == "ui" then mem.newconnfloors[floor] = not mem.newconnfloors[floor] end elseif mem.screenstate == "oobe_connection" or mem.screenstate == "connection" then - local exp = event.fields.floors and minetest.explode_textlist_event(event.fields.floors) or {} + local exp = event.fields.floors and core.explode_textlist_event(event.fields.floors) or {} if event.fields.back then mem.screenstate = (mem.screenstate == "oobe_connection" and "oobe_connections" or "connections") elseif event.fields.save then @@ -906,134 +936,140 @@ fs("background9[0,0;16,12;celevator_fs_bg.png;true;3]") if mem.screenstate == "oobe_welcome" then fs("image[6,1;4,2;celevator_logo.png]") - fs("label[1,4;Welcome to your new MTronic XT elevator dispatcher!]") - fs("label[1,4.5;Before continuing, make sure you have at least two controllers in group operation mode and ready to connect.]") - fs("label[1,5.5;Press Next to begin.]") - fs("button[1,10;2,1;license;License Info]") - fs("button[13,10;2,1;next;Next >]") + fs("label[1,4;"..S("Welcome to your new MTronic XT elevator dispatcher!").."]") + fs("label[1,4.5;"..S("Before continuing, make sure you have at least two controllers in group operation mode and ready to connect.").."]") + fs("label[1,5.5;"..S("Press Next to begin.").."]") + fs("button[1,10;3,1;license;"..S("License Info").."]") + fs("button[13,10;2,1;next;"..S("Next >").."]") elseif mem.screenstate == "oobe_license" then - local licensefile = io.open(minetest.get_modpath("celevator")..DIR_DELIM.."LICENSE") - local license = minetest.formspec_escape(licensefile:read("*all")) + local licensefile = io.open(core.get_modpath("celevator").."/LICENSE") + local license = core.formspec_escape(licensefile:read("*all")) licensefile:close() - fs("textarea[1,1;14,8;license;This applies to the whole celevator mod\\, not just this dispatcher:;"..license.."]") + fs("textarea[1,1;14,8;license;"..core.formspec_escape(S("This applies to the whole celevator mod, not just this dispatcher:"))..";"..license.."]") fs("button[7,10.5;2,1;back;OK]") elseif mem.screenstate == "oobe_floortable" or mem.screenstate == "floortable" then if mem.screenstate == "oobe_floortable" then - fs("label[1,1;Enter details of all floors this group will serve, then press Next.]") - fs("label[1,1.3;Include all floors served by any car in the group, even if not served by all cars.]") - fs("button[1,10;2,1;back;< Back]") - fs("button[13,10;2,1;next;Next >]") + fs("label[1,1;"..S("Enter details of all floors this group will serve, then press Next.").."]") + fs("label[1,1.3;"..S("Include all floors served by any car in the group, even if not served by all cars.").."]") + fs("button[1,10;2,1;back;"..S("< Back").."]") + fs("button[13,10;2,1;next;"..S("Next >").."]") else - fs("label[1,1;EDIT FLOOR TABLE]") - fs("button[1,10;2,1;next;Done]") + fs("label[1,1;"..S("EDIT FLOOR TABLE").."]") + fs("button[1,10;2,1;next;"..S("Done").."]") end fs("textlist[1,2;6,7;floor;") for i=#mem.params.floornames,1,-1 do - fs(minetest.formspec_escape(string.format("%d - Height: %d - PI: %s",i,mem.params.floorheights[i],mem.params.floornames[i]))..(i==1 and "" or ",")) + local floortext = S("@1 - Height: @2 - PI: @3",i,mem.params.floorheights[i] or "??",mem.params.floornames[i] or "??") + fs(core.formspec_escape(floortext)..(i==1 and "" or ",")) end fs(";"..tostring(#mem.params.floornames-mem.editingfloor+1)..";false]") - if #mem.params.floornames < 100 then fs("button[8,2;2,1;add;New Floor]") end - fs("button[8,3.5;2,1;edit;Edit Floor]") - if #mem.params.floornames > 2 then fs("button[8,5;2,1;remove;Remove Floor]") end - if mem.editingfloor < #mem.params.floornames then fs("button[8,6.5;2,1;moveup;Move Up]") end - if mem.editingfloor > 1 then fs("button[8,8;2,1;movedown;Move Down") end + local maxfloors = tonumber(core.settings:get("celevator.max_landings")) or 100 + if #mem.params.floornames < maxfloors then fs("button[8,2;2,1;add;"..S("New Floor").."]") end + fs("button[8,3.5;2,1;edit;"..S("Edit Floor").."]") + if #mem.params.floornames > 2 then fs("button[8,5;2,1;remove;"..S("Remove Floor").."]") end + if mem.editingfloor < #mem.params.floornames then fs("button[8,6.5;2,1;moveup;"..S("Move Up").."]") end + if mem.editingfloor > 1 then fs("button[8,8;2,1;movedown;"..S("Move Down").."]") end elseif mem.screenstate == "oobe_floortable_edit" or mem.screenstate == "floortable_edit" then if mem.screenstate == "oobe_floortable_edit" then - fs("button[7,10.5;2,1;back;OK]") - fs("label[1,5;The Floor Height is the distance (in meters/nodes) from the floor level of this floor to the floor level of the next floor.]") - fs("label[1,5.5;(not used at the highest floor)]") - fs("label[1,6.5;The Floor Name is how the floor will be displayed on the position indicators.]") + fs("button[7,10.5;2,1;back;"..S("OK").."]") + local help1 = S("The Floor Height is the distance (in meters/nodes) from the floor level of this floor to the floor level of the next floor.") + local help2 = S("(not used at the highest floor)") + local help3 = S("The Floor Name is how the floor will be displayed on the position indicators.") + fs("label[1,5;"..help1.."]") + fs("label[1,5.5;"..help2.."]") + fs("label[1,6.5;"..help3.."]") else - fs("button[7,10.5;2,1;save;Save]") + fs("button[7,10.5;2,1;save;"..S("Save").."]") end - fs("label[1,1;Editing floor "..tostring(mem.editingfloor).."]") - fs("field[1,3;3,1;height;Floor Height;"..tostring(mem.params.floorheights[mem.editingfloor]).."]") - fs("field[5,3;3,1;name;Floor Name;"..minetest.formspec_escape(mem.params.floornames[mem.editingfloor]).."]") + fs("label[1,1;"..S("Editing Floor @1",tostring(mem.editingfloor)).."]") + fs("field[1,3;3,1;height;"..S("Floor Height")..";"..tostring(mem.params.floorheights[mem.editingfloor]).."]") + fs("field[5,3;3,1;name;"..S("Floor Name")..";"..core.formspec_escape(mem.params.floornames[mem.editingfloor]).."]") elseif mem.screenstate == "oobe_connections" or mem.screenstate == "connections" then if mem.screenstate == "oobe_connections" then - fs("label[1,1;Connect to each car in the group, then click Done.]") - fs("button[1,10;2,1;back;< Back]") - if #mem.params.carids > 0 then fs("button[13,10;2,1;next;Done >]") end + fs("label[1,1;"..S("Connect to each car in the group, then click Done.").."]") + fs("button[1,10;2,1;back;"..S("< Back").."]") + if #mem.params.carids > 0 then fs("button[13,10;2,1;next;"..S("Done").."]") end else - fs("label[1,1;EDIT CONNECTIONS]") - if #mem.params.carids > 0 then fs("button[1,10;2,1;next;Done]") end + fs("label[1,1;"..S("EDIT CONNECTIONS").."]") + if #mem.params.carids > 0 then fs("button[1,10;2,1;next;"..S("Done").."]") end end if #mem.params.carids > 0 then fs("textlist[1,2;6,7;connection;") for i=#mem.params.carids,1,-1 do - fs(string.format("Car %d - ID #%d",i,mem.params.carids[i])..(i==1 and "" or ",")) + local connectiontext = S("Car @1 - ID #@2",i,mem.params.carids[i]) + fs(connectiontext..(i==1 and "" or ",")) end fs(";"..tostring(#mem.params.carids-mem.editingconnection+1)..";false]") else - fs("label[1,2;No Connections]") + fs("label[1,2;"..S("No Connections").."]") end - if #mem.params.carids < 16 then fs("button[8,2;3,1;add;New Connection]") end - if #mem.params.carids > 0 then fs("button[8,3.5;3,1;edit;Edit Connection]") end - if #mem.params.carids > 0 then fs("button[8,5;3,1;remove;Remove Connection]") end + local maxcars = tonumber(core.settings:get("celevator.max_group")) or 16 + if #mem.params.carids < maxcars then fs("button[8,2;3,1;add;"..S("New Connection").."]") end + if #mem.params.carids > 0 then fs("button[8,3.5;3,1;edit;"..S("Edit Connection").."]") end + if #mem.params.carids > 0 then fs("button[8,5;3,1;remove;"..S("Remove Connection").."]") end elseif mem.screenstate == "oobe_newconnection" or mem.screenstate == "newconnection" then local numfloors = 0 for _,v in ipairs(mem.newconnfloors) do if v then numfloors = numfloors + 1 end end if mem.screenstate == "oobe_newconnection" then - fs("label[1,1;Enter the car ID and select the floors served (click them to toggle), then click Connect.]") - fs("label[1,1.3;You must select at least two floors.]") - fs("button[1,10;2,1;back;< Back]") - if numfloors >= 2 then fs("button[13,10;2,1;connect;Connect >]") end + fs("label[1,1;"..S("Enter the car ID and select the floors served (click them to toggle), then click Connect.").."]") + fs("label[1,1.3;"..S("You must select at least two floors.").."]") + fs("button[1,10;2,1;back;"..S("< Back").."]") + if numfloors >= 2 then fs("button[13,10;2,1;connect;"..S("Connect").."]") end else - fs("label[1,1;NEW CONNECTION]") - fs("button[1,10;2,1;back;Back]") - if numfloors >= 2 then fs("button[13,10;2,1;connect;Connect]") end + fs("label[1,1;"..S("NEW CONNECTION").."]") + fs("button[1,10;2,1;back;"..S("Back").."]") + if numfloors >= 2 then fs("button[13,10;2,1;connect;"..S("Connect").."]") end end fs("textlist[8,2;6,7;floors;") for i=#mem.params.floornames,1,-1 do - fs(string.format("%s - %s",minetest.formspec_escape(mem.params.floornames[i]),mem.newconnfloors[i] and "YES" or "NO")..(i==1 and "" or ",")) + fs(string.format("%s - %s",core.formspec_escape(mem.params.floornames[i]),mem.newconnfloors[i] and S("YES") or S("NO"))..(i==1 and "" or ",")) end fs(";0;false]") - fs("field[2,3;4,1;carid;Car ID;]") + fs("field[2,3;4,1;carid;"..S("Car ID")..";]") elseif mem.screenstate == "oobe_connection" or mem.screenstate == "connection" then local numfloors = 0 for _,v in ipairs(mem.newconnfloors) do if v then numfloors = numfloors + 1 end end if mem.screenstate == "oobe_newconnection" then - fs("label[1,1;Enter the car ID and select the floors served (click them to toggle), then click Connect.]") - fs("label[1,1.3;You must select at least two floors.]") - fs("button[1,10;2,1;back;< Back]") - if numfloors >= 2 then fs("button[13,10;2,1;save;Save >]") end + fs("label[1,1;"..S("Enter the car ID and select the floors served (click them to toggle), then click Connect.").."]") + fs("label[1,1.3;"..S("You must select at least two floors.").."]") + fs("button[1,10;2,1;back;"..S("< Back").."]") + if numfloors >= 2 then fs("button[13,10;2,1;save;"..S("Save").."]") end else - fs("label[1,1;EDIT CONNECTION]") - fs("button[1,10;2,1;back;< Back]") - if numfloors >= 2 then fs("button[13,10;2,1;save;Save >]") end + fs("label[1,1;"..S("EDIT CONNECTION").."]") + fs("button[1,10;2,1;back;"..S("< Back").."]") + if numfloors >= 2 then fs("button[13,10;2,1;save;"..S("Save").."]") end end fs("textlist[8,2;6,7;floors;") for i=#mem.params.floornames,1,-1 do - fs(string.format("%s - %s",minetest.formspec_escape(mem.params.floornames[i]),mem.newconnfloors[i] and "YES" or "NO")..(i==1 and "" or ",")) + fs(string.format("%s - %s",core.formspec_escape(mem.params.floornames[i]),mem.newconnfloors[i] and S("YES") or S("NO"))..(i==1 and "" or ",")) end fs(";0;false]") - fs("label[2,3;Car ID: "..mem.params.carids[mem.editingconnection].."]") + fs("label[2,3;"..S("Car ID: @1",mem.params.carids[mem.editingconnection]).."]") elseif mem.screenstate == "oobe_connecting" or mem.screenstate == "connecting" then - fs("label[1,1;Connecting to controller...]") + fs("label[1,1;"..S("Connecting to controller...").."]") elseif mem.screenstate == "oobe_connectionfailed" or mem.screenstate == "connectionfailed" then - fs("label[4,4;Connection timed out!]") - fs("label[4,5;Make sure the car ID is correct and]") - fs("label[4,5.5;that the controller is ready to pair.]") - fs("button[1,10;2,1;back;< Back]") + fs("label[4,4;"..S("Connection timed out!").."]") + fs("label[4,5;"..S("Make sure the car ID is correct and\nthat the controller is ready to connect.").."]") + fs("button[1,10;2,1;back;"..S("< Back").."]") elseif mem.screenstate == "status" then if not mem.screenpage then mem.screenpage = 1 end - fs("label[1,1;GROUP DISPLAY]") + fs("label[1,1;"..S("GROUP DISPLAY").."]") fs("box[1.5,1.5;0.1,10;#AAAAAAFF]") fs("box[18.5,1.5;0.1,10;#AAAAAAFF]") - fs("label[0.55,11.5;UP]") - fs("label[18.85,11.5;DOWN]") - fs("button[15,0.5;2,1;menu;Menu]") + fs("image[0.45,11;0.2,0.4;celevator_menu_small_arrow.png]") + fs("image[19.4,11;0.2,0.4;celevator_menu_small_arrow.png^[transformFY]") + fs("button[15,0.5;2,1;menu;"..S("Menu").."]") fs("style_type[image_button;font=mono;font_size=*0.75]") for car=1,#mem.params.carids,1 do local xp = 1.7+(car-1) local carid = mem.params.carids[car] local carstate = mem.carstatus[carid].state - fs(string.format("label[%f,11;CAR %d]",xp,car)) - fs(string.format("label[%f,11.35;%s]",xp+0.1,minetest.colorize("#ff5555",(carstate == "normal" and " IN" or "OUT")))) + fs(string.format("label[%f,11;%s]",xp,S("CAR @1",car))) + fs(string.format("label[%f,11.35;%s]",xp+0.1,core.colorize("#ff5555",(carstate == "normal" and S(" IN") or S("OUT"))))) end local lowestfloor = (mem.screenpage-1)*10+1 for i=1,math.min(10,#mem.params.floornames-lowestfloor+1),1 do @@ -1041,11 +1077,11 @@ elseif mem.screenstate == "status" then local floor = i+lowestfloor-1 fs(string.format("label[0.9,%f;%s]",yp+0.35,mem.params.floornames[floor])) local uplabel = "" - if mem.upcalls[floor] then uplabel = minetest.colorize("#55FF55",math.floor(mem.upeta[floor] or 0)) end + if mem.upcalls[floor] then uplabel = core.colorize("#55FF55",math.floor(mem.upeta[floor] or 0)) end if floor < #mem.params.floornames then fs(string.format("image_button[0.15,%f;0.75,0.75;celevator_fs_bg.png;upcall%d;%s]",yp,floor,uplabel)) end fs(string.format("label[18.65,%f;%s]",yp+0.35,mem.params.floornames[floor])) local dnlabel = "" - if mem.dncalls[floor] then dnlabel = minetest.colorize("#FF5555",math.floor(mem.dneta[floor] or 0)) end + if mem.dncalls[floor] then dnlabel = core.colorize("#FF5555",math.floor(mem.dneta[floor] or 0)) end if floor > 1 then fs(string.format("image_button[19.1,%f;0.75,0.75;celevator_fs_bg.png;dncall%d;%s]",yp,floor,dnlabel)) end for car=1,#mem.params.carids,1 do local xp = 1.7+(car-1) @@ -1053,10 +1089,10 @@ elseif mem.screenstate == "status" then local carfloor = realtocarfloor(carid,floor) if carfloor then local ccdot = mem.carstatus[carid].carcalls[carfloor] and "*" or "" - local groupup = mem.carstatus[carid].groupupcalls[carfloor] and minetest.colorize("#55FF55","^") or "" - local swingup = mem.carstatus[carid].swingupcalls[carfloor] and minetest.colorize("#FFFF55","^") or "" - local swingdn = mem.carstatus[carid].swingdncalls[carfloor] and minetest.colorize("#FFFF55","v") or "" - local groupdn = mem.carstatus[carid].groupdncalls[carfloor] and minetest.colorize("#FF5555","v") or "" + local groupup = mem.carstatus[carid].groupupcalls[carfloor] and core.colorize("#55FF55","^") or "" + local swingup = mem.carstatus[carid].swingupcalls[carfloor] and core.colorize("#FFFF55","^") or "" + local swingdn = mem.carstatus[carid].swingdncalls[carfloor] and core.colorize("#FFFF55","v") or "" + local groupdn = mem.carstatus[carid].groupdncalls[carfloor] and core.colorize("#FF5555","v") or "" ccdot = groupup..swingup..ccdot..swingdn..groupdn if getpos(carid) == floor then local cargraphics = { @@ -1068,9 +1104,9 @@ elseif mem.screenstate == "status" then } ccdot = cargraphics[mem.carstatus[carid].doorstate] if mem.carstatus[carid].direction == "up" then - ccdot = minetest.colorize("#55FF55",ccdot) + ccdot = core.colorize("#55FF55",ccdot) elseif mem.carstatus[carid].direction == "down" then - ccdot = minetest.colorize("#FF5555",ccdot) + ccdot = core.colorize("#FF5555",ccdot) end end fs(string.format("image_button[%f,%f;0.75,0.75;celevator_fs_bg.png;carcall%02d%d;%s]",xp,yp,car,floor,ccdot)) @@ -1084,12 +1120,12 @@ elseif mem.screenstate == "status" then fs("image_button[5,0.5;0.75,0.75;celevator_menu_arrow.png;scrollup;;false;false;celevator_menu_arrow.png]") end elseif mem.screenstate == "menu" then - fs("label[1,1;MAIN MENU]") - fs("button[1,3;3,1;floortable;Edit Floor Table]") - fs("button[1,4.5;3,1;connections;Edit Connections]") - fs("button[1,10;3,1;back;< Back]") + fs("label[1,1;"..S("MAIN MENU").."]") + fs("button[1,3;3,1;floortable;"..S("Edit Floor Table").."]") + fs("button[1,4.5;3,1;connections;"..S("Edit Connections").."]") + fs("button[1,10;3,1;back;"..S("< Back").."]") end -mem.infotext = string.format("ID: %d",mem.carid) +mem.infotext = S("ID: @1",mem.carid) return pos,mem,changedinterrupts 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..ac707d8 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..3e2b464 100644 --- a/docs/file_sources +++ b/docs/file_sources @@ -1,4 +1,10 @@ -All code: Written by cheapie +Code: Written by the following contributors: +* cheapie +* j-r (Jürgen Rühle) + +Locales: Translated by the following contributors: +* cheapie (es) +* pgimeno (es) All textures: Hand-drawn by cheapie using GIMP @@ -25,6 +31,10 @@ Originally from "elevator bell dings closeup nice.flac" by kyles on Freesound, o https://freesound.org/people/kyles/sounds/453980/ Edited by cheapie. +* celevator_chime2_up.ogg and celevator_chime2_down.ogg +Synthesized in Faust Music Creator by cheapie. +Edited by cheapie. + * celevator_door_close.ogg, celevator_door_open.ogg, and celevator_door_reverse.ogg Originally from "elevator doors open close.wav" by omsomaque on Freesound, originally licensed under CC0. https://freesound.org/people/omsomaque/sounds/584911/ @@ -44,3 +54,11 @@ Edited by cheapie. Originally from "Fujitec Traction Elevator Machine Room" by ElevDSM on YouTube, explicit permission has been obtained from the author to use these sounds here and distribute them under mod's license. https://www.youtube.com/watch?v=0rPZrkEreAo Edited by cheapie. + +* celevator_alarm.ogg +Originally from "School bell.wav" by deleted_user_7020630 on Freesound, originally licensed under CC0. +https://freesound.org/people/deleted_user_7020630/sounds/378394/ +Edited by cheapie. + +* celevator_phone.ogg +Synthesized in Audacity by cheapie. diff --git a/door_2speedglass.lua b/door_2speedglass.lua new file mode 100644 index 0000000..22eafab --- /dev/null +++ b/door_2speedglass.lua @@ -0,0 +1,641 @@ +celevator.doors.twospeedglass = {} + +local S = core.get_translator("celevator") + +core.register_node("celevator:hwdoor_fast_glass_bottom",{ + description = S("Glass 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_glass_topbottom.png^[transformFY", + "celevator_door_glass_topbottom.png^[transformFY", + }, + groups = { + not_in_creative_inventory = 1, + _celevator_hwdoor_root = 1, + oddly_breakable_by_hand = 2, + }, + drop = "celevator:hwdoor_glass", + paramtype = "light", + paramtype2 = "4dir", + drawtype = "nodebox", + use_texture_alpha = "clip", + 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 = core.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 = core.dir_to_yaw(core.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_glass_%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 core.get_node(piecepos).name == piecename then core.remove_node(piecepos) end + end + end + end, + _celevator_doortype = "twospeedglass", +}) + +core.register_node("celevator:hwdoor_fast_glass_middle",{ + description = S("Glass 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_glass_middle.png", + "celevator_door_glass_middle.png", + }, + groups = { + not_in_creative_inventory = 1, + }, + drop = "", + paramtype = "light", + paramtype2 = "4dir", + drawtype = "nodebox", + use_texture_alpha = "clip", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.5,0.4,0.5,0.5,0.5}, + }, + }, + _celevator_doortype = "twospeedglass", +}) + +core.register_node("celevator:hwdoor_fast_glass_top",{ + description = S("Glass 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_glass_topbottom.png", + "celevator_door_glass_topbottom.png", + }, + groups = { + not_in_creative_inventory = 1, + }, + drop = "", + paramtype = "light", + paramtype2 = "4dir", + drawtype = "nodebox", + use_texture_alpha = "clip", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.5,0.4,0.5,0.5,0.5}, + }, + }, + _celevator_doortype = "twospeedglass", +}) + +core.register_node("celevator:hwdoor_slow_glass_bottom",{ + description = S("Glass 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_glass_topbottom.png^[transformFY", + "celevator_door_glass_topbottom.png^[transformFY", + }, + groups = { + not_in_creative_inventory = 1, + }, + drop = "", + paramtype = "light", + paramtype2 = "4dir", + drawtype = "nodebox", + use_texture_alpha = "clip", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.5,0.3,0.5,0.5,0.4}, + }, + }, + _celevator_doortype = "twospeedglass", +}) + +core.register_node("celevator:hwdoor_slow_glass_middle",{ + description = S("Glass 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_glass_middle.png", + "celevator_door_glass_middle.png", + }, + groups = { + not_in_creative_inventory = 1, + }, + drop = "", + paramtype = "light", + paramtype2 = "4dir", + drawtype = "nodebox", + use_texture_alpha = "clip", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.5,0.3,0.5,0.5,0.4}, + }, + }, + _celevator_doortype = "twospeedglass", +}) + +core.register_node("celevator:hwdoor_slow_glass_top",{ + description = S("Glass 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_glass_topbottom.png", + "celevator_door_glass_topbottom.png", + }, + groups = { + not_in_creative_inventory = 1, + }, + drop = "", + paramtype = "light", + paramtype2 = "4dir", + drawtype = "nodebox", + use_texture_alpha = "clip", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.5,0.3,0.5,0.5,0.4}, + }, + }, + _celevator_doortype = "twospeedglass", +}) + +core.register_node("celevator:hwdoor_glass",{ + description = S("Glass Elevator Hoistway Door"), + paramtype2 = "4dir", + buildable_to = true, + inventory_image = "celevator_door_glass_inventory.png", + wield_image = "celevator_door_glass_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 + core.remove_node(pos) + return true + end + local name = player:get_player_name() + local newnode = core.get_node(pos) + local facedir = core.dir_to_yaw(core.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 placeoffset = vector.new(x,y,0) + local placepos = vector.add(pos,vector.rotate_around_axis(placeoffset,vector.new(0,1,0),facedir)) + local replaces = core.get_node(placepos).name + if not (core.registered_nodes[replaces] and core.registered_nodes[replaces].buildable_to) then + local errormsg = S("Can't place door here - position @1m to the right and @2m up is blocked!",x,y) + core.chat_send_player(name,errormsg) + core.remove_node(pos) + return true + end + if core.is_protected(placepos,name) and not core.check_player_privs(name,{protection_bypass=true}) then + local errormsg = S("Can't place door here - position @1m to the right and @2m up is protected!",x,y) + core.chat_send_player(name,errormsg) + core.record_protection_violation(placepos,name) + core.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_glass_%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)) + core.set_node(placepos,{name=piecename,param2=newnode.param2}) + if y==0 then + celevator.doors.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 = core.registered_nodes[celevator.get_node(carpos).name] or {} + if carndef._root then + celevator.get_meta(carpos):set_string("doortype","glass") + celevator.doors.spawncardoors(carpos,core.fourdir_to_dir(newnode.param2),"glass",true) + end + end, +}) + +core.register_lbm({ + label = "Respawn hoistway door sills (2-speed glass)", + name = "celevator:spawn_sill_twospeedglass", + nodenames = { + "celevator:hwdoor_fast_glass_bottom", + "celevator:hwdoor_slow_glass_bottom", + }, + run_at_every_load = true, + action = celevator.doors.placesill, +}) + +celevator.doors.twospeedglass.spawncardoors = function(pos,dir,replace) + local refs = {} + for x=2,1,-1 do + for y=1,3,1 do + local yaw = core.dir_to_yaw(dir)+math.pi + 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]) + if replace then + local oldrefs = core.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 = core.add_entity(doorpos,"celevator:car_door") + ref:set_yaw(yaw) + ref:set_properties({ + wield_item = nname, + }) + table.insert(refs,ref) + end + end + return refs +end + +function celevator.doors.twospeedglass.hwopen(pos,drivepos) + celevator.doors.hwdoor_step_enabled = true + local hwdoors_moving = core.deserialize(celevator.storage:get_string("hwdoors_moving")) or {} + local hash = core.hash_node_position(pos) + if not hwdoors_moving[hash] then + local param2 = celevator.get_node(pos).param2 + local fdir = core.fourdir_to_dir(param2) + local otherpanel = vector.add(pos,vector.rotate_around_axis(fdir,vector.new(0,1,0),-math.pi/2)) + local positions = { + pos, + vector.add(pos,vector.new(0,1,0)), + vector.add(pos,vector.new(0,2,0)), + otherpanel, + vector.add(otherpanel,vector.new(0,1,0)), + vector.add(otherpanel,vector.new(0,2,0)), + } + local oldnodes = {} + for i,position in ipairs(positions) do + oldnodes[i] = celevator.get_node(position) + end + local erefs = celevator.drives.entity.nodestoentities(positions,"celevator:hwdoor_moving") + hwdoors_moving[hash] = { + direction = "open", + positions = positions, + nodes = oldnodes, + time = 0, + opendir = vector.rotate_around_axis(fdir,vector.new(0,1,0),-math.pi/2), + drivepos = drivepos, + param2 = param2, + doortype = "twospeedglass", + } + celevator.doors.erefs[hash] = erefs + celevator.storage:set_string("hwdoors_moving",core.serialize(hwdoors_moving)) + core.set_node(pos,{name="celevator:hwdoor_placeholder",param2=param2}) + local pmeta = celevator.get_meta(pos) + pmeta:set_string("data",core.serialize(hwdoors_moving[hash])) + pmeta:set_string("state","opening") + pmeta:set_string("doortype","twospeedglass") + local carpos = vector.add(pos,fdir) + local carndef = core.registered_nodes[celevator.get_node(carpos).name] or {} + if carndef._root then + celevator.doors.caropen(carpos) + end + elseif hwdoors_moving[hash].direction == "close" then + hwdoors_moving[hash].direction = "open" + hwdoors_moving[hash].time = math.pi-hwdoors_moving[hash].time + celevator.storage:set_string("hwdoors_moving",core.serialize(hwdoors_moving)) + local fdir = core.fourdir_to_dir(hwdoors_moving[hash].param2) + local carpos = vector.add(pos,fdir) + local carndef = core.registered_nodes[celevator.get_node(carpos).name] or {} + if carndef._root then + celevator.doors.caropen(carpos) + end + core.set_node(pos,{name="celevator:hwdoor_placeholder",param2=hwdoors_moving[hash].param2}) + local pmeta = celevator.get_meta(pos) + pmeta:set_string("data",core.serialize(hwdoors_moving[hash])) + pmeta:set_string("state","opening") + pmeta:set_string("doortype","twospeedglass") + end +end + +function celevator.doors.twospeedglass.hwclose(pos,drivepos,nudge) + celevator.doors.hwdoor_step_enabled = true + local hwdoors_moving = core.deserialize(celevator.storage:get_string("hwdoors_moving")) or {} + local hash = core.hash_node_position(pos) + if hwdoors_moving[hash] then + return + end + local pmeta = celevator.get_meta(pos) + local state = pmeta:get_string("state") + if state ~= "open" then return end + local fdir = core.fourdir_to_dir(celevator.get_node(pos).param2) + local carpos = vector.add(pos,fdir) + local carndef = core.registered_nodes[celevator.get_node(carpos).name] or {} + if carndef._root then + celevator.doors.carclose(carpos,nudge) + end + local data = core.deserialize(pmeta:get_string("data")) + if not data then return end + for i=1,6,1 do + core.set_node(data.positions[i],data.nodes[i]) + end + data.direction = "close" + data.time = 0 + data.drivepos = drivepos + data.nudging = nudge + local erefs = celevator.drives.entity.nodestoentities(data.positions,"celevator:hwdoor_moving") + local foffset = vector.multiply(data.opendir,2) + local soffset = data.opendir + for i=1,3,1 do + erefs[i]:set_pos(vector.add(erefs[i]:get_pos(),foffset)) + end + for i=4,6,1 do + erefs[i]:set_pos(vector.add(erefs[i]:get_pos(),soffset)) + end + celevator.doors.erefs[hash] = erefs + hwdoors_moving[hash] = data + celevator.storage:set_string("hwdoors_moving",core.serialize(hwdoors_moving)) +end + +function celevator.doors.twospeedglass.hwstep(hash,data,dtime,hwdoors_moving) + local present = celevator.doors.erefs[hash] + if present then + for i=1,6,1 do + if not celevator.doors.erefs[hash][i]:get_pos() then + present = false + break + end + end + end + if present then + if data.direction == "open" then + data.time = data.time+dtime + local vel = math.sin(data.time) + for i=1,3,1 do + celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel)) + end + for i=4,6,1 do + celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel/2)) + end + if data.time >= math.pi then + for i=1,6,1 do + celevator.doors.erefs[hash][i]:remove() + end + celevator.get_meta(data.positions[1]):set_string("state","open") + if hwdoors_moving[hash].drivepos then celevator.get_meta(hwdoors_moving[hash].drivepos):set_string("doorstate","open") end + hwdoors_moving[hash] = nil + end + elseif data.direction == "close" then + local speed = 0.66 + if data.nudging then speed = 0.2 end + data.time = data.time+(speed*dtime) + local vel = math.sin(data.time) + for i=1,3,1 do + celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel*-speed)) + end + for i=4,6,1 do + celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel/2*-speed)) + end + if data.time >= math.pi then + for i=1,6,1 do + celevator.doors.erefs[hash][i]:set_pos(data.positions[i]) + end + celevator.drives.entity.entitiestonodes(celevator.doors.erefs[hash]) + if hwdoors_moving[hash].drivepos then celevator.get_meta(hwdoors_moving[hash].drivepos):set_string("doorstate","closed") end + hwdoors_moving[hash] = nil + end + end + else + if data.direction == "open" then + for i=1,6,1 do + if celevator.doors.erefs[hash] then + celevator.doors.erefs[hash][i]:remove() + end + end + celevator.get_meta(data.positions[1]):set_string("state","open") + if hwdoors_moving[hash].drivepos then celevator.get_meta(hwdoors_moving[hash].drivepos):set_string("doorstate","open") end + hwdoors_moving[hash] = nil + elseif data.direction == "close" then + for i=1,6,1 do + core.set_node(data.positions[i],data.nodes[i]) + end + celevator.get_meta(data.positions[1]):set_string("state","closed") + if hwdoors_moving[hash].drivepos then celevator.get_meta(hwdoors_moving[hash].drivepos):set_string("doorstate","closed") end + hwdoors_moving[hash] = nil + end + end +end + +function celevator.doors.twospeedglass.caropen(pos) + celevator.doors.cardoor_step_enabled = true + local cardoors_moving = core.deserialize(celevator.storage:get_string("cardoors_moving")) or {} + local hash = core.hash_node_position(pos) + local cartimer = core.get_node_timer(pos) + cartimer:start(0.25) + if not cardoors_moving[hash] then + local fdir = core.fourdir_to_dir(celevator.get_node(pos).param2) + local otherpanel = vector.add(pos,vector.rotate_around_axis(fdir,vector.new(0,1,0),-math.pi/2)) + local positions = { + pos, + vector.add(pos,vector.new(0,1,0)), + vector.add(pos,vector.new(0,2,0)), + otherpanel, + vector.add(otherpanel,vector.new(0,1,0)), + vector.add(otherpanel,vector.new(0,2,0)), + } + local erefs = {} + for _,dpos in ipairs(positions) do + local objs = core.get_objects_inside_radius(dpos,0.5) + for _,obj in pairs(objs) do + if obj:get_luaentity() and obj:get_luaentity().name == "celevator:car_door" then + table.insert(erefs,obj) + end + end + end + cardoors_moving[hash] = { + direction = "open", + positions = positions, + time = 0, + opendir = vector.rotate_around_axis(fdir,vector.new(0,1,0),-math.pi/2), + doortype = "twospeedglass", + } + core.sound_play("celevator_door_open",{ + pos = pos, + gain = 0.4, + max_hear_distance = 10 + },true) + celevator.doors.erefs[hash] = erefs + celevator.storage:set_string("cardoors_moving",core.serialize(cardoors_moving)) + local meta = celevator.get_meta(pos) + meta:set_string("doordata",core.serialize(cardoors_moving[hash])) + meta:set_string("doorstate","opening") + elseif cardoors_moving[hash].direction == "close" then + if cardoors_moving[hash].soundhandle then + core.sound_stop(cardoors_moving[hash].soundhandle) + end + core.sound_play("celevator_door_reverse",{ + pos = pos, + gain = 1, + max_hear_distance = 10 + },true) + core.sound_play("celevator_door_open",{ + pos = pos, + gain = 0.4, + start_time = math.max(0,2.75-cardoors_moving[hash].time), + max_hear_distance = 10 + },true) + cardoors_moving[hash].direction = "open" + cardoors_moving[hash].time = math.pi-cardoors_moving[hash].time + celevator.storage:set_string("cardoors_moving",core.serialize(cardoors_moving)) + end +end + +function celevator.doors.twospeedglass.carclose(pos,nudge) + celevator.doors.cardoor_step_enabled = true + local cardoors_moving = core.deserialize(celevator.storage:get_string("cardoors_moving")) or {} + local hash = core.hash_node_position(pos) + if cardoors_moving[hash] then + return + end + local meta = celevator.get_meta(pos) + local state = meta:get_string("doorstate") + if state ~= "open" then return end + local data = core.deserialize(meta:get_string("doordata")) + if not data then return end + local dir = core.fourdir_to_dir(celevator.get_node(pos).param2) + data.direction = "close" + data.time = 0 + data.doortype = "twospeedglass" + local erefs = celevator.doors.spawncardoors(pos,dir,"twospeedglass") + local soffset = data.opendir + local foffset = vector.multiply(soffset,2) + for i=1,3,1 do + erefs[i]:set_pos(vector.add(erefs[i]:get_pos(),foffset)) + end + for i=4,6,1 do + erefs[i]:set_pos(vector.add(erefs[i]:get_pos(),soffset)) + end + celevator.doors.erefs[hash] = erefs + if nudge then + data.soundhandle = core.sound_play("celevator_nudge",{ + pos = pos, + gain = 0.75, + max_hear_distance = 10 + }) + else + data.soundhandle = core.sound_play("celevator_door_close",{ + pos = pos, + gain = 0.3, + max_hear_distance = 10 + }) + end + data.nudging = nudge + cardoors_moving[hash] = data + celevator.storage:set_string("cardoors_moving",core.serialize(cardoors_moving)) +end + +function celevator.doors.twospeedglass.carstep(hash,data,dtime,cardoors_moving) + local present = celevator.doors.erefs[hash] + if present then + for i=1,6,1 do + if not (celevator.doors.erefs[hash][i] and celevator.doors.erefs[hash][i]:get_pos()) then + present = false + break + end + end + end + if present then + if data.direction == "open" then + data.time = data.time+dtime + local vel = math.sin(data.time) + for i=1,3,1 do + celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel)) + end + for i=4,6,1 do + celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel/2)) + end + if data.time >= math.pi then + for i=1,6,1 do + celevator.doors.erefs[hash][i]:remove() + end + celevator.get_meta(data.positions[1]):set_string("doorstate","open") + cardoors_moving[hash] = nil + end + elseif data.direction == "close" then + local speed = 0.66 + if data.nudging then speed = 0.2 end + data.time = data.time+(speed*dtime) + local vel = math.sin(data.time) + for i=1,3,1 do + celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel*-speed)) + end + for i=4,6,1 do + celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel/2*-speed)) + end + if data.time >= math.pi then + for _,ref in ipairs(celevator.doors.erefs[hash]) do + ref:remove() + end + local carmeta = celevator.get_meta(data.positions[1]) + carmeta:set_string("doorstate","closed") + cardoors_moving[hash] = nil + local cartimer = core.get_node_timer(data.positions[1]) + cartimer:stop() + local fdir = core.facedir_to_dir(core.get_node(data.positions[1]).param2) + celevator.doors.spawncardoors(data.positions[1],fdir,"twospeedglass") + end + end + else + if data.direction == "open" then + for i=1,6,1 do + if celevator.doors.erefs[hash] and celevator.doors.erefs[hash][i] then + celevator.doors.erefs[hash][i]:remove() + end + end + celevator.get_meta(data.positions[1]):set_string("doorstate","open") + cardoors_moving[hash] = nil + elseif data.direction == "close" then + local fdir = core.fourdir_to_dir(celevator.get_node(data.positions[1]).param2) + celevator.doors.spawncardoors(data.positions[1],vector.rotate_around_axis(fdir,vector.new(0,1,0),math.pi),"twospeedglass") + celevator.get_meta(data.positions[1]):set_string("doorstate","closed") + cardoors_moving[hash] = nil + end + end +end diff --git a/door_2speedmetal.lua b/door_2speedmetal.lua new file mode 100644 index 0000000..b074722 --- /dev/null +++ b/door_2speedmetal.lua @@ -0,0 +1,635 @@ +celevator.doors.twospeedmetal = {} + +local S = core.get_translator("celevator") + +core.register_node("celevator:hwdoor_fast_steel_bottom",{ + description = S("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 = core.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 = core.dir_to_yaw(core.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 core.get_node(piecepos).name == piecename then core.remove_node(piecepos) end + end + end + end, + _celevator_doortype = "twospeedmetal", +}) + +core.register_node("celevator:hwdoor_fast_steel_middle",{ + description = S("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}, + }, + }, + _celevator_doortype = "twospeedmetal", +}) + +core.register_node("celevator:hwdoor_fast_steel_top",{ + description = S("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}, + }, + }, + _celevator_doortype = "twospeedmetal", +}) + +core.register_node("celevator:hwdoor_slow_steel_bottom",{ + description = S("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}, + }, + }, + _celevator_doortype = "twospeedmetal", +}) + +core.register_node("celevator:hwdoor_slow_steel_middle",{ + description = S("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}, + }, + }, + _celevator_doortype = "twospeedmetal", +}) + +core.register_node("celevator:hwdoor_slow_steel_top",{ + description = S("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}, + }, + }, + _celevator_doortype = "twospeedmetal", +}) + +core.register_node("celevator:hwdoor_steel",{ + description = S("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 + core.remove_node(pos) + return true + end + local name = player:get_player_name() + local newnode = core.get_node(pos) + local facedir = core.dir_to_yaw(core.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 placeoffset = vector.new(x,y,0) + local placepos = vector.add(pos,vector.rotate_around_axis(placeoffset,vector.new(0,1,0),facedir)) + local replaces = core.get_node(placepos).name + if not (core.registered_nodes[replaces] and core.registered_nodes[replaces].buildable_to) then + local errormsg = S("Can't place door here - position @1m to the right and @2m up is blocked!",x,y) + core.chat_send_player(name,errormsg) + core.remove_node(pos) + return true + end + if core.is_protected(placepos,name) and not core.check_player_privs(name,{protection_bypass=true}) then + local errormsg = S("Can't place door here - position @1m to the right and @2m up is protected!",x,y) + core.chat_send_player(name,errormsg) + core.record_protection_violation(placepos,name) + core.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)) + core.set_node(placepos,{name=piecename,param2=newnode.param2}) + if y==0 then + celevator.doors.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 = core.registered_nodes[celevator.get_node(carpos).name] or {} + if carndef._root then + celevator.get_meta(carpos):set_string("doortype","steel") + celevator.doors.spawncardoors(carpos,core.fourdir_to_dir(newnode.param2),"steel",true) + end + end, +}) + +core.register_lbm({ + label = "Respawn hoistway door sills (2-speed metal)", + name = "celevator:spawn_sill_twospeedmetal", + nodenames = { + "celevator:hwdoor_fast_steel_bottom", + "celevator:hwdoor_slow_steel_bottom", + }, + run_at_every_load = true, + action = celevator.doors.placesill, +}) + +celevator.doors.twospeedmetal.spawncardoors = function(pos,dir,replace) + local refs = {} + for x=2,1,-1 do + for y=1,3,1 do + local yaw = core.dir_to_yaw(dir)+math.pi + 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_steel_%s",xnames[x],ynames[y]) + if replace then + local oldrefs = core.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 = core.add_entity(doorpos,"celevator:car_door") + ref:set_yaw(yaw) + ref:set_properties({ + wield_item = nname, + }) + table.insert(refs,ref) + end + end + return refs +end + +function celevator.doors.twospeedmetal.hwopen(pos,drivepos) + celevator.doors.hwdoor_step_enabled = true + local hwdoors_moving = core.deserialize(celevator.storage:get_string("hwdoors_moving")) or {} + local hash = core.hash_node_position(pos) + if not hwdoors_moving[hash] then + local param2 = celevator.get_node(pos).param2 + local fdir = core.fourdir_to_dir(param2) + local otherpanel = vector.add(pos,vector.rotate_around_axis(fdir,vector.new(0,1,0),-math.pi/2)) + local positions = { + pos, + vector.add(pos,vector.new(0,1,0)), + vector.add(pos,vector.new(0,2,0)), + otherpanel, + vector.add(otherpanel,vector.new(0,1,0)), + vector.add(otherpanel,vector.new(0,2,0)), + } + local oldnodes = {} + for i,position in ipairs(positions) do + oldnodes[i] = celevator.get_node(position) + end + local erefs = celevator.drives.entity.nodestoentities(positions,"celevator:hwdoor_moving") + hwdoors_moving[hash] = { + direction = "open", + positions = positions, + nodes = oldnodes, + time = 0, + opendir = vector.rotate_around_axis(fdir,vector.new(0,1,0),-math.pi/2), + drivepos = drivepos, + param2 = param2, + doortype = "twospeedmetal", + } + celevator.doors.erefs[hash] = erefs + celevator.storage:set_string("hwdoors_moving",core.serialize(hwdoors_moving)) + core.set_node(pos,{name="celevator:hwdoor_placeholder",param2=param2}) + local pmeta = celevator.get_meta(pos) + pmeta:set_string("data",core.serialize(hwdoors_moving[hash])) + pmeta:set_string("state","opening") + pmeta:set_string("doortype","twospeedmetal") + local carpos = vector.add(pos,fdir) + local carndef = core.registered_nodes[celevator.get_node(carpos).name] or {} + if carndef._root then + celevator.doors.caropen(carpos) + end + elseif hwdoors_moving[hash].direction == "close" then + hwdoors_moving[hash].direction = "open" + hwdoors_moving[hash].time = math.pi-hwdoors_moving[hash].time + celevator.storage:set_string("hwdoors_moving",core.serialize(hwdoors_moving)) + local fdir = core.fourdir_to_dir(hwdoors_moving[hash].param2) + local carpos = vector.add(pos,fdir) + local carndef = core.registered_nodes[celevator.get_node(carpos).name] or {} + if carndef._root then + celevator.doors.caropen(carpos) + end + core.set_node(pos,{name="celevator:hwdoor_placeholder",param2=hwdoors_moving[hash].param2}) + local pmeta = celevator.get_meta(pos) + pmeta:set_string("data",core.serialize(hwdoors_moving[hash])) + pmeta:set_string("state","opening") + pmeta:set_string("doortype","twospeedmetal") + end +end + +function celevator.doors.twospeedmetal.hwclose(pos,drivepos,nudge) + celevator.doors.hwdoor_step_enabled = true + local hwdoors_moving = core.deserialize(celevator.storage:get_string("hwdoors_moving")) or {} + local hash = core.hash_node_position(pos) + if hwdoors_moving[hash] then + return + end + local pmeta = celevator.get_meta(pos) + local state = pmeta:get_string("state") + if state ~= "open" then return end + local fdir = core.fourdir_to_dir(celevator.get_node(pos).param2) + local carpos = vector.add(pos,fdir) + local carndef = core.registered_nodes[celevator.get_node(carpos).name] or {} + if carndef._root then + celevator.doors.carclose(carpos,nudge) + end + local data = core.deserialize(pmeta:get_string("data")) + if not data then return end + for i=1,6,1 do + core.set_node(data.positions[i],data.nodes[i]) + end + data.direction = "close" + data.time = 0 + data.drivepos = drivepos + data.nudging = nudge + local erefs = celevator.drives.entity.nodestoentities(data.positions,"celevator:hwdoor_moving") + local foffset = vector.multiply(data.opendir,2) + local soffset = data.opendir + for i=1,3,1 do + erefs[i]:set_pos(vector.add(erefs[i]:get_pos(),foffset)) + end + for i=4,6,1 do + erefs[i]:set_pos(vector.add(erefs[i]:get_pos(),soffset)) + end + celevator.doors.erefs[hash] = erefs + hwdoors_moving[hash] = data + celevator.storage:set_string("hwdoors_moving",core.serialize(hwdoors_moving)) +end + +function celevator.doors.twospeedmetal.hwstep(hash,data,dtime,hwdoors_moving) + local present = celevator.doors.erefs[hash] + if present then + for i=1,6,1 do + if not celevator.doors.erefs[hash][i]:get_pos() then + present = false + break + end + end + end + if present then + if data.direction == "open" then + data.time = data.time+dtime + local vel = math.sin(data.time) + for i=1,3,1 do + celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel)) + end + for i=4,6,1 do + celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel/2)) + end + if data.time >= math.pi then + for i=1,6,1 do + celevator.doors.erefs[hash][i]:remove() + end + celevator.get_meta(data.positions[1]):set_string("state","open") + if hwdoors_moving[hash].drivepos then celevator.get_meta(hwdoors_moving[hash].drivepos):set_string("doorstate","open") end + hwdoors_moving[hash] = nil + end + elseif data.direction == "close" then + local speed = 0.66 + if data.nudging then speed = 0.2 end + data.time = data.time+(speed*dtime) + local vel = math.sin(data.time) + for i=1,3,1 do + celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel*-speed)) + end + for i=4,6,1 do + celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel/2*-speed)) + end + if data.time >= math.pi then + for i=1,6,1 do + celevator.doors.erefs[hash][i]:set_pos(data.positions[i]) + end + celevator.drives.entity.entitiestonodes(celevator.doors.erefs[hash]) + if hwdoors_moving[hash].drivepos then celevator.get_meta(hwdoors_moving[hash].drivepos):set_string("doorstate","closed") end + hwdoors_moving[hash] = nil + end + end + else + if data.direction == "open" then + for i=1,6,1 do + if celevator.doors.erefs[hash] then + celevator.doors.erefs[hash][i]:remove() + end + end + celevator.get_meta(data.positions[1]):set_string("state","open") + if hwdoors_moving[hash].drivepos then celevator.get_meta(hwdoors_moving[hash].drivepos):set_string("doorstate","open") end + hwdoors_moving[hash] = nil + elseif data.direction == "close" then + for i=1,6,1 do + core.set_node(data.positions[i],data.nodes[i]) + end + celevator.get_meta(data.positions[1]):set_string("state","closed") + if hwdoors_moving[hash].drivepos then celevator.get_meta(hwdoors_moving[hash].drivepos):set_string("doorstate","closed") end + hwdoors_moving[hash] = nil + end + end +end + +function celevator.doors.twospeedmetal.caropen(pos) + celevator.doors.cardoor_step_enabled = true + local cardoors_moving = core.deserialize(celevator.storage:get_string("cardoors_moving")) or {} + local hash = core.hash_node_position(pos) + local cartimer = core.get_node_timer(pos) + cartimer:start(0.25) + if not cardoors_moving[hash] then + local fdir = core.fourdir_to_dir(celevator.get_node(pos).param2) + local otherpanel = vector.add(pos,vector.rotate_around_axis(fdir,vector.new(0,1,0),-math.pi/2)) + local positions = { + pos, + vector.add(pos,vector.new(0,1,0)), + vector.add(pos,vector.new(0,2,0)), + otherpanel, + vector.add(otherpanel,vector.new(0,1,0)), + vector.add(otherpanel,vector.new(0,2,0)), + } + local erefs = {} + for _,dpos in ipairs(positions) do + local objs = core.get_objects_inside_radius(dpos,0.5) + for _,obj in pairs(objs) do + if obj:get_luaentity() and obj:get_luaentity().name == "celevator:car_door" then + table.insert(erefs,obj) + end + end + end + cardoors_moving[hash] = { + direction = "open", + positions = positions, + time = 0, + opendir = vector.rotate_around_axis(fdir,vector.new(0,1,0),-math.pi/2), + doortype = "twospeedmetal", + } + core.sound_play("celevator_door_open",{ + pos = pos, + gain = 0.4, + max_hear_distance = 10 + },true) + celevator.doors.erefs[hash] = erefs + celevator.storage:set_string("cardoors_moving",core.serialize(cardoors_moving)) + local meta = celevator.get_meta(pos) + meta:set_string("doordata",core.serialize(cardoors_moving[hash])) + meta:set_string("doorstate","opening") + elseif cardoors_moving[hash].direction == "close" then + if cardoors_moving[hash].soundhandle then + core.sound_stop(cardoors_moving[hash].soundhandle) + end + core.sound_play("celevator_door_reverse",{ + pos = pos, + gain = 1, + max_hear_distance = 10 + },true) + core.sound_play("celevator_door_open",{ + pos = pos, + gain = 0.4, + start_time = math.max(0,2.75-cardoors_moving[hash].time), + max_hear_distance = 10 + },true) + cardoors_moving[hash].direction = "open" + cardoors_moving[hash].time = math.pi-cardoors_moving[hash].time + celevator.storage:set_string("cardoors_moving",core.serialize(cardoors_moving)) + end +end + +function celevator.doors.twospeedmetal.carclose(pos,nudge) + celevator.doors.cardoor_step_enabled = true + local cardoors_moving = core.deserialize(celevator.storage:get_string("cardoors_moving")) or {} + local hash = core.hash_node_position(pos) + if cardoors_moving[hash] then + return + end + local meta = celevator.get_meta(pos) + local state = meta:get_string("doorstate") + if state ~= "open" then return end + local data = core.deserialize(meta:get_string("doordata")) + if not data then return end + local dir = core.fourdir_to_dir(celevator.get_node(pos).param2) + data.direction = "close" + data.time = 0 + data.doortype = "twospeedmetal" + local erefs = celevator.doors.spawncardoors(pos,dir,"twospeedmetal") + local soffset = data.opendir + local foffset = vector.multiply(soffset,2) + for i=1,3,1 do + erefs[i]:set_pos(vector.add(erefs[i]:get_pos(),foffset)) + end + for i=4,6,1 do + erefs[i]:set_pos(vector.add(erefs[i]:get_pos(),soffset)) + end + celevator.doors.erefs[hash] = erefs + if nudge then + data.soundhandle = core.sound_play("celevator_nudge",{ + pos = pos, + gain = 0.75, + max_hear_distance = 10 + }) + else + data.soundhandle = core.sound_play("celevator_door_close",{ + pos = pos, + gain = 0.3, + max_hear_distance = 10 + }) + end + data.nudging = nudge + cardoors_moving[hash] = data + celevator.storage:set_string("cardoors_moving",core.serialize(cardoors_moving)) +end + +function celevator.doors.twospeedmetal.carstep(hash,data,dtime,cardoors_moving) + local present = celevator.doors.erefs[hash] + if present then + for i=1,6,1 do + if not (celevator.doors.erefs[hash][i] and celevator.doors.erefs[hash][i]:get_pos()) then + present = false + break + end + end + end + if present then + if data.direction == "open" then + data.time = data.time+dtime + local vel = math.sin(data.time) + for i=1,3,1 do + celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel)) + end + for i=4,6,1 do + celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel/2)) + end + if data.time >= math.pi then + for i=1,6,1 do + celevator.doors.erefs[hash][i]:remove() + end + celevator.get_meta(data.positions[1]):set_string("doorstate","open") + cardoors_moving[hash] = nil + end + elseif data.direction == "close" then + local speed = 0.66 + if data.nudging then speed = 0.2 end + data.time = data.time+(speed*dtime) + local vel = math.sin(data.time) + for i=1,3,1 do + celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel*-speed)) + end + for i=4,6,1 do + celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel/2*-speed)) + end + if data.time >= math.pi then + for _,ref in ipairs(celevator.doors.erefs[hash]) do + ref:remove() + end + local carmeta = celevator.get_meta(data.positions[1]) + carmeta:set_string("doorstate","closed") + cardoors_moving[hash] = nil + local cartimer = core.get_node_timer(data.positions[1]) + cartimer:stop() + local fdir = core.facedir_to_dir(core.get_node(data.positions[1]).param2) + celevator.doors.spawncardoors(data.positions[1],fdir,"twospeedmetal") + end + end + else + if data.direction == "open" then + for i=1,6,1 do + if celevator.doors.erefs[hash] and celevator.doors.erefs[hash][i] then + celevator.doors.erefs[hash][i]:remove() + end + end + celevator.get_meta(data.positions[1]):set_string("doorstate","open") + cardoors_moving[hash] = nil + elseif data.direction == "close" then + local fdir = core.fourdir_to_dir(celevator.get_node(data.positions[1]).param2) + celevator.doors.spawncardoors(data.positions[1],vector.rotate_around_axis(fdir,vector.new(0,1,0),math.pi),"twospeedmetal") + celevator.get_meta(data.positions[1]):set_string("doorstate","closed") + cardoors_moving[hash] = nil + end + end +end diff --git a/door_centerglass.lua b/door_centerglass.lua new file mode 100644 index 0000000..9684399 --- /dev/null +++ b/door_centerglass.lua @@ -0,0 +1,641 @@ +celevator.doors.centerglass = {} + +local S = core.get_translator("celevator") + +core.register_node("celevator:hwdoor_left_glass_bottom",{ + description = S("Glass Hoistway Door (left, 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_glass_topbottom.png^[transformFY", + "celevator_door_glass_topbottom.png^[transformFY", + }, + groups = { + not_in_creative_inventory = 1, + _celevator_hwdoor_root = 1, + oddly_breakable_by_hand = 2, + }, + drop = "celevator:hwdoor_centerglass", + paramtype = "light", + paramtype2 = "4dir", + drawtype = "nodebox", + use_texture_alpha = "clip", + 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 = core.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 = core.dir_to_yaw(core.fourdir_to_dir(node.param2)) + local xnames = { + [0] = "left", + [1] = "right", + } + 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_glass_%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 core.get_node(piecepos).name == piecename then core.remove_node(piecepos) end + end + end + end, + _celevator_doortype = "centerglass", +}) + +core.register_node("celevator:hwdoor_left_glass_middle",{ + description = S("Glass Hoistway Door (left, middle - you hacker you!)"), + tiles = { + "celevator_transparent.png", + "celevator_transparent.png", + "celevator_door_glass_edge.png", + "celevator_door_glass_edge.png", + "celevator_door_glass_middle.png", + "celevator_door_glass_middle.png", + }, + groups = { + not_in_creative_inventory = 1, + }, + drop = "", + paramtype = "light", + paramtype2 = "4dir", + drawtype = "nodebox", + use_texture_alpha = "clip", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.5,0.4,0.5,0.5,0.5}, + }, + }, + _celevator_doortype = "centerglass", +}) + +core.register_node("celevator:hwdoor_left_glass_top",{ + description = S("Glass Hoistway Door (left, 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_glass_topbottom.png", + "celevator_door_glass_topbottom.png", + }, + groups = { + not_in_creative_inventory = 1, + }, + drop = "", + paramtype = "light", + paramtype2 = "4dir", + drawtype = "nodebox", + use_texture_alpha = "clip", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.5,0.4,0.5,0.5,0.5}, + }, + }, + _celevator_doortype = "centerglass", +}) + +core.register_node("celevator:hwdoor_right_glass_bottom",{ + description = S("Glass Hoistway Door (right, 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_glass_topbottom.png^[transformFY", + "celevator_door_glass_topbottom.png^[transformFY", + }, + groups = { + not_in_creative_inventory = 1, + }, + drop = "", + paramtype = "light", + paramtype2 = "4dir", + drawtype = "nodebox", + use_texture_alpha = "clip", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.5,0.4,0.5,0.5,0.5}, + }, + }, + _celevator_doortype = "centerglass", +}) + +core.register_node("celevator:hwdoor_right_glass_middle",{ + description = S("Glass Hoistway Door (right, middle - you hacker you!)"), + tiles = { + "celevator_transparent.png", + "celevator_transparent.png", + "celevator_door_glass_edge.png", + "celevator_door_glass_edge.png", + "celevator_door_glass_middle.png", + "celevator_door_glass_middle.png", + }, + groups = { + not_in_creative_inventory = 1, + }, + drop = "", + paramtype = "light", + paramtype2 = "4dir", + drawtype = "nodebox", + use_texture_alpha = "clip", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.5,0.4,0.5,0.5,0.5}, + }, + }, + _celevator_doortype = "centerglass", +}) + +core.register_node("celevator:hwdoor_right_glass_top",{ + description = S("Glass Hoistway Door (right, 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_glass_topbottom.png", + "celevator_door_glass_topbottom.png", + }, + groups = { + not_in_creative_inventory = 1, + }, + drop = "", + paramtype = "light", + paramtype2 = "4dir", + drawtype = "nodebox", + use_texture_alpha = "clip", + node_box = { + type = "fixed", + fixed = { + {-0.5,-0.5,0.4,0.5,0.5,0.5}, + }, + }, + _celevator_doortype = "centerglass", +}) + +core.register_node("celevator:hwdoor_centerglass",{ + description = S("Center-Opening Glass Elevator Hoistway Door"), + paramtype2 = "4dir", + buildable_to = true, + inventory_image = "celevator_door_centerglass_inventory.png", + wield_image = "celevator_door_centerglass_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 + core.remove_node(pos) + return true + end + local name = player:get_player_name() + local newnode = core.get_node(pos) + local facedir = core.dir_to_yaw(core.fourdir_to_dir(newnode.param2)) + local xnames = { + [0] = "left", + [1] = "right", + } + local ynames = { + [0] = "bottom", + [1] = "middle", + [2] = "top", + } + for x=0,1,1 do + for y=0,2,1 do + 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 = core.get_node(placepos).name + if not (core.registered_nodes[replaces] and core.registered_nodes[replaces].buildable_to) then + local errormsg = S("Can't place door here - position @1m to the right and @2m up is blocked!",x,y) + core.chat_send_player(name,errormsg) + core.remove_node(pos) + return true + end + if core.is_protected(placepos,name) and not core.check_player_privs(name,{protection_bypass=true}) then + local errormsg = S("Can't place door here - position @1m to the right and @2m up is protected!",x,y) + core.chat_send_player(name,errormsg) + core.record_protection_violation(placepos,name) + core.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_glass_%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)) + core.set_node(placepos,{name=piecename,param2=newnode.param2}) + if y==0 then + celevator.doors.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 = core.registered_nodes[celevator.get_node(carpos).name] or {} + if carndef._root then + celevator.get_meta(carpos):set_string("doortype","centerglass") + celevator.doors.spawncardoors(carpos,core.fourdir_to_dir(newnode.param2),"centerglass",true) + end + end, +}) + +core.register_lbm({ + label = "Respawn hoistway door sills (center-opening glass)", + name = "celevator:spawn_sill_centerglass", + nodenames = { + "celevator:hwdoor_left_glass_bottom", + "celevator:hwdoor_right_glass_bottom", + }, + run_at_every_load = true, + action = celevator.doors.placesill, +}) + +celevator.doors.centerglass.spawncardoors = function(pos,dir,replace) + local refs = {} + for x=2,1,-1 do + for y=1,3,1 do + local yaw = core.dir_to_yaw(dir)+math.pi + local doorpos = vector.add(pos,vector.rotate_around_axis(vector.new(x-2,y-1,0),vector.new(0,1,0),yaw)) + local xnames = {"left","right"} + local ynames = {"bottom","middle","top"} + local nname = string.format("celevator:hwdoor_%s_glass_%s",xnames[x],ynames[y]) + if replace then + local oldrefs = core.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 = core.add_entity(doorpos,"celevator:car_door") + ref:set_yaw(yaw) + ref:set_properties({ + wield_item = nname, + }) + table.insert(refs,ref) + end + end + return refs +end + +function celevator.doors.centerglass.hwopen(pos,drivepos) + celevator.doors.hwdoor_step_enabled = true + local hwdoors_moving = core.deserialize(celevator.storage:get_string("hwdoors_moving")) or {} + local hash = core.hash_node_position(pos) + if not hwdoors_moving[hash] then + local param2 = celevator.get_node(pos).param2 + local fdir = core.fourdir_to_dir(param2) + local otherpanel = vector.add(pos,vector.rotate_around_axis(fdir,vector.new(0,1,0),-math.pi/2)) + local positions = { + pos, + vector.add(pos,vector.new(0,1,0)), + vector.add(pos,vector.new(0,2,0)), + otherpanel, + vector.add(otherpanel,vector.new(0,1,0)), + vector.add(otherpanel,vector.new(0,2,0)), + } + local oldnodes = {} + for i,position in ipairs(positions) do + oldnodes[i] = celevator.get_node(position) + end + local erefs = celevator.drives.entity.nodestoentities(positions,"celevator:hwdoor_moving") + hwdoors_moving[hash] = { + direction = "open", + positions = positions, + nodes = oldnodes, + time = 0, + opendir = vector.rotate_around_axis(fdir,vector.new(0,1,0),-math.pi/2), + drivepos = drivepos, + param2 = param2, + doortype = "centerglass", + } + celevator.doors.erefs[hash] = erefs + celevator.storage:set_string("hwdoors_moving",core.serialize(hwdoors_moving)) + core.set_node(pos,{name="celevator:hwdoor_placeholder",param2=param2}) + local pmeta = celevator.get_meta(pos) + pmeta:set_string("data",core.serialize(hwdoors_moving[hash])) + pmeta:set_string("state","opening") + pmeta:set_string("doortype","centerglass") + local carpos = vector.add(pos,fdir) + local carndef = core.registered_nodes[celevator.get_node(carpos).name] or {} + if carndef._root then + celevator.doors.caropen(carpos) + end + elseif hwdoors_moving[hash].direction == "close" then + hwdoors_moving[hash].direction = "open" + hwdoors_moving[hash].time = math.pi-hwdoors_moving[hash].time + celevator.storage:set_string("hwdoors_moving",core.serialize(hwdoors_moving)) + local fdir = core.fourdir_to_dir(hwdoors_moving[hash].param2) + local carpos = vector.add(pos,fdir) + local carndef = core.registered_nodes[celevator.get_node(carpos).name] or {} + if carndef._root then + celevator.doors.caropen(carpos) + end + core.set_node(pos,{name="celevator:hwdoor_placeholder",param2=hwdoors_moving[hash].param2}) + local pmeta = celevator.get_meta(pos) + pmeta:set_string("data",core.serialize(hwdoors_moving[hash])) + pmeta:set_string("state","opening") + pmeta:set_string("doortype","centerglass") + end +end + +function celevator.doors.centerglass.hwclose(pos,drivepos,nudge) + celevator.doors.hwdoor_step_enabled = true + local hwdoors_moving = core.deserialize(celevator.storage:get_string("hwdoors_moving")) or {} + local hash = core.hash_node_position(pos) + if hwdoors_moving[hash] then + return + end + local pmeta = celevator.get_meta(pos) + local state = pmeta:get_string("state") + if state ~= "open" then return end + local fdir = core.fourdir_to_dir(celevator.get_node(pos).param2) + local carpos = vector.add(pos,fdir) + local carndef = core.registered_nodes[celevator.get_node(carpos).name] or {} + if carndef._root then + celevator.doors.carclose(carpos,nudge) + end + local data = core.deserialize(pmeta:get_string("data")) + if not data then return end + for i=1,6,1 do + core.set_node(data.positions[i],data.nodes[i]) + end + data.direction = "close" + data.time = 0 + data.drivepos = drivepos + data.nudging = nudge + local erefs = celevator.drives.entity.nodestoentities(data.positions,"celevator:hwdoor_moving") + local roffset = vector.multiply(data.opendir,-1) + local loffset = data.opendir + for i=1,3,1 do + erefs[i]:set_pos(vector.add(erefs[i]:get_pos(),roffset)) + end + for i=4,6,1 do + erefs[i]:set_pos(vector.add(erefs[i]:get_pos(),loffset)) + end + celevator.doors.erefs[hash] = erefs + hwdoors_moving[hash] = data + celevator.storage:set_string("hwdoors_moving",core.serialize(hwdoors_moving)) +end + +function celevator.doors.centerglass.hwstep(hash,data,dtime,hwdoors_moving) + local present = celevator.doors.erefs[hash] + if present then + for i=1,6,1 do + if not celevator.doors.erefs[hash][i]:get_pos() then + present = false + break + end + end + end + if present then + if data.direction == "open" then + data.time = data.time+dtime + local vel = math.sin(data.time) + for i=1,3,1 do + celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel*-0.5)) + end + for i=4,6,1 do + celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel*0.5)) + end + if data.time >= math.pi then + for i=1,6,1 do + celevator.doors.erefs[hash][i]:remove() + end + celevator.get_meta(data.positions[1]):set_string("state","open") + if hwdoors_moving[hash].drivepos then celevator.get_meta(hwdoors_moving[hash].drivepos):set_string("doorstate","open") end + hwdoors_moving[hash] = nil + end + elseif data.direction == "close" then + local speed = 0.66 + if data.nudging then speed = 0.2 end + data.time = data.time+(speed*dtime) + local vel = math.sin(data.time) + for i=1,3,1 do + celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel/2*speed)) + end + for i=4,6,1 do + celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel/2*-speed)) + end + if data.time >= math.pi then + for i=1,6,1 do + celevator.doors.erefs[hash][i]:set_pos(data.positions[i]) + end + celevator.drives.entity.entitiestonodes(celevator.doors.erefs[hash]) + if hwdoors_moving[hash].drivepos then celevator.get_meta(hwdoors_moving[hash].drivepos):set_string("doorstate","closed") end + hwdoors_moving[hash] = nil + end + end + else + if data.direction == "open" then + for i=1,6,1 do + if celevator.doors.erefs[hash] then + celevator.doors.erefs[hash][i]:remove() + end + end + celevator.get_meta(data.positions[1]):set_string("state","open") + if hwdoors_moving[hash].drivepos then celevator.get_meta(hwdoors_moving[hash].drivepos):set_string("doorstate","open") end + hwdoors_moving[hash] = nil + elseif data.direction == "close" then + for i=1,6,1 do + core.set_node(data.positions[i],data.nodes[i]) + end + celevator.get_meta(data.positions[1]):set_string("state","closed") + if hwdoors_moving[hash].drivepos then celevator.get_meta(hwdoors_moving[hash].drivepos):set_string("doorstate","closed") end + hwdoors_moving[hash] = nil + end + end +end + +function celevator.doors.centerglass.caropen(pos) + celevator.doors.cardoor_step_enabled = true + local cardoors_moving = core.deserialize(celevator.storage:get_string("cardoors_moving")) or {} + local hash = core.hash_node_position(pos) + local cartimer = core.get_node_timer(pos) + cartimer:start(0.25) + if not cardoors_moving[hash] then + local fdir = core.fourdir_to_dir(celevator.get_node(pos).param2) + local otherpanel = vector.add(pos,vector.rotate_around_axis(fdir,vector.new(0,1,0),-math.pi/2)) + local positions = { + pos, + vector.add(pos,vector.new(0,1,0)), + vector.add(pos,vector.new(0,2,0)), + otherpanel, + vector.add(otherpanel,vector.new(0,1,0)), + vector.add(otherpanel,vector.new(0,2,0)), + } + local erefs = {} + for _,dpos in ipairs(positions) do + local objs = core.get_objects_inside_radius(dpos,0.5) + for _,obj in pairs(objs) do + if obj:get_luaentity() and obj:get_luaentity().name == "celevator:car_door" then + table.insert(erefs,obj) + end + end + end + cardoors_moving[hash] = { + direction = "open", + positions = positions, + time = 0, + opendir = vector.rotate_around_axis(fdir,vector.new(0,1,0),-math.pi/2), + doortype = "centerglass", + } + core.sound_play("celevator_door_open",{ + pos = pos, + gain = 0.4, + max_hear_distance = 10 + },true) + celevator.doors.erefs[hash] = erefs + celevator.storage:set_string("cardoors_moving",core.serialize(cardoors_moving)) + local meta = celevator.get_meta(pos) + meta:set_string("doordata",core.serialize(cardoors_moving[hash])) + meta:set_string("doorstate","opening") + elseif cardoors_moving[hash].direction == "close" then + if cardoors_moving[hash].soundhandle then + core.sound_stop(cardoors_moving[hash].soundhandle) + end + core.sound_play("celevator_door_reverse",{ + pos = pos, + gain = 1, + max_hear_distance = 10 + },true) + core.sound_play("celevator_door_open",{ + pos = pos, + gain = 0.4, + start_time = math.max(0,2.75-cardoors_moving[hash].time), + max_hear_distance = 10 + },true) + cardoors_moving[hash].direction = "open" + cardoors_moving[hash].time = math.pi-cardoors_moving[hash].time + celevator.storage:set_string("cardoors_moving",core.serialize(cardoors_moving)) + end +end + +function celevator.doors.centerglass.carclose(pos,nudge) + celevator.doors.cardoor_step_enabled = true + local cardoors_moving = core.deserialize(celevator.storage:get_string("cardoors_moving")) or {} + local hash = core.hash_node_position(pos) + if cardoors_moving[hash] then + return + end + local meta = celevator.get_meta(pos) + local state = meta:get_string("doorstate") + if state ~= "open" then return end + local data = core.deserialize(meta:get_string("doordata")) + if not data then return end + local dir = core.fourdir_to_dir(celevator.get_node(pos).param2) + data.direction = "close" + data.time = 0 + data.doortype = "centerglass" + local erefs = celevator.doors.spawncardoors(pos,dir,"centerglass") + local loffset = data.opendir + local roffset = vector.multiply(loffset,-1) + for i=1,3,1 do + erefs[i]:set_pos(vector.add(erefs[i]:get_pos(),roffset)) + end + for i=4,6,1 do + erefs[i]:set_pos(vector.add(erefs[i]:get_pos(),loffset)) + end + celevator.doors.erefs[hash] = erefs + if nudge then + data.soundhandle = core.sound_play("celevator_nudge",{ + pos = pos, + gain = 0.75, + max_hear_distance = 10 + }) + else + data.soundhandle = core.sound_play("celevator_door_close",{ + pos = pos, + gain = 0.3, + max_hear_distance = 10 + }) + end + data.nudging = nudge + cardoors_moving[hash] = data + celevator.storage:set_string("cardoors_moving",core.serialize(cardoors_moving)) +end + +function celevator.doors.centerglass.carstep(hash,data,dtime,cardoors_moving) + local present = celevator.doors.erefs[hash] + if present then + for i=1,6,1 do + if not (celevator.doors.erefs[hash][i] and celevator.doors.erefs[hash][i]:get_pos()) then + present = false + break + end + end + end + if present then + if data.direction == "open" then + data.time = data.time+dtime + local vel = math.sin(data.time) + for i=1,3,1 do + celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel*-0.5)) + end + for i=4,6,1 do + celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel*0.5)) + end + if data.time >= math.pi then + for i=1,6,1 do + celevator.doors.erefs[hash][i]:remove() + end + celevator.get_meta(data.positions[1]):set_string("doorstate","open") + cardoors_moving[hash] = nil + end + elseif data.direction == "close" then + local speed = 0.66 + if data.nudging then speed = 0.2 end + data.time = data.time+(speed*dtime) + local vel = math.sin(data.time) + for i=1,3,1 do + celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel/2*speed)) + end + for i=4,6,1 do + celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel/2*-speed)) + end + if data.time >= math.pi then + for _,ref in ipairs(celevator.doors.erefs[hash]) do + ref:remove() + end + local carmeta = celevator.get_meta(data.positions[1]) + carmeta:set_string("doorstate","closed") + cardoors_moving[hash] = nil + local cartimer = core.get_node_timer(data.positions[1]) + cartimer:stop() + local fdir = core.facedir_to_dir(core.get_node(data.positions[1]).param2) + celevator.doors.spawncardoors(data.positions[1],fdir,"centerglass") + end + end + else + if data.direction == "open" then + for i=1,6,1 do + if celevator.doors.erefs[hash] and celevator.doors.erefs[hash][i] then + celevator.doors.erefs[hash][i]:remove() + end + end + celevator.get_meta(data.positions[1]):set_string("doorstate","open") + cardoors_moving[hash] = nil + elseif data.direction == "close" then + local fdir = core.fourdir_to_dir(celevator.get_node(data.positions[1]).param2) + celevator.doors.spawncardoors(data.positions[1],vector.rotate_around_axis(fdir,vector.new(0,1,0),math.pi),"centerglass") + celevator.get_meta(data.positions[1]):set_string("doorstate","closed") + cardoors_moving[hash] = nil + end + end +end diff --git a/door_centermetal.lua b/door_centermetal.lua new file mode 100644 index 0000000..8857ed0 --- /dev/null +++ b/door_centermetal.lua @@ -0,0 +1,636 @@ +celevator.doors.centermetal = {} + +local S = core.get_translator("celevator") + +core.register_node("celevator:hwdoor_left_steel_bottom",{ + description = S("Steel Hoistway Door (left, 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_centersteel", + 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 = core.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 = core.dir_to_yaw(core.fourdir_to_dir(node.param2)) + local xnames = { + [0] = "left", + [1] = "right", + } + 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 core.get_node(piecepos).name == piecename then core.remove_node(piecepos) end + end + end + end, + _celevator_doortype = "centermetal", +}) + +core.register_node("celevator:hwdoor_left_steel_middle",{ + description = S("Steel Hoistway Door (left, 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}, + }, + }, + _celevator_doortype = "centermetal", +}) + +core.register_node("celevator:hwdoor_left_steel_top",{ + description = S("Steel Hoistway Door (left, 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}, + }, + }, + _celevator_doortype = "centermetal", +}) + +core.register_node("celevator:hwdoor_right_steel_bottom",{ + description = S("Steel Hoistway Door (right, 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.4,0.5,0.5,0.5}, + }, + }, + _celevator_doortype = "centermetal", +}) + +core.register_node("celevator:hwdoor_right_steel_middle",{ + description = S("Steel Hoistway Door (right, 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}, + }, + }, + _celevator_doortype = "centermetal", +}) + +core.register_node("celevator:hwdoor_right_steel_top",{ + description = S("Steel Hoistway Door (right, 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}, + }, + }, + _celevator_doortype = "centermetal", +}) + +core.register_node("celevator:hwdoor_centersteel",{ + description = S("Center-Opening Steel Elevator Hoistway Door"), + paramtype2 = "4dir", + buildable_to = true, + inventory_image = "celevator_door_centermetal_inventory.png", + wield_image = "celevator_door_centermetal_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 + core.remove_node(pos) + return true + end + local name = player:get_player_name() + local newnode = core.get_node(pos) + local facedir = core.dir_to_yaw(core.fourdir_to_dir(newnode.param2)) + local xnames = { + [0] = "left", + [1] = "right", + } + local ynames = { + [0] = "bottom", + [1] = "middle", + [2] = "top", + } + for x=0,1,1 do + for y=0,2,1 do + 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 = core.get_node(placepos).name + if not (core.registered_nodes[replaces] and core.registered_nodes[replaces].buildable_to) then + local errormsg = S("Can't place door here - position @1m to the right and @2m up is blocked!",x,y) + core.chat_send_player(name,errormsg) + core.remove_node(pos) + return true + end + if core.is_protected(placepos,name) and not core.check_player_privs(name,{protection_bypass=true}) then + local errormsg = S("Can't place door here - position @1m to the right and @2m up is protected!",x,y) + core.chat_send_player(name,errormsg) + core.record_protection_violation(placepos,name) + core.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)) + core.set_node(placepos,{name=piecename,param2=newnode.param2}) + if y==0 then + celevator.doors.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 = core.registered_nodes[celevator.get_node(carpos).name] or {} + if carndef._root then + celevator.get_meta(carpos):set_string("doortype","centermetal") + celevator.doors.spawncardoors(carpos,core.fourdir_to_dir(newnode.param2),"centermetal",true) + end + end, +}) + +core.register_lbm({ + label = "Respawn hoistway door sills (center-opening steel)", + name = "celevator:spawn_sill_centermetal", + nodenames = { + "celevator:hwdoor_left_steel_bottom", + "celevator:hwdoor_right_steel_bottom", + }, + run_at_every_load = true, + action = celevator.doors.placesill, +}) + +celevator.doors.centermetal.spawncardoors = function(pos,dir,replace) + local refs = {} + for x=2,1,-1 do + for y=1,3,1 do + local yaw = core.dir_to_yaw(dir)+math.pi + local doorpos = vector.add(pos,vector.rotate_around_axis(vector.new(x-2,y-1,0),vector.new(0,1,0),yaw)) + local xnames = {"left","right"} + local ynames = {"bottom","middle","top"} + local nname = string.format("celevator:hwdoor_%s_steel_%s",xnames[x],ynames[y]) + if replace then + local oldrefs = core.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 = core.add_entity(doorpos,"celevator:car_door") + ref:set_yaw(yaw) + ref:set_properties({ + wield_item = nname, + }) + table.insert(refs,ref) + end + end + return refs +end + +function celevator.doors.centermetal.hwopen(pos,drivepos) + celevator.doors.hwdoor_step_enabled = true + local hwdoors_moving = core.deserialize(celevator.storage:get_string("hwdoors_moving")) or {} + local hash = core.hash_node_position(pos) + if not hwdoors_moving[hash] then + local param2 = celevator.get_node(pos).param2 + local fdir = core.fourdir_to_dir(param2) + local otherpanel = vector.add(pos,vector.rotate_around_axis(fdir,vector.new(0,1,0),-math.pi/2)) + local positions = { + pos, + vector.add(pos,vector.new(0,1,0)), + vector.add(pos,vector.new(0,2,0)), + otherpanel, + vector.add(otherpanel,vector.new(0,1,0)), + vector.add(otherpanel,vector.new(0,2,0)), + } + local oldnodes = {} + for i,position in ipairs(positions) do + oldnodes[i] = celevator.get_node(position) + end + local erefs = celevator.drives.entity.nodestoentities(positions,"celevator:hwdoor_moving") + hwdoors_moving[hash] = { + direction = "open", + positions = positions, + nodes = oldnodes, + time = 0, + opendir = vector.rotate_around_axis(fdir,vector.new(0,1,0),-math.pi/2), + drivepos = drivepos, + param2 = param2, + doortype = "centermetal", + } + celevator.doors.erefs[hash] = erefs + celevator.storage:set_string("hwdoors_moving",core.serialize(hwdoors_moving)) + core.set_node(pos,{name="celevator:hwdoor_placeholder",param2=param2}) + local pmeta = celevator.get_meta(pos) + pmeta:set_string("data",core.serialize(hwdoors_moving[hash])) + pmeta:set_string("state","opening") + pmeta:set_string("doortype","centermetal") + local carpos = vector.add(pos,fdir) + local carndef = core.registered_nodes[celevator.get_node(carpos).name] or {} + if carndef._root then + celevator.doors.caropen(carpos) + end + elseif hwdoors_moving[hash].direction == "close" then + hwdoors_moving[hash].direction = "open" + hwdoors_moving[hash].time = math.pi-hwdoors_moving[hash].time + celevator.storage:set_string("hwdoors_moving",core.serialize(hwdoors_moving)) + local fdir = core.fourdir_to_dir(hwdoors_moving[hash].param2) + local carpos = vector.add(pos,fdir) + local carndef = core.registered_nodes[celevator.get_node(carpos).name] or {} + if carndef._root then + celevator.doors.caropen(carpos) + end + core.set_node(pos,{name="celevator:hwdoor_placeholder",param2=hwdoors_moving[hash].param2}) + local pmeta = celevator.get_meta(pos) + pmeta:set_string("data",core.serialize(hwdoors_moving[hash])) + pmeta:set_string("state","opening") + pmeta:set_string("doortype","centermetal") + end +end + +function celevator.doors.centermetal.hwclose(pos,drivepos,nudge) + celevator.doors.hwdoor_step_enabled = true + local hwdoors_moving = core.deserialize(celevator.storage:get_string("hwdoors_moving")) or {} + local hash = core.hash_node_position(pos) + if hwdoors_moving[hash] then + return + end + local pmeta = celevator.get_meta(pos) + local state = pmeta:get_string("state") + if state ~= "open" then return end + local fdir = core.fourdir_to_dir(celevator.get_node(pos).param2) + local carpos = vector.add(pos,fdir) + local carndef = core.registered_nodes[celevator.get_node(carpos).name] or {} + if carndef._root then + celevator.doors.carclose(carpos,nudge) + end + local data = core.deserialize(pmeta:get_string("data")) + if not data then return end + for i=1,6,1 do + core.set_node(data.positions[i],data.nodes[i]) + end + data.direction = "close" + data.time = 0 + data.drivepos = drivepos + data.nudging = nudge + data.doortype = "centermetal" + local erefs = celevator.drives.entity.nodestoentities(data.positions,"celevator:hwdoor_moving") + local roffset = vector.multiply(data.opendir,-1) + local loffset = data.opendir + for i=1,3,1 do + erefs[i]:set_pos(vector.add(erefs[i]:get_pos(),roffset)) + end + for i=4,6,1 do + erefs[i]:set_pos(vector.add(erefs[i]:get_pos(),loffset)) + end + celevator.doors.erefs[hash] = erefs + hwdoors_moving[hash] = data + celevator.storage:set_string("hwdoors_moving",core.serialize(hwdoors_moving)) +end + +function celevator.doors.centermetal.hwstep(hash,data,dtime,hwdoors_moving) + local present = celevator.doors.erefs[hash] + if present then + for i=1,6,1 do + if not celevator.doors.erefs[hash][i]:get_pos() then + present = false + break + end + end + end + if present then + if data.direction == "open" then + data.time = data.time+dtime + local vel = math.sin(data.time) + for i=1,3,1 do + celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel*-0.5)) + end + for i=4,6,1 do + celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel*0.5)) + end + if data.time >= math.pi then + for i=1,6,1 do + celevator.doors.erefs[hash][i]:remove() + end + celevator.get_meta(data.positions[1]):set_string("state","open") + if hwdoors_moving[hash].drivepos then celevator.get_meta(hwdoors_moving[hash].drivepos):set_string("doorstate","open") end + hwdoors_moving[hash] = nil + end + elseif data.direction == "close" then + local speed = 0.66 + if data.nudging then speed = 0.2 end + data.time = data.time+(speed*dtime) + local vel = math.sin(data.time) + for i=1,3,1 do + celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel/2*speed)) + end + for i=4,6,1 do + celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel/2*-speed)) + end + if data.time >= math.pi then + for i=1,6,1 do + celevator.doors.erefs[hash][i]:set_pos(data.positions[i]) + end + celevator.drives.entity.entitiestonodes(celevator.doors.erefs[hash]) + if hwdoors_moving[hash].drivepos then celevator.get_meta(hwdoors_moving[hash].drivepos):set_string("doorstate","closed") end + hwdoors_moving[hash] = nil + end + end + else + if data.direction == "open" then + for i=1,6,1 do + if celevator.doors.erefs[hash] then + celevator.doors.erefs[hash][i]:remove() + end + end + celevator.get_meta(data.positions[1]):set_string("state","open") + if hwdoors_moving[hash].drivepos then celevator.get_meta(hwdoors_moving[hash].drivepos):set_string("doorstate","open") end + hwdoors_moving[hash] = nil + elseif data.direction == "close" then + for i=1,6,1 do + core.set_node(data.positions[i],data.nodes[i]) + end + celevator.get_meta(data.positions[1]):set_string("state","closed") + if hwdoors_moving[hash].drivepos then celevator.get_meta(hwdoors_moving[hash].drivepos):set_string("doorstate","closed") end + hwdoors_moving[hash] = nil + end + end +end + +function celevator.doors.centermetal.caropen(pos) + celevator.doors.cardoor_step_enabled = true + local cardoors_moving = core.deserialize(celevator.storage:get_string("cardoors_moving")) or {} + local hash = core.hash_node_position(pos) + local cartimer = core.get_node_timer(pos) + cartimer:start(0.25) + if not cardoors_moving[hash] then + local fdir = core.fourdir_to_dir(celevator.get_node(pos).param2) + local otherpanel = vector.add(pos,vector.rotate_around_axis(fdir,vector.new(0,1,0),-math.pi/2)) + local positions = { + pos, + vector.add(pos,vector.new(0,1,0)), + vector.add(pos,vector.new(0,2,0)), + otherpanel, + vector.add(otherpanel,vector.new(0,1,0)), + vector.add(otherpanel,vector.new(0,2,0)), + } + local erefs = {} + for _,dpos in ipairs(positions) do + local objs = core.get_objects_inside_radius(dpos,0.5) + for _,obj in pairs(objs) do + if obj:get_luaentity() and obj:get_luaentity().name == "celevator:car_door" then + table.insert(erefs,obj) + end + end + end + cardoors_moving[hash] = { + direction = "open", + positions = positions, + time = 0, + opendir = vector.rotate_around_axis(fdir,vector.new(0,1,0),-math.pi/2), + doortype = "centermetal", + } + core.sound_play("celevator_door_open",{ + pos = pos, + gain = 0.4, + max_hear_distance = 10 + },true) + celevator.doors.erefs[hash] = erefs + celevator.storage:set_string("cardoors_moving",core.serialize(cardoors_moving)) + local meta = celevator.get_meta(pos) + meta:set_string("doordata",core.serialize(cardoors_moving[hash])) + meta:set_string("doorstate","opening") + elseif cardoors_moving[hash].direction == "close" then + if cardoors_moving[hash].soundhandle then + core.sound_stop(cardoors_moving[hash].soundhandle) + end + core.sound_play("celevator_door_reverse",{ + pos = pos, + gain = 1, + max_hear_distance = 10 + },true) + core.sound_play("celevator_door_open",{ + pos = pos, + gain = 0.4, + start_time = math.max(0,2.75-cardoors_moving[hash].time), + max_hear_distance = 10 + },true) + cardoors_moving[hash].direction = "open" + cardoors_moving[hash].time = math.pi-cardoors_moving[hash].time + celevator.storage:set_string("cardoors_moving",core.serialize(cardoors_moving)) + end +end + +function celevator.doors.centermetal.carclose(pos,nudge) + celevator.doors.cardoor_step_enabled = true + local cardoors_moving = core.deserialize(celevator.storage:get_string("cardoors_moving")) or {} + local hash = core.hash_node_position(pos) + if cardoors_moving[hash] then + return + end + local meta = celevator.get_meta(pos) + local state = meta:get_string("doorstate") + if state ~= "open" then return end + local data = core.deserialize(meta:get_string("doordata")) + if not data then return end + local dir = core.fourdir_to_dir(celevator.get_node(pos).param2) + data.direction = "close" + data.time = 0 + data.doortype = "centermetal" + local erefs = celevator.doors.spawncardoors(pos,dir,"centermetal") + local loffset = data.opendir + local roffset = vector.multiply(loffset,-1) + for i=1,3,1 do + erefs[i]:set_pos(vector.add(erefs[i]:get_pos(),roffset)) + end + for i=4,6,1 do + erefs[i]:set_pos(vector.add(erefs[i]:get_pos(),loffset)) + end + celevator.doors.erefs[hash] = erefs + if nudge then + data.soundhandle = core.sound_play("celevator_nudge",{ + pos = pos, + gain = 0.75, + max_hear_distance = 10 + }) + else + data.soundhandle = core.sound_play("celevator_door_close",{ + pos = pos, + gain = 0.3, + max_hear_distance = 10 + }) + end + data.nudging = nudge + cardoors_moving[hash] = data + celevator.storage:set_string("cardoors_moving",core.serialize(cardoors_moving)) +end + +function celevator.doors.centermetal.carstep(hash,data,dtime,cardoors_moving) + local present = celevator.doors.erefs[hash] + if present then + for i=1,6,1 do + if not (celevator.doors.erefs[hash][i] and celevator.doors.erefs[hash][i]:get_pos()) then + present = false + break + end + end + end + if present then + if data.direction == "open" then + data.time = data.time+dtime + local vel = math.sin(data.time) + for i=1,3,1 do + celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel*-0.5)) + end + for i=4,6,1 do + celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel*0.5)) + end + if data.time >= math.pi then + for i=1,6,1 do + celevator.doors.erefs[hash][i]:remove() + end + celevator.get_meta(data.positions[1]):set_string("doorstate","open") + cardoors_moving[hash] = nil + end + elseif data.direction == "close" then + local speed = 0.66 + if data.nudging then speed = 0.2 end + data.time = data.time+(speed*dtime) + local vel = math.sin(data.time) + for i=1,3,1 do + celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel/2*speed)) + end + for i=4,6,1 do + celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel/2*-speed)) + end + if data.time >= math.pi then + for _,ref in ipairs(celevator.doors.erefs[hash]) do + ref:remove() + end + local carmeta = celevator.get_meta(data.positions[1]) + carmeta:set_string("doorstate","closed") + cardoors_moving[hash] = nil + local cartimer = core.get_node_timer(data.positions[1]) + cartimer:stop() + local fdir = core.facedir_to_dir(core.get_node(data.positions[1]).param2) + celevator.doors.spawncardoors(data.positions[1],fdir,"centermetal") + end + end + else + if data.direction == "open" then + for i=1,6,1 do + if celevator.doors.erefs[hash] and celevator.doors.erefs[hash][i] then + celevator.doors.erefs[hash][i]:remove() + end + end + celevator.get_meta(data.positions[1]):set_string("doorstate","open") + cardoors_moving[hash] = nil + elseif data.direction == "close" then + local fdir = core.fourdir_to_dir(celevator.get_node(data.positions[1]).param2) + celevator.doors.spawncardoors(data.positions[1],vector.rotate_around_axis(fdir,vector.new(0,1,0),math.pi),"centermetal") + celevator.get_meta(data.positions[1]):set_string("doorstate","closed") + cardoors_moving[hash] = nil + end + end +end @@ -1,206 +1,37 @@ celevator.doors = {} +local S = core.get_translator("celevator") + celevator.doors.erefs = {} -local function placesill(pos,node) - local erefs = minetest.get_objects_inside_radius(pos,0.5) +local typealiases = { + glass = "twospeedglass", + steel = "twospeedmetal", +} + +local function typelookup(doortype) + if (not doortype) or doortype == "" then return "twospeedglass" end + return typealiases[doortype] or doortype +end + +--These get overwritten on globalstep and aren't settings. +--They're just set to true here so the globalstep functions run at least once, +--in case a door was moving when the server last shut down. +celevator.doors.hwdoor_step_enabled = true +celevator.doors.cardoor_step_enabled = true + +function celevator.doors.placesill(pos,node) + local erefs = core.get_objects_inside_radius(pos,0.5) for _,ref in pairs(erefs) do if ref:get_luaentity() and ref:get_luaentity().name == "celevator:door_sill" then return end 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 - entity:set_properties({ - wield_item = "celevator:door_sill_double", - }) - end + local yaw = core.dir_to_yaw(core.fourdir_to_dir(node.param2)) + local entity = core.add_entity(pos,"celevator:door_sill") entity:set_yaw(yaw) end -minetest.register_node("celevator:hwdoor_fast_glass_bottom",{ - description = "Glass 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_glass_topbottom.png^[transformFY", - "celevator_door_glass_topbottom.png^[transformFY", - }, - groups = { - not_in_creative_inventory = 1, - _celevator_hwdoor_root = 1, - oddly_breakable_by_hand = 2, - }, - drop = "celevator:hwdoor_glass", - paramtype = "light", - paramtype2 = "4dir", - drawtype = "nodebox", - use_texture_alpha = "clip", - 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_glass_%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_glass_middle",{ - description = "Glass 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_glass_middle.png", - "celevator_door_glass_middle.png", - }, - groups = { - not_in_creative_inventory = 1, - }, - drop = "", - paramtype = "light", - paramtype2 = "4dir", - drawtype = "nodebox", - use_texture_alpha = "clip", - node_box = { - type = "fixed", - fixed = { - {-0.5,-0.5,0.4,0.5,0.5,0.5}, - }, - }, -}) - -minetest.register_node("celevator:hwdoor_fast_glass_top",{ - description = "Glass 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_glass_topbottom.png", - "celevator_door_glass_topbottom.png", - }, - groups = { - not_in_creative_inventory = 1, - }, - drop = "", - paramtype = "light", - paramtype2 = "4dir", - drawtype = "nodebox", - use_texture_alpha = "clip", - node_box = { - type = "fixed", - fixed = { - {-0.5,-0.5,0.4,0.5,0.5,0.5}, - }, - }, -}) - -minetest.register_node("celevator:hwdoor_slow_glass_bottom",{ - description = "Glass 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_glass_topbottom.png^[transformFY", - "celevator_door_glass_topbottom.png^[transformFY", - }, - groups = { - not_in_creative_inventory = 1, - }, - drop = "", - paramtype = "light", - paramtype2 = "4dir", - drawtype = "nodebox", - use_texture_alpha = "clip", - node_box = { - type = "fixed", - fixed = { - {-0.5,-0.5,0.3,0.5,0.5,0.4}, - }, - }, -}) - -minetest.register_node("celevator:hwdoor_slow_glass_middle",{ - description = "Glass 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_glass_middle.png", - "celevator_door_glass_middle.png", - }, - groups = { - not_in_creative_inventory = 1, - }, - drop = "", - paramtype = "light", - paramtype2 = "4dir", - drawtype = "nodebox", - use_texture_alpha = "clip", - node_box = { - type = "fixed", - fixed = { - {-0.5,-0.5,0.3,0.5,0.5,0.4}, - }, - }, -}) - -minetest.register_node("celevator:hwdoor_slow_glass_top",{ - description = "Glass 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_glass_topbottom.png", - "celevator_door_glass_topbottom.png", - }, - groups = { - not_in_creative_inventory = 1, - }, - drop = "", - paramtype = "light", - paramtype2 = "4dir", - drawtype = "nodebox", - use_texture_alpha = "clip", - 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!)", +core.register_node("celevator:hwdoor_placeholder",{ + description = S("Hoistway Door Open-State Placeholder (you hacker you!)"), groups = { not_in_creative_inventory = 1, }, @@ -225,496 +56,122 @@ minetest.register_node("celevator:hwdoor_placeholder",{ }, }) -minetest.register_entity("celevator:hwdoor_moving",{ +core.register_entity("celevator:hwdoor_moving",{ initial_properties = { - visual = "wielditem", - visual_size = vector.new(0.667,0.667,0.667), - wield_item = "default:dirt", + visual = "node", + node = {name="air"}, static_save = false, pointable = false, }, }) -function celevator.doors.hwopen(pos,drivepos) - local hwdoors_moving = minetest.deserialize(celevator.storage:get_string("hwdoors_moving")) or {} - local hash = minetest.hash_node_position(pos) - if not hwdoors_moving[hash] then - local param2 = celevator.get_node(pos).param2 - local fdir = minetest.fourdir_to_dir(param2) - local otherpanel = vector.add(pos,vector.rotate_around_axis(fdir,vector.new(0,1,0),-math.pi/2)) - local positions = { - pos, - vector.add(pos,vector.new(0,1,0)), - vector.add(pos,vector.new(0,2,0)), - otherpanel, - vector.add(otherpanel,vector.new(0,1,0)), - vector.add(otherpanel,vector.new(0,2,0)), - } - local oldnodes = {} - for i,position in ipairs(positions) do - oldnodes[i] = celevator.get_node(position) - end - local erefs = celevator.drives.entity.nodestoentities(positions,"celevator:hwdoor_moving") - hwdoors_moving[hash] = { - direction = "open", - positions = positions, - nodes = oldnodes, - time = 0, - opendir = vector.rotate_around_axis(fdir,vector.new(0,1,0),-math.pi/2), - drivepos = drivepos, - param2 = param2, - } - celevator.doors.erefs[hash] = erefs - celevator.storage:set_string("hwdoors_moving",minetest.serialize(hwdoors_moving)) - minetest.set_node(pos,{name="celevator:hwdoor_placeholder",param2=param2}) - local pmeta = celevator.get_meta(pos) - pmeta:set_string("data",minetest.serialize(hwdoors_moving[hash])) - pmeta:set_string("state","opening") - local carpos = vector.add(pos,fdir) - if celevator.get_node(carpos).name == "celevator:car_000" then - celevator.doors.caropen(carpos) - end - elseif hwdoors_moving[hash].direction == "close" then - hwdoors_moving[hash].direction = "open" - hwdoors_moving[hash].time = math.pi-hwdoors_moving[hash].time - 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 - celevator.doors.caropen(carpos) - end - minetest.set_node(pos,{name="celevator:hwdoor_placeholder",param2=hwdoors_moving[hash].param2}) - local pmeta = celevator.get_meta(pos) - pmeta:set_string("data",minetest.serialize(hwdoors_moving[hash])) - pmeta:set_string("state","opening") +function celevator.doors.hwopen(pos,...) + local nname = celevator.get_node(pos).name + local doortype + if nname == "celevator:hwdoor_placeholder" then + doortype = celevator.get_meta(pos):get_string("doortype") + else + local ndef = core.registered_nodes[nname] + if not ndef then return end + doortype = ndef._celevator_doortype end + if not doortype then + local hwdoors_moving = core.deserialize(celevator.storage:get_string("hwdoors_moving")) or {} + doortype = hwdoors_moving[core.hash_node_position(pos)].doortype + end + celevator.doors[typelookup(doortype)].hwopen(pos,...) end -function celevator.doors.hwclose(pos,drivepos,nudge) - local hwdoors_moving = minetest.deserialize(celevator.storage:get_string("hwdoors_moving")) or {} - local hash = minetest.hash_node_position(pos) - if hwdoors_moving[hash] then - return - end +function celevator.doors.hwclose(pos,...) local pmeta = celevator.get_meta(pos) - local state = pmeta:get_string("state") - 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 - celevator.doors.carclose(carpos,nudge) - end - local data = minetest.deserialize(pmeta:get_string("data")) - if not data then return end - for i=1,6,1 do - minetest.set_node(data.positions[i],data.nodes[i]) - end - data.direction = "close" - data.time = 0 - data.drivepos = drivepos - data.nudging = nudge - local erefs = celevator.drives.entity.nodestoentities(data.positions,"celevator:hwdoor_moving") - local foffset = vector.multiply(data.opendir,2) - local soffset = data.opendir - for i=1,3,1 do - erefs[i]:set_pos(vector.add(erefs[i]:get_pos(),foffset)) - end - for i=4,6,1 do - erefs[i]:set_pos(vector.add(erefs[i]:get_pos(),soffset)) - end - celevator.doors.erefs[hash] = erefs - hwdoors_moving[hash] = data - celevator.storage:set_string("hwdoors_moving",minetest.serialize(hwdoors_moving)) + local doortype = typelookup(pmeta:get_string("doortype")) + celevator.doors[doortype].hwclose(pos,...) end function celevator.doors.hwstep(dtime) - local hwdoors_moving = minetest.deserialize(celevator.storage:get_string("hwdoors_moving")) or {} + if not celevator.doors.hwdoor_step_enabled then return end + local hwdoors_moving = core.deserialize(celevator.storage:get_string("hwdoors_moving")) or {} local save = false for hash,data in pairs(hwdoors_moving) do save = true - local present = celevator.doors.erefs[hash] - if present then - for i=1,6,1 do - if not celevator.doors.erefs[hash][i]:get_pos() then - present = false - break - end - end - end - if present then - if data.direction == "open" then - data.time = data.time+dtime - local vel = math.sin(data.time) - for i=1,3,1 do - celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel)) - end - for i=4,6,1 do - celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel/2)) - end - if data.time >= math.pi then - for i=1,6,1 do - celevator.doors.erefs[hash][i]:remove() - end - celevator.get_meta(data.positions[1]):set_string("state","open") - if hwdoors_moving[hash].drivepos then celevator.get_meta(hwdoors_moving[hash].drivepos):set_string("doorstate","open") end - hwdoors_moving[hash] = nil - end - elseif data.direction == "close" then - local speed = 0.66 - if data.nudging then speed = 0.2 end - data.time = data.time+(speed*dtime) - local vel = math.sin(data.time) - for i=1,3,1 do - celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel*-speed)) - end - for i=4,6,1 do - celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel/2*-speed)) - end - if data.time >= math.pi then - for i=1,6,1 do - celevator.doors.erefs[hash][i]:set_pos(data.positions[i]) - end - celevator.drives.entity.entitiestonodes(celevator.doors.erefs[hash]) - if hwdoors_moving[hash].drivepos then celevator.get_meta(hwdoors_moving[hash].drivepos):set_string("doorstate","closed") end - hwdoors_moving[hash] = nil - end - end - else - if data.direction == "open" then - for i=1,6,1 do - if celevator.doors.erefs[hash] then - celevator.doors.erefs[hash][i]:remove() - end - end - celevator.get_meta(data.positions[1]):set_string("state","open") - if hwdoors_moving[hash].drivepos then celevator.get_meta(hwdoors_moving[hash].drivepos):set_string("doorstate","open") end - hwdoors_moving[hash] = nil - elseif data.direction == "close" then - for i=1,6,1 do - minetest.set_node(data.positions[i],data.nodes[i]) - end - celevator.get_meta(data.positions[1]):set_string("state","closed") - if hwdoors_moving[hash].drivepos then celevator.get_meta(hwdoors_moving[hash].drivepos):set_string("doorstate","closed") end - hwdoors_moving[hash] = nil - end - end + local doortype = typelookup(data.doortype) + celevator.doors[doortype].hwstep(hash,data,dtime,hwdoors_moving) end if save then - celevator.storage:set_string("hwdoors_moving",minetest.serialize(hwdoors_moving)) + celevator.storage:set_string("hwdoors_moving",core.serialize(hwdoors_moving)) end + celevator.doors.hwdoor_step_enabled = save end -minetest.register_globalstep(celevator.doors.hwstep) +core.register_globalstep(celevator.doors.hwstep) function celevator.doors.carstep(dtime) - local cardoors_moving = minetest.deserialize(celevator.storage:get_string("cardoors_moving")) or {} + if not celevator.doors.cardoor_step_enabled then return end + local cardoors_moving = core.deserialize(celevator.storage:get_string("cardoors_moving")) or {} local save = false for hash,data in pairs(cardoors_moving) do save = true - local present = celevator.doors.erefs[hash] - if present then - for i=1,6,1 do - if not (celevator.doors.erefs[hash][i] and celevator.doors.erefs[hash][i]:get_pos()) then - present = false - break - end - end - end - if present then - if data.direction == "open" then - data.time = data.time+dtime - local vel = math.sin(data.time) - for i=1,3,1 do - celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel)) - end - for i=4,6,1 do - celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel/2)) - end - if data.time >= math.pi then - for i=1,6,1 do - celevator.doors.erefs[hash][i]:remove() - end - celevator.get_meta(data.positions[1]):set_string("doorstate","open") - cardoors_moving[hash] = nil - end - elseif data.direction == "close" then - local speed = 0.66 - if data.nudging then speed = 0.2 end - data.time = data.time+(speed*dtime) - local vel = math.sin(data.time) - for i=1,3,1 do - celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel*-speed)) - end - for i=4,6,1 do - celevator.doors.erefs[hash][i]:set_velocity(vector.multiply(data.opendir,vel/2*-speed)) - end - if data.time >= math.pi then - for _,ref in ipairs(celevator.doors.erefs[hash]) do - ref:set_velocity(vector.new(0,0,0)) - end - celevator.get_meta(data.positions[1]):set_string("doorstate","closed") - cardoors_moving[hash] = nil - local cartimer = minetest.get_node_timer(data.positions[1]) - cartimer:stop() - end - end - else - if data.direction == "open" then - for i=1,6,1 do - if celevator.doors.erefs[hash] and celevator.doors.erefs[hash][i] then - celevator.doors.erefs[hash][i]:remove() - end - end - celevator.get_meta(data.positions[1]):set_string("doorstate","open") - cardoors_moving[hash] = nil - elseif data.direction == "close" then - local fdir = minetest.fourdir_to_dir(celevator.get_node(data.positions[1]).param2) - celevator.doors.spawncardoors(data.positions[1],vector.rotate_around_axis(fdir,vector.new(0,1,0),math.pi)) - celevator.get_meta(data.positions[1]):set_string("doorstate","closed") - cardoors_moving[hash] = nil - end - end + local doortype = typelookup(data.doortype) + celevator.doors[doortype].carstep(hash,data,dtime,cardoors_moving) end if save then - celevator.storage:set_string("cardoors_moving",minetest.serialize(cardoors_moving)) + celevator.storage:set_string("cardoors_moving",core.serialize(cardoors_moving)) end + celevator.doors.cardoor_step_enabled = save end -minetest.register_globalstep(celevator.doors.carstep) +core.register_globalstep(celevator.doors.carstep) -minetest.register_entity("celevator:car_door",{ +core.register_entity("celevator:car_door",{ initial_properties = { visual = "wielditem", visual_size = vector.new(0.667,0.667,0.667), wield_item = "default:dirt", static_save = false, pointable = false, - glow = minetest.LIGHT_MAX, + glow = core.LIGHT_MAX, }, }) -function celevator.doors.spawncardoors(pos,dir) - local refs = {} - for x=2,1,-1 do - for y=1,3,1 do - local yaw = minetest.dir_to_yaw(dir)+math.pi - 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 ref = minetest.add_entity(doorpos,"celevator:car_door") - ref:set_yaw(yaw) - ref:set_properties({ - wield_item = nname, - }) - table.insert(refs,ref) - end - end - return refs +function celevator.doors.spawncardoors(pos,dir,doortype,replace) + doortype = typelookup(doortype) + return celevator.doors[doortype].spawncardoors(pos,dir,replace) end function celevator.doors.caropen(pos) - local cardoors_moving = minetest.deserialize(celevator.storage:get_string("cardoors_moving")) or {} - local hash = minetest.hash_node_position(pos) - local cartimer = minetest.get_node_timer(pos) - cartimer:start(0.25) - if not cardoors_moving[hash] then - local fdir = minetest.fourdir_to_dir(celevator.get_node(pos).param2) - local otherpanel = vector.add(pos,vector.rotate_around_axis(fdir,vector.new(0,1,0),-math.pi/2)) - local positions = { - pos, - vector.add(pos,vector.new(0,1,0)), - vector.add(pos,vector.new(0,2,0)), - otherpanel, - vector.add(otherpanel,vector.new(0,1,0)), - vector.add(otherpanel,vector.new(0,2,0)), - } - local erefs = {} - for _,dpos in ipairs(positions) do - local objs = minetest.get_objects_inside_radius(dpos,0.1) - for _,obj in pairs(objs) do - if obj:get_luaentity() and obj:get_luaentity().name == "celevator:car_door" then - table.insert(erefs,obj) - end - end - end - cardoors_moving[hash] = { - direction = "open", - positions = positions, - time = 0, - opendir = vector.rotate_around_axis(fdir,vector.new(0,1,0),-math.pi/2), - } - minetest.sound_play("celevator_door_open",{ - pos = pos, - gain = 0.4, - max_hear_distance = 10 - },true) - celevator.doors.erefs[hash] = erefs - celevator.storage:set_string("cardoors_moving",minetest.serialize(cardoors_moving)) - local meta = celevator.get_meta(pos) - meta:set_string("doordata",minetest.serialize(cardoors_moving[hash])) - meta:set_string("doorstate","opening") - elseif cardoors_moving[hash].direction == "close" then - if cardoors_moving[hash].soundhandle then - minetest.sound_stop(cardoors_moving[hash].soundhandle) - end - minetest.sound_play("celevator_door_reverse",{ - pos = pos, - gain = 1, - max_hear_distance = 10 - },true) - minetest.sound_play("celevator_door_open",{ - pos = pos, - gain = 0.4, - start_time = math.max(0,2.75-cardoors_moving[hash].time), - max_hear_distance = 10 - },true) - cardoors_moving[hash].direction = "open" - cardoors_moving[hash].time = math.pi-cardoors_moving[hash].time - celevator.storage:set_string("cardoors_moving",minetest.serialize(cardoors_moving)) - end + local meta = celevator.get_meta(pos) + local doortype = typelookup(meta:get_string("doortype")) + celevator.doors[doortype].caropen(pos) end -function celevator.doors.carclose(pos,nudge) - local cardoors_moving = minetest.deserialize(celevator.storage:get_string("cardoors_moving")) or {} - local hash = minetest.hash_node_position(pos) - if cardoors_moving[hash] then - return - end +function celevator.doors.carclose(pos,...) local meta = celevator.get_meta(pos) - local state = meta:get_string("doorstate") - if state ~= "open" then return end - local data = minetest.deserialize(meta:get_string("doordata")) - if not data then return end - 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 soffset = data.opendir - local foffset = vector.multiply(soffset,2) - for i=1,3,1 do - erefs[i]:set_pos(vector.add(erefs[i]:get_pos(),foffset)) - end - for i=4,6,1 do - erefs[i]:set_pos(vector.add(erefs[i]:get_pos(),soffset)) - end - celevator.doors.erefs[hash] = erefs - if nudge then - data.soundhandle = minetest.sound_play("celevator_nudge",{ - pos = pos, - gain = 0.75, - max_hear_distance = 10 - }) - else - data.soundhandle = minetest.sound_play("celevator_door_close",{ - pos = pos, - gain = 0.3, - max_hear_distance = 10 - }) - end - data.nudging = nudge - cardoors_moving[hash] = data - celevator.storage:set_string("cardoors_moving",minetest.serialize(cardoors_moving)) + local doortype = typelookup(meta:get_string("doortype")) + celevator.doors[doortype].carclose(pos,...) end -minetest.register_abm({ +core.register_abm({ label = "Respawn car doors", - nodenames = {"celevator:car_000"}, + nodenames = {"group:_celevator_car_root"}, interval = 1, chance = 1, action = function(pos) - if minetest.get_meta(pos):get_string("doorstate") ~= "closed" then return end - local entitiesnearby = minetest.get_objects_inside_radius(pos,0.5) + if core.get_meta(pos):get_string("doorstate") ~= "closed" then return end + local entitiesnearby = core.get_objects_inside_radius(pos,0.5) for _,i in pairs(entitiesnearby) do if i:get_luaentity() and i:get_luaentity().name == "celevator:car_door" then return end end - local fdir = minetest.facedir_to_dir(minetest.get_node(pos).param2) - celevator.doors.spawncardoors(pos,fdir) + local fdir = core.facedir_to_dir(core.get_node(pos).param2) + local carmeta = core.get_meta(pos) + local doortype = carmeta:get_string("doortype") + celevator.doors.spawncardoors(pos,fdir,doortype) end, }) -minetest.register_node("celevator:hwdoor_glass",{ - description = "Glass Elevator Hoistway Door", - paramtype2 = "4dir", - buildable_to = true, - inventory_image = "celevator_door_glass_inventory.png", - wield_image = "celevator_door_glass_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 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 - for x=0,1,1 do - for y=0,2,1 do - local piecename = string.format("celevator:hwdoor_%s_glass_%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 - end, -}) - -minetest.register_node("celevator:door_sill_single",{ - description = "Hoistway Door Sill, Single Track (you hacker you!)", - drop = "", - groups = { - not_in_creative_inventory = 1, - }, - paramtype = "light", - drawtype = "nodebox", - node_box = { - type = "fixed", - fixed = { - {-0.5,-0.5,0.28,0.5,-0.495,0.5}, - }, - }, - tiles = { - "celevator_door_sill_single.png^[transformR180", - "celevator_cabinet_sides.png", - }, -}) - -minetest.register_node("celevator:door_sill_double",{ - description = "Hoistway Door Sill, Double Track (you hacker you!)", +core.register_node("celevator:door_sill",{ + description = S("Hoistway Door Sill, Double Track (you hacker you!)"), drop = "", groups = { not_in_creative_inventory = 1, @@ -728,26 +185,19 @@ minetest.register_node("celevator:door_sill_double",{ }, }, tiles = { - "celevator_door_sill_double.png^[transformR180", + "celevator_door_sill.png^[transformR180", "celevator_cabinet_sides.png", }, }) -minetest.register_entity("celevator:door_sill",{ +core.register_entity("celevator:door_sill",{ initial_properties = { visual = "wielditem", visual_size = vector.new(0.667,0.667,0.667), - wield_item = "celevator:door_sill_single", + wield_item = "celevator:door_sill", static_save = false, pointable = false, - glow = minetest.LIGHT_MAX, + glow = core.LIGHT_MAX, }, }) -minetest.register_lbm({ - label = "Respawn hoistway door sills", - name = "celevator:spawn_sill", - nodenames = {"celevator:hwdoor_fast_glass_bottom","celevator:hwdoor_slow_glass_bottom"}, - run_at_every_load = true, - action = placesill, -}) diff --git a/drive_entity.lua b/drive_entity.lua index ae72bca..edc47c6 100644 --- a/drive_entity.lua +++ b/drive_entity.lua @@ -1,6 +1,12 @@ +local S = core.get_translator("celevator") + +local copfscontext = {} + +local keyswitchfscontext = {} + celevator.drives.entity = { - name = "Drive", - description = "Normal entity-based drive", + name = S("Elevator Drive"), + description = S("Normal entity-based drive"), nname = "celevator:drive", buzzsoundhandles = {}, movementsoundhandles = {}, @@ -9,30 +15,37 @@ celevator.drives.entity = { carsoundstate = {}, entityinfo = {}, sheaverefs = {}, + step_enabled = true, --Not a setting, is overwritten on globalstep, true here to check for running drives on startup } +local playerposlimits = {} + local function update_ui(pos) - local meta = minetest.get_meta(pos) + local meta = core.get_meta(pos) local apos = tonumber(meta:get_string("apos")) or 0 - local status = "Idle" + local status local vel = tonumber(meta:get_string("vel")) or 0 local state = meta:get_string("state") + local velstr = string.format("%0.02f",math.abs(vel)) + local aposstr = string.format("%0.02f",apos) if state == "running" and vel > 0 then - status = string.format("Running: Up, %0.02f m/s",vel) + status = S("Drive - Running: Up, @1m/s - Position: @2m",velstr,aposstr) elseif state == "running" and vel < 0 then - status = string.format("Running: Down, %0.02f m/s",math.abs(vel)) + status = S("Drive - Running: Down, @1m/s - Position: @2m",velstr,aposstr) elseif state == "fakerunning" and vel > 0 then - status = string.format("Running (simulated): Up, %0.02f m/s",vel) + status = S("Drive - Running (simulated): Up, @1m/s - Position: @2m",velstr,aposstr) elseif state == "fakerunning" and vel < 0 then - status = string.format("Running (simulated): Down, %0.02f m/s",math.abs(vel)) + status = S("Drive - Running (simulated): Down, @1m/s - Position: @2m",velstr,aposstr) + else + status = S("Drive - Idle") end - meta:set_string("infotext",string.format("Drive - %s - Position: %0.02f m",status,apos)) + meta:set_string("infotext",status) end local function playbuzz(pos) - local hash = minetest.hash_node_position(pos) + local hash = core.hash_node_position(pos) if celevator.drives.entity.buzzsoundhandles[hash] == "cancel" then return end - celevator.drives.entity.buzzsoundhandles[hash] = minetest.sound_play("celevator_drive_run",{ + celevator.drives.entity.buzzsoundhandles[hash] = core.sound_play("celevator_drive_run",{ pos = pos, loop = true, gain = 0.1, @@ -40,78 +53,78 @@ local function playbuzz(pos) end local function startbuzz(pos) - local hash = minetest.hash_node_position(pos) + local hash = core.hash_node_position(pos) if celevator.drives.entity.buzzsoundhandles[hash] == "cancel" then celevator.drives.entity.buzzsoundhandles[hash] = nil return end if celevator.drives.entity.buzzsoundhandles[hash] then return end celevator.drives.entity.buzzsoundhandles[hash] = "pending" - minetest.after(0.5,playbuzz,pos) + core.after(0.5,playbuzz,pos) end local function stopbuzz(pos) - local hash = minetest.hash_node_position(pos) + local hash = core.hash_node_position(pos) if not celevator.drives.entity.buzzsoundhandles[hash] then return end if celevator.drives.entity.buzzsoundhandles[hash] == "pending" then celevator.drives.entity.buzzsoundhandles[hash] = "cancel" end if type(celevator.drives.entity.buzzsoundhandles[hash]) ~= "string" then - minetest.sound_stop(celevator.drives.entity.buzzsoundhandles[hash]) + core.sound_stop(celevator.drives.entity.buzzsoundhandles[hash]) celevator.drives.entity.buzzsoundhandles[hash] = nil end end local function motorsound(pos,newstate) - local hash = minetest.hash_node_position(pos) + local hash = core.hash_node_position(pos) local oldstate = celevator.drives.entity.movementsoundstate[hash] oldstate = oldstate or "idle" if oldstate == newstate then return end - local carid = minetest.get_meta(pos):get_int("carid") - local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid))) + local carid = core.get_meta(pos):get_int("carid") + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) if not (carinfo and carinfo.machinepos) then return end local oldhandle = celevator.drives.entity.movementsoundhandles[hash] if newstate == "slow" then if oldstate == "idle" then - minetest.sound_play("celevator_brake_release",{ + core.sound_play("celevator_brake_release",{ pos = carinfo.machinepos, gain = 1, },true) - celevator.drives.entity.movementsoundhandles[hash] = minetest.sound_play("celevator_motor_slow",{ + celevator.drives.entity.movementsoundhandles[hash] = core.sound_play("celevator_motor_slow",{ pos = carinfo.machinepos, loop = true, gain = 1, }) elseif oldstate == "accel" or oldstate == "fast" or oldstate == "decel" then - if oldhandle then minetest.sound_stop(oldhandle) end - celevator.drives.entity.movementsoundhandles[hash] = minetest.sound_play("celevator_motor_slow",{ + if oldhandle then core.sound_stop(oldhandle) end + celevator.drives.entity.movementsoundhandles[hash] = core.sound_play("celevator_motor_slow",{ pos = carinfo.machinepos, loop = true, gain = 1, }) end elseif newstate == "accel" then - if oldhandle then minetest.sound_stop(oldhandle) end - celevator.drives.entity.movementsoundhandles[hash] = minetest.sound_play("celevator_motor_accel",{ + if oldhandle then core.sound_stop(oldhandle) end + celevator.drives.entity.movementsoundhandles[hash] = core.sound_play("celevator_motor_accel",{ pos = carinfo.machinepos, gain = 1, }) elseif newstate == "fast" then - if oldhandle then minetest.sound_stop(oldhandle) end - celevator.drives.entity.movementsoundhandles[hash] = minetest.sound_play("celevator_motor_fast",{ + if oldhandle then core.sound_stop(oldhandle) end + celevator.drives.entity.movementsoundhandles[hash] = core.sound_play("celevator_motor_fast",{ pos = carinfo.machinepos, loop = true, gain = 1, }) elseif newstate == "decel" then - if oldhandle then minetest.sound_stop(oldhandle) end - celevator.drives.entity.movementsoundhandles[hash] = minetest.sound_play("celevator_motor_decel",{ + if oldhandle then core.sound_stop(oldhandle) end + celevator.drives.entity.movementsoundhandles[hash] = core.sound_play("celevator_motor_decel",{ pos = carinfo.machinepos, gain = 1, }) elseif newstate == "idle" then - if oldhandle then minetest.sound_stop(oldhandle) end - minetest.sound_play("celevator_brake_apply",{ + if oldhandle then core.sound_stop(oldhandle) end + core.sound_play("celevator_brake_apply",{ pos = carinfo.machinepos, gain = 1, },true) @@ -121,7 +134,7 @@ end local function carsound(pos,newstate,speed) if speed < 0.5 then return end - local hash = minetest.hash_node_position(pos) + local hash = core.hash_node_position(pos) local oldstate = celevator.drives.entity.carsoundstate[hash] oldstate = oldstate or "idle" if oldstate == newstate then return end @@ -131,37 +144,37 @@ local function carsound(pos,newstate,speed) local oldhandle = celevator.drives.entity.carsoundhandles[hash] local gain = math.min(1,speed/6) if newstate == "accel" then - if oldhandle then minetest.sound_stop(oldhandle) end - celevator.drives.entity.carsoundhandles[hash] = minetest.sound_play("celevator_car_start",{ + if oldhandle then core.sound_stop(oldhandle) end + celevator.drives.entity.carsoundhandles[hash] = core.sound_play("celevator_car_start",{ object = eref, gain = gain, }) - minetest.after(3,function() + core.after(3,function() if celevator.drives.entity.carsoundstate[hash] == "accel" then carsound(pos,"run",speed) end end) elseif newstate == "run" then - if oldhandle then minetest.sound_stop(oldhandle) end - celevator.drives.entity.carsoundhandles[hash] = minetest.sound_play("celevator_car_run",{ + if oldhandle then core.sound_stop(oldhandle) end + celevator.drives.entity.carsoundhandles[hash] = core.sound_play("celevator_car_run",{ object = eref, loop = true, gain = gain, }) elseif newstate == "decel" then - if oldhandle then minetest.sound_stop(oldhandle) end - celevator.drives.entity.carsoundhandles[hash] = minetest.sound_play("celevator_car_stop",{ + if oldhandle then core.sound_stop(oldhandle) end + celevator.drives.entity.carsoundhandles[hash] = core.sound_play("celevator_car_stop",{ object = eref, gain = gain, }) elseif newstate == "stopped" then - if oldhandle then minetest.sound_stop(oldhandle) end + if oldhandle then core.sound_stop(oldhandle) end end celevator.drives.entity.carsoundstate[hash] = newstate end local function compareexchangesound(pos,compare,new) - local hash = minetest.hash_node_position(pos) + local hash = core.hash_node_position(pos) local oldstate = celevator.drives.entity.movementsoundstate[hash] if oldstate == compare then motorsound(pos,new) @@ -170,17 +183,17 @@ end local function accelsound(pos) motorsound(pos,"slow") - minetest.after(1,compareexchangesound,pos,"slow","accel") - minetest.after(4,compareexchangesound,pos,"accel","fast") + core.after(1,compareexchangesound,pos,"slow","accel") + core.after(4,compareexchangesound,pos,"accel","fast") end local function decelsound(pos) motorsound(pos,"decel") - minetest.after(2,compareexchangesound,pos,"decel","slow") + core.after(2,compareexchangesound,pos,"decel","slow") end -minetest.register_node("celevator:drive",{ - description = "Elevator "..celevator.drives.entity.name, +core.register_node("celevator:drive",{ + description = celevator.drives.entity.name, groups = { cracky = 1, _celevator_drive = 1, @@ -206,7 +219,7 @@ minetest.register_node("celevator:drive",{ }, _celevator_drive_type = "entity", after_place_node = function(pos) - local meta = minetest.get_meta(pos) + local meta = core.get_meta(pos) meta:set_string("apos","0") meta:set_string("dpos","0") meta:set_string("vel","0") @@ -220,38 +233,109 @@ minetest.register_node("celevator:drive",{ on_destruct = stopbuzz, }) -minetest.register_entity("celevator:car_moving",{ +core.register_entity("celevator:car_moving",{ initial_properties = { - visual = "wielditem", - visual_size = vector.new(0.667,0.667,0.667), - wield_item = "default:dirt", + visual = "node", + node = {name="air"}, static_save = false, - glow = minetest.LIGHT_MAX, + glow = core.LIGHT_MAX, pointable = false, }, }) +core.register_entity("celevator:player_holder",{ + initial_properties = { + visual = "cube", + textures = { + "blank.png", + "blank.png", + "blank.png", + "blank.png", + "blank.png", + "blank.png", + }, + 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 = 40 + 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/10),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) + local hash = core.hash_node_position(pos) if nodes[hash] then return nodes end nodes[hash] = true - if minetest.get_item_group(celevator.get_node(pos).name,"_connects_xp") == 1 then + if core.get_item_group(celevator.get_node(pos).name,"_connects_xp") == 1 then celevator.drives.entity.gathercar(vector.add(pos,vector.rotate_around_axis(vector.new(1,0,0),vector.new(0,1,0),yaw)),yaw,nodes) end - if minetest.get_item_group(celevator.get_node(pos).name,"_connects_xm") == 1 then + if core.get_item_group(celevator.get_node(pos).name,"_connects_xm") == 1 then celevator.drives.entity.gathercar(vector.add(pos,vector.rotate_around_axis(vector.new(-1,0,0),vector.new(0,1,0),yaw)),yaw,nodes) end - if minetest.get_item_group(celevator.get_node(pos).name,"_connects_yp") == 1 then + if core.get_item_group(celevator.get_node(pos).name,"_connects_yp") == 1 then celevator.drives.entity.gathercar(vector.add(pos,vector.new(0,1,0)),yaw,nodes) end - if minetest.get_item_group(celevator.get_node(pos).name,"_connects_ym") == 1 then + if core.get_item_group(celevator.get_node(pos).name,"_connects_ym") == 1 then celevator.drives.entity.gathercar(vector.add(pos,vector.new(0,-1,0)),yaw,nodes) end - if minetest.get_item_group(celevator.get_node(pos).name,"_connects_zp") == 1 then + if core.get_item_group(celevator.get_node(pos).name,"_connects_zp") == 1 then celevator.drives.entity.gathercar(vector.add(pos,vector.rotate_around_axis(vector.new(0,0,1),vector.new(0,1,0),yaw)),yaw,nodes) end - if minetest.get_item_group(celevator.get_node(pos).name,"_connects_zm") == 1 then + if core.get_item_group(celevator.get_node(pos).name,"_connects_zm") == 1 then celevator.drives.entity.gathercar(vector.add(pos,vector.rotate_around_axis(vector.new(0,0,-1),vector.new(0,1,0),yaw)),yaw,nodes) end return nodes @@ -259,18 +343,50 @@ 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) - local eref = minetest.add_entity(pos,(ename or "celevator:car_moving")) + local attach = core.get_objects_inside_radius(pos,0.9) + local eref = core.add_entity(pos,(ename or "celevator:car_moving")) eref:set_properties({ - wield_item = node.name, + node = {name = node.name}, + }) + eref:set_yaw(core.dir_to_yaw(core.fourdir_to_dir(node.param2))) + eref:set_armor_groups({ + immortal = 1, }) - 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 = core.registered_nodes[node.name] or {} + local nbox = ndef.selection_box or ndef.node_box + if nbox and nbox.fixed then + local selbox = {0,0,0,0,0,0} + if type(nbox.fixed[1]) ~= "table" then + selbox = table.copy(nbox.fixed) + else + for _,box in ipairs(nbox.fixed) do + for i=1,3 do + selbox[i] = math.min(selbox[i],box[i]) + end + for i=4,6 do + selbox[i] = math.max(selbox[i],box[i]) + end + end + end + selbox.rotate = true + eref:set_properties({selectionbox=selbox}) + end + 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) + local topattach = core.get_objects_inside_radius(toppos,0.75) for _,ref in pairs(topattach) do table.insert(attach,ref) end @@ -285,16 +401,49 @@ function celevator.drives.entity.nodestoentities(nodes,ename) } if attachref:get_luaentity() and included[attachref:get_luaentity().name] then table.insert(refs,attachref) - else + elseif attachref:is_player() then 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) + local holder = core.add_entity(attachpos,"celevator:player_holder") + holder:set_attach(eref,"",vector.multiply(attachoffset,10),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.subtract(attachpos,basepos) + attachref:set_attach(eref,"",vector.multiply(attachoffset,10),vector.new(0,0,0)) + end + end + local meta = celevator.get_meta(pos) + local carid = meta:get_int("carid") + if carid ~= 0 then + if core.get_item_group(node.name,"_has_cop") == 1 then + eref:set_properties({ + pointable = true, + }) + eref:get_luaentity().on_rightclick = function(self,player) + celevator.drives.entity.coprightclick(carid,player,self.object:get_pos()) + end + elseif core.get_item_group(node.name,"_has_keyswitches") == 1 then + eref:set_properties({ + pointable = true, + }) + eref:get_luaentity().on_rightclick = function(self,player) + celevator.drives.entity.keyswitchrightclick(carid,player,self.object:get_pos()) + end end end end - minetest.remove_node(pos) + core.remove_node(pos) end return refs end @@ -307,12 +456,10 @@ function celevator.drives.entity.entitiestonodes(refs,carid) local ename = eref:get_luaentity() and eref:get_luaentity().name if pos and (ename == "celevator:car_moving" or ename == "celevator:hwdoor_moving") then pos = vector.round(pos) - local node = { - name = eref:get_properties().wield_item, - param2 = minetest.dir_to_fourdir(minetest.yaw_to_dir(eref:get_yaw())) - } - if minetest.get_item_group(eref:get_properties().wield_item,"_connects_yp") ~= 1 then top = true end - minetest.set_node(pos,node) + local node = eref:get_properties().node or {name="air"} + node.param2 = core.dir_to_fourdir(core.yaw_to_dir(eref:get_yaw())) + if core.get_item_group(node.name,"_connects_yp") ~= 1 then top = true end + core.set_node(pos,node) eref:remove() if carid then celevator.get_meta(pos):set_int("carid",carid) end elseif pos and ename == "celevator:incar_pi_entity" then @@ -329,14 +476,19 @@ function celevator.drives.entity.entitiestonodes(refs,carid) ["celevator:car_door"] = true, ["celevator:tapehead"] = true, } - for _,i in ipairs(minetest.get_objects_inside_radius(pos,0.9)) do + for _,i in ipairs(core.get_objects_inside_radius(pos,0.9)) do 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) + core.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) @@ -352,15 +504,16 @@ function celevator.drives.entity.entitiestonodes(refs,carid) end function celevator.drives.entity.step(dtime) - local entitydrives_running = minetest.deserialize(celevator.storage:get_string("entitydrives_running")) or {} + if not celevator.drives.entity.step_enabled then return end + local entitydrives_running = core.deserialize(celevator.storage:get_string("entitydrives_running")) or {} local save = false for i,hash in ipairs(entitydrives_running) do save = true - local pos = minetest.get_position_from_hash(hash) + local pos = core.get_position_from_hash(hash) local node = celevator.get_node(pos) local sound = false if node.name == "ignore" then - minetest.forceload_block(pos,true) + core.forceload_block(pos,true) elseif node.name ~= "celevator:drive" then table.remove(entitydrives_running,i) else @@ -373,10 +526,11 @@ 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")) + local origin = core.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)) + core.log("error","[celevator] [entity drive] Invalid origin for drive at "..core.pos_to_string(pos)) meta:set_string("fault","badorigin") table.remove(entitydrives_running,i) return @@ -391,10 +545,10 @@ function celevator.drives.entity.step(dtime) end end local startv = vector.add(origin,vector.new(0,startpos,0)) - local hashes = celevator.drives.entity.gathercar(startv,minetest.dir_to_yaw(minetest.fourdir_to_dir(celevator.get_node(startv).param2))) + local hashes = celevator.drives.entity.gathercar(startv,core.dir_to_yaw(core.fourdir_to_dir(celevator.get_node(startv).param2))) local nodes = {} for carhash in pairs(hashes) do - local carpos = minetest.get_position_from_hash(carhash) + local carpos = core.get_position_from_hash(carhash) if vector.equals(startv,carpos) then table.insert(nodes,1,carpos) --0,0,0 node must be first in the list else @@ -402,7 +556,12 @@ function celevator.drives.entity.step(dtime) end end local carparam2 = celevator.get_node(nodes[1]).param2 + local cardef = core.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 +591,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,core.dir_to_yaw(core.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 + core.after(0.25,celevator.drives.entity.updatecopformspec,pos) + 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 +645,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,core.dir_to_yaw(core.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 + core.after(0.25,celevator.drives.entity.updatecopformspec,pos) + 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 @@ -515,25 +688,40 @@ function celevator.drives.entity.step(dtime) end end if save then - celevator.storage:set_string("entitydrives_running",minetest.serialize(entitydrives_running)) + celevator.storage:set_string("entitydrives_running",core.serialize(entitydrives_running)) end + celevator.drives.entity.step_enabled = save end -minetest.register_globalstep(celevator.drives.entity.step) +core.register_globalstep(celevator.drives.entity.step) function celevator.drives.entity.moveto(pos,target,inspection) local meta = celevator.get_meta(pos) 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 - local origin = minetest.string_to_pos(meta:get_string("origin")) + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) + 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 = core.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)) + core.log("error","[celevator] [entity drive] Invalid origin for drive at "..core.pos_to_string(pos)) meta:set_string("fault","badorigin") return end - if target < 0 or origin.y + target > (carinfo.machinepos.y-3) then + if target < 0 or origin.y + target > (carinfo.machinepos.y-3) or target ~= target then meta:set_string("fault","outofbounds") return end @@ -553,8 +741,8 @@ function celevator.drives.entity.moveto(pos,target,inspection) meta:set_string("state","start") meta:set_int("inspection",inspection and 1 or 0) meta:set_string("startpos",meta:get_string("apos")) - local hash = minetest.hash_node_position(pos) - local entitydrives_running = minetest.deserialize(celevator.storage:get_string("entitydrives_running")) or {} + local hash = core.hash_node_position(pos) + local entitydrives_running = core.deserialize(celevator.storage:get_string("entitydrives_running")) or {} local running = false for _,dhash in ipairs(entitydrives_running) do if hash == dhash then @@ -563,8 +751,9 @@ function celevator.drives.entity.moveto(pos,target,inspection) end end if not running then + celevator.drives.entity.step_enabled = true table.insert(entitydrives_running,hash) - celevator.storage:set_string("entitydrives_running",minetest.serialize(entitydrives_running)) + celevator.storage:set_string("entitydrives_running",core.serialize(entitydrives_running)) --Controller needs to see something so it knows the drive is running local apos = tonumber(meta:get_string("apos")) if apos and apos > target then @@ -587,7 +776,7 @@ function celevator.drives.entity.estop(pos) local apos = math.floor(tonumber(meta:get_string("apos"))+0.5) meta:set_string("dpos",tostring(apos)) meta:set_string("apos",tostring(apos)) - local hash = minetest.hash_node_position(pos) + local hash = core.hash_node_position(pos) local handles = celevator.drives.entity.entityinfo[hash].handles meta:set_string("state","stopped") meta:set_string("vel","0") @@ -596,11 +785,12 @@ function celevator.drives.entity.estop(pos) stopbuzz(pos) motorsound(pos,"idle") if carid ~= 0 then celevator.drives.entity.sheavetonode(carid) end - minetest.after(0.25,celevator.drives.entity.updatecopformspec,pos) + core.after(0.25,celevator.drives.entity.updatecopformspec,pos) end function celevator.drives.entity.setmaxvel(pos,maxvel) + if maxvel ~= maxvel then return end local meta = celevator.get_meta(pos) meta:set_string("maxvel",tostring(maxvel)) end @@ -611,12 +801,12 @@ function celevator.drives.entity.rezero(pos) end function celevator.drives.entity.getstatus(pos,call2) - local node = minetest.get_node(pos) + local node = core.get_node(pos) if node.name == "ignore" and not call2 then - minetest.forceload_block(pos,true) + core.forceload_block(pos,true) return celevator.drives.entity.get_status(pos,true) elseif node.name ~= "celevator:drive" then - minetest.log("error","[celevator] [entity drive] Could not load drive status at "..minetest.pos_to_string(pos)) + core.log("error","[celevator] [entity drive] Could not load drive status at "..core.pos_to_string(pos)) return {fault = "metaload"} else local meta = celevator.get_meta(pos) @@ -635,27 +825,27 @@ function celevator.drives.entity.getstatus(pos,call2) end function celevator.drives.entity.movedoors(drivepos,direction,nudge) - local drivehash = minetest.hash_node_position(drivepos) - local entitydrives_running = minetest.deserialize(celevator.storage:get_string("entitydrives_running")) or {} + local drivehash = core.hash_node_position(drivepos) + local entitydrives_running = core.deserialize(celevator.storage:get_string("entitydrives_running")) or {} local drivemeta = celevator.get_meta(drivepos) for _,hash in pairs(entitydrives_running) do if drivehash == hash then - minetest.log("error","[celevator] [entity drive] Attempted to open doors while drive at "..minetest.pos_to_string(drivepos).." was still moving") + core.log("error","[celevator] [entity drive] Attempted to open doors while drive at "..core.pos_to_string(drivepos).." was still moving") drivemeta:set_string("fault","doorinterlock") return end end - local origin = minetest.string_to_pos(drivemeta:get_string("origin")) + local origin = core.string_to_pos(drivemeta:get_string("origin")) if not origin then - minetest.log("error","[celevator] [entity drive] Invalid origin for drive at "..minetest.pos_to_string(drivepos)) + core.log("error","[celevator] [entity drive] Invalid origin for drive at "..core.pos_to_string(drivepos)) drivemeta:set_string("fault","badorigin") return end local apos = tonumber(drivemeta:get_string("apos")) or 0 local carpos = vector.add(origin,vector.new(0,apos,0)) local carnode = celevator.get_node(carpos) - local hwdoorpos = vector.add(carpos,vector.rotate_around_axis(minetest.fourdir_to_dir(carnode.param2),vector.new(0,1,0),math.pi)) - local isroot = minetest.get_item_group(celevator.get_node(hwdoorpos).name,"_celevator_hwdoor_root") == 1 + local hwdoorpos = vector.add(carpos,vector.rotate_around_axis(core.fourdir_to_dir(carnode.param2),vector.new(0,1,0),math.pi)) + local isroot = core.get_item_group(celevator.get_node(hwdoorpos).name,"_celevator_hwdoor_root") == 1 if direction == "open" and (isroot or drivemeta:get_string("doorstate") == "closing") then celevator.doors.hwopen(hwdoorpos,drivepos) drivemeta:set_string("doorstate","opening") @@ -671,27 +861,29 @@ end function celevator.drives.entity.pibeep(drivepos) local drivemeta = celevator.get_meta(drivepos) - local origin = minetest.string_to_pos(drivemeta:get_string("origin")) + local origin = core.string_to_pos(drivemeta:get_string("origin")) if not origin then - minetest.log("error","[celevator] [entity drive] Invalid origin for drive at "..minetest.pos_to_string(drivepos)) + core.log("error","[celevator] [entity drive] Invalid origin for drive at "..core.pos_to_string(drivepos)) drivemeta:set_string("fault","badorigin") return end local apos = tonumber(drivemeta:get_string("apos")) or 0 local beeppos = vector.add(origin,vector.new(0,apos+2,0)) - minetest.sound_play("celevator_pi_beep",{ + core.sound_play("celevator_pi_beep",{ pos = beeppos, gain = 1, },true) end local function carsearch(pos) - for i=1,500,1 do + local maxdistance = tonumber(core.settings:get("celevator.max_height")) or 500 + maxdistance = math.max(1,maxdistance) + for i=1,maxdistance,1 do local searchpos = vector.subtract(pos,vector.new(0,i,0)) local node = celevator.get_node(searchpos) - if minetest.get_item_group(node.name,"_celevator_car") == 1 then - local yaw = minetest.dir_to_yaw(minetest.fourdir_to_dir(node.param2)) - local offsettext = minetest.registered_nodes[node.name]._position + if core.get_item_group(node.name,"_celevator_car") == 1 then + local yaw = core.dir_to_yaw(core.fourdir_to_dir(node.param2)) + local offsettext = core.registered_nodes[node.name]._position local xoffset = tonumber(string.sub(offsettext,1,1)) local yoffset = tonumber(string.sub(offsettext,2,2)) local zoffset = tonumber(string.sub(offsettext,3,3)) @@ -707,36 +899,36 @@ local function updatecarpos(pos) if meta:get_int("carid") == 0 then return end local carpos = carsearch(pos) if carpos then - meta:set_string("origin",minetest.pos_to_string(carpos)) - celevator.get_meta(carpos):set_string("machinepos",minetest.pos_to_string(pos)) - meta:set_string("infotext",string.format("Using car with origin %s",minetest.pos_to_string(carpos))) + meta:set_string("origin",core.pos_to_string(carpos)) + celevator.get_meta(carpos):set_string("machinepos",core.pos_to_string(pos)) + meta:set_string("infotext",S("Using car with origin @1",core.pos_to_string(carpos))) local carid = meta:get_int("carid") - local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid))) + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) if not (carinfo and carinfo.controllerpos) then return end carinfo.origin = carpos - celevator.storage:set_string(string.format("car%d",carid),minetest.serialize(carinfo)) + celevator.storage:set_string(string.format("car%d",carid),core.serialize(carinfo)) local drivepos = celevator.controller.finddrive(carinfo.controllerpos) if drivepos then local drivemeta = celevator.get_meta(drivepos) if drivemeta:get_string("state") == "uninit" then - drivemeta:set_string("origin",minetest.pos_to_string(carpos)) + drivemeta:set_string("origin",core.pos_to_string(carpos)) drivemeta:set_string("state","stopped") drivemeta:set_int("carid",carid) end end - local caryaw = minetest.dir_to_yaw(minetest.fourdir_to_dir(celevator.get_node(carpos).param2)) + local caryaw = core.dir_to_yaw(core.fourdir_to_dir(celevator.get_node(carpos).param2)) local carnodes = celevator.drives.entity.gathercar(carpos,caryaw) for hash in pairs(carnodes) do - local carmeta = celevator.get_meta(minetest.get_position_from_hash(hash)) + local carmeta = celevator.get_meta(core.get_position_from_hash(hash)) carmeta:set_int("carid",carid) end else - meta:set_string("infotext","No car found! Punch to try again") + meta:set_string("infotext",S("No car found! Punch to try again")) end end -minetest.register_node("celevator:machine",{ - description = "Elevator Hoist Machine", +core.register_node("celevator:machine",{ + description = S("Elevator Hoist Machine"), groups = { dig_immediate = 2, _celevator_machine = 1, @@ -780,54 +972,54 @@ minetest.register_node("celevator:machine",{ }, after_place_node = function(pos,player) if not player:is_player() then - minetest.remove_node(pos) + core.remove_node(pos) return true end - local newnode = minetest.get_node(pos) - local facedir = minetest.dir_to_yaw(minetest.fourdir_to_dir(newnode.param2)) + local newnode = core.get_node(pos) + local facedir = core.dir_to_yaw(core.fourdir_to_dir(newnode.param2)) local motorpos = vector.add(pos,vector.rotate_around_axis(vector.new(-1,0,0),vector.new(0,1,0),facedir)) - local motorreplaces = minetest.get_node(motorpos).name + local motorreplaces = core.get_node(motorpos).name local sheavepos = vector.add(pos,vector.rotate_around_axis(vector.new(0,0,-1),vector.new(0,1,0),facedir)) - local sheavereplaces = minetest.get_node(sheavepos).name + local sheavereplaces = core.get_node(sheavepos).name local name = player:get_player_name() - if not (minetest.registered_nodes[motorreplaces] and minetest.registered_nodes[motorreplaces].buildable_to) then - minetest.chat_send_player(name,"Can't place machine here - no room for the motor (to the left)!") - minetest.remove_node(pos) + if not (core.registered_nodes[motorreplaces] and core.registered_nodes[motorreplaces].buildable_to) then + core.chat_send_player(name,S("Can't place machine here - no room for the motor (to the left)!")) + core.remove_node(pos) return true end - if minetest.is_protected(motorpos,name) and not minetest.check_player_privs(name,{protection_bypass=true}) then - minetest.chat_send_player(name,"Can't place machine here - space for the motor (to the left) is protected!") - minetest.record_protection_violation(motorpos,name) - minetest.remove_node(pos) + if core.is_protected(motorpos,name) and not core.check_player_privs(name,{protection_bypass=true}) then + core.chat_send_player(name,S("Can't place machine here - space for the motor (to the left) is protected!")) + core.record_protection_violation(motorpos,name) + core.remove_node(pos) return true end - if not (minetest.registered_nodes[sheavereplaces] and minetest.registered_nodes[sheavereplaces].buildable_to) then - minetest.chat_send_player(name,"Can't place machine here - no room for the sheave (in front)!") - minetest.remove_node(pos) + if not (core.registered_nodes[sheavereplaces] and core.registered_nodes[sheavereplaces].buildable_to) then + core.chat_send_player(name,S("Can't place machine here - no room for the sheave (in front)!")) + core.remove_node(pos) return true end - if minetest.is_protected(sheavepos,name) and not minetest.check_player_privs(name,{protection_bypass=true}) then - minetest.chat_send_player(name,"Can't place machine here - space for the sheave (in front) is protected!") - minetest.record_protection_violation(sheavepos,name) - minetest.remove_node(pos) + if core.is_protected(sheavepos,name) and not core.check_player_privs(name,{protection_bypass=true}) then + core.chat_send_player(name,S("Can't place machine here - space for the sheave (in front) is protected!")) + core.record_protection_violation(sheavepos,name) + core.remove_node(pos) return true end - local meta = minetest.get_meta(pos) - meta:set_string("formspec","formspec_version[7]size[8,5]field[0.5,0.5;7,1;carid;Car ID;]button[3,3.5;2,1;save;Save]") - minetest.set_node(motorpos,{name="celevator:motor",param2=newnode.param2}) - minetest.set_node(sheavepos,{name="celevator:sheave",param2=newnode.param2}) + local meta = core.get_meta(pos) + meta:set_string("formspec","formspec_version[7]size[8,5]field[0.5,0.5;7,1;carid;"..S("Car ID")..";]button[3,3.5;2,1;save;"..S("Save").."]") + core.set_node(motorpos,{name="celevator:motor",param2=newnode.param2}) + core.set_node(sheavepos,{name="celevator:sheave",param2=newnode.param2}) end, after_dig_node = function(pos,node) - local facedir = minetest.dir_to_yaw(minetest.fourdir_to_dir(node.param2)) + local facedir = core.dir_to_yaw(core.fourdir_to_dir(node.param2)) local motorpos = vector.add(pos,vector.rotate_around_axis(vector.new(-1,0,0),vector.new(0,1,0),facedir)) - if minetest.get_node(motorpos).name == "celevator:motor" then - minetest.remove_node(motorpos) + if core.get_node(motorpos).name == "celevator:motor" then + core.remove_node(motorpos) end local sheavepos = vector.add(pos,vector.rotate_around_axis(vector.new(0,0,-1),vector.new(0,1,0),facedir)) - if minetest.get_node(sheavepos).name == "celevator:sheave" then - minetest.remove_node(sheavepos) + if core.get_node(sheavepos).name == "celevator:sheave" then + core.remove_node(sheavepos) end - local erefs = minetest.get_objects_inside_radius(sheavepos,0.5) + local erefs = core.get_objects_inside_radius(sheavepos,0.5) for _,ref in pairs(erefs) do if ref:get_luaentity() and ref:get_luaentity().name == "celevator:sheave_moving" then ref:remove() @@ -835,26 +1027,26 @@ minetest.register_node("celevator:machine",{ end end, on_punch = function(pos) - local meta = minetest.get_meta(pos) - if not minetest.string_to_pos(meta:get_string("origin")) then + local meta = core.get_meta(pos) + if not core.string_to_pos(meta:get_string("origin")) then updatecarpos(pos) end end, on_receive_fields = function(pos,_,fields) if tonumber(fields.carid) then local carid = tonumber(fields.carid) - local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid))) + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) if not carinfo then return end local oldmachinepos = carinfo.machinepos if oldmachinepos then local oldmachine = celevator.get_node(oldmachinepos) - if oldmachine.name == "celevator:machine" then + if oldmachine.name == "celevator:machine" and not vector.equals(pos,oldmachinepos) then return end end carinfo.machinepos = pos - celevator.storage:set_string(string.format("car%d",carid),minetest.serialize(carinfo)) - local meta = minetest.get_meta(pos) + celevator.storage:set_string(string.format("car%d",carid),core.serialize(carinfo)) + local meta = core.get_meta(pos) meta:set_int("carid",carid) meta:set_string("formspec","") updatecarpos(pos) @@ -862,9 +1054,11 @@ minetest.register_node("celevator:machine",{ end, }) -minetest.register_node("celevator:motor",{ - description = "Hoist Motor (you hacker you!)", +core.register_node("celevator:motor",{ + description = S("Hoist Motor (you hacker you!)"), groups = { + cracky = 3, + oddly_breakable_by_hand = 1, not_in_creative_inventory = 1, }, drop = "", @@ -896,9 +1090,11 @@ minetest.register_node("celevator:motor",{ }, }) -minetest.register_node("celevator:sheave",{ - description = "Sheave (you hacker you!)", +core.register_node("celevator:sheave",{ + description = S("Sheave (you hacker you!)"), groups = { + cracky = 3, + oddly_breakable_by_hand = 1, not_in_creative_inventory = 1, }, drop = "", @@ -929,9 +1125,11 @@ minetest.register_node("celevator:sheave",{ }, }) -minetest.register_node("celevator:sheave_centered",{ - description = "Centered Sheave (you hacker you!)", +core.register_node("celevator:sheave_centered",{ + description = S("Centered Sheave (you hacker you!)"), groups = { + cracky = 3, + oddly_breakable_by_hand = 1, not_in_creative_inventory = 1, }, drop = "", @@ -962,7 +1160,7 @@ minetest.register_node("celevator:sheave_centered",{ }, }) -minetest.register_entity("celevator:sheave_moving",{ +core.register_entity("celevator:sheave_moving",{ initial_properties = { visual = "wielditem", visual_size = vector.new(0.667,0.667,0.667), @@ -973,13 +1171,13 @@ minetest.register_entity("celevator:sheave_moving",{ }) function celevator.drives.entity.sheavetoentity(carid) - local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid))) + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) if not (carinfo and carinfo.machinepos) then return end - local dir = minetest.fourdir_to_dir(celevator.get_node(carinfo.machinepos).param2) + local dir = core.fourdir_to_dir(celevator.get_node(carinfo.machinepos).param2) local pos = vector.add(carinfo.machinepos,vector.multiply(dir,-1)) - minetest.set_node(pos,{ + core.set_node(pos,{ name = "celevator:sheave", - param2 = minetest.dir_to_fourdir(dir), + param2 = core.dir_to_fourdir(dir), }) local sheaverefs = celevator.drives.entity.nodestoentities({pos},"celevator:sheave_moving") celevator.drives.entity.sheaverefs[carid] = sheaverefs @@ -988,48 +1186,111 @@ function celevator.drives.entity.sheavetoentity(carid) end function celevator.drives.entity.sheavetonode(carid) - local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid))) + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) if not (carinfo and carinfo.machinepos) then return end - local dir = minetest.fourdir_to_dir(celevator.get_node(carinfo.machinepos).param2) + local dir = core.fourdir_to_dir(celevator.get_node(carinfo.machinepos).param2) local pos = vector.add(carinfo.machinepos,vector.multiply(dir,-1)) local erefs = celevator.drives.entity.sheaverefs[carid] if erefs and erefs[1] then erefs[1]:remove() end - minetest.set_node(pos,{ + core.set_node(pos,{ name = "celevator:sheave", - param2 = minetest.dir_to_fourdir(dir), + param2 = core.dir_to_fourdir(dir), }) end function celevator.drives.entity.updatecopformspec(drivepos) - local entitydrives_running = minetest.deserialize(celevator.storage:get_string("entitydrives_running")) or {} - if entitydrives_running[minetest.hash_node_position(drivepos)] then return end + local entitydrives_running = core.deserialize(celevator.storage:get_string("entitydrives_running")) or {} + if entitydrives_running[core.hash_node_position(drivepos)] then return end local drivemeta = celevator.get_meta(drivepos) local carid = drivemeta:get_int("carid") if carid == 0 then return end - local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid))) + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) if not carinfo then return end local copformspec = celevator.get_meta(carinfo.controllerpos):get_string("copformspec") local switchformspec = celevator.get_meta(carinfo.controllerpos):get_string("switchformspec") - local origin = minetest.string_to_pos(drivemeta:get_string("origin")) - if not origin then - minetest.log("error","[celevator] [entity drive] Invalid origin for drive at "..minetest.pos_to_string(drivepos)) - drivemeta:set_string("fault","badorigin") - return + for playername,context in pairs(copfscontext) do + if carid == context.carid then + core.show_formspec(playername,"celevator:cop",copformspec) + end end - local apos = tonumber(drivemeta:get_string("apos")) or 0 - if apos == math.floor(apos) then - local carpos = vector.add(origin,vector.new(0,apos,0)) - local carnodes = celevator.drives.entity.gathercar(carpos,minetest.dir_to_yaw(minetest.fourdir_to_dir(celevator.get_node(carpos).param2))) - 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 - celevator.get_meta(piecepos):set_string("formspec",copformspec) - elseif piece.name == "celevator:car_000" then - celevator.get_meta(piecepos):set_string("formspec",switchformspec) - end + for playername,context in pairs(keyswitchfscontext) do + if carid == context.carid then + core.show_formspec(playername,"celevator:keyswitches",switchformspec) end end end + +function celevator.drives.entity.coprightclick(carid,player,pos) + if type(player) == "userdata" then player = player:get_player_name() end + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) + if not (carinfo and carinfo.controllerpos) then return end + if not celevator.controller.iscontroller(carinfo.controllerpos) then return end + local meta = celevator.get_meta(carinfo.controllerpos) + local formspec = meta:get_string("copformspec") + core.show_formspec(player,"celevator:cop",formspec) + copfscontext[player] = {carid = carid,pos = pos} +end + +function celevator.drives.entity.keyswitchrightclick(carid,player,pos) + if type(player) == "userdata" then player = player:get_player_name() end + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) + if not (carinfo and carinfo.controllerpos) then return end + if not celevator.controller.iscontroller(carinfo.controllerpos) then return end + local meta = celevator.get_meta(carinfo.controllerpos) + local formspec = meta:get_string("switchformspec") + core.show_formspec(player,"celevator:keyswitches",formspec) + keyswitchfscontext[player] = {carid = carid,pos = pos} +end + +core.register_on_player_receive_fields(function(player,formname,fields) + local playername = player:get_player_name() + if formname == "celevator:cop" then + if fields.quit then + copfscontext[playername] = nil + end + local carid = (copfscontext[playername] or {}).carid + if not carid then return end + local coppos = copfscontext[playername].pos + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) + if not carinfo then return end + local protected = core.is_protected(vector.round(coppos),playername) and not core.check_player_privs(playername,{protection_bypass=true}) + local event = { + type = "cop", + fields = fields, + player = playername, + protected = protected, + } + if fields.alarm then + core.sound_play({name="celevator_alarm"},{pos=coppos,max_hear_distance=32,ephemeral=true}) + elseif fields.phone then + core.sound_play({name="celevator_phone"},{pos=coppos,gain=0.3,max_hear_distance=8,ephemeral=true}) + end + celevator.controller.run(carinfo.controllerpos,event) + return true + elseif formname == "celevator:keyswitches" then + if fields.quit then + keyswitchfscontext[playername] = nil + end + local carid = (keyswitchfscontext[playername] or {}).carid + if not carid then return end + local switchpos = keyswitchfscontext[playername].pos + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) + if not carinfo then return end + if core.is_protected(switchpos,playername) and not core.check_player_privs(playername,{protection_bypass=true}) then + core.chat_send_player(playername,S("You don't have access to these switches.")) + core.record_protection_violation(switchpos,playername) + return + end + local event = { + type = "copswitches", + fields = fields, + player = playername, + } + celevator.controller.run(carinfo.controllerpos,event) + return true + else + return false + end +end) diff --git a/drive_null.lua b/drive_null.lua index 1a22e22..5fd2d5d 100644 --- a/drive_null.lua +++ b/drive_null.lua @@ -1,27 +1,34 @@ +local S = core.get_translator("celevator") + celevator.drives.null = { - name = "Null Drive", - description = "Simulation only, no movement, for testing and demonstration", + name = S("Null Drive"), + description = S("Simulation only, no movement, for testing and demonstration"), nname = "celevator:drive_null", soundhandles = {}, + step_enabled = true, --Not a setting, is overwritten on globalstep, true here to check for running drives on startup } local function update_ui(pos) - local meta = minetest.get_meta(pos) + local meta = core.get_meta(pos) local apos = tonumber(meta:get_string("apos")) or 0 - local status = "Idle" + local status local vel = tonumber(meta:get_string("vel")) or 0 + local velstr = string.format("%0.02f",math.abs(vel)) + local aposstr = string.format("%0.02f",apos) if vel > 0 then - status = string.format("Running: Up, %0.02f m/s",vel) + status = S("Null Drive - Running: Up, @1m/s - Position: @2m",velstr,aposstr) elseif vel < 0 then - status = string.format("Running: Down, %0.02f m/s",math.abs(vel)) + status = S("Null Drive - Running: Down, @1m/s - Position: @2m",velstr,aposstr) + else + status = S("Null Drive - Idle") end - meta:set_string("infotext",string.format("Null Drive - %s - Position: %0.02f m",status,apos)) + meta:set_string("infotext",status) end local function playbuzz(pos) - local hash = minetest.hash_node_position(pos) + local hash = core.hash_node_position(pos) if celevator.drives.null.soundhandles[hash] == "cancel" then return end - celevator.drives.null.soundhandles[hash] = minetest.sound_play("celevator_drive_run",{ + celevator.drives.null.soundhandles[hash] = core.sound_play("celevator_drive_run",{ pos = pos, loop = true, gain = 0.4, @@ -29,32 +36,33 @@ local function playbuzz(pos) end local function startbuzz(pos) - local hash = minetest.hash_node_position(pos) + local hash = core.hash_node_position(pos) if celevator.drives.null.soundhandles[hash] == "cancel" then celevator.drives.null.soundhandles[hash] = nil return end if celevator.drives.null.soundhandles[hash] then return end celevator.drives.null.soundhandles[hash] = "pending" - minetest.after(0.5,playbuzz,pos) + core.after(0.5,playbuzz,pos) end local function stopbuzz(pos) - local hash = minetest.hash_node_position(pos) + local hash = core.hash_node_position(pos) if not celevator.drives.null.soundhandles[hash] then return end if celevator.drives.null.soundhandles[hash] == "pending" then celevator.drives.null.soundhandles[hash] = "cancel" end if type(celevator.drives.null.soundhandles[hash]) ~= "string" then - minetest.sound_stop(celevator.drives.null.soundhandles[hash]) + core.sound_stop(celevator.drives.null.soundhandles[hash]) celevator.drives.null.soundhandles[hash] = nil end end -minetest.register_node("celevator:drive_null",{ +core.register_node("celevator:drive_null",{ description = celevator.drives.null.name, groups = { - cracky = 1, + cracky = 3, + oddly_breakable_by_hand = 1, not_in_creative_inventory = 1, }, tiles = { @@ -78,7 +86,7 @@ minetest.register_node("celevator:drive_null",{ }, _celevator_drive_type = "null", after_place_node = function(pos) - local meta = minetest.get_meta(pos) + local meta = core.get_meta(pos) meta:set_string("apos","0") meta:set_string("dpos","0") meta:set_string("vel","0") @@ -90,19 +98,20 @@ minetest.register_node("celevator:drive_null",{ }) function celevator.drives.null.step(dtime) - local nulldrives_running = minetest.deserialize(celevator.storage:get_string("nulldrives_running")) or {} + if not celevator.drives.null.step_enabled then return end + local nulldrives_running = core.deserialize(celevator.storage:get_string("nulldrives_running")) or {} local save = false for i,hash in ipairs(nulldrives_running) do save = true - local pos = minetest.get_position_from_hash(hash) + local pos = core.get_position_from_hash(hash) local node = celevator.get_node(pos) local sound = false if node.name == "ignore" then - minetest.forceload_block(pos,true) + core.forceload_block(pos,true) elseif node.name ~= "celevator:drive_null" then table.remove(nulldrives_running,i) else - local meta = minetest.get_meta(pos) + local meta = core.get_meta(pos) local apos = tonumber(meta:get_string("apos")) or 0 local dpos = tonumber(meta:get_string("dpos")) or 0 local maxvel = tonumber(meta:get_string("maxvel")) or 0.2 @@ -144,17 +153,18 @@ function celevator.drives.null.step(dtime) end end if save then - celevator.storage:set_string("nulldrives_running",minetest.serialize(nulldrives_running)) + celevator.storage:set_string("nulldrives_running",core.serialize(nulldrives_running)) end + celevator.drives.null.step_enabled = save end -minetest.register_globalstep(celevator.drives.null.step) +core.register_globalstep(celevator.drives.null.step) function celevator.drives.null.moveto(pos,target) - local meta = minetest.get_meta(pos) + local meta = core.get_meta(pos) meta:set_string("dpos",tostring(target)) - local hash = minetest.hash_node_position(pos) - local nulldrives_running = minetest.deserialize(celevator.storage:get_string("nulldrives_running")) or {} + local hash = core.hash_node_position(pos) + local nulldrives_running = core.deserialize(celevator.storage:get_string("nulldrives_running")) or {} local running = false for _,dhash in ipairs(nulldrives_running) do if hash == dhash then @@ -163,8 +173,9 @@ function celevator.drives.null.moveto(pos,target) end end if not running then + celevator.drives.null.step_enabled = true table.insert(nulldrives_running,hash) - celevator.storage:set_string("nulldrives_running",minetest.serialize(nulldrives_running)) + celevator.storage:set_string("nulldrives_running",core.serialize(nulldrives_running)) end end @@ -173,13 +184,13 @@ function celevator.drives.null.resetpos(pos) end function celevator.drives.null.estop(pos) - local meta = minetest.get_meta(pos) + local meta = core.get_meta(pos) meta:set_string("dpos",meta:get_string("apos")) meta:set_string("vel","0") end function celevator.drives.null.setmaxvel(pos,maxvel) - local meta = minetest.get_meta(pos) + local meta = core.get_meta(pos) meta:set_string("maxvel",tostring(maxvel)) end @@ -188,35 +199,35 @@ function celevator.drives.null.rezero(pos) end function celevator.drives.null.movedoors(drivepos,direction) - local drivehash = minetest.hash_node_position(drivepos) - local nulldrives_running = minetest.deserialize(celevator.storage:get_string("nulldrives_running")) or {} + local drivehash = core.hash_node_position(drivepos) + local nulldrives_running = core.deserialize(celevator.storage:get_string("nulldrives_running")) or {} for _,hash in pairs(nulldrives_running) do if drivehash == hash then return end end - local drivemeta = minetest.get_meta(drivepos) + local drivemeta = core.get_meta(drivepos) if direction == "open" then drivemeta:set_string("doorstate","opening") - minetest.after(math.pi+0.5,function() - minetest.get_meta(drivepos):set_string("doorstate","open") + core.after(math.pi+0.5,function() + core.get_meta(drivepos):set_string("doorstate","open") end) elseif direction == "close" then drivemeta:set_string("doorstate","closing") - minetest.after((math.pi/0.66)+0.5,function() - minetest.get_meta(drivepos):set_string("doorstate","closed") + core.after((math.pi/0.66)+0.5,function() + core.get_meta(drivepos):set_string("doorstate","closed") end) end end function celevator.drives.null.getstatus(pos,call2) - local node = minetest.get_node(pos) + local node = core.get_node(pos) if node.name == "ignore" and not call2 then - minetest.forceload_block(pos,true) + core.forceload_block(pos,true) return celevator.drives.null.get_status(pos,true) elseif node.name ~= "celevator:drive_null" then - minetest.log("error","[celevator] [null drive] Could not load drive status at "..minetest.pos_to_string(pos)) + core.log("error","[celevator] [null drive] Could not load drive status at "..core.pos_to_string(pos)) return else - local meta = minetest.get_meta(pos) + local meta = core.get_meta(pos) local ret = {} ret.apos = tonumber(meta:get_string("apos")) or 0 ret.dpos = tonumber(meta:get_string("dpos")) or 0 @@ -232,7 +243,7 @@ function celevator.drives.null.resetfault(pos) --This drive has no possible faults at this time --(drive communication faults are generated by the controller), --but the controller expects to be able to call this - minetest.get_meta(pos):set_string("fault","") + core.get_meta(pos):set_string("fault","") end function celevator.drives.null.updatecopformspec() diff --git a/framework.lua b/framework.lua index 1793634..e2aed27 100644 --- a/framework.lua +++ b/framework.lua @@ -1,20 +1,20 @@ celevator = { drives = {}, - storage = minetest.get_mod_storage(), + storage = core.get_mod_storage(), } function celevator.get_node(pos) - local node = minetest.get_node_or_nil(pos) + local node = core.get_node_or_nil(pos) if node then return node end VoxelManip(pos,pos) - return minetest.get_node(pos) + return core.get_node(pos) end function celevator.get_meta(pos) - if minetest.get_node_or_nil(pos) then - return minetest.get_meta(pos) + if core.get_node_or_nil(pos) then + return core.get_meta(pos) else VoxelManip(pos,pos) - return minetest.get_meta(pos) + return core.get_meta(pos) end end diff --git a/fs1switch.lua b/fs1switch.lua index 5949250..49be80a 100644 --- a/fs1switch.lua +++ b/fs1switch.lua @@ -1,5 +1,7 @@ celevator.fs1switch = {} +local S = core.get_translator("celevator") + local function maketex(switchpos,lit) local tex = "celevator_fs1switch_"..switchpos..".png" if lit then tex = tex.."^celevator_fs1switch_led.png" end @@ -12,42 +14,42 @@ local nodebox = { } local function resetspring(pos) - local node = minetest.get_node(pos) + local node = core.get_node(pos) local offstates = { ["celevator:fs1switch_reset"] = "celevator:fs1switch_off", ["celevator:fs1switch_reset_lit"] = "celevator:fs1switch_off_lit", } if offstates[node.name] then node.name = offstates[node.name] - minetest.swap_node(pos,node) + core.swap_node(pos,node) end end local function rightclick(pos,node,player) if not (player and player:is_player()) then return end - local meta = minetest.get_meta(pos) + local meta = core.get_meta(pos) if meta:get_string("formspec") ~= "" 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 a key for this switch.") - minetest.record_protection_violation(pos,name) + if core.is_protected(pos,name) and not core.check_player_privs(name,{protection_bypass=true}) then + core.chat_send_player(name,S("You don't have a key for this switch.")) + core.record_protection_violation(pos,name) return end if node.name == "celevator:fs1switch_off" then node.name = "celevator:fs1switch_on" - minetest.swap_node(pos,node) + core.swap_node(pos,node) elseif node.name == "celevator:fs1switch_on" then node.name = "celevator:fs1switch_reset" - minetest.swap_node(pos,node) - minetest.after(0.5,resetspring,pos) + core.swap_node(pos,node) + core.after(0.5,resetspring,pos) elseif node.name == "celevator:fs1switch_off_lit" or node.name == "celevator:fs1switch_on_lit" then node.name = "celevator:fs1switch_reset_lit" - minetest.swap_node(pos,node) - minetest.after(0.5,resetspring,pos) + core.swap_node(pos,node) + core.after(0.5,resetspring,pos) end 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))) + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) if not carinfo then return end local controllerpos = carinfo.controllerpos local dispatcher = false @@ -56,7 +58,7 @@ local function rightclick(pos,node,player) dispatcher = true end if not controllerpos then return end - local controllermeta = minetest.get_meta(controllerpos) + local controllermeta = core.get_meta(controllerpos) if controllermeta:get_int("carid") ~= carid then return end if node.name == "celevator:fs1switch_reset" or node.name == "celevator:fs1switch_reset_lit" then if dispatcher then @@ -87,32 +89,41 @@ function celevator.fs1switch.setled(pos,on) local node = celevator.get_node(pos) if on and onstates[node.name] then node.name = onstates[node.name] - minetest.swap_node(pos,node) + core.swap_node(pos,node) elseif (not on) and offstates[node.name] then node.name = offstates[node.name] - minetest.swap_node(pos,node) + core.swap_node(pos,node) end end local function unpair(pos) - local meta = minetest.get_meta(pos) + local meta = core.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))) + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) if not (carinfo and carinfo.fs1switches) then return end for i,fs1switch in pairs(carinfo.fs1switches) do if vector.equals(pos,fs1switch.pos) then table.remove(carinfo.fs1switches,i) - celevator.storage:set_string(string.format("car%d",carid),minetest.serialize(carinfo)) + celevator.storage:set_string(string.format("car%d",carid),core.serialize(carinfo)) end end end local switchstates = {"off","on","reset"} +local descriptions = { + off = S("Elevator Fire Service Phase 1 Keyswitch"), + on = S("Elevator Fire Service Phase 1 Keyswitch (on state - you hacker you!)"), + reset = S("Elevator Fire Service Phase 1 Keyswitch (reset state - you hacker you!)"), + offlit = S("Elevator Fire Service Phase 1 Keyswitch (lit - you hacker you!)"), + onlit = S("Elevator Fire Service Phase 1 Keyswitch (on state, lit - you hacker you!)"), + resetlit = S("Elevator Fire Service Phase 1 Keyswitch (reset state, lit - you hacker you!)"), +} + for _,switchpos in ipairs(switchstates) do - minetest.register_node("celevator:fs1switch_"..switchpos,{ - description = "Elevator Fire Service Phase 1 Keyswitch"..(switchpos == "off" and "" or string.format(" (%s state - you hacker you!)",switchpos)), + core.register_node("celevator:fs1switch_"..switchpos,{ + description = descriptions[switchpos], groups = { dig_immediate = 2, not_in_creative_inventory = (switchpos == "off" and 0 or 1), @@ -136,36 +147,36 @@ for _,switchpos in ipairs(switchstates) do fixed = nodebox, }, after_place_node = function(pos) - local meta = minetest.get_meta(pos) - meta:set_string("formspec","formspec_version[7]size[8,5]field[0.5,0.5;7,1;carid;Car ID;]button[3,3.5;2,1;save;Save]") + local meta = core.get_meta(pos) + meta:set_string("formspec","formspec_version[7]size[8,5]field[0.5,0.5;7,1;carid;"..S("Car ID")..";]button[3,3.5;2,1;save;"..S("Save").."]") end, on_receive_fields = function(pos,_,fields,player) local carid = tonumber(fields.carid or 0) if not (carid and carid >= 1 and carid == math.floor(carid)) then return end - local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid))) + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) if not carinfo then return end local controllerpos = carinfo.controllerpos or carinfo.dispatcherpos if not controllerpos then return end local name = player:get_player_name() - if minetest.is_protected(controllerpos,name) and not minetest.check_player_privs(name,{protection_bypass=true}) then + if core.is_protected(controllerpos,name) and not core.check_player_privs(name,{protection_bypass=true}) then if player:is_player() then - minetest.chat_send_player(name,"Can't connect to a controller/dispatcher you don't have access to.") - minetest.record_protection_violation(controllerpos,name) + core.chat_send_player(name,S("Can't connect to a controller/dispatcher you don't have access to.")) + core.record_protection_violation(controllerpos,name) end return end if not carinfo.fs1switches then carinfo.fs1switches = {} end table.insert(carinfo.fs1switches,{pos=pos}) - celevator.storage:set_string(string.format("car%d",carid),minetest.serialize(carinfo)) - local meta = minetest.get_meta(pos) + celevator.storage:set_string(string.format("car%d",carid),core.serialize(carinfo)) + local meta = core.get_meta(pos) meta:set_int("carid",carid) meta:set_string("formspec","") end, on_rightclick = rightclick, on_destruct = unpair, }) - minetest.register_node("celevator:fs1switch_"..switchpos.."_lit",{ - description = "Elevator Fire Service Phase 1 Keyswitch"..string.format(" (%s state, lit - you hacker you!)",switchpos), + core.register_node("celevator:fs1switch_"..switchpos.."_lit",{ + description = descriptions[switchpos.."lit"], groups = { dig_immediate = 2, not_in_creative_inventory = 1, diff --git a/genericswitch.lua b/genericswitch.lua index d52e9c9..71342f8 100644 --- a/genericswitch.lua +++ b/genericswitch.lua @@ -1,13 +1,15 @@ +local S = core.get_translator("celevator") + local inputoptions = { { id = "none", - desc = "(none)", + desc = S("(none)"), func_on = function() end, needsfloor = false, }, { id = "carcall", - desc = "Car Call at Landing:", + desc = S("Car Call at Landing:"), func_on = function(controllerpos,floor) celevator.controller.run(controllerpos,{ type = "remotemsg", @@ -19,7 +21,7 @@ local inputoptions = { }, { id = "upcall", - desc = "Up Call (simplex car) at Landing:", + desc = S("Up Call (simplex car) at Landing:"), func_on = function(controllerpos,floor) celevator.controller.run(controllerpos,{ type = "remotemsg", @@ -31,7 +33,7 @@ local inputoptions = { }, { id = "downcall", - desc = "Down Call (simplex car) at Landing:", + desc = S("Down Call (simplex car) at Landing:"), func_on = function(controllerpos,floor) celevator.controller.run(controllerpos,{ type = "remotemsg", @@ -43,7 +45,7 @@ local inputoptions = { }, { id = "swingupcall", - desc = "Up Call (swing) at Landing:", + desc = S("Up Call (swing) at Landing:"), func_on = function(controllerpos,floor) celevator.controller.run(controllerpos,{ type = "remotemsg", @@ -55,7 +57,7 @@ local inputoptions = { }, { id = "swingdowncall", - desc = "Down Call (swing) at Landing:", + desc = S("Down Call (swing) at Landing:"), func_on = function(controllerpos,floor) celevator.controller.run(controllerpos,{ type = "remotemsg", @@ -67,7 +69,7 @@ local inputoptions = { }, { id = "fs1off", - desc = "Deactivate Fire Service Phase 1", + desc = S("Deactivate Fire Service Phase 1"), func_on = function(controllerpos) celevator.controller.run(controllerpos,{ type = "fs1switch", @@ -78,7 +80,7 @@ local inputoptions = { }, { id = "fs1on", - desc = "Activate Fire Service (main landing) Phase 1", + desc = S("Activate Fire Service (main landing) Phase 1"), func_on = function(controllerpos) celevator.controller.run(controllerpos,{ type = "fs1switch", @@ -89,7 +91,7 @@ local inputoptions = { }, { id = "fs1onalt", - desc = "Activate Fire Service (alternate landing) Phase 1", + desc = S("Activate Fire Service (alternate landing) Phase 1"), func_on = function(controllerpos) celevator.controller.run(controllerpos,{ type = "fs1switch", @@ -101,7 +103,7 @@ local inputoptions = { }, { id = "mrsmoke", - desc = "Machine Room or Hoistway Smoke Detector", + desc = S("Machine Room or Hoistway Smoke Detector"), func_on = function(controllerpos) celevator.controller.run(controllerpos,{ type = "mrsmoke", @@ -111,7 +113,7 @@ local inputoptions = { }, { id = "secdeny", - desc = "Lock Car Calls at Landing:", + desc = S("Lock Car Calls at Landing:"), func_on = function(controllerpos,floor) celevator.controller.run(controllerpos,{ type = "remotemsg", @@ -126,7 +128,7 @@ local inputoptions = { }, { id = "secauth", - desc = "Require Auth for Car Calls at Landing:", + desc = S("Require Auth for Car Calls at Landing:"), func_on = function(controllerpos,floor) celevator.controller.run(controllerpos,{ type = "remotemsg", @@ -141,7 +143,7 @@ local inputoptions = { }, { id = "secallow", - desc = "Unlock Car Calls at Landing:", + desc = S("Unlock Car Calls at Landing:"), func_on = function(controllerpos,floor) celevator.controller.run(controllerpos,{ type = "remotemsg", @@ -154,18 +156,42 @@ local inputoptions = { end, needsfloor = true, }, + { + id = "swingon", + desc = S("Activate Swing Operation"), + func_on = function(controllerpos) + celevator.controller.run(controllerpos,{ + type = "remotemsg", + channel = "swing", + msg = true, + }) + end, + needsfloor = false, + }, + { + id = "swingoff", + desc = S("Deactivate Swing Operation"), + func_on = function(controllerpos) + celevator.controller.run(controllerpos,{ + type = "remotemsg", + channel = "swing", + msg = false, + }) + end, + needsfloor = false, + }, } local dinputoptions = { { id = "none", - desc = "(none)", + desc = S("(none)"), func_on = function() end, needsfloor = false, }, { id = "upcall", - desc = "Up Call at Landing:", + desc = S("Up Call at Landing:"), func_on = function(dispatcherpos,floor) celevator.dispatcher.run(dispatcherpos,{ type = "remotemsg", @@ -177,7 +203,7 @@ local dinputoptions = { }, { id = "downcall", - desc = "Down Call at Landing:", + desc = S("Down Call at Landing:"), func_on = function(dispatcherpos,floor) celevator.dispatcher.run(dispatcherpos,{ type = "remotemsg", @@ -189,7 +215,7 @@ local dinputoptions = { }, { id = "fs1off", - desc = "Deactivate Fire Service Phase 1", + desc = S("Deactivate Fire Service Phase 1"), func_on = function(dispatcherpos) celevator.dispatcher.run(dispatcherpos,{ type = "fs1switch", @@ -200,7 +226,7 @@ local dinputoptions = { }, { id = "fs1on", - desc = "Activate Fire Service Phase 1", + desc = S("Activate Fire Service Phase 1"), func_on = function(dispatcherpos) celevator.dispatcher.run(dispatcherpos,{ type = "fs1switch", @@ -212,46 +238,46 @@ local dinputoptions = { } local function updateinputform(pos) - local meta = minetest.get_meta(pos) + local meta = core.get_meta(pos) local dmode = meta:get_int("dispatcher") == 1 - local fs = "formspec_version[7]size[8,8.5]" - fs = fs.."tabheader[0,0;1;tab;Controller,Dispatcher;"..(dmode and "2" or "1")..";true;true]" - fs = fs.."vertlabel[0.33,1;ON]" - fs = fs.."dropdown[1,0.5;6,1;signal_on;" + local fs = "formspec_version[7]size[9,8.5]" + fs = fs.."tabheader[0,0;1;tab;"..S("Controller")..","..S("Dispatcher")..";"..(dmode and "2" or "1")..";true;true]" + fs = fs.."vertlabel[0.33,1;"..S("ON").."]" + fs = fs.."dropdown[1,0.5;7,1;signal_on;" local selected_on = 1 local currentid_on = meta:get_string("signal_on") for k,v in ipairs(dmode and dinputoptions or inputoptions) do - fs = fs..minetest.formspec_escape(v.desc).."," + fs = fs..core.formspec_escape(v.desc).."," if v.id == currentid_on then selected_on = k end end fs = string.sub(fs,1,-2) fs = fs..";"..selected_on..";false]" - fs = fs.."field[0.5,2;3,1;carid;"..(dmode and "Dispatcher ID" or "Car ID")..";${carid}]" - fs = fs.."field[4.5,2;3,1;floor_on;Landing Number;${floor_on}]" - fs = fs.."box[0,3.25;8,0.1;#CCCCCC]" - fs = fs.."vertlabel[0.33,4;OFF]" - fs = fs.."dropdown[1,3.5;6,1;signal_off;" + fs = fs.."field[0.5,2;3,1;carid;"..(dmode and S("Dispatcher ID") or S("Car ID"))..";${carid}]" + fs = fs.."field[4.5,2;3,1;floor_on;"..S("Landing Number")..";${floor_on}]" + fs = fs.."box[0,3.25;9,0.1;#CCCCCC]" + fs = fs.."vertlabel[0.33,4;"..S("OFF").."]" + fs = fs.."dropdown[1,3.5;7,1;signal_off;" local selected_off = 1 local currentid_off = meta:get_string("signal_off") for k,v in ipairs(dmode and dinputoptions or inputoptions) do - fs = fs..minetest.formspec_escape(v.desc).."," + fs = fs..core.formspec_escape(v.desc).."," if v.id == currentid_off then selected_off = k end end fs = string.sub(fs,1,-2) fs = fs..";"..selected_off..";false]" - fs = fs.."field[4.5,5;3,1;floor_off;Landing Number;${floor_off}]" - fs = fs.."label[1.5,6.5;Not all signal options require a landing number.]" - fs = fs.."button_exit[2.5,7;3,1;save;Save]" + fs = fs.."field[4.5,5;3,1;floor_off;"..S("Landing Number")..";${floor_off}]" + fs = fs.."label[1.5,6.5;"..S("Not all signal options require a landing number.").."]" + fs = fs.."button_exit[2.5,7;3,1;save;"..S("Save").."]" meta:set_string("formspec",fs) end local function handleinputfields(pos,_,fields,player) if fields.quit and not fields.save then return end - local meta = minetest.get_meta(pos) + local meta = core.get_meta(pos) local name = player:get_player_name() - if minetest.is_protected(pos,name) and not minetest.check_player_privs(name,{protection_bypass=true}) then + if core.is_protected(pos,name) and not core.check_player_privs(name,{protection_bypass=true}) then if player:is_player() then - minetest.record_protection_violation(pos,name) + core.record_protection_violation(pos,name) end return end @@ -260,24 +286,24 @@ local function handleinputfields(pos,_,fields,player) if not tonumber(fields.carid) then return end meta:set_int("carid",fields.carid) local carid = tonumber(fields.carid) - local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid))) or {} + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) or {} if dmode then if not carinfo.dispatcherpos then return end if not celevator.dispatcher.isdispatcher(carinfo.dispatcherpos) then return end - if minetest.is_protected(carinfo.dispatcherpos,name) and not minetest.check_player_privs(name,{protection_bypass=true}) then + if core.is_protected(carinfo.dispatcherpos,name) and not core.check_player_privs(name,{protection_bypass=true}) then if player:is_player() then - minetest.chat_send_player(name,"Can't connect to a dispatcher you don't have access to.") - minetest.record_protection_violation(carinfo.dispatcherpos,name) + core.chat_send_player(name,S("Can't connect to a dispatcher you don't have access to.")) + core.record_protection_violation(carinfo.dispatcherpos,name) end return end else if not carinfo.controllerpos then return end if not celevator.controller.iscontroller(carinfo.controllerpos) then return end - if minetest.is_protected(carinfo.controllerpos,name) and not minetest.check_player_privs(name,{protection_bypass=true}) then + if core.is_protected(carinfo.controllerpos,name) and not core.check_player_privs(name,{protection_bypass=true}) then if player:is_player() then - minetest.chat_send_player(name,"Can't connect to a controller you don't have access to.") - minetest.record_protection_violation(carinfo.controllerpos,name) + core.chat_send_player(name,S("Can't connect to a controller you don't have access to.")) + core.record_protection_violation(carinfo.controllerpos,name) end return end @@ -305,22 +331,22 @@ local function handleinputfields(pos,_,fields,player) meta:set_string("signal_on",def_on.id) meta:set_string("signal_off",def_off.id) updateinputform(pos) - local infotext = carid.." - "..def_on.desc..(def_on.needsfloor and " "..floor_on or "") + local infotext = " - "..def_on.desc..(def_on.needsfloor and " "..floor_on or "") if def_on.id == "none" or def_off.id ~= "none" then infotext = infotext.." / "..def_off.desc..(def_off.needsfloor and " "..floor_off or "") end if dmode then - infotext = "Dispatcher: "..infotext + infotext = S("Dispatcher: @1",carid)..infotext else - infotext = "Car: "..infotext + infotext = S("Car: @1",carid)..infotext end meta:set_string("infotext",infotext) if def_on.id ~= "none" or def_off.id ~= "none" then meta:set_string("formspec","") local momentary = def_off.id == "none" - local node = minetest.get_node(pos) + local node = core.get_node(pos) node.name = (momentary and "celevator:genericswitch_momentary_off" or "celevator:genericswitch_maintained_off") - minetest.swap_node(pos,node) + core.swap_node(pos,node) end elseif fields.tab then meta:set_int("dispatcher",tonumber(fields.tab)-1) @@ -329,10 +355,10 @@ local function handleinputfields(pos,_,fields,player) end local function handleinput(pos,on) - local meta = minetest.get_meta(pos) + local meta = core.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))) or {} + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) or {} local dmode = meta:get_int("dispatcher") == 1 if dmode then if not carinfo.dispatcherpos then return end @@ -358,8 +384,8 @@ local function handleinput(pos,on) end end -minetest.register_node("celevator:genericswitch",{ - description = "Elevator Keyswitch", +core.register_node("celevator:genericswitch",{ + description = S("Elevator Keyswitch"), tiles = { "celevator_cabinet_sides.png", "celevator_cabinet_sides.png", @@ -381,15 +407,15 @@ minetest.register_node("celevator:genericswitch",{ }, }, after_place_node = function(pos) - local meta = minetest.get_meta(pos) + local meta = core.get_meta(pos) meta:set_int("floor",1) updateinputform(pos) end, on_receive_fields = handleinputfields, }) -minetest.register_node("celevator:genericswitch_maintained_off",{ - description = "Elevator Keyswitch (maintained, off state - you hacker you!)", +core.register_node("celevator:genericswitch_maintained_off",{ + description = S("Elevator Keyswitch (maintained, off state - you hacker you!)"), tiles = { "celevator_cabinet_sides.png", "celevator_cabinet_sides.png", @@ -414,19 +440,19 @@ minetest.register_node("celevator:genericswitch_maintained_off",{ }, on_rightclick = function(pos,node,player) 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 a key for this switch.") - minetest.record_protection_violation(pos,name) + if core.is_protected(pos,name) and not core.check_player_privs(name,{protection_bypass=true}) then + core.chat_send_player(name,S("You don't have a key for this switch.")) + core.record_protection_violation(pos,name) return end node.name = "celevator:genericswitch_maintained_on" - minetest.swap_node(pos,node) + core.swap_node(pos,node) handleinput(pos,true) end, }) -minetest.register_node("celevator:genericswitch_maintained_on",{ - description = "Elevator Keyswitch (maintained, on state - you hacker you!)", +core.register_node("celevator:genericswitch_maintained_on",{ + description = S("Elevator Keyswitch (maintained, on state - you hacker you!)"), tiles = { "celevator_cabinet_sides.png", "celevator_cabinet_sides.png", @@ -451,19 +477,19 @@ minetest.register_node("celevator:genericswitch_maintained_on",{ }, on_rightclick = function(pos,node,player) 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 a key for this switch.") - minetest.record_protection_violation(pos,name) + if core.is_protected(pos,name) and not core.check_player_privs(name,{protection_bypass=true}) then + core.chat_send_player(name,S("You don't have a key for this switch.")) + core.record_protection_violation(pos,name) return end node.name = "celevator:genericswitch_maintained_off" - minetest.swap_node(pos,node) + core.swap_node(pos,node) handleinput(pos,false) end, }) -minetest.register_node("celevator:genericswitch_momentary_off",{ - description = "Elevator Keyswitch (momentary, off state - you hacker you!)", +core.register_node("celevator:genericswitch_momentary_off",{ + description = S("Elevator Keyswitch (momentary, off state - you hacker you!)"), tiles = { "celevator_cabinet_sides.png", "celevator_cabinet_sides.png", @@ -488,26 +514,26 @@ minetest.register_node("celevator:genericswitch_momentary_off",{ }, on_rightclick = function(pos,node,player) 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 a key for this switch.") - minetest.record_protection_violation(pos,name) + if core.is_protected(pos,name) and not core.check_player_privs(name,{protection_bypass=true}) then + core.chat_send_player(name,S("You don't have a key for this switch.")) + core.record_protection_violation(pos,name) return end node.name = "celevator:genericswitch_momentary_on" - minetest.swap_node(pos,node) + core.swap_node(pos,node) handleinput(pos,true) - minetest.after(1,function() - local newnode = minetest.get_node(pos) + core.after(1,function() + local newnode = core.get_node(pos) if newnode.name == "celevator:genericswitch_momentary_on" then newnode.name = "celevator:genericswitch_momentary_off" - minetest.swap_node(pos,newnode) + core.swap_node(pos,newnode) end end) end, }) -minetest.register_node("celevator:genericswitch_momentary_on",{ - description = "Elevator Keyswitch (momentary, on state - you hacker you!)", +core.register_node("celevator:genericswitch_momentary_on",{ + description = S("Elevator Keyswitch (momentary, on state - you hacker you!)"), tiles = { "celevator_cabinet_sides.png", "celevator_cabinet_sides.png", diff --git a/governor.lua b/governor.lua new file mode 100644 index 0000000..d4e9da6 --- /dev/null +++ b/governor.lua @@ -0,0 +1,137 @@ +local S = core.get_translator("celevator") + +local function spawngovsheave(pos) + local entitiesnearby = core.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 = core.add_entity(pos,"celevator:governor_sheave") + local fdir = core.fourdir_to_dir(core.get_node(pos).param2) + local yaw = core.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 + +core.register_node("celevator:governor",{ + description = S("Elevator Governor"), + groups = { + cracky = 3, + oddly_breakable_by_hand = 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) + core.get_meta(pos):set_string("formspec","field[carid;"..S("Car ID")..";]") + spawngovsheave(pos) + end, + after_dig_node = function(pos) + local entitiesnearby = core.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 = core.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 = core.get_meta(pos) + meta:set_string("controllerpos",core.pos_to_string(carinfo.controllerpos)) + meta:set_string("formspec","") + end, +}) + +core.register_node("celevator:governor_sheave",{ + description = S("Governor Sheave (you hacker you!)"), + groups = { + cracky = 3, + oddly_breakable_by_hand = 1, + 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 = {}, + }, +}) + +core.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()) + if not core.compare_block_status(governorpos,"active") then return self.object:remove() end + local governormeta = celevator.get_meta(governorpos) + local controllerpos = core.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, +}) + +core.register_lbm({ + name = "celevator:spawngovsheave", + label = "Spawn governor sheaves", + nodenames = {"celevator:governor"}, + run_at_every_load = true, + action = spawngovsheave, +}) @@ -1,7 +1,16 @@ local components = { "framework", "car", + "car_standard", + "car_glassback", + "car_metal", + "car_metalglass", + "car_fullglass", "doors", + "door_2speedglass", + "door_2speedmetal", + "door_centerglass", + "door_centermetal", "drive_null", "drive_entity", "controller", @@ -12,19 +21,22 @@ local components = { "dbdkiosk", "genericswitch", "decorations", + "governor", "crafts", + "chatcommands", } local integrations = { "laptop", "mesecons", "digilines", + "digistuff", } for _,i in ipairs(integrations) do - if minetest.get_modpath(i) then table.insert(components,i) end + if core.get_modpath(i) then table.insert(components,i) end end for _,v in ipairs(components) do - dofile(string.format("%s%s%s.lua",minetest.get_modpath("celevator"),DIR_DELIM,v)) + dofile(string.format("%s/%s.lua",core.get_modpath("celevator"),v)) end @@ -1,11 +1,13 @@ +local S = core.get_translator("celevator") + laptop.register_app("celevator",{ app_name = "mView", - app_info = "Remote interface for MTronic XT elevator controllers", + app_info = S("Remote interface for MTronic XT elevator controllers"), app_icon = "celevator_laptop_icon.png", formspec_func = function(_,mtos) local ram = mtos.bdev:get_app_storage("ram","celevator") local mem = mtos.bdev:get_app_storage("hdd","celevator") - if not mem then return mtos.theme:get_label("0.5,0.5","This application requires a hard disk drive.") end + if not mem then return mtos.theme:get_label("0.5,0.5",S("This application requires a hard disk drive.")) end if not mem.connections then mem.connections = {} end if not ram.screenstate then ram.screenstate = (#mem.connections > 0 and "connections" or "welcome") end if not mem.selectedconnection then mem.selectedconnection = 1 end @@ -16,73 +18,77 @@ laptop.register_app("celevator",{ if ram.screenstate == "welcome" then fs = fs.."background9[5.5,1;4,2;celevator_fs_bg.png;false;3]" fs = fs.."image[5.75,1;4,2;celevator_logo.png]" - fs = fs..mtos.theme:get_label("2,4","Welcome to the mView remote interface for MTronic XT elevator controllers!") - fs = fs..mtos.theme:get_label("2,6","Add a connection to get started.") - fs = fs..mtos.theme:get_button("5.5,7;4,1","major","connections","Add/Edit Connections") + fs = fs..mtos.theme:get_label("2,4",S("Welcome to the mView remote interface for MTronic XT elevator controllers!")) + fs = fs..mtos.theme:get_label("2,6",S("Add a connection to get started.")) + fs = fs..mtos.theme:get_button("5.5,7;4,1","major","connections",S("Add/Edit Connections")) elseif ram.screenstate == "connections" then - fs = fs..mtos.theme:get_label("0.5,0.5","MANAGE CONNECTIONS") + fs = fs..mtos.theme:get_label("0.5,0.5",S("MANAGE CONNECTIONS")) if #mem.connections > 0 then fs = fs.."textlist[1,2;6,7;connection;" for i=#mem.connections,1,-1 do - local text = string.format("ID %d - %s",mem.connections[i].carid,mem.connections[i].name) - fs = fs..minetest.formspec_escape(text) + local text = S("ID @1 - @2",mem.connections[i].carid,mem.connections[i].name) + fs = fs..core.formspec_escape(text) fs = fs..(i==1 and "" or ",") end fs = fs..";"..tostring(#mem.connections-mem.selectedconnection+1)..";false]" else - fs = fs..mtos.theme:get_label("1,2","No Connections") + fs = fs..mtos.theme:get_label("1,2",S("No Connections")) end - fs = fs..mtos.theme:get_button("8,2;3,1","major","new","New Connection") + fs = fs..mtos.theme:get_button("8,2;3,1","major","new",S("New Connection")) if mem.connections[mem.selectedconnection] then - fs = fs..mtos.theme:get_button("8,3;3,1","major","edit","Edit Connection") - fs = fs..mtos.theme:get_button("8,4;3,1","major","delete","Delete Connection") - fs = fs..mtos.theme:get_button("8,7;3,1","major","connect","Connect >") - if #mem.connections > mem.selectedconnection then fs = fs..mtos.theme:get_button("8,5;3,1","major","moveup","Move Up") end - if mem.selectedconnection > 1 then fs = fs..mtos.theme:get_button("8,6;3,1","major","movedown","Move Down") end + fs = fs..mtos.theme:get_button("8,3;3,1","major","edit",S("Edit Connection")) + fs = fs..mtos.theme:get_button("8,4;3,1","major","delete",S("Delete Connection")) + fs = fs..mtos.theme:get_button("8,7;3,1","major","connect",S("Connect >")) + if #mem.connections > mem.selectedconnection then fs = fs..mtos.theme:get_button("8,5;3,1","major","moveup",S("Move Up")) end + if mem.selectedconnection > 1 then fs = fs..mtos.theme:get_button("8,6;3,1","major","movedown",S("Move Down")) end end elseif ram.screenstate == "newconnection" then - fs = fs..mtos.theme:get_label("0.5,0.5","NEW CONNECTION") - fs = fs..mtos.theme:get_label("0.5,1","Please enter the ID you would like to connect to and a name for the connection.") - fs = fs..mtos.theme:get_label("0.7,1.8","ID") - fs = fs..mtos.theme:get_label("3.7,1.8","Name") - fs = fs..string.format("field[1,2.5;2,1;carid;;%s]",minetest.formspec_escape(mem.newconnection.carid)) - fs = fs..string.format("field[4,2.5;4,1;name;;%s]",minetest.formspec_escape(mem.newconnection.name)) - fs = fs..mtos.theme:get_button("3,4;3,1","major","save","Save") - fs = fs..mtos.theme:get_button("3,5.5;3,1","major","cancel","Cancel") + fs = fs..mtos.theme:get_label("0.5,0.5",S("NEW CONNECTION")) + fs = fs..mtos.theme:get_label("0.5,1",S("Please enter the ID you would like to connect to and a name for the connection.")) + fs = fs..mtos.theme:get_label("0.7,1.8",S("ID")) + fs = fs..mtos.theme:get_label("3.7,1.8",S("Name")) + fs = fs..string.format("field[1,2.5;2,1;carid;;%s]",core.formspec_escape(mem.newconnection.carid)) + fs = fs..string.format("field[4,2.5;4,1;name;;%s]",core.formspec_escape(mem.newconnection.name)) + fs = fs..mtos.theme:get_button("3,4;3,1","major","save",S("Save")) + fs = fs..mtos.theme:get_button("3,5.5;3,1","major","cancel",S("Cancel")) elseif ram.screenstate == "editconnection" then - fs = fs..mtos.theme:get_label("0.5,0.5","EDIT CONNECTION") - fs = fs..mtos.theme:get_label("0.7,1.8","ID: "..mem.connections[mem.selectedconnection].carid) - fs = fs..mtos.theme:get_label("3.7,1.8","Name") - fs = fs..string.format("field[4,2.5;4,1;name;;%s]",minetest.formspec_escape(mem.connections[mem.selectedconnection].name)) - fs = fs..mtos.theme:get_button("3,4;3,1","major","save","Save") - fs = fs..mtos.theme:get_button("3,5.5;3,1","major","cancel","Cancel") + fs = fs..mtos.theme:get_label("0.5,0.5",S("EDIT CONNECTION")) + fs = fs..mtos.theme:get_label("0.7,1.8",S("ID: @1",mem.connections[mem.selectedconnection].carid)) + fs = fs..mtos.theme:get_label("3.7,1.8",S("Name")) + fs = fs..string.format("field[4,2.5;4,1;name;;%s]",core.formspec_escape(mem.connections[mem.selectedconnection].name)) + fs = fs..mtos.theme:get_button("3,4;3,1","major","save",S("Save")) + fs = fs..mtos.theme:get_button("3,5.5;3,1","major","cancel",S("Cancel")) elseif ram.screenstate == "notfound" then - fs = fs..mtos.theme:get_label("0.5,0.5","Error") - 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") + fs = fs..mtos.theme:get_label("0.5,0.5",S("Error")) + fs = fs..mtos.theme:get_label("0.5,1",S("Could not find a controller or dispatcher with the given ID.")) + fs = fs..mtos.theme:get_label("0.5,1.3",S("Please check the ID number and try again.")) + fs = fs..mtos.theme:get_button("0.5,3;2,1","major","ok",S("OK")) + elseif ram.screenstate == "protected" then + fs = fs..mtos.theme:get_label("0.5,0.5",S("Error")) + fs = fs..mtos.theme:get_label("0.5,1",S("Controller or dispatcher is protected.")) + fs = fs..mtos.theme:get_button("0.5,3;2,1","major","ok",S("OK")) elseif ram.screenstate == "dispatcherstatus" then local connection = mem.connections[mem.selectedconnection] local pos = connection.pos if celevator.dispatcher.isdispatcher(pos) then - local meta = minetest.get_meta(pos) - local dmem = minetest.deserialize(meta:get_string("mem")) + local meta = core.get_meta(pos) + local dmem = core.deserialize(meta:get_string("mem")) if not dmem then return end fs = fs.."background9[-0.1,0.4;15.2,10.05;celevator_fs_bg.png;false;3]" - fs = fs.."label[0.5,0.5;"..string.format("Connected to %s (ID %d)",connection.name,connection.carid).."]" - fs = fs.."button[1,1;2,1;disconnect;Disconnect]" + fs = fs.."label[0.5,0.5;"..S("Connected to @1 (ID @2)",connection.name,connection.carid).."]" + fs = fs.."button[1,1;2,1;disconnect;"..S("Disconnect").."]" fs = fs.."box[0.5,1;0.1,9;#AAAAAAFF]" fs = fs.."box[14.25,1;0.1,9;#AAAAAAFF]" fs = fs.."style_type[label;font_size=*0.75]" - fs = fs.."label[0.05,10;UP]" - fs = fs.."label[14.35,10;DOWN]" + fs = fs.."image[0.15,9.8;0.2,0.4;celevator_menu_small_arrow.png]" + fs = fs.."image[14.55,9.8;0.2,0.4;celevator_menu_small_arrow.png^[transformFY]" fs = fs.."style_type[image_button;font=mono;font_size=*0.66]" for car=1,#dmem.params.carids,1 do local xp = (car-1)*0.75+1 local carid = dmem.params.carids[car] local carstate = dmem.carstatus[carid].state - fs = fs..string.format("label[%f,9.8;CAR %d]",xp,car) - fs = fs..string.format("label[%f,10;%s]",xp+0.1,minetest.colorize("#ff5555",(carstate == "normal" and " IN" or "OUT"))) + fs = fs..string.format("label[%f,9.8;%s]",xp,S("CAR @1",car)) + fs = fs..string.format("label[%f,10;%s]",xp+0.1,core.colorize("#ff5555",(carstate == "normal" and S(" IN") or S("OUT")))) end local lowestfloor = (mem.screenpage-1)*10+1 local maxfloor = #dmem.params.floornames @@ -138,11 +144,11 @@ laptop.register_app("celevator",{ local floor = i+lowestfloor-1 fs = fs..string.format("label[0.62,%f;%s]",yp+0.05,dmem.params.floornames[floor]) local uplabel = "" - if dmem.upcalls[floor] then uplabel = minetest.colorize("#55FF55",math.floor(dmem.upeta[floor] or 0)) end + if dmem.upcalls[floor] then uplabel = core.colorize("#55FF55",math.floor(dmem.upeta[floor] or 0)) end if floor < #dmem.params.floornames then fs = fs..string.format("image_button[0,%f;0.66,0.66;celevator_fs_bg.png;upcall%d;%s]",yp,floor,uplabel) end fs = fs..string.format("label[14,%f;%s]",yp+0.05,dmem.params.floornames[floor]) local dnlabel = "" - if dmem.dncalls[floor] then dnlabel = minetest.colorize("#FF5555",math.floor(dmem.dneta[floor] or 0)) end + if dmem.dncalls[floor] then dnlabel = core.colorize("#FF5555",math.floor(dmem.dneta[floor] or 0)) end if floor > 1 then fs = fs..string.format("image_button[14.4,%f;0.66,0.66;celevator_fs_bg.png;dncall%d;%s]",yp,floor,dnlabel) end for car=1,#dmem.params.carids,1 do local xp = (car-1)*0.75+1 @@ -150,10 +156,10 @@ laptop.register_app("celevator",{ local carfloor = realtocarfloor(carid,floor) if carfloor then local ccdot = dmem.carstatus[carid].carcalls[carfloor] and "*" or "" - local groupup = dmem.carstatus[carid].groupupcalls[carfloor] and minetest.colorize("#55FF55","^") or "" - local swingup = dmem.carstatus[carid].swingupcalls[carfloor] and minetest.colorize("#FFFF55","^") or "" - local swingdn = dmem.carstatus[carid].swingdncalls[carfloor] and minetest.colorize("#FFFF55","v") or "" - local groupdn = dmem.carstatus[carid].groupdncalls[carfloor] and minetest.colorize("#FF5555","v") or "" + local groupup = dmem.carstatus[carid].groupupcalls[carfloor] and core.colorize("#55FF55","^") or "" + local swingup = dmem.carstatus[carid].swingupcalls[carfloor] and core.colorize("#FFFF55","^") or "" + local swingdn = dmem.carstatus[carid].swingdncalls[carfloor] and core.colorize("#FFFF55","v") or "" + local groupdn = dmem.carstatus[carid].groupdncalls[carfloor] and core.colorize("#FF5555","v") or "" ccdot = groupup..swingup..ccdot..swingdn..groupdn if getpos(carid) == floor then local cargraphics = { @@ -165,9 +171,9 @@ laptop.register_app("celevator",{ } ccdot = cargraphics[dmem.carstatus[carid].doorstate] if dmem.carstatus[carid].direction == "up" then - ccdot = minetest.colorize("#55FF55",ccdot) + ccdot = core.colorize("#55FF55",ccdot) elseif dmem.carstatus[carid].direction == "down" then - ccdot = minetest.colorize("#FF5555",ccdot) + ccdot = core.colorize("#FF5555",ccdot) end end fs = fs..string.format("image_button[%f,%f;0.66,0.66;celevator_fs_bg.png;carcall%02d%d;%s]",xp,yp,car,floor,ccdot) @@ -182,32 +188,33 @@ laptop.register_app("celevator",{ local connection = mem.connections[mem.selectedconnection] local pos = connection.pos if celevator.controller.iscontroller(pos) then - local meta = minetest.get_meta(pos) - local cmem = minetest.deserialize(meta:get_string("mem")) + local meta = core.get_meta(pos) + local cmem = core.deserialize(meta:get_string("mem")) if not cmem then return end local modenames = { - normal = "Normal Operation", - uninit = "Uninitialized", - resync = "Position Sync - Floor", - bfdemand = "Position Sync - Terminal", - fault = "Fault", - stop = "Emergency Stop", - mrinspect = "Machine Room Inspection", - carinspect = "Car Top Inspection", - inspconflict = "Inspection Conflict", - fs1 = "Fire Service - Phase 1", - fs2 = "Fire Service - Phase 2", - fs2hold = "Fire Service - Phase 2 Hold", - indep = "Independent Service", - capture = "Captured", - test = "Test Mode", + normal = S("Normal Operation"), + uninit = S("Uninitialized"), + resync = S("Position Sync - Floor"), + bfdemand = S("Position Sync - Terminal"), + fault = S("Fault"), + stop = S("Emergency Stop"), + mrinspect = S("Machine Room Inspection"), + carinspect = S("Car Top Inspection"), + inspconflict = "Inspection Conflict", -- No longer used + fs1 = S("Fire Service - Phase 1"), + fs2 = S("Fire Service - Phase 2"), + fs2hold = S("Fire Service - Phase 2 Hold"), + indep = S("Independent Service"), + capture = S("Captured"), + test = S("Test Mode"), + swing = S("Swing Operation"), } local doorstates = { - open = "Open", - opening = "Opening", - closing = "Closing", - closed = "Closed", - testtiming = "Closed", + open = S("Doors Open"), + opening = S("Doors Opening"), + closing = S("Doors Closing"), + closed = S("Doors Closed"), + testtiming = S("Doors Closed"), } local carpos = 0 local carfloor = 0 @@ -219,15 +226,18 @@ laptop.register_app("celevator",{ break end end - fs = fs..mtos.theme:get_label("1,1",string.format("Connected to %s (ID %d)",connection.name,connection.carid)) + fs = fs..mtos.theme:get_label("1,1",S("Connected to @1 (ID @2)",connection.name,connection.carid)) fs = fs..mtos.theme:get_label("1,2",modenames[cmem.carstate]) - fs = fs..mtos.theme:get_label("1,2.5",string.format("Doors %s",doorstates[cmem.doorstate])) - local pi = minetest.formspec_escape(cmem.params.floornames[carfloor]) - fs = fs..mtos.theme:get_label("1,3",string.format("Position: %0.02fm Speed: %+0.02fm/s PI: %s",cmem.drive.status.apos,cmem.drive.status.vel,pi)) + fs = fs..mtos.theme:get_label("1,2.5",doorstates[cmem.doorstate]) + local pi = core.formspec_escape(cmem.params.floornames[carfloor]) + local posfmt = string.format("%0.02f",cmem.drive.status.apos) + local speedfmt = string.format("%+0.02f",cmem.drive.status.vel) + local posmsg = S("Position: @1m Speed: @2m/s PI: @3",posfmt,speedfmt,pi) + fs = fs..mtos.theme:get_label("1,3",posmsg) if #cmem.faultlog > 0 then - fs = fs..mtos.theme:get_label("1,3.5","Fault(s) Active") + fs = fs..mtos.theme:get_label("1,3.5",S("Fault(s) Active")) else - fs = fs..mtos.theme:get_label("1,3.5","No Current Faults") + fs = fs..mtos.theme:get_label("1,3.5",S("No Current Faults")) end fs = fs.."background9[8,0.3;6.2,10;celevator_fs_bg.png;false;3]" fs = fs.."style_type[image_button;font=mono;font_size=*0.75]" @@ -235,14 +245,14 @@ laptop.register_app("celevator",{ fs = fs.."box[11.808,0.75;0.05,9;#AAAAAAFF]" fs = fs.."box[12.708,0.75;0.05,9;#AAAAAAFF]" fs = fs.."box[13.725,0.75;0.1,9;#AAAAAAFF]" - fs = fs.."label[11.25,0.3;UP]" - fs = fs.."label[12.042,0.3;CAR]" - fs = fs.."label[12.825,0.3;DOWN]" + fs = fs.."image[11.2,0.3;0.2,0.4;celevator_menu_small_arrow.png]" + fs = fs.."label[12.042,0.3;"..S("CAR").."]" + fs = fs.."image[13.1,0.3;0.2,0.4;celevator_menu_small_arrow.png^[transformFY]" if mem.scrollfollowscar then mem.screenpage = math.floor((carfloor-1)/10)+1 end local maxfloor = #cmem.params.floornames local bottom = (mem.screenpage-1)*10+1 if maxfloor > 10 then - fs = fs..string.format("checkbox[8.4,1.5;scrollfollowscar;Follow Car;%s]",tostring(mem.scrollfollowscar)) + fs = fs..string.format("checkbox[8.4,1.7;scrollfollowscar;"..S("Follow Car")..";%s]",tostring(mem.scrollfollowscar)) if bottom+9 < maxfloor then fs = fs.."image_button[8.5,1;0.75,0.75;celevator_menu_arrow.png;scrollup;;false;false;celevator_menu_arrow.png]" end @@ -254,7 +264,7 @@ laptop.register_app("celevator",{ local ypos = (11-(i*0.9))*0.9-0.75 local floornum = bottom+i if floornum > maxfloor then break end - fs = fs..string.format("label[10.125,%f;%s]",ypos-0.2,minetest.formspec_escape(cmem.params.floornames[floornum])) + fs = fs..string.format("label[10.125,%f;%s]",ypos-0.2,core.formspec_escape(cmem.params.floornames[floornum])) local ccdot = cmem.carcalls[floornum] and "*" or "" if carfloor == floornum then local cargraphics = { @@ -266,25 +276,25 @@ laptop.register_app("celevator",{ } ccdot = cargraphics[cmem.doorstate] if cmem.direction == "up" then - ccdot = minetest.colorize("#55FF55",ccdot) + ccdot = core.colorize("#55FF55",ccdot) elseif cmem.direction == "down" then - ccdot = minetest.colorize("#FF5555",ccdot) + ccdot = core.colorize("#FF5555",ccdot) end end fs = fs..string.format("image_button[11.925,%f;0.75,0.75;celevator_fs_bg.png;carcall%d;%s]",ypos-0.25,floornum,ccdot) if floornum < maxfloor then - local arrow = cmem.upcalls[floornum] and minetest.colorize("#55FF55","^") or "" + local arrow = cmem.upcalls[floornum] and core.colorize("#55FF55","^") or "" if cmem.params.groupmode == "group" then - arrow = cmem.groupupcalls[floornum] and minetest.colorize("#55FF55","^") or "" - arrow = (cmem.swingupcalls[floornum] and minetest.colorize("#FFFF55","^") or "")..arrow + arrow = cmem.groupupcalls[floornum] and core.colorize("#55FF55","^") or "" + arrow = (cmem.swingupcalls[floornum] and core.colorize("#FFFF55","^") or "")..arrow end fs = fs..string.format("image_button[11.025,%f;0.75,0.75;celevator_fs_bg.png;upcall%d;%s]",ypos-0.25,floornum,arrow) end if floornum > 1 then - local arrow = cmem.dncalls[floornum] and minetest.colorize("#FF5555","v") or "" + local arrow = cmem.dncalls[floornum] and core.colorize("#FF5555","v") or "" if cmem.params.groupmode == "group" then - arrow = cmem.swingdncalls[floornum] and minetest.colorize("#FFFF55","v") or "" - arrow = (cmem.groupdncalls[floornum] and minetest.colorize("#FF5555","v") or "")..arrow + arrow = cmem.swingdncalls[floornum] and core.colorize("#FFFF55","v") or "" + arrow = (cmem.groupdncalls[floornum] and core.colorize("#FF5555","v") or "")..arrow end fs = fs..string.format("image_button[12.825,%f;0.75,0.75;celevator_fs_bg.png;downcall%d;%s]",ypos-0.25,floornum,arrow) end @@ -292,7 +302,7 @@ laptop.register_app("celevator",{ else ram.screenstate = "notfound" end - fs = fs..mtos.theme:get_button("1,8;3,1","major","disconnect","Disconnect") + fs = fs..mtos.theme:get_button("1,8;3,1","major","disconnect",S("Disconnect")) end return fs end, @@ -305,7 +315,7 @@ laptop.register_app("celevator",{ ram.screenstate = "connections" end elseif ram.screenstate == "connections" then - local exp = fields.connection and minetest.explode_textlist_event(fields.connection) or {} + local exp = fields.connection and core.explode_textlist_event(fields.connection) or {} if fields.new then ram.screenstate = "newconnection" mem.newconnection.name = "Untitled" @@ -331,10 +341,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 core.is_protected(cpos,mtos.sysram.current_player) and not core.check_player_privs(mtos.sysram.current_player,{protection_bypass=true}) then + core.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 @@ -352,7 +368,7 @@ laptop.register_app("celevator",{ if fields.save then local carid = tonumber(fields.carid) if not (carid and math.floor(carid) == carid) then return end - local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid))) + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) if not carinfo then return end local pos = carinfo.controllerpos local itemtype @@ -365,6 +381,11 @@ laptop.register_app("celevator",{ ram.screenstate = "notfound" return end + if core.is_protected(pos,mtos.sysram.current_player) and not core.check_player_privs(mtos.sysram.current_player,{protection_bypass=true}) then + core.record_protection_violation(pos,mtos.sysram.current_player) + ram.screenstate = "protected" + return + end local connection = { name = fields.name, carid = carid, @@ -381,6 +402,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" @@ -388,8 +413,8 @@ laptop.register_app("celevator",{ end local pos = mem.connections[mem.selectedconnection].pos if celevator.dispatcher.isdispatcher(pos) then - local meta = minetest.get_meta(pos) - local dmem = minetest.deserialize(meta:get_string("mem")) + local meta = core.get_meta(pos) + local dmem = core.deserialize(meta:get_string("mem")) if not dmem then return end for k in pairs(fields) do if string.sub(k,1,7) == "carcall" then @@ -446,8 +471,8 @@ laptop.register_app("celevator",{ end local pos = mem.connections[mem.selectedconnection].pos if celevator.controller.iscontroller(pos) then - local meta = minetest.get_meta(pos) - local cmem = minetest.deserialize(meta:get_string("mem")) + local meta = core.get_meta(pos) + local cmem = core.deserialize(meta:get_string("mem")) if not cmem then return end local carcallacceptstates = { normal = true, diff --git a/locale/celevator.es.tr b/locale/celevator.es.tr new file mode 100644 index 0000000..17d002e --- /dev/null +++ b/locale/celevator.es.tr @@ -0,0 +1,377 @@ +# textdomain: celevator +Elevator Up Call Button=Botón de llamada de ascensor (subir) +Elevator Down Call Button=Botón de llamada de ascensor (bajar) +Elevator Up and Down Call Buttons=Botón de llamada de ascensor (subir y bajar) +Elevator Call Button (on state - you hacker you!)=Botón de llamada de ascensor (estado activado) +Error reading car information!@nPlease remove and replace this node.=¡Error al leer la información de la cabina!@nRetire y reemplace este bloque. +Controller/dispatcher is missing!@nPlease remove and replace this node.=¡El controlador/despachador no está presente!@nRetire y reemplace este bloque. +Controller/dispatcher found but with incorrect ID!@nPlease remove and replace this node.=¡El controlador/despachador tiene un número incorrecto!@nRetire y reemplace este bloque. +Car (part @1 - you hacker you!)=Cabina del ascensor (parte @1) +You don't have access to these switches.=No tienes acceso a estos interruptores. +Really remove this car?=¿De verdad quieres eliminar esta cabina? +Yes=Sí +No=No +Car-top Inspection Box, Off State (you hacker you!)=Controles de inspección en el techo de la cabina (estado desactivado) +Car-top Inspection Box, On State (you hacker you!)=Controles de inspección en el techo de la cabina (estado activado) +Full-Glass Elevator Car=Cabina del ascensor en todo vidrio +Glass-Back Elevator Car=Cabina del ascensor con parte trasera en vidrio +Metal Elevator Car=Cabina del ascensor en metal +Can't place car here - position @1m to the right, @2m up, and @3m back is blocked!=No se puede colocar la cabina aquí - hay una posición bloqueada @1 m a la derecha, @2 m hacia arriba, y @3 m hacia atrás +Can't place car here - position @1m to the right, @2m up, and @3m back is protected!=No se puede colocar la cabina aquí - hay una posición protegida @1 m a la derecha, @2 m hacia arriba, y @3 m hacia atrás +Metal Glass-Back Elevator Car=Cabina del ascensor en metal con parte trasera en vidrio +Basic Elevator Car=Cabina del ascensor básica +Places a car call at the specified landing on the specified elevator=Realiza una llamada de ascensor en la planta y ascensor especificados +<car ID> <landing number>=<número del ascensor> <número de planta> +Invalid car ID=Número de ascensor no válido +Invalid landing number=Número de planta no válido +No such car or car info is missing=El ascensor especificado o su información no existe +Controller is missing=El controlador no está presente +Controller found but with wrong ID=El controlador tiene un número incorrecto +Controller is protected=El controlador está protegido +Command sent=Comando enviado +Places an up hall call at the specified landing on the specified elevator or dispatcher=Realiza una llamada para subir a la planta y el ascensor/despachador especificados +Dispatcher is missing=El despachador no está presente +Dispatcher found but with wrong ID=El despachador tiene un número incorrecto +Dispatcher is protected=El despachador está protegido +Places a down hall call at the specified landing on the specified elevator or dispatcher=Realiza una llamada para bajar a la planta y el ascensor/despachador especificados +View the status of the specified elevator=Mostrar el estado del ascensor especificado +<car ID>=<número del ascensor> +Failed to load controller memory=Error al leer la memoria del controlador +Reload celevator controller firmware from disk=Recargar el firmware del controlador celevator +Elevator Controller=Controlador de ascensor +Controller (door open - you hacker you!)=Controlador (con puerta abierta) +Controller (top section - you hacker you!)=Controlador (mitad superior) +Controller (top section, car in motion - you hacker you!)=Controlador (mitad superior con cabina en movimiento) +Controller (top section, open - you hacker you!)=Controlador (mitad superior con puerta abierta) +Controller (top section, open, car in motion - you hacker you!)=Controlador (mitad superior con puerta abierta y cabina en movimiento) +Door Open Timeout=El tiempo para abrir las puertas ha expirado +Door Close Timeout=El tiempo para cerrar las puertas ha expirado +Lost Communication With Drive=Comunicación perdida con el inversor +Drive Not Configured=Inversor no inicializado +Drive Metadata Load Failure=Error al leer la memoria del inversor +Drive Origin Invalid=Error en posición de origen del inversor +Attempted to Move Doors With Car in Motion=Intentó abrir las puertas con la cabina en movimiento +Target Position Out of Bounds=Error en posición objetivo +Hoist Machine Missing=La máquina no está presente +Drive<->Machine ID Mismatch=Desajuste entre números de inversor <-> máquina +Controller<->Drive ID Mismatch=Desajuste entre números de controlador <-> inversor +Welcome to your new MTronic XT elevator controller!=¡Bienvenido a su nuevo controlador de ascensor MTronic XT! +This setup wizard is designed to get your elevator up and running as quickly as possible.=Este asistente de configuración está diseñado para poner en funcionamiento su ascensor lo más rápido posible. +This applies to the whole celevator mod, not just this controller:=Esto se aplica a todo el mod «celevator», no solo a este controlador: +Select a group operation mode:=Seleccione un modo de operación en grupo: +Simplex=Único ascensor +This will be the only elevator in the group. Hall calls will be handled by this controller.=Este será el único ascensor del grupo.@nLas llamadas desde los pisos serán gestionadas por este controlador. +Group=Grupo +This elevator will participate in a group with others. Hall calls will be handled by a dispatcher.=Este ascensor participará en un grupo con otros ascensores.@nLas llamadas desde las plantas serán gestionadas por un despachador. +Waiting for connection from dispatcher...=Esperando la conexión del despachador... +This controller's car ID is: @1=El número de este ascensor es: @1 +Enter details of all floors this elevator will serve, then press Done.=Ingrese los detalles de todas las plantas a las que dará servicio este ascensor y, a continuación, haga clic en «Listo». +CAR STATUS=ESTADO DE LA CABINA +Fault History=Historial de averías +Edit Parameters=Editar parámetros +FAULT=AVERÍA +INSP/ACCESS=INSP./ACCESO +NORMAL OPERATION=FUNCIONAMIENTO NORMAL +UP=SUBIENDO +DRIVE CMD=COMANDO AL INVERSOR +DOWN=BAJANDO +HIGH SPEED=ALTA VELOCIDAD +DOOR ZONE=ZONA DE PUERTA +DOORS LOCKED=PUERTAS BLOQUEADAS +RUN=MARCHA +STOP=PARADA +CAPTURE=CAPTURAR +TEST=PRUEBA +INSPECT=INSPECC. +NORMAL=NORMAL +UP =SUBIR +DOWN =BAJAR +EDIT PARAMETERS=EDITAR PARÁMETROS +Door Dwell Timer=Temporizador de puerta +Contract Speed (m/s)=Velocidad máx. (m/s) +Inspection Speed (m/s)=Velocidad inspecc. (m/s) +Main Egress Landing=Planta principal +Nudging Timer=Temporizador de empuje +Alternate Recall Landing=Planta alterna +Reset Doors=Restablecer puertas +Reset Controller=Restablecer controlador +Car Call Security=Seguridad de llamadas +FAULT HISTORY=HISTORIAL DE AVERÍAS +Clear=Borrar +CAR CALL SECURITY=SEGURIDAD DE LLAMADAS +Authorized Users Only=Solo usarios autorizados +Locked=Bloqueado +Security Disabled=Función de seguridad deshabilitada +Allow Swing Calls When Not In Swing Operation=Permitir llamadas separadas aun cuando esté en modo grupo +Unlock in Independent=Desbloqear en modo de servicio independiente +Extra Allowed Users=Usuarios adicionales permitidos +Hide Button=Ocultar el botón +Also Hide in Fire/Independent Service=También en modos de incendio/servicio independiente +Main landing cannot be locked=La planta principal no se puede bloquear. +Suppress Beep Sound=Desactivar el sonido «bip» +ID @1: Floor @2 - @3 - @4=Número @1: Planta @2 - @3 - @4 +Call@nCancel=Cancelar +HOLD=MANTENIDO +FIRE SVC=INCENDIO +IND SVC=INDEPENDIENTE +CAR LIGHT=LUZ +CAR FAN=VENTILADOR +Normal Operation=Funcionamiento normal +Fault=Avería +Emergency Stop=Parada de emergencia +Independent Service=Modo de servicio independiente +Swing Operation=Modo separado +Doors Opening=Puertas abriéndose +Doors Open=Puertas abiertas +Doors Closing=Puertas cerrándose +Doors Closed=Puertas cerradas +Please select a floor:=Por favor, seleccione una planta: +Please use elevator=Por favor, use el ascensor +ERROR=ERROR +Could not find a suitable elevator=No se pudo encontrar un ascensor adecuado. +Please try again later=Por favor, inténtelo de nuevo más tarde. +Elevator Destination Entry Kiosk=Puesto de selección de destino del ascensor +Landing Number=Número de planta +Elevator Elastomeric Buffer=Amortiguador elástico para ascensor +Elevator Oil-Filled Buffer=Amortiguador hidráulico para ascensor +Elevator Oil-Filled Buffer (top half - you hacker you!)=Amortiguador hidráulico para ascensor (mitad superior) +Elevator Guide Rail=Carril guía de ascensor +Elevator Guide Rail with Bracket=Carril guía con soporte de ascensor +Elevator Positioning System Tape=Cinta del sistema de posicionamiento de ascensor +Elevator Positioning System Tape with Magnets=Cinta con imanes del sistema de posicionamiento de ascensor +Elevator Positioning System Tape with Bracket=Cinta con soporte del sistema de posicionamiento de ascensor +Elevator Positioning System Tapehead (off, you hacker you!)=Lector de cinta del sistema de posicionamiento de ascensor (desactivado) +Elevator Positioning System Tapehead (ULM on, you hacker you!)=Lector de cinta del sistema de posicionamiento de ascensor (señal ULM activado) +Elevator Positioning System Tapehead (ULM and DZ on, you hacker you!)=Lector de cinta del sistema de posicionamiento de ascensor (señales ULM y DZ activado) +Elevator Positioning System Tapehead (ULM, DLM, and DZ on, you hacker you!)=Lector de cinta del sistema de posicionamiento de ascensor (señales ULM, DLM, y DZ activado) +Elevator Positioning System Tapehead (DLM and DZ on, you hacker you!)=Lector de cinta del sistema de posicionamiento de ascensor (señales DLM y DZ activado) +Elevator Positioning System Tapehead (DLM on, you hacker you!)=Lector de cinta del sistema de posicionamiento de ascensor (señal DLM activado) +Elevator Digilines Input/Output=Módulo de entrada/salida de Digilines para el ascensor +Channel=Canal +Elevator Digilines Multi-Car Input/Output=Módulo de entrada/salida de Digilines para múltiples ascensores +You need either the 'protection_bypass' or 'server' privilege to use this.=Necesitas el privilegio 'protection_bypass' o 'server' para poder usar esto. +Elevator Dispatcher=Despachador de ascensor +Dispatcher (door open - you hacker you!)=Despachador de ascensor (con puerta abierta) +Dispatcher (top section - you hacker you!)=Despachador de ascensor (mitad superior) +Dispatcher (top section, open - you hacker you!)=Despachador de ascensor (mitad superior con puerta abierta) +Firmware reloaded successfully=El firmware se recargó correctamente +Can't place cabinet - no room for the top half!=No se puede colocar el armario de control aquí - ¡no hay espacio para la mitad superior! +Can't place cabinet - top half is protected!=No se puede colocar el armario de control aquí - ¡el espacio para la mitad superior está protegido! +Hold the sneak button while digging to remove.=Mantén pulsado el botón de sigilo mientras cavas para eliminarlo. +Can't open cabinet - cabinet is locked.=No se puede abrir el armario - la puerta está cerrada con llave. +Welcome to your new MTronic XT elevator dispatcher!=¡Bienvenido a su nuevo despachador de ascensores MTronic XT! +Before continuing, make sure you have at least two controllers in group operation mode and ready to connect.=Antes de continuar, asegúrese de tener al menos dos controladores en modo de funcionamiento grupal y listos para conectarse. +This applies to the whole celevator mod, not just this dispatcher:=Esto se aplica a todo el mod «celevator», no solo a este despachador: +Enter details of all floors this group will serve, then press Next.=Ingrese los detalles de todas las plantas a las que dará servicio este grupo y, a continuación, haga clic en «Siguiente». +Include all floors served by any car in the group, even if not served by all cars.=Incluya todas las plantas a las que pueda acceder cualquiera de los ascensores del grupo, incluso si no todas las plantas son accesibles por todos los ascensores. +Connect to each car in the group, then click Done.=Conéctese a cada ascensor del grupo y luego haga clic en «Listo». +EDIT CONNECTIONS=EDITAR CONEXIONES +Car @1 - ID #@2=Ascensor @1 - Número @2 +Remove Connection=Eliminar conexión +Enter the car ID and select the floors served (click them to toggle), then click Connect.=Ingrese la identificación del ascensor y seleccione las plantas servidas (haga clic en ellas para cambiar sí/no), luego haga clic en «Conectar». +You must select at least two floors.=Debe seleccionar al menos dos plantas. +Connect=Conectar +YES=SÍ +NO=NO +Car ID: @1=Número del ascensor: @1 +Connecting to controller...=Conectando al controlador... +Connection timed out!=¡El tiempo de conexión ha expirado! +Make sure the car ID is correct and@nthat the controller is ready to connect.=Asegúrese de que el número del ascensor esté correcto@ny que el controlador esté listo para conectar +GROUP DISPLAY=ESTADO DEL GRUPO +Menu=Menú +MAIN MENU=MENÚ PRINCIPAL +Edit Connections=Editar conexiones +Press Next to begin.=Haz clic en «siguiente» para comenzar. +License Info=Información de la licencia +Next >=Siguiente > +< Back=< Atrás +Done=Listo +EDIT FLOOR TABLE=EDICIÓN DE LA TABLA DE PLANTAS +@1 - Height: @2 - PI: @3=@1 - Altura: @2 - Nombre: @3 +New Floor=Planta nueva +Edit Floor=Editar planta +Remove Floor=Eliminar planta +The Floor Height is the distance (in meters/nodes) from the floor level of this floor to the floor level of the next floor.=La altura de la planta es la distancia (en metros/nodos) desde el nivel del suelo de esta planta hasta el nivel del suelo de la planta siguiente. +(not used at the highest floor)=(No se utiliza en la planta más alta) +The Floor Name is how the floor will be displayed on the position indicators.=El nombre de la planta es la forma en que se mostrará la planta en los indicadores de posición. +Editing Floor @1=Editando la planta @1 +Floor Height=Altura de la planta +Floor Name=Nombre de la planta +Edit Floor Table=Tabla de plantas +Back=Atrás +No Connections=Nignuna conexión +New Connection=Conexión nueva +Edit Connection=Editar conexión +NEW CONNECTION=CONEXIÓN NUEVA +EDIT CONNECTION=EDITAR CONEXIÓN +CAR @1=ASC. @1 + IN= OK +OUT= -- +OK=OK +Move Up=Subir +Move Down=Bajar +ID: @1=Número: @1 +Glass Hoistway Door (fast, bottom - you hacker you!)=Puerta de ascensor en vidrio (alta velocidad, parte inferior) +Glass Hoistway Door (fast, middle - you hacker you!)=Puerta de ascensor en vidrio (alta velocidad, parte media) +Glass Hoistway Door (fast, top - you hacker you!)=Puerta de ascensor en vidrio (alta velocidad, parte superior) +Glass Hoistway Door (slow, bottom - you hacker you!)=Puerta de ascensor en vidrio (baja velocidad, parte inferior) +Glass Hoistway Door (slow, middle - you hacker you!)=Puerta de ascensor en vidrio (baja velocidad, parte media) +Glass Hoistway Door (slow, top - you hacker you!)=Puerta de ascensor en vidrio (baja velocidad, parte superior) +Glass Elevator Hoistway Door=Puerta de ascensor en vidrio +Steel Hoistway Door (fast, bottom - you hacker you!)=Puerta de ascensor en acero (alta velocidad, parte inferior) +Steel Hoistway Door (fast, middle - you hacker you!)=Puerta de ascensor en acero (alta velocidad, parte media) +Steel Hoistway Door (fast, top - you hacker you!)=Puerta de ascensor en acero (alta velocidad, parte superior) +Steel Hoistway Door (slow, bottom - you hacker you!)=Puerta de ascensor en acero (baja velocidad, parte inferior) +Steel Hoistway Door (slow, middle - you hacker you!)=Puerta de ascensor en acero (baja velocidad, parte media) +Steel Hoistway Door (slow, top - you hacker you!)=Puerta de ascensor en acero (baja velocidad, parte superior) +Steel Elevator Hoistway Door=Puerta de ascensor en acero +Can't place door here - position @1m to the right and @2m up is blocked!=No se puede colocar la puerta aquí - hay una posición bloqueada @1 m a la derecha y @2 m hacia arriba +Can't place door here - position @1m to the right and @2m up is protected!=No se puede colocar la puerta aquí - hay una posición protegida @1 m a la derecha y @2 m hacia arriba +Glass Hoistway Door (left, bottom - you hacker you!)=Puerta de ascensor en vidrio (lado izquierdo, parte inferior) +Glass Hoistway Door (left, middle - you hacker you!)=Puerta de ascensor en vidrio (lado izquierdo, parte media) +Glass Hoistway Door (left, top - you hacker you!)=Puerta de ascensor en vidrio (lado izquierdo, parte superior) +Glass Hoistway Door (right, bottom - you hacker you!)=Puerta de ascensor en vidrio (lado derecho, parte inferior) +Glass Hoistway Door (right, middle - you hacker you!)=Puerta de ascensor en vidrio (lado derecho, parte media) +Glass Hoistway Door (right, top - you hacker you!)=Puerta de ascensor en vidrio (lado derecho, parte superior) +Center-Opening Glass Elevator Hoistway Door=Puerta de ascensor en vidrio de apertura central +Steel Hoistway Door (left, bottom - you hacker you!)=Puerta de ascensor en acero (lado izquierdo, parte inferior) +Steel Hoistway Door (left, middle - you hacker you!)=Puerta de ascensor en acero (lado izquierdo, parte media) +Steel Hoistway Door (left, top - you hacker you!)=Puerta de ascensor en acero (lado izquierdo, parte superior) +Steel Hoistway Door (right, bottom - you hacker you!)=Puerta de ascensor en acero (lado derecho, parte inferior) +Steel Hoistway Door (right, middle - you hacker you!)=Puerta de ascensor en acero (lado derecho, parte media) +Steel Hoistway Door (right, top - you hacker you!)=Puerta de ascensor en acero (lado derecho, parte superior) +Center-Opening Steel Elevator Hoistway Door=Puerta de ascensor en acero de apertura central +Hoistway Door Open-State Placeholder (you hacker you!)=Marcador de posición para puertas de ascensor abiertas +Hoistway Door Sill, Double Track (you hacker you!)=Alféizar de puerta para ascensor (pista doble) +Elevator Drive=Inversor de frecuencia para ascensor +Normal entity-based drive=Inversor de frecuencia normal basado en entidades +Drive - Running: Up, @1m/s - Position: @2m=Inversor - Subiendo a @1 m/s - Posición: @2 m +Drive - Running: Down, @1m/s - Position: @2m=Inversor - Bajando a @1 m/s - Posición: @2 m +Drive - Running (simulated): Up, @1m/s - Position: @2m=Inversor - Subiendo (simulado) a @1 m/s - Posición: @2 m +Drive - Running (simulated): Down, @1m/s - Position: @2m=Inversor - Bajando (simulado) a @1 m/s - Posición: @2 m +Drive - Idle=Inversor - Inactivo +Using car with origin @1=Usando la cabina con posición de origen @1 +No car found! Punch to try again=¡No se encontró ninguna cabina! Golpea para intentarlo de nuevo +Elevator Hoist Machine=Máquina del ascensor +Can't place machine here - no room for the motor (to the left)!=No se puede colocar la máquina aquí - ¡no hay espacio para el motor (a la izquierda)! +Can't place machine here - space for the motor (to the left) is protected!=No se puede colocar la máquina aquí - ¡el espacio para el motor (a la izquierda) está protegida! +Can't place machine here - no room for the sheave (in front)!=No se puede colocar la máquina aquí - ¡no hay espacio para la polea (al frente)! +Can't place machine here - space for the sheave (in front) is protected!=No se puede colocar la máquina aquí - ¡el espacio para la polea (al frente) está protegida! +Hoist Motor (you hacker you!)=Motor +Sheave (you hacker you!)=Polea +Centered Sheave (you hacker you!)=Polea centrada +Null Drive=Inversor de frecuencia simulado +Simulation only, no movement, for testing and demonstration=Solo para simulación y prueba, sin movimiento +Null Drive - Running: Up, @1m/s - Position: @2m=Inversor Simulado - Subiendo a @1 m/s - Posición: @2 m +Null Drive - Running: Down, @1m/s - Position: @2m=Inversor Simulado - Bajando a @1 m/s - Posición: @2 m +Null Drive - Idle=Inversor Simulado - Inactivo +Elevator Fire Service Phase 1 Keyswitch=Interruptor de la fase 1 del modo de incendio del ascensor +Elevator Fire Service Phase 1 Keyswitch (on state - you hacker you!)=Interruptor de la fase 1 del modo de incendio del ascensor (estado activado) +Elevator Fire Service Phase 1 Keyswitch (reset state - you hacker you!)=Interruptor de la fase 1 del modo de incendio del ascensor (estado de reinicio) +Elevator Fire Service Phase 1 Keyswitch (lit - you hacker you!)=Interruptor de la fase 1 del modo de incendio del ascensor (con luz activado) +Elevator Fire Service Phase 1 Keyswitch (on state, lit - you hacker you!)=Interruptor de la fase 1 del modo de incendio del ascensor (estado activado y con luz activado) +Elevator Fire Service Phase 1 Keyswitch (reset state, lit - you hacker you!)=Interruptor de la fase 1 del modo de incendio del ascensor (estado de reinicio y con luz activado) +Can't connect to a controller/dispatcher you don't have access to.=No se puede conectar a un controlador/despachador al que no se tiene acceso. +Save=Guardar +Car ID=Número del ascensor +Elevator Keyswitch=Interruptor de llave del ascensor +Elevator Keyswitch (maintained, off state - you hacker you!)=Interruptor de llave del ascensor (mantenido, en estado desactivado) +Elevator Keyswitch (maintained, on state - you hacker you!)=Interruptor de llave del ascensor (mantenido, en estado activado) +Elevator Keyswitch (momentary, off state - you hacker you!)=Interruptor de llave del ascensor (momentáneo, en estado desactivado) +Elevator Keyswitch (momentary, on state - you hacker you!)=Interruptor de llave del ascensor (momentáneo, en estado activado) +(none)=(ninguno) +ON=ENCENDIDO +OFF=APAGADO +Dispatcher ID=Número del despachador +You don't have a key for this switch.=No tienes la llave para este interruptor. +Car Call at Landing:=Llamada de cabina a la planta: +Up Call (simplex car) at Landing:=Llamada para subir (único ascensor) de la planta: +Down Call (simplex car) at Landing:=Llamada para bajar (único ascensor) de la planta: +Up Call (swing) at Landing:=Llamada para subir (modo separado) de la planta: +Down Call (swing) at Landing:=Llamada para bajar (modo separado) de la planta: +Deactivate Fire Service Phase 1=Desactivar la fase 1 del modo de incendio +Activate Fire Service (main landing) Phase 1=Activar la fase 1 (planta primaria) del modo de incendio +Activate Fire Service (alternate landing) Phase 1=Activar la fase 1 (planta alternativa) del modo de incendio +Machine Room or Hoistway Smoke Detector=Detector de humo en la sala de máquinas o en el hueco +Lock Car Calls at Landing:=Bloquea las llamadas a la planta: +Require Auth for Car Calls at Landing:=Requiere autentificación para las llamadas a la planta: +Unlock Car Calls at Landing:=Desbloquea las llamadas a la planta: +Activate Swing Operation=Activar modo separado +Deactivate Swing Operation=Desactivar modo separado +Up Call at Landing:=Llamada para subir de la planta: +Down Call at Landing:=Llamada para bajar de la planta: +Activate Fire Service Phase 1=Activar la fase 1 del modo de incendio +Controller=Controlador +Dispatcher=Despachador +Not all signal options require a landing number.=No todas las opciones de señalización requieren@nun número de planta. +Dispatcher: @1=Despachador: @1 +Car: @1=Ascensor: @1 +Can't connect to a dispatcher you don't have access to.=No se puede conectar a un despachador al que no se tiene acceso. +Can't connect to a controller you don't have access to.=No se puede conectar a un controlador al que no se tiene acceso. +Elevator Governor=Limitador de velocidad del ascensor +Governor Sheave (you hacker you!)=Polea de limitador de velocidad +Remote interface for MTronic XT elevator controllers=Interfaz remota para controladores de ascensores MTronic XT +This application requires a hard disk drive.=Este aplicación requiere un disco duro. +Welcome to the mView remote interface for MTronic XT elevator controllers!=¡Bienvenido a la interfaz remota mView para los controladores de ascensores MTronic XT! +Add a connection to get started.=Añade una conexión para empezar. +Add/Edit Connections=Añadir/editar conexiones +MANAGE CONNECTIONS=GESTIONAR CONEXIONES +ID @1 - @2=Número @1 - @2 +Delete Connection=Eliminar conexión +Connect >=Conectar > +Please enter the ID you would like to connect to and a name for the connection.=Por favor, introduzca el número al que desea conectarse y un nombre para la conexión. +ID=Número +Name=Nombre +Error=Error +Could not find a controller or dispatcher with the given ID.=No se pudo encontrar un controlador o despachador con el número proporcionado. +Please check the ID number and try again.=Por favor, compruebe el número y inténtelo de nuevo. +Controller or dispatcher is protected.=El controlador o el despachador está protegido. +Connected to @1 (ID @2)=Conectado a @1 (Número @2) +Disconnect=Desconectar +Uninitialized=No inicializado +Position Sync - Floor=Sincronización de posición - planta +Position Sync - Terminal=Sincronización de posición - terminal +Machine Room Inspection=Modo de inspección (sala de máquinas) +Car Top Inspection=Modo de inspección (techo de la cabina) +Fire Service - Phase 1=Modo de incendio (fase 1) +Fire Service - Phase 2=Modo de incendio (fase 2) +Fire Service - Phase 2 Hold=Modo de incendio (fase 2, modo de retención) +Captured=Capturado +Test Mode=Modo de prueba +Cancel=Cancelar +CAR=CABINA +Follow Car=Seguimiento de cabina +Position: @1m Speed: @2m/s PI: @3=Posición: @1 m Velocidad: @2 m/s Planta: @3 +Fault(s) Active=Avería(s) activa(s) +No Current Faults=Ninguna avería +Inspection (Any)=Modo de inspección (cualquier) +Fire Service=Modo de incendio +Fire Service Phase 1=Modo de incendio - fase 1 +Fire Service Phase 2=Modo de incendio - fase 2 +Moving Up=Subiendo +Moving Down=Bajando +Moving (Any Direction)=Moviéndose en cualquier dirección +Collecting Up Calls=Recopilando llamadas para subir +Collecting Down Calls=Recopilando llamadas para bajar +Car Light Switch=Interruptor de luz +Car Fan Switch=Interruptor de ventilador +Up Call Exists at Landing:=Existe una llamada de subida en la planta: +Down Call Exists at Landing:=Existe una llamada de bajada en la planta: +Car Call Exists at Landing:=Existe una llamada desde el ascensor en la planta: +Car at Landing:=Está en la planta: +Moving to Landing:=Está moviéndose a la planta: +Elevator Mesecons Output=Salida Mesecons para ascensor +Elevator Mesecons Output (on state - you hacker you!)=Salida Mesecons para ascensor (estado activado) +Elevator Mesecons Input=Entrada Mesecons para ascensor +Elevator Mesecons Input (on state - you hacker you!)=Entrada Mesecons para ascensor (estado activado) +Elevator Position Indicator=Indicador de posición del ascensor +Elevator Up Lantern=Luz indicadora de llegada del ascensor (subiendo) +Elevator Up Lantern (vertical)=Luz vertical indicadora de llegada del ascensor (subiendo) +Elevator Up Position Indicator / Lantern Combo=Luz indicadora de llegada del ascensor (subiendo) e indicador de su posición +Elevator Down Lantern=Luz indicadora de llegada del ascensor (bajando) +Elevator Down Lantern (vertical)=Luz vertical indicadora de llegada del ascensor (bajando) +Elevator Down Position Indicator / Lantern Combo=Luz indicadora de llegada del ascensor (bajando) e indicador de su posición +Elevator Up and Down Lantern=Luz indicadora de llegada del ascensor (subiendo y bajando) +Elevator Up and Down Lantern (vertical)=Luz vertical indicadora de llegada del ascensor (subiendo y bajando) +Elevator Up and Down Position Indicator / Lantern Combo=Luz indicadora de llegada del ascensor (subiendo y bajando) e indicador de su posición +Sound=Sonida diff --git a/locale/template.txt b/locale/template.txt new file mode 100644 index 0000000..17e2f72 --- /dev/null +++ b/locale/template.txt @@ -0,0 +1,377 @@ +# textdomain: celevator +Elevator Up Call Button= +Elevator Down Call Button= +Elevator Up and Down Call Buttons= +Elevator Call Button (on state - you hacker you!)= +Error reading car information!@nPlease remove and replace this node.= +Controller/dispatcher is missing!@nPlease remove and replace this node.= +Controller/dispatcher found but with incorrect ID!@nPlease remove and replace this node.= +Car (part @1 - you hacker you!)= +You don't have access to these switches.= +Really remove this car?= +Yes= +No= +Car-top Inspection Box, Off State (you hacker you!)= +Car-top Inspection Box, On State (you hacker you!)= +Full-Glass Elevator Car= +Glass-Back Elevator Car= +Metal Elevator Car= +Can't place car here - position @1m to the right, @2m up, and @3m back is blocked!= +Can't place car here - position @1m to the right, @2m up, and @3m back is protected!= +Metal Glass-Back Elevator Car= +Basic Elevator Car= +Places a car call at the specified landing on the specified elevator= +<car ID> <landing number>= +Invalid car ID= +Invalid landing number= +No such car or car info is missing= +Controller is missing= +Controller found but with wrong ID= +Controller is protected= +Command sent= +Places an up hall call at the specified landing on the specified elevator or dispatcher= +Dispatcher is missing= +Dispatcher found but with wrong ID= +Dispatcher is protected= +Places a down hall call at the specified landing on the specified elevator or dispatcher= +View the status of the specified elevator= +<car ID>= +Failed to load controller memory= +Reload celevator controller firmware from disk= +Elevator Controller= +Controller (door open - you hacker you!)= +Controller (top section - you hacker you!)= +Controller (top section, car in motion - you hacker you!)= +Controller (top section, open - you hacker you!)= +Controller (top section, open, car in motion - you hacker you!)= +Door Open Timeout= +Door Close Timeout= +Lost Communication With Drive= +Drive Not Configured= +Drive Metadata Load Failure= +Drive Origin Invalid= +Attempted to Move Doors With Car in Motion= +Target Position Out of Bounds= +Hoist Machine Missing= +Drive<->Machine ID Mismatch= +Controller<->Drive ID Mismatch= +Welcome to your new MTronic XT elevator controller!= +This setup wizard is designed to get your elevator up and running as quickly as possible.= +This applies to the whole celevator mod, not just this controller:= +Select a group operation mode:= +Simplex= +This will be the only elevator in the group. Hall calls will be handled by this controller.= +Group= +This elevator will participate in a group with others. Hall calls will be handled by a dispatcher.= +Waiting for connection from dispatcher...= +This controller's car ID is: @1= +Enter details of all floors this elevator will serve, then press Done.= +CAR STATUS= +Fault History= +Edit Parameters= +FAULT= +INSP/ACCESS= +NORMAL OPERATION= +UP= +DRIVE CMD= +DOWN= +HIGH SPEED= +DOOR ZONE= +DOORS LOCKED= +RUN= +STOP= +CAPTURE= +TEST= +INSPECT= +NORMAL= +UP = +DOWN = +EDIT PARAMETERS= +Door Dwell Timer= +Contract Speed (m/s)= +Inspection Speed (m/s)= +Main Egress Landing= +Nudging Timer= +Alternate Recall Landing= +Reset Doors= +Reset Controller= +Car Call Security= +FAULT HISTORY= +Clear= +CAR CALL SECURITY= +Authorized Users Only= +Locked= +Security Disabled= +Allow Swing Calls When Not In Swing Operation= +Unlock in Independent= +Extra Allowed Users= +Hide Button= +Also Hide in Fire/Independent Service= +Main landing cannot be locked= +Suppress Beep Sound= +ID @1: Floor @2 - @3 - @4= +Call@nCancel= +HOLD= +FIRE SVC= +IND SVC= +CAR LIGHT= +CAR FAN= +Normal Operation= +Fault= +Emergency Stop= +Independent Service= +Swing Operation= +Doors Opening= +Doors Open= +Doors Closing= +Doors Closed= +Please select a floor:= +Please use elevator= +ERROR= +Could not find a suitable elevator= +Please try again later= +Elevator Destination Entry Kiosk= +Landing Number= +Elevator Elastomeric Buffer= +Elevator Oil-Filled Buffer= +Elevator Oil-Filled Buffer (top half - you hacker you!)= +Elevator Guide Rail= +Elevator Guide Rail with Bracket= +Elevator Positioning System Tape= +Elevator Positioning System Tape with Magnets= +Elevator Positioning System Tape with Bracket= +Elevator Positioning System Tapehead (off, you hacker you!)= +Elevator Positioning System Tapehead (ULM on, you hacker you!)= +Elevator Positioning System Tapehead (ULM and DZ on, you hacker you!)= +Elevator Positioning System Tapehead (ULM, DLM, and DZ on, you hacker you!)= +Elevator Positioning System Tapehead (DLM and DZ on, you hacker you!)= +Elevator Positioning System Tapehead (DLM on, you hacker you!)= +Elevator Digilines Input/Output= +Channel= +Elevator Digilines Multi-Car Input/Output= +You need either the 'protection_bypass' or 'server' privilege to use this.= +Elevator Dispatcher= +Dispatcher (door open - you hacker you!)= +Dispatcher (top section - you hacker you!)= +Dispatcher (top section, open - you hacker you!)= +Firmware reloaded successfully= +Can't place cabinet - no room for the top half!= +Can't place cabinet - top half is protected!= +Hold the sneak button while digging to remove.= +Can't open cabinet - cabinet is locked.= +Welcome to your new MTronic XT elevator dispatcher!= +Before continuing, make sure you have at least two controllers in group operation mode and ready to connect.= +This applies to the whole celevator mod, not just this dispatcher:= +Enter details of all floors this group will serve, then press Next.= +Include all floors served by any car in the group, even if not served by all cars.= +Connect to each car in the group, then click Done.= +EDIT CONNECTIONS= +Car @1 - ID #@2= +Remove Connection= +Enter the car ID and select the floors served (click them to toggle), then click Connect.= +You must select at least two floors.= +Connect= +YES= +NO= +Car ID: @1= +Connecting to controller...= +Connection timed out!= +Make sure the car ID is correct and@nthat the controller is ready to connect.= +GROUP DISPLAY= +Menu= +MAIN MENU= +Edit Connections= +Press Next to begin.= +License Info= +Next >= +< Back= +Done= +EDIT FLOOR TABLE= +@1 - Height: @2 - PI: @3= +New Floor= +Edit Floor= +Remove Floor= +The Floor Height is the distance (in meters/nodes) from the floor level of this floor to the floor level of the next floor.= +(not used at the highest floor)= +The Floor Name is how the floor will be displayed on the position indicators.= +Editing Floor @1= +Floor Height= +Floor Name= +Edit Floor Table= +Back= +No Connections= +New Connection= +Edit Connection= +NEW CONNECTION= +EDIT CONNECTION= +CAR @1= + IN= +OUT= +OK= +Move Up= +Move Down= +ID: @1= +Glass Hoistway Door (fast, bottom - you hacker you!)= +Glass Hoistway Door (fast, middle - you hacker you!)= +Glass Hoistway Door (fast, top - you hacker you!)= +Glass Hoistway Door (slow, bottom - you hacker you!)= +Glass Hoistway Door (slow, middle - you hacker you!)= +Glass Hoistway Door (slow, top - you hacker you!)= +Glass Elevator Hoistway Door= +Steel Hoistway Door (fast, bottom - you hacker you!)= +Steel Hoistway Door (fast, middle - you hacker you!)= +Steel Hoistway Door (fast, top - you hacker you!)= +Steel Hoistway Door (slow, bottom - you hacker you!)= +Steel Hoistway Door (slow, middle - you hacker you!)= +Steel Hoistway Door (slow, top - you hacker you!)= +Steel Elevator Hoistway Door= +Can't place door here - position @1m to the right and @2m up is blocked!= +Can't place door here - position @1m to the right and @2m up is protected!= +Glass Hoistway Door (left, bottom - you hacker you!)= +Glass Hoistway Door (left, middle - you hacker you!)= +Glass Hoistway Door (left, top - you hacker you!)= +Glass Hoistway Door (right, bottom - you hacker you!)= +Glass Hoistway Door (right, middle - you hacker you!)= +Glass Hoistway Door (right, top - you hacker you!)= +Center-Opening Glass Elevator Hoistway Door= +Steel Hoistway Door (left, bottom - you hacker you!)= +Steel Hoistway Door (left, middle - you hacker you!)= +Steel Hoistway Door (left, top - you hacker you!)= +Steel Hoistway Door (right, bottom - you hacker you!)= +Steel Hoistway Door (right, middle - you hacker you!)= +Steel Hoistway Door (right, top - you hacker you!)= +Center-Opening Steel Elevator Hoistway Door= +Hoistway Door Open-State Placeholder (you hacker you!)= +Hoistway Door Sill, Double Track (you hacker you!)= +Elevator Drive= +Normal entity-based drive= +Drive - Running: Up, @1m/s - Position: @2m= +Drive - Running: Down, @1m/s - Position: @2m= +Drive - Running (simulated): Up, @1m/s - Position: @2m= +Drive - Running (simulated): Down, @1m/s - Position: @2m= +Drive - Idle= +Using car with origin @1= +No car found! Punch to try again= +Elevator Hoist Machine= +Can't place machine here - no room for the motor (to the left)!= +Can't place machine here - space for the motor (to the left) is protected!= +Can't place machine here - no room for the sheave (in front)!= +Can't place machine here - space for the sheave (in front) is protected!= +Hoist Motor (you hacker you!)= +Sheave (you hacker you!)= +Centered Sheave (you hacker you!)= +Null Drive= +Simulation only, no movement, for testing and demonstration= +Null Drive - Running: Up, @1m/s - Position: @2m= +Null Drive - Running: Down, @1m/s - Position: @2m= +Null Drive - Idle= +Elevator Fire Service Phase 1 Keyswitch= +Elevator Fire Service Phase 1 Keyswitch (on state - you hacker you!)= +Elevator Fire Service Phase 1 Keyswitch (reset state - you hacker you!)= +Elevator Fire Service Phase 1 Keyswitch (lit - you hacker you!)= +Elevator Fire Service Phase 1 Keyswitch (on state, lit - you hacker you!)= +Elevator Fire Service Phase 1 Keyswitch (reset state, lit - you hacker you!)= +Can't connect to a controller/dispatcher you don't have access to.= +Save= +Car ID= +Elevator Keyswitch= +Elevator Keyswitch (maintained, off state - you hacker you!)= +Elevator Keyswitch (maintained, on state - you hacker you!)= +Elevator Keyswitch (momentary, off state - you hacker you!)= +Elevator Keyswitch (momentary, on state - you hacker you!)= +(none)= +ON= +OFF= +Dispatcher ID= +You don't have a key for this switch.= +Car Call at Landing:= +Up Call (simplex car) at Landing:= +Down Call (simplex car) at Landing:= +Up Call (swing) at Landing:= +Down Call (swing) at Landing:= +Deactivate Fire Service Phase 1= +Activate Fire Service (main landing) Phase 1= +Activate Fire Service (alternate landing) Phase 1= +Machine Room or Hoistway Smoke Detector= +Lock Car Calls at Landing:= +Require Auth for Car Calls at Landing:= +Unlock Car Calls at Landing:= +Activate Swing Operation= +Deactivate Swing Operation= +Up Call at Landing:= +Down Call at Landing:= +Activate Fire Service Phase 1= +Controller= +Dispatcher= +Not all signal options require a landing number.= +Dispatcher: @1= +Car: @1= +Can't connect to a dispatcher you don't have access to.= +Can't connect to a controller you don't have access to.= +Elevator Governor= +Governor Sheave (you hacker you!)= +Remote interface for MTronic XT elevator controllers= +This application requires a hard disk drive.= +Welcome to the mView remote interface for MTronic XT elevator controllers!= +Add a connection to get started.= +Add/Edit Connections= +MANAGE CONNECTIONS= +ID @1 - @2= +Delete Connection= +Connect >= +Please enter the ID you would like to connect to and a name for the connection.= +ID= +Name= +Error= +Could not find a controller or dispatcher with the given ID.= +Please check the ID number and try again.= +Controller or dispatcher is protected.= +Connected to @1 (ID @2)= +Disconnect= +Uninitialized= +Position Sync - Floor= +Position Sync - Terminal= +Machine Room Inspection= +Car Top Inspection= +Fire Service - Phase 1= +Fire Service - Phase 2= +Fire Service - Phase 2 Hold= +Captured= +Test Mode= +Cancel= +CAR= +Follow Car= +Position: @1m Speed: @2m/s PI: @3= +Fault(s) Active= +No Current Faults= +Inspection (Any)= +Fire Service= +Fire Service Phase 1= +Fire Service Phase 2= +Moving Up= +Moving Down= +Moving (Any Direction)= +Collecting Up Calls= +Collecting Down Calls= +Car Light Switch= +Car Fan Switch= +Up Call Exists at Landing:= +Down Call Exists at Landing:= +Car Call Exists at Landing:= +Car at Landing:= +Moving to Landing:= +Elevator Mesecons Output= +Elevator Mesecons Output (on state - you hacker you!)= +Elevator Mesecons Input= +Elevator Mesecons Input (on state - you hacker you!)= +Elevator Position Indicator= +Elevator Up Lantern= +Elevator Up Lantern (vertical)= +Elevator Up Position Indicator / Lantern Combo= +Elevator Down Lantern= +Elevator Down Lantern (vertical)= +Elevator Down Position Indicator / Lantern Combo= +Elevator Up and Down Lantern= +Elevator Up and Down Lantern (vertical)= +Elevator Up and Down Position Indicator / Lantern Combo= +Sound= diff --git a/mesecons.lua b/mesecons.lua index 7064821..b126381 100644 --- a/mesecons.lua +++ b/mesecons.lua @@ -1,3 +1,5 @@ +local S = core.get_translator("celevator") + local iorules = { vector.new(-1,0,0), vector.new(1,0,0), @@ -20,7 +22,7 @@ end local outputoptions = { { id = "normal", - desc = "Normal Operation", + desc = S("Normal Operation"), func = function(mem) return (mem.carstate == "normal") end, @@ -28,7 +30,7 @@ local outputoptions = { }, { id = "fault", - desc = "Fault", + desc = S("Fault"), func = function(mem) return (mem.carstate == "fault") end, @@ -36,7 +38,7 @@ local outputoptions = { }, { id = "estop", - desc = "Emergency Stop", + desc = S("Emergency Stop"), func = function(mem) return (mem.carstate == "stop") end, @@ -44,7 +46,7 @@ local outputoptions = { }, { id = "inspect", - desc = "Inspection (Any)", + desc = S("Inspection (Any)"), func = function(mem) return (mem.carstate == "mrinspect" or mem.carstate == "inspconflict" or mem.carstate == "carinspect") end, @@ -52,7 +54,7 @@ local outputoptions = { }, { id = "fire", - desc = "Fire Service", + desc = S("Fire Service"), func = function(mem) return (mem.carstate == "fs1" or mem.carstate == "fs2" or mem.carstate == "fs2hold") end, @@ -60,7 +62,7 @@ local outputoptions = { }, { id = "fire1", - desc = "Fire Service Phase 1", + desc = S("Fire Service Phase 1"), func = function(mem) return (mem.carstate == "fs1") end, @@ -68,7 +70,7 @@ local outputoptions = { }, { id = "fire2", - desc = "Fire Service Phase 2", + desc = S("Fire Service Phase 2"), func = function(mem) return (mem.carstate == "fs2" or mem.carstate == "fs2hold") end, @@ -76,15 +78,23 @@ local outputoptions = { }, { id = "independent", - desc = "Independent Service", + desc = S("Independent Service"), func = function(mem) return (mem.carstate == "indep") end, needsfloor = false, }, { + id = "swing", + desc = S("Swing Operation"), + func = function(mem) + return (mem.carstate == "swing") + end, + needsfloor = false, + }, + { id = "opening", - desc = "Doors Opening", + desc = S("Doors Opening"), func = function(mem) return (mem.doorstate == "opening") end, @@ -92,7 +102,7 @@ local outputoptions = { }, { id = "open", - desc = "Doors Open", + desc = S("Doors Open"), func = function(mem) return (mem.doorstate == "open") end, @@ -100,7 +110,7 @@ local outputoptions = { }, { id = "closing", - desc = "Doors Closing", + desc = S("Doors Closing"), func = function(mem) return (mem.doorstate == "closing") end, @@ -108,7 +118,7 @@ local outputoptions = { }, { id = "closed", - desc = "Doors Closed", + desc = S("Doors Closed"), func = function(mem) return (mem.doorstate == "closed") end, @@ -116,7 +126,7 @@ local outputoptions = { }, { id = "moveup", - desc = "Moving Up", + desc = S("Moving Up"), func = function(mem) return (mem.drive.status and mem.drive.status.vel > 0) end, @@ -124,7 +134,7 @@ local outputoptions = { }, { id = "movedown", - desc = "Moving Down", + desc = S("Moving Down"), func = function(mem) return (mem.drive.status and mem.drive.status.vel < 0) end, @@ -132,7 +142,7 @@ local outputoptions = { }, { id = "moving", - desc = "Moving (Any Direction)", + desc = S("Moving (Any Direction)"), func = function(mem) return (mem.drive.status and mem.drive.status.vel ~= 0) end, @@ -140,7 +150,7 @@ local outputoptions = { }, { id = "collectorup", - desc = "Collecting Up Calls", + desc = S("Collecting Up Calls"), func = function(mem) return (mem.carstate == "normal" and mem.direction == "up") end, @@ -148,7 +158,7 @@ local outputoptions = { }, { id = "collectordown", - desc = "Collecting Down Calls", + desc = S("Collecting Down Calls"), func = function(mem) return (mem.carstate == "normal" and mem.direction == "down") end, @@ -156,7 +166,7 @@ local outputoptions = { }, { id = "lightsw", - desc = "Car Light Switch", + desc = S("Car Light Switch"), func = function(mem) return mem.lightsw end, @@ -164,7 +174,7 @@ local outputoptions = { }, { id = "fansw", - desc = "Car Fan Switch", + desc = S("Car Fan Switch"), func = function(mem) return mem.fansw end, @@ -172,7 +182,7 @@ local outputoptions = { }, { id = "upcall", - desc = "Up Call Exists at Landing:", + desc = S("Up Call Exists at Landing:"), func = function(mem,floor) return mem.upcalls[floor] end, @@ -180,7 +190,7 @@ local outputoptions = { }, { id = "downcall", - desc = "Down Call Exists at Landing:", + desc = S("Down Call Exists at Landing:"), func = function(mem,floor) return mem.dncalls[floor] end, @@ -188,7 +198,7 @@ local outputoptions = { }, { id = "carcall", - desc = "Car Call Exists at Landing:", + desc = S("Car Call Exists at Landing:"), func = function(mem,floor) return mem.carcalls[floor] end, @@ -196,7 +206,7 @@ local outputoptions = { }, { id = "apos", - desc = "Car at Landing:", + desc = S("Car at Landing:"), func = function(mem,floor) if mem.drive.status then return (getpos(mem,nil,true) == floor) @@ -206,7 +216,7 @@ local outputoptions = { }, { id = "dpos", - desc = "Moving to Landing:", + desc = S("Moving to Landing:"), func = function(mem,floor) if mem.drive.status then return (getpos(mem,mem.drive.status.dpos) == floor) @@ -219,7 +229,7 @@ local outputoptions = { local doutputoptions = { { id = "fire", - desc = "Fire Service", + desc = S("Fire Service"), func = function(mem) return mem.fs1led end, @@ -227,7 +237,7 @@ local doutputoptions = { }, { id = "upcall", - desc = "Up Call Exists at Landing:", + desc = S("Up Call Exists at Landing:"), func = function(mem,floor) return mem.upcalls[floor] end, @@ -235,7 +245,7 @@ local doutputoptions = { }, { id = "downcall", - desc = "Down Call Exists at Landing:", + desc = S("Down Call Exists at Landing:"), func = function(mem,floor) return mem.dncalls[floor] end, @@ -246,7 +256,7 @@ local doutputoptions = { local inputoptions = { { id = "carcall", - desc = "Car Call at Landing:", + desc = S("Car Call at Landing:"), func_on = function(controllerpos,floor) celevator.controller.run(controllerpos,{ type = "remotemsg", @@ -258,7 +268,7 @@ local inputoptions = { }, { id = "upcall", - desc = "Up Call (simplex car) at Landing:", + desc = S("Up Call (simplex car) at Landing:"), func_on = function(controllerpos,floor) celevator.controller.run(controllerpos,{ type = "remotemsg", @@ -270,7 +280,7 @@ local inputoptions = { }, { id = "downcall", - desc = "Down Call (simplex car) at Landing:", + desc = S("Down Call (simplex car) at Landing:"), func_on = function(controllerpos,floor) celevator.controller.run(controllerpos,{ type = "remotemsg", @@ -282,7 +292,7 @@ local inputoptions = { }, { id = "swingupcall", - desc = "Up Call (swing) at Landing:", + desc = S("Up Call (swing) at Landing:"), func_on = function(controllerpos,floor) celevator.controller.run(controllerpos,{ type = "remotemsg", @@ -294,7 +304,7 @@ local inputoptions = { }, { id = "swingdowncall", - desc = "Down Call (swing) at Landing:", + desc = S("Down Call (swing) at Landing:"), func_on = function(controllerpos,floor) celevator.controller.run(controllerpos,{ type = "remotemsg", @@ -306,7 +316,7 @@ local inputoptions = { }, { id = "fs1off", - desc = "Deactivate Fire Service Phase 1", + desc = S("Deactivate Fire Service Phase 1"), func_on = function(controllerpos) celevator.controller.run(controllerpos,{ type = "fs1switch", @@ -317,7 +327,7 @@ local inputoptions = { }, { id = "fs1on", - desc = "Activate Fire Service (main landing) Phase 1", + desc = S("Activate Fire Service (main landing) Phase 1"), func_on = function(controllerpos) celevator.controller.run(controllerpos,{ type = "fs1switch", @@ -328,7 +338,7 @@ local inputoptions = { }, { id = "fs1onalt", - desc = "Activate Fire Service (alternate landing) Phase 1", + desc = S("Activate Fire Service (alternate landing) Phase 1"), func_on = function(controllerpos) celevator.controller.run(controllerpos,{ type = "fs1switch", @@ -340,7 +350,7 @@ local inputoptions = { }, { id = "mrsmoke", - desc = "Machine Room or Hoistway Smoke Detector", + desc = S("Machine Room or Hoistway Smoke Detector"), func_on = function(controllerpos) celevator.controller.run(controllerpos,{ type = "mrsmoke", @@ -350,7 +360,7 @@ local inputoptions = { }, { id = "secdeny", - desc = "Lock Car Calls at Landing:", + desc = S("Lock Car Calls at Landing:"), func_on = function(controllerpos,floor) celevator.controller.run(controllerpos,{ type = "remotemsg", @@ -365,7 +375,7 @@ local inputoptions = { }, { id = "secauth", - desc = "Require Auth for Car Calls at Landing:", + desc = S("Require Auth for Car Calls at Landing:"), func_on = function(controllerpos,floor) celevator.controller.run(controllerpos,{ type = "remotemsg", @@ -380,7 +390,7 @@ local inputoptions = { }, { id = "secallow", - desc = "Unlock Car Calls at Landing:", + desc = S("Unlock Car Calls at Landing:"), func_on = function(controllerpos,floor) celevator.controller.run(controllerpos,{ type = "remotemsg", @@ -393,12 +403,36 @@ local inputoptions = { end, needsfloor = true, }, + { + id = "swingon", + desc = S("Activate Swing Operation"), + func_on = function(controllerpos) + celevator.controller.run(controllerpos,{ + type = "remotemsg", + channel = "swing", + msg = true, + }) + end, + needsfloor = false, + }, + { + id = "swingoff", + desc = S("Deactivate Swing Operation"), + func_on = function(controllerpos) + celevator.controller.run(controllerpos,{ + type = "remotemsg", + channel = "swing", + msg = false, + }) + end, + needsfloor = false, + }, } local dinputoptions = { { id = "upcall", - desc = "Up Call at Landing:", + desc = S("Up Call at Landing:"), func_on = function(dispatcherpos,floor) celevator.dispatcher.run(dispatcherpos,{ type = "remotemsg", @@ -410,7 +444,7 @@ local dinputoptions = { }, { id = "downcall", - desc = "Down Call at Landing:", + desc = S("Down Call at Landing:"), func_on = function(dispatcherpos,floor) celevator.dispatcher.run(dispatcherpos,{ type = "remotemsg", @@ -422,7 +456,7 @@ local dinputoptions = { }, { id = "fs1off", - desc = "Deactivate Fire Service Phase 1", + desc = S("Deactivate Fire Service Phase 1"), func_on = function(dispatcherpos) celevator.dispatcher.run(dispatcherpos,{ type = "fs1switch", @@ -433,7 +467,7 @@ local dinputoptions = { }, { id = "fs1on", - desc = "Activate Fire Service Phase 1", + desc = S("Activate Fire Service Phase 1"), func_on = function(dispatcherpos) celevator.dispatcher.run(dispatcherpos,{ type = "fs1switch", @@ -445,33 +479,33 @@ local dinputoptions = { } local function updateoutputform(pos) - local meta = minetest.get_meta(pos) + local meta = core.get_meta(pos) local dmode = meta:get_int("dispatcher") == 1 - local fs = "formspec_version[7]size[8,6.5]" - fs = fs.."tabheader[0,0;1;tab;Controller,Dispatcher;"..(dmode and "2" or "1")..";true;true]" - fs = fs.."dropdown[1,0.5;6,1;signal;" + local fs = "formspec_version[7]size[9,6.5]" + fs = fs.."tabheader[0,0;1;tab;"..S("Controller")..","..S("Dispatcher")..";"..(dmode and "2" or "1")..";true;true]" + fs = fs.."dropdown[1,0.5;7,1;signal;" local selected = 1 local currentid = meta:get_string("signal") for k,v in ipairs(dmode and doutputoptions or outputoptions) do - fs = fs..minetest.formspec_escape(v.desc).."," + fs = fs..core.formspec_escape(v.desc).."," if v.id == currentid then selected = k end end fs = string.sub(fs,1,-2) fs = fs..";"..selected..";false]" - fs = fs.."field[0.5,2.5;3,1;carid;"..(dmode and "Dispatcher ID" or "Car ID")..";${carid}]" - fs = fs.."field[4.5,2.5;3,1;floor;Landing Number;${floor}]" - fs = fs.."label[1.5,4;Not all signal options require a landing number.]" - fs = fs.."button_exit[2.5,5;3,1;save;Save]" + fs = fs.."field[0.5,2.5;3,1;carid;"..(dmode and S("Dispatcher ID") or S("Car ID"))..";${carid}]" + fs = fs.."field[4.5,2.5;3,1;floor;"..S("Landing Number")..";${floor}]" + fs = fs.."label[1.5,4;"..S("Not all signal options require a landing number.").."]" + fs = fs.."button_exit[2.5,5;3,1;save;"..S("Save").."]" meta:set_string("formspec",fs) end local function handleoutputfields(pos,_,fields,player) - local meta = minetest.get_meta(pos) + local meta = core.get_meta(pos) if fields.quit and not fields.save 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 + if core.is_protected(pos,name) and not core.check_player_privs(name,{protection_bypass=true}) then if player:is_player() then - minetest.record_protection_violation(pos,name) + core.record_protection_violation(pos,name) end return end @@ -480,24 +514,24 @@ local function handleoutputfields(pos,_,fields,player) if not tonumber(fields.carid) then return end meta:set_int("carid",fields.carid) local carid = tonumber(fields.carid) - local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid))) or {} + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) or {} if dmode then if not carinfo.dispatcherpos then return end if not celevator.dispatcher.isdispatcher(carinfo.dispatcherpos) then return end - if minetest.is_protected(carinfo.dispatcherpos,name) and not minetest.check_player_privs(name,{protection_bypass=true}) then + if core.is_protected(carinfo.dispatcherpos,name) and not core.check_player_privs(name,{protection_bypass=true}) then if player:is_player() then - minetest.chat_send_player(name,"Can't connect to a dispatcher you don't have access to.") - minetest.record_protection_violation(carinfo.dispatcherpos,name) + core.chat_send_player(name,S("Can't connect to a dispatcher you don't have access to.")) + core.record_protection_violation(carinfo.dispatcherpos,name) end return end else if not carinfo.controllerpos then return end if not celevator.controller.iscontroller(carinfo.controllerpos) then return end - if minetest.is_protected(carinfo.controllerpos,name) and not minetest.check_player_privs(name,{protection_bypass=true}) then + if core.is_protected(carinfo.controllerpos,name) and not core.check_player_privs(name,{protection_bypass=true}) then if player:is_player() then - minetest.chat_send_player(name,"Can't connect to a controller you don't have access to.") - minetest.record_protection_violation(carinfo.controllerpos,name) + core.chat_send_player(name,S("Can't connect to a controller you don't have access to.")) + core.record_protection_violation(carinfo.controllerpos,name) end return end @@ -514,11 +548,11 @@ local function handleoutputfields(pos,_,fields,player) if def.needsfloor and not floor then return end meta:set_string("signal",def.id) updateoutputform(pos) - local infotext = carid.." - "..def.desc..(def.needsfloor and " "..floor or "") + local infotext = " - "..def.desc..(def.needsfloor and " "..floor or "") if dmode then - infotext = "Dispatcher: "..infotext + infotext = S("Dispatcher: @1",carid)..infotext else - infotext = "Car: "..infotext + infotext = S("Car: @1",carid)..infotext end meta:set_string("infotext",infotext) elseif fields.tab then @@ -527,8 +561,8 @@ local function handleoutputfields(pos,_,fields,player) end end -minetest.register_node("celevator:mesecons_output_off",{ - description = "Elevator Mesecons Output", +core.register_node("celevator:mesecons_output_off",{ + description = S("Elevator Mesecons Output"), tiles = { "celevator_meseconsoutput_top_off.png", "celevator_cabinet_sides.png", @@ -552,15 +586,15 @@ minetest.register_node("celevator:mesecons_output_off",{ }, }, after_place_node = function(pos) - local meta = minetest.get_meta(pos) + local meta = core.get_meta(pos) meta:set_int("floor",1) updateoutputform(pos) end, on_receive_fields = handleoutputfields, }) -minetest.register_node("celevator:mesecons_output_on",{ - description = "Elevator Mesecons Output (on state - you hacker you!)", +core.register_node("celevator:mesecons_output_on",{ + description = S("Elevator Mesecons Output (on state - you hacker you!)"), tiles = { "celevator_meseconsoutput_top_on.png", "celevator_cabinet_sides.png", @@ -586,25 +620,25 @@ minetest.register_node("celevator:mesecons_output_on",{ }, }, after_place_node = function(pos) - local meta = minetest.get_meta(pos) + local meta = core.get_meta(pos) meta:set_int("floor",1) updateoutputform(pos) end, on_receive_fields = handleoutputfields, }) -minetest.register_abm({ +core.register_abm({ label = "Update mesecons output", nodenames = {"celevator:mesecons_output_off","celevator:mesecons_output_on",}, interval = 1, chance = 1, action = function(pos,node) - local meta = minetest.get_meta(pos) + local meta = core.get_meta(pos) local dmode = meta:get_int("dispatcher") == 1 local oldstate = (node.name == "celevator:mesecons_output_on") 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))) or {} + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) or {} if dmode then if not carinfo.dispatcherpos then return end if not celevator.dispatcher.isdispatcher(carinfo.dispatcherpos) then return end @@ -613,7 +647,7 @@ minetest.register_abm({ if not celevator.controller.iscontroller(carinfo.controllerpos) then return end end local floor = meta:get_int("floor") - local mem = minetest.deserialize(minetest.get_meta(dmode and carinfo.dispatcherpos or carinfo.controllerpos):get_string("mem")) or {} + local mem = core.deserialize(core.get_meta(dmode and carinfo.dispatcherpos or carinfo.controllerpos):get_string("mem")) or {} local signal = meta:get_string("signal") local def for _,v in ipairs(dmode and doutputoptions or outputoptions) do @@ -623,10 +657,14 @@ minetest.register_abm({ end end if not def then return end + if not mem.upcalls then + --Memory ended up blank somehow + return + end local newstate = def.func(mem,floor) if newstate ~= oldstate then node.name = (newstate and "celevator:mesecons_output_on" or "celevator:mesecons_output_off") - minetest.swap_node(pos,node) + core.swap_node(pos,node) if newstate then mesecon.receptor_on(pos,iorules) else @@ -637,33 +675,33 @@ minetest.register_abm({ }) local function updateinputform(pos) - local meta = minetest.get_meta(pos) + local meta = core.get_meta(pos) local dmode = meta:get_int("dispatcher") == 1 - local fs = "formspec_version[7]size[8,6.5]" - fs = fs.."tabheader[0,0;1;tab;Controller,Dispatcher;"..(dmode and "2" or "1")..";true;true]" - fs = fs.."dropdown[1,0.5;6,1;signal;" + local fs = "formspec_version[7]size[9,6.5]" + fs = fs.."tabheader[0,0;1;tab;"..S("Controller")..","..S("Dispatcher")..";"..(dmode and "2" or "1")..";true;true]" + fs = fs.."dropdown[1,0.5;7,1;signal;" local selected = 1 local currentid = meta:get_string("signal") for k,v in ipairs(dmode and dinputoptions or inputoptions) do - fs = fs..minetest.formspec_escape(v.desc).."," + fs = fs..core.formspec_escape(v.desc).."," if v.id == currentid then selected = k end end fs = string.sub(fs,1,-2) fs = fs..";"..selected..";false]" - fs = fs.."field[0.5,2.5;3,1;carid;"..(dmode and "Dispatcher ID" or "Car ID")..";${carid}]" - fs = fs.."field[4.5,2.5;3,1;floor;Landing Number;${floor}]" - fs = fs.."label[1.5,4;Not all signal options require a landing number.]" - fs = fs.."button_exit[2.5,5;3,1;save;Save]" + fs = fs.."field[0.5,2.5;3,1;carid;"..(dmode and S("Dispatcher ID") or S("Car ID"))..";${carid}]" + fs = fs.."field[4.5,2.5;3,1;floor;"..S("Landing Number")..";${floor}]" + fs = fs.."label[1.5,4;"..S("Not all signal options require a landing number.").."]" + fs = fs.."button_exit[2.5,5;3,1;save;"..S("Save").."]" meta:set_string("formspec",fs) end local function handleinputfields(pos,_,fields,player) if fields.quit and not fields.save then return end - local meta = minetest.get_meta(pos) + local meta = core.get_meta(pos) local name = player:get_player_name() - if minetest.is_protected(pos,name) and not minetest.check_player_privs(name,{protection_bypass=true}) then + if core.is_protected(pos,name) and not core.check_player_privs(name,{protection_bypass=true}) then if player:is_player() then - minetest.record_protection_violation(pos,name) + core.record_protection_violation(pos,name) end return end @@ -672,24 +710,24 @@ local function handleinputfields(pos,_,fields,player) if not tonumber(fields.carid) then return end meta:set_int("carid",fields.carid) local carid = tonumber(fields.carid) - local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid))) or {} + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) or {} if dmode then if not carinfo.dispatcherpos then return end if not celevator.dispatcher.isdispatcher(carinfo.dispatcherpos) then return end - if minetest.is_protected(carinfo.dispatcherpos,name) and not minetest.check_player_privs(name,{protection_bypass=true}) then + if core.is_protected(carinfo.dispatcherpos,name) and not core.check_player_privs(name,{protection_bypass=true}) then if player:is_player() then - minetest.chat_send_player(name,"Can't connect to a dispatcher you don't have access to.") - minetest.record_protection_violation(carinfo.dispatcherpos,name) + core.chat_send_player(name,S("Can't connect to a dispatcher you don't have access to.")) + core.record_protection_violation(carinfo.dispatcherpos,name) end return end else if not carinfo.controllerpos then return end if not celevator.controller.iscontroller(carinfo.controllerpos) then return end - if minetest.is_protected(carinfo.controllerpos,name) and not minetest.check_player_privs(name,{protection_bypass=true}) then + if core.is_protected(carinfo.controllerpos,name) and not core.check_player_privs(name,{protection_bypass=true}) then if player:is_player() then - minetest.chat_send_player(name,"Can't connect to a controller you don't have access to.") - minetest.record_protection_violation(carinfo.controllerpos,name) + core.chat_send_player(name,S("Can't connect to a controller you don't have access to.")) + core.record_protection_violation(carinfo.controllerpos,name) end return end @@ -706,11 +744,11 @@ local function handleinputfields(pos,_,fields,player) if def.needsfloor and not floor then return end meta:set_string("signal",def.id) updateinputform(pos) - local infotext = carid.." - "..def.desc..(def.needsfloor and " "..floor or "") + local infotext = " - "..def.desc..(def.needsfloor and " "..floor or "") if dmode then - infotext = "Dispatcher: "..infotext + infotext = S("Dispatcher: @1",carid)..infotext else - infotext = "Car: "..infotext + infotext = S("Car: @1",carid)..infotext end meta:set_string("infotext",infotext) elseif fields.tab then @@ -720,10 +758,10 @@ local function handleinputfields(pos,_,fields,player) end local function handleinput(pos,on) - local meta = minetest.get_meta(pos) + local meta = core.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))) or {} + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) or {} local dmode = meta:get_int("dispatcher") == 1 if dmode then if not carinfo.dispatcherpos then return end @@ -757,8 +795,8 @@ local function handleinput(pos,on) end end -minetest.register_node("celevator:mesecons_input_off",{ - description = "Elevator Mesecons Input", +core.register_node("celevator:mesecons_input_off",{ + description = S("Elevator Mesecons Input"), tiles = { "celevator_meseconsinput_top_off.png", "celevator_cabinet_sides.png", @@ -780,21 +818,21 @@ minetest.register_node("celevator:mesecons_input_off",{ rules = iorules, action_on = function(pos,node) node.name = "celevator:mesecons_input_on" - minetest.swap_node(pos,node) + core.swap_node(pos,node) handleinput(pos,true) end, }, }, after_place_node = function(pos) - local meta = minetest.get_meta(pos) + local meta = core.get_meta(pos) meta:set_int("floor",1) updateinputform(pos) end, on_receive_fields = handleinputfields, }) -minetest.register_node("celevator:mesecons_input_on",{ - description = "Elevator Mesecons Input (on state - you hacker you!)", +core.register_node("celevator:mesecons_input_on",{ + description = S("Elevator Mesecons Input (on state - you hacker you!)"), tiles = { "celevator_meseconsinput_top_on.png", "celevator_cabinet_sides.png", @@ -818,13 +856,13 @@ minetest.register_node("celevator:mesecons_input_on",{ rules = iorules, action_off = function(pos,node) node.name = "celevator:mesecons_input_off" - minetest.swap_node(pos,node) + core.swap_node(pos,node) handleinput(pos,false) end, }, }, after_place_node = function(pos) - local meta = minetest.get_meta(pos) + local meta = core.get_meta(pos) meta:set_int("floor",1) updateinputform(pos) end, @@ -1,5 +1,5 @@ name = celevator description = Realistic Elevators -optional_depends = laptop,mesecons,digilines +optional_depends = laptop,mesecons,digilines,xcompat,mesecons_lightstone,mesecons_button,digistuff author = cheapie -min_minetest_version = 5.7 +min_minetest_version = 5.12 diff --git a/pilantern.lua b/pilantern.lua index 7dda0a5..7b36253 100644 --- a/pilantern.lua +++ b/pilantern.lua @@ -1,6 +1,19 @@ celevator.pi = {} celevator.lantern = {} +celevator.lantern.chimesounds = { + { + up = "celevator_chime_up", + down = "celevator_chime_down", + }, + { + up = {name="celevator_chime2_up",gain=0.7}, + down = {name="celevator_chime2_down",gain=0.7}, + }, +} + +local S = core.get_translator("celevator") + local boringside = "[combine:64x64".. ":0,0=celevator_cabinet_sides.png".. ":32,0=celevator_cabinet_sides.png".. @@ -8,31 +21,33 @@ local boringside = "[combine:64x64".. ":32,32=celevator_cabinet_sides.png" local displaytex = boringside..":16,40=celevator_pi_background.png" -minetest.register_entity("celevator:pi_entity",{ +core.register_entity("celevator:pi_entity",{ initial_properties = { visual = "upright_sprite", physical = false, collisionbox = {0,0,0,0,0,0,}, textures = {"celevator_transparent.png",}, static_save = false, - glow = minetest.LIGHT_MAX, + glow = core.LIGHT_MAX, }, }) -minetest.register_entity("celevator:incar_pi_entity",{ +core.register_entity("celevator:incar_pi_entity",{ initial_properties = { visual = "upright_sprite", physical = false, collisionbox = {0,0,0,0,0,0,}, textures = {"celevator_transparent.png",}, static_save = false, - glow = minetest.LIGHT_MAX, + glow = core.LIGHT_MAX, }, on_step = function(self) + if not self.object then return end local pos = self.object:get_pos() + if not core.compare_block_status(pos,"active") then return self.object:remove() end local props = self.object:get_properties() if props.breath_max and props.breath_max ~= 0 then - local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",props.breath_max))) + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",props.breath_max))) if not carinfo then return end local text = carinfo.pitext or "--" if string.len(text) < 3 then text = string.rep(" ",3-string.len(text))..text end @@ -48,7 +63,7 @@ minetest.register_entity("celevator:incar_pi_entity",{ self.object:set_properties({textures = {etex}}) else local carpos = vector.round(pos) - local carmeta = minetest.get_meta(carpos) + local carmeta = core.get_meta(carpos) local carid = carmeta:get_int("carid") if carid > 0 then self.object:set_properties({breath_max=carid}) end end @@ -56,7 +71,7 @@ minetest.register_entity("celevator:incar_pi_entity",{ }) function celevator.pi.removeentity(pos) - local entitiesnearby = minetest.get_objects_inside_radius(pos,0.5) + local entitiesnearby = core.get_objects_inside_radius(pos,0.5) for _,i in pairs(entitiesnearby) do if i:get_luaentity() and (i:get_luaentity().name == "celevator:pi_entity" or i:get_luaentity().name == "celevator:incar_pi_entity") then i:remove() @@ -80,16 +95,16 @@ end function celevator.pi.updatedisplay(pos) celevator.pi.removeentity(pos) - local meta = minetest.get_meta(pos) + local meta = core.get_meta(pos) local text = meta:get_string("text") - local entity = minetest.add_entity(pos,"celevator:pi_entity") - local fdir = minetest.facedir_to_dir(celevator.get_node(pos).param2) + local entity = core.add_entity(pos,"celevator:pi_entity") + local fdir = core.facedir_to_dir(celevator.get_node(pos).param2) local uparrow = meta:get_int("uparrow") > 0 local downarrow = meta:get_int("downarrow") > 0 local flash_fs = meta:get_int("flash_fs") > 0 local flash_is = meta:get_int("flash_is") > 0 local flashtimer = meta:get_int("flashtimer") > 0 - local islantern = minetest.get_item_group(celevator.get_node(pos).name,"_celevator_lantern") == 1 + local islantern = core.get_item_group(celevator.get_node(pos).name,"_celevator_lantern") == 1 local etex = celevator.pi.generatetexture(text,uparrow,downarrow,islantern) if flash_fs then if flashtimer then etex = celevator.pi.generatetexture(" FS",uparrow,downarrow,islantern) end @@ -106,8 +121,8 @@ function celevator.pi.updatedisplay(pos) end function celevator.pi.flash(pos,what) - if minetest.get_item_group(celevator.get_node(pos).name,"_celevator_pi") ~= 1 then return end - local meta = minetest.get_meta(pos) + if core.get_item_group(celevator.get_node(pos).name,"_celevator_pi") ~= 1 then return end + local meta = core.get_meta(pos) if what == "FS" then meta:set_int("flash_is",0) meta:set_int("flash_fs",1) @@ -123,8 +138,8 @@ end function celevator.pi.settext(pos,text) if not text then text = " --" end - if minetest.get_item_group(celevator.get_node(pos).name,"_celevator_pi") ~= 1 then return end - local meta = minetest.get_meta(pos) + if core.get_item_group(celevator.get_node(pos).name,"_celevator_pi") ~= 1 then return end + local meta = core.get_meta(pos) if string.len(text) < 3 then text = string.rep(" ",3-string.len(text))..text end @@ -133,8 +148,8 @@ function celevator.pi.settext(pos,text) end function celevator.pi.setarrow(pos,which,active) - if minetest.get_item_group(celevator.get_node(pos).name,"_celevator_pi") ~= 1 then return end - local meta = minetest.get_meta(pos) + if core.get_item_group(celevator.get_node(pos).name,"_celevator_pi") ~= 1 then return end + local meta = core.get_meta(pos) if which == "up" then meta:set_int("uparrow",active and 1 or 0) elseif which == "down" then @@ -143,8 +158,8 @@ function celevator.pi.setarrow(pos,which,active) celevator.pi.updatedisplay(pos) end -minetest.register_node("celevator:pi",{ - description = "Elevator Position Indicator", +core.register_node("celevator:pi",{ + description = S("Elevator Position Indicator"), groups = { dig_immediate = 2, _celevator_pi = 1, @@ -169,17 +184,17 @@ minetest.register_node("celevator:pi",{ }, }, after_place_node = function(pos) - local meta = minetest.get_meta(pos) - meta:set_string("formspec","formspec_version[7]size[8,5]field[0.5,0.5;7,1;carid;Car ID;]button[3,3.5;2,1;save;Save]") + local meta = core.get_meta(pos) + meta:set_string("formspec","formspec_version[7]size[8,5]field[0.5,0.5;7,1;carid;"..S("Car ID")..";]button[3,3.5;2,1;save;"..S("Save").."]") end, on_receive_fields = function(pos,_,fields) if tonumber(fields.carid) then local carid = tonumber(fields.carid) - local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid))) + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) if not (carinfo and carinfo.pis) then return end table.insert(carinfo.pis,{pos=pos}) - celevator.storage:set_string(string.format("car%d",carid),minetest.serialize(carinfo)) - local meta = minetest.get_meta(pos) + celevator.storage:set_string(string.format("car%d",carid),core.serialize(carinfo)) + local meta = core.get_meta(pos) meta:set_int("carid",carid) meta:set_string("formspec","") celevator.pi.settext(pos,carinfo.pitext) @@ -187,70 +202,73 @@ minetest.register_node("celevator:pi",{ end, on_destruct = function(pos) celevator.pi.removeentity(pos) - local meta = minetest.get_meta(pos) + local meta = core.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))) + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) if not (carinfo and carinfo.pis) then return end for i,pi in pairs(carinfo.pis) do if vector.equals(pos,pi.pos) then table.remove(carinfo.pis,i) - celevator.storage:set_string(string.format("car%d",carid),minetest.serialize(carinfo)) + celevator.storage:set_string(string.format("car%d",carid),core.serialize(carinfo)) end end end, on_construct = function(pos) - local meta = minetest.get_meta(pos) + local meta = core.get_meta(pos) meta:set_string("text","--") celevator.pi.updatedisplay(pos) end, }) function celevator.lantern.setlight(pos,dir,newstate) + local soundset = core.get_meta(pos):get_int("sound") or 1 + local sounds = celevator.lantern.chimesounds[soundset] + if not sounds then sounds = celevator.lantern.chimesounds[1] end local node = celevator.get_node(pos) - if minetest.get_item_group(node.name,"_celevator_lantern") ~= 1 then return end + if core.get_item_group(node.name,"_celevator_lantern") ~= 1 then return end if dir == "up" then - if minetest.get_item_group(node.name,"_celevator_lantern_has_up") ~= 1 then return end - local lit = minetest.get_item_group(node.name,"_celevator_lantern_up_lit") == 1 + if core.get_item_group(node.name,"_celevator_lantern_has_up") ~= 1 then return end + local lit = core.get_item_group(node.name,"_celevator_lantern_up_lit") == 1 if lit == newstate then return end local newname = "celevator:lantern_" - if minetest.get_item_group(node.name,"_celevator_pi") == 1 then newname = "celevator:pilantern_" end - if minetest.get_item_group(node.name,"_celevator_lantern_vertical") == 1 then newname = "celevator:lantern_vertical_" end - if minetest.get_item_group(node.name,"_celevator_lantern_has_down") == 1 then + if core.get_item_group(node.name,"_celevator_pi") == 1 then newname = "celevator:pilantern_" end + if core.get_item_group(node.name,"_celevator_lantern_vertical") == 1 then newname = "celevator:lantern_vertical_" end + if core.get_item_group(node.name,"_celevator_lantern_has_down") == 1 then newname = newname.."both" else newname = newname.."up" end if newstate then newname = newname.."_upon" - minetest.sound_play("celevator_chime_up",{pos = pos},true) + core.sound_play(sounds.up,{pos = pos},true) end - if minetest.get_item_group(node.name,"_celevator_lantern_down_lit") == 1 then + if core.get_item_group(node.name,"_celevator_lantern_down_lit") == 1 then newname = newname.."_downon" end node.name = newname - minetest.swap_node(pos,node) + core.swap_node(pos,node) elseif dir == "down" then - if minetest.get_item_group(node.name,"_celevator_lantern_has_down") ~= 1 then return end - local lit = minetest.get_item_group(node.name,"_celevator_lantern_down_lit") == 1 + if core.get_item_group(node.name,"_celevator_lantern_has_down") ~= 1 then return end + local lit = core.get_item_group(node.name,"_celevator_lantern_down_lit") == 1 if lit == newstate then return end local newname = "celevator:lantern_" - if minetest.get_item_group(node.name,"_celevator_pi") == 1 then newname = "celevator:pilantern_" end - if minetest.get_item_group(node.name,"_celevator_lantern_vertical") == 1 then newname = "celevator:lantern_vertical_" end - if minetest.get_item_group(node.name,"_celevator_lantern_has_up") == 1 then + if core.get_item_group(node.name,"_celevator_pi") == 1 then newname = "celevator:pilantern_" end + if core.get_item_group(node.name,"_celevator_lantern_vertical") == 1 then newname = "celevator:lantern_vertical_" end + if core.get_item_group(node.name,"_celevator_lantern_has_up") == 1 then newname = newname.."both" else newname = newname.."down" end - if minetest.get_item_group(node.name,"_celevator_lantern_up_lit") == 1 then + if core.get_item_group(node.name,"_celevator_lantern_up_lit") == 1 then newname = newname.."_upon" end if newstate then newname = newname.."_downon" - minetest.sound_play("celevator_chime_down",{pos = pos},true) + core.sound_play(sounds.down,{pos = pos},true) end node.name = newname - minetest.swap_node(pos,node) + core.swap_node(pos,node) end end @@ -326,17 +344,59 @@ local function makeverticallanterntex(dir,upon,downon) return(tex) end +local upname = S("Elevator Up Lantern") +local upvname = S("Elevator Up Lantern (vertical)") +local upcname = S("Elevator Up Position Indicator / Lantern Combo") +local downname = S("Elevator Down Lantern") +local downvname = S("Elevator Down Lantern (vertical)") +local downcname = S("Elevator Down Position Indicator / Lantern Combo") +local bothname = S("Elevator Up and Down Lantern") +local bothvname = S("Elevator Up and Down Lantern (vertical)") +local bothcname = S("Elevator Up and Down Position Indicator / Lantern Combo") + local validstates = { - {"up",false,false,"Up"}, - {"up",true,false,"Up"}, - {"down",false,false,"Down"}, - {"down",false,true,"Down"}, - {"both",false,false,"Up and Down"}, - {"both",true,false,"Up and Down"}, - {"both",false,true,"Up and Down"}, - {"both",true,true,"Up and Down"}, + {"up",false,false,upname,upvname,upcname}, + {"up",true,false,upname,upvname,upcname}, + {"down",false,false,downname,downvname,downcname}, + {"down",false,true,downname,downvname,downcname}, + {"both",false,false,bothname,bothvname,bothcname}, + {"both",true,false,bothname,bothvname,bothcname}, + {"both",false,true,bothname,bothvname,bothcname}, + {"both",true,true,bothname,bothvname,bothcname}, } +function celevator.lantern.makeformspec(pos) + local meta = core.get_meta(pos) + local fs = "formspec_version[7]size[8,5]" + fs = fs.."field[0.5,0.5;7,1;carid;"..S("Car ID")..";]" + fs = fs.."field[0.5,2;3.25,1;landing;"..S("Landing Number")..";]" + fs = fs.."label[4.25,1.85;"..S("Sound").."]" + fs = fs.."dropdown[4.25,2;3.25,1;sound;" + for i=1,#celevator.lantern.chimesounds do + fs = fs..tostring(i).."," + end + fs = string.sub(fs,1,-2) + fs = fs..";1;true]" + fs = fs.."button[3,3.5;2,1;save;"..S("Save").."]" + meta:set_string("formspec",fs) +end + +function celevator.lantern.handlefields(pos,_,fields) + if not fields.save then return end + if tonumber(fields.carid) and tonumber(fields.landing) then + local carid = tonumber(fields.carid) + local landing = tonumber(fields.landing) + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) + if not (carinfo and carinfo.lanterns) then return end + table.insert(carinfo.lanterns,{pos=pos,landing=landing}) + celevator.storage:set_string(string.format("car%d",carid),core.serialize(carinfo)) + local meta = core.get_meta(pos) + meta:set_int("carid",carid) + meta:set_string("formspec","") + meta:set_int("sound",tonumber(fields.sound) or 1) + end +end + for _,state in ipairs(validstates) do local nname = "celevator:pilantern_"..state[1] local dropname = nname @@ -350,8 +410,8 @@ for _,state in ipairs(validstates) do light = light + 4 end local idle = not (state[2] or state[3]) - local description = string.format("Elevator %s Position Indicator/Lantern Combo%s",state[4],(idle and "" or " (on state, you hacker you!)")) - minetest.register_node(nname,{ + local description = state[6] + core.register_node(nname,{ description = description, groups = { dig_immediate = 2, @@ -383,47 +443,46 @@ for _,state in ipairs(validstates) do {-0.25,-0.5,0.475,0.25,0.125,0.5}, }, }, - after_place_node = function(pos) - local meta = minetest.get_meta(pos) - meta:set_string("formspec","formspec_version[7]size[8,5]field[0.5,0.5;7,1;carid;Car ID;]field[0.5,2;7,1;landing;Landing Number;]button[3,3.5;2,1;save;Save]") - end, + after_place_node = celevator.lantern.makeformspec, on_receive_fields = function(pos,_,fields) + if not fields.save then return end if tonumber(fields.carid) and tonumber(fields.landing) then local carid = tonumber(fields.carid) local landing = tonumber(fields.landing) - local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid))) + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) if not (carinfo and carinfo.pis and carinfo.lanterns) then return end table.insert(carinfo.pis,{pos=pos}) table.insert(carinfo.lanterns,{pos=pos,landing=landing}) - celevator.storage:set_string(string.format("car%d",carid),minetest.serialize(carinfo)) - local meta = minetest.get_meta(pos) + celevator.storage:set_string(string.format("car%d",carid),core.serialize(carinfo)) + local meta = core.get_meta(pos) meta:set_int("carid",carid) meta:set_string("formspec","") celevator.pi.settext(pos,carinfo.pitext) + meta:set_int("sound",tonumber(fields.sound) or 1) end end, on_destruct = function(pos) celevator.pi.removeentity(pos) - local meta = minetest.get_meta(pos) + local meta = core.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))) + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) if not (carinfo and carinfo.pis and carinfo.lanterns) then return end for i,pi in pairs(carinfo.pis) do if vector.equals(pos,pi.pos) then table.remove(carinfo.pis,i) - celevator.storage:set_string(string.format("car%d",carid),minetest.serialize(carinfo)) + celevator.storage:set_string(string.format("car%d",carid),core.serialize(carinfo)) end end for i,lantern in pairs(carinfo.lanterns) do if vector.equals(pos,lantern.pos) then table.remove(carinfo.lanterns,i) - celevator.storage:set_string(string.format("car%d",carid),minetest.serialize(carinfo)) + celevator.storage:set_string(string.format("car%d",carid),core.serialize(carinfo)) end end end, on_construct = function(pos) - local meta = minetest.get_meta(pos) + local meta = core.get_meta(pos) meta:set_string("text","--") celevator.pi.updatedisplay(pos) end, @@ -433,8 +492,8 @@ for _,state in ipairs(validstates) do if state[2] then nname = nname.."_upon" end if state[3] then nname = nname.."_downon" end idle = not (state[2] or state[3]) - description = string.format("Elevator %s Lantern%s",state[4],(idle and "" or " (on state, you hacker you!)")) - minetest.register_node(nname,{ + description = state[4] + core.register_node(nname,{ description = description, inventory_image = string.format("[combine:32x32:0,5=celevator_lantern_background_%s.png",(state[1] == "both" and "updown" or state[1])), groups = { @@ -455,33 +514,18 @@ for _,state in ipairs(validstates) do boringside, makelanterntex(state[1],state[2],state[3]) }, - after_place_node = function(pos) - local meta = minetest.get_meta(pos) - meta:set_string("formspec","formspec_version[7]size[8,5]field[0.5,0.5;7,1;carid;Car ID;]field[0.5,2;7,1;landing;Landing Number;]button[3,3.5;2,1;save;Save]") - end, - on_receive_fields = function(pos,_,fields) - if tonumber(fields.carid) and tonumber(fields.landing) then - local carid = tonumber(fields.carid) - local landing = tonumber(fields.landing) - local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid))) - if not (carinfo and carinfo.lanterns) then return end - table.insert(carinfo.lanterns,{pos=pos,landing=landing}) - celevator.storage:set_string(string.format("car%d",carid),minetest.serialize(carinfo)) - local meta = minetest.get_meta(pos) - meta:set_int("carid",carid) - meta:set_string("formspec","") - end - end, + after_place_node = celevator.lantern.makeformspec, + on_receive_fields = celevator.lantern.handlefields, on_destruct = function(pos) - local meta = minetest.get_meta(pos) + local meta = core.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))) + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) if not (carinfo and carinfo.lanterns) then return end for i,lantern in pairs(carinfo.lanterns) do if vector.equals(pos,lantern.pos) then table.remove(carinfo.lanterns,i) - celevator.storage:set_string(string.format("car%d",carid),minetest.serialize(carinfo)) + celevator.storage:set_string(string.format("car%d",carid),core.serialize(carinfo)) end end end, @@ -500,8 +544,8 @@ for _,state in ipairs(validstates) do dropname = nname if state[2] then nname = nname.."_upon" end if state[3] then nname = nname.."_downon" end - description = string.format("Elevator %s Lantern (vertical)%s",state[4],(idle and "" or " (on state, you hacker you!)")) - minetest.register_node(nname,{ + description = state[5] + core.register_node(nname,{ description = description, inventory_image = string.format("[combine:40x40:10,0=celevator_lantern_vertical_background_%s.png",(state[1] == "both" and "updown" or state[1])), groups = { @@ -523,33 +567,18 @@ for _,state in ipairs(validstates) do boringside, makeverticallanterntex(state[1],state[2],state[3]) }, - after_place_node = function(pos) - local meta = minetest.get_meta(pos) - meta:set_string("formspec","formspec_version[7]size[8,5]field[0.5,0.5;7,1;carid;Car ID;]field[0.5,2;7,1;landing;Landing Number;]button[3,3.5;2,1;save;Save]") - end, - on_receive_fields = function(pos,_,fields) - if tonumber(fields.carid) and tonumber(fields.landing) then - local carid = tonumber(fields.carid) - local landing = tonumber(fields.landing) - local carinfo = minetest.deserialize(celevator.storage:get_string(string.format("car%d",carid))) - if not (carinfo and carinfo.lanterns) then return end - table.insert(carinfo.lanterns,{pos=pos,landing=landing}) - celevator.storage:set_string(string.format("car%d",carid),minetest.serialize(carinfo)) - local meta = minetest.get_meta(pos) - meta:set_int("carid",carid) - meta:set_string("formspec","") - end - end, + after_place_node = celevator.lantern.makeformspec, + on_receive_fields = celevator.lantern.handlefields, on_destruct = function(pos) - local meta = minetest.get_meta(pos) + local meta = core.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))) + local carinfo = core.deserialize(celevator.storage:get_string(string.format("car%d",carid))) if not (carinfo and carinfo.lanterns) then return end for i,lantern in pairs(carinfo.lanterns) do if vector.equals(pos,lantern.pos) then table.remove(carinfo.lanterns,i) - celevator.storage:set_string(string.format("car%d",carid),minetest.serialize(carinfo)) + celevator.storage:set_string(string.format("car%d",carid),core.serialize(carinfo)) end end end, @@ -566,15 +595,42 @@ for _,state in ipairs(validstates) do }) end -minetest.register_abm({ +core.register_abm({ label = "Respawn / Flash PI displays", nodenames = {"group:_celevator_pi"}, interval = 1, chance = 1, action = function(pos) - local meta = minetest.get_meta(pos) + local meta = core.get_meta(pos) local flashtimer = meta:get_int("flashtimer") > 0 meta:set_int("flashtimer",flashtimer and 0 or 1) celevator.pi.updatedisplay(pos) end, }) + +core.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 = core.get_meta(pos) + local carid = meta:get_int("carid") + if not (carid and carid > 0) then return end --Not set up yet + local carinfo = core.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/settingtypes.txt b/settingtypes.txt new file mode 100644 index 0000000..ef4023f --- /dev/null +++ b/settingtypes.txt @@ -0,0 +1,32 @@ +[Limits] + +# The maximum distance that will be checked for a car when configuring a hoist machine. +# This determines the height of the tallest possible elevator. +# Reducing this value does not affect existing elevators. +# NOTE: In the worst case, a vertical column of mapblocks this tall may have to be emerged. +celevator.max_height (Maximum height) int 500 3 65535 + +# The highest number of landings that any one elevator or group can serve. +# Values much higher than 100 are likely to not fit on most screens. +# Reducing this value does not remove landings from existing elevators or groups. +celevator.max_landings (Maximum landings) int 100 2 1000 + +# The maximum number of cars in a group. +# Reducing this value does not remove cars from existing groups. +celevator.max_group (Maximum group size) int 16 2 16 + +# The maximum speed of an elevator, in meters/nodes per second. +# Depending on the server's active block range and mapblock load speed, +# setting an elevator to a speed too high may cause players to fall out. +celevator.max_speed (Maximum speed) float 20.0 1.0 100.0 + +[Protection] + +# Car top inspection controls require area access to operate +celevator.cartop_protected (Car top controls protected) bool false + +# Controller and dispatcher cabinets require area access to open +celevator.controller_cabinet_protected (Controller cabinet protected) bool true + +# Open controllers/dispatchers require area access to interact with +celevator.controller_screen_protected (Controller screen protected) bool false diff --git a/sounds/celevator_alarm.ogg b/sounds/celevator_alarm.ogg Binary files differnew file mode 100644 index 0000000..561ac4e --- /dev/null +++ b/sounds/celevator_alarm.ogg diff --git a/sounds/celevator_chime2_down.ogg b/sounds/celevator_chime2_down.ogg Binary files differnew file mode 100644 index 0000000..479e213 --- /dev/null +++ b/sounds/celevator_chime2_down.ogg diff --git a/sounds/celevator_chime2_up.ogg b/sounds/celevator_chime2_up.ogg Binary files differnew file mode 100644 index 0000000..4723252 --- /dev/null +++ b/sounds/celevator_chime2_up.ogg diff --git a/sounds/celevator_phone.ogg b/sounds/celevator_phone.ogg Binary files differnew file mode 100644 index 0000000..ae12398 --- /dev/null +++ b/sounds/celevator_phone.ogg diff --git a/textures/celevator_car_fullglass_inventory.png b/textures/celevator_car_fullglass_inventory.png Binary files differnew file mode 100644 index 0000000..fb50175 --- /dev/null +++ b/textures/celevator_car_fullglass_inventory.png diff --git a/textures/celevator_car_fullglass_wield.png b/textures/celevator_car_fullglass_wield.png Binary files differnew file mode 100644 index 0000000..653e453 --- /dev/null +++ b/textures/celevator_car_fullglass_wield.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_copbutton_alarm.png b/textures/celevator_copbutton_alarm.png Binary files differnew file mode 100644 index 0000000..3ad852e --- /dev/null +++ b/textures/celevator_copbutton_alarm.png diff --git a/textures/celevator_copbutton_phone.png b/textures/celevator_copbutton_phone.png Binary files differnew file mode 100644 index 0000000..dc8b9a6 --- /dev/null +++ b/textures/celevator_copbutton_phone.png diff --git a/textures/celevator_door_centerglass_inventory.png b/textures/celevator_door_centerglass_inventory.png Binary files differnew file mode 100644 index 0000000..adc0741 --- /dev/null +++ b/textures/celevator_door_centerglass_inventory.png diff --git a/textures/celevator_door_centermetal_inventory.png b/textures/celevator_door_centermetal_inventory.png Binary files differnew file mode 100644 index 0000000..d60464e --- /dev/null +++ b/textures/celevator_door_centermetal_inventory.png diff --git a/textures/celevator_door_glass_inventory.png b/textures/celevator_door_glass_inventory.png Binary files differindex 4ebf6f9..41450a2 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..1706658 --- /dev/null +++ b/textures/celevator_door_metal_inventory.png diff --git a/textures/celevator_door_sill.png b/textures/celevator_door_sill.png Binary files differnew file mode 100644 index 0000000..651cf50 --- /dev/null +++ b/textures/celevator_door_sill.png diff --git a/textures/celevator_door_sill_double.png b/textures/celevator_door_sill_double.png Binary files differdeleted file mode 100644 index ca80c97..0000000 --- a/textures/celevator_door_sill_double.png +++ /dev/null diff --git a/textures/celevator_door_sill_single.png b/textures/celevator_door_sill_single.png Binary files differdeleted file mode 100644 index 7f3d611..0000000 --- a/textures/celevator_door_sill_single.png +++ /dev/null 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 diff --git a/textures/celevator_menu_small_arrow.png b/textures/celevator_menu_small_arrow.png Binary files differnew file mode 100644 index 0000000..5ab4761 --- /dev/null +++ b/textures/celevator_menu_small_arrow.png |
