diff options
Diffstat (limited to 'drive_entity.lua')
| -rw-r--r-- | drive_entity.lua | 518 |
1 files changed, 335 insertions, 183 deletions
diff --git a/drive_entity.lua b/drive_entity.lua index ae72bca..e2d2655 100644 --- a/drive_entity.lua +++ b/drive_entity.lua @@ -1,6 +1,8 @@ +local S = core.get_translator("celevator") + 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 +11,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 +49,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 +130,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 +140,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 +179,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 +215,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 +229,112 @@ 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", 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", + }, + --I have no idea where this magic number comes from, but it seems about right and that's good enough + visual_size = vector.new(3,3,3), + static_save = false, pointable = false, }, + on_step = function(self,dtime) + local obj = self.object + local car,_,attachoffset = obj:get_attach() + if not car then + obj:remove() + return + end + local children = obj:get_children() + local player + for _,i in pairs(children) do + if i:is_player() then + player = i + end + end + if not player then return end + local caryaw = car:get_yaw() + local playeryaw = player:get_look_horizontal() + local attachrot = vector.new(0,(caryaw-playeryaw)*57.296,0) + local control = player:get_player_control() + if (control.up or control.down or control.left or control.right) then + local walkspeed = 120 + local walkamount = walkspeed*dtime + local displacement = vector.new(0,0,0) + if control.up then + displacement = vector.add(displacement,vector.new(0,0,walkamount)) + end + if control.down then + displacement = vector.add(displacement,vector.new(0,0,0-walkamount)) + end + if control.left then + displacement = vector.add(displacement,vector.new(0-walkamount,0,0)) + end + if control.right then + displacement = vector.add(displacement,vector.new(walkamount,0,0)) + end + displacement = vector.rotate_around_axis(displacement,vector.new(0,1,0),playeryaw) + displacement = vector.rotate_around_axis(displacement,vector.new(0,-1,0),caryaw) + local oldattachoffset = vector.copy(attachoffset) + attachoffset = vector.add(attachoffset,displacement) + local realattachoffset = vector.rotate_around_axis(vector.multiply(attachoffset,1/30),vector.new(0,1,0),caryaw) + local newpos = vector.add(car:get_pos(),realattachoffset) + local limits = playerposlimits[player:get_player_name()] or {} + if limits.xmin and limits.xmax and limits.xmin < limits.xmax then + if newpos.x > limits.xmax or newpos.x < limits.xmin then + attachoffset = oldattachoffset + end + end + if limits.zmin and limits.zmax and limits.zmin < limits.zmax then + if newpos.z > limits.zmax or newpos.z < limits.zmin then + attachoffset = oldattachoffset + end + end + end + obj:set_attach(car,"",attachoffset,vector.new(0,0,0)) + player:set_attach(obj,"",vector.new(0,0,0),attachrot) + end, }) function celevator.drives.entity.gathercar(pos,yaw,nodes) if not nodes then nodes = {} end - local hash = minetest.hash_node_position(pos) + 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 +342,29 @@ 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, }) - eref:set_yaw(minetest.dir_to_yaw(minetest.fourdir_to_dir(node.param2))) + eref:set_yaw(core.dir_to_yaw(core.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 {} + 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 +379,31 @@ function celevator.drives.entity.nodestoentities(nodes,ename) } if attachref:get_luaentity() and included[attachref:get_luaentity().name] then table.insert(refs,attachref) + elseif attachref:is_player() then + local attachpos = attachref:get_pos() + local basepos = eref:get_pos() + local attachoffset = vector.subtract(attachpos,basepos) + attachoffset = vector.rotate_around_axis(attachoffset,vector.new(0,-1,0),eref:get_yaw()) + local holder = core.add_entity(attachpos,"celevator:player_holder") + holder:set_attach(eref,"",vector.multiply(attachoffset,30),vector.new(0,0,0)) + attachref:set_attach(holder,"") + local extra = 0.25 --To allow getting closer to walls + playerposlimits[attachref:get_player_name()] = { + xmin = xmin-extra, + xmax = xmax+extra, + zmin = zmin-extra, + zmax = zmax+extra, + } else local attachpos = attachref:get_pos() local basepos = eref:get_pos() - local attachoffset = vector.multiply(vector.subtract(attachpos,basepos),30) + local attachoffset = vector.subtract(attachpos,basepos) attachoffset = vector.rotate_around_axis(attachoffset,vector.new(0,-1,0),eref:get_yaw()) - attachref:set_attach(eref,"",attachoffset) + attachref:set_attach(eref,"",vector.multiply(attachoffset,30),vector.new(0,0,0)) end end end - minetest.remove_node(pos) + core.remove_node(pos) end return refs end @@ -309,10 +418,10 @@ function celevator.drives.entity.entitiestonodes(refs,carid) pos = vector.round(pos) local node = { name = eref:get_properties().wield_item, - param2 = minetest.dir_to_fourdir(minetest.yaw_to_dir(eref:get_yaw())) + param2 = core.dir_to_fourdir(core.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) + if core.get_item_group(eref:get_properties().wield_item,"_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 +438,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 +466,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 +488,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 +507,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 +518,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 +553,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 +607,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,21 +650,36 @@ 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 @@ -553,8 +703,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 +713,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 +738,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,7 +747,7 @@ 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 @@ -611,12 +762,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 +786,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,15 +822,15 @@ 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) @@ -689,9 +840,9 @@ local function carsearch(pos) for i=1,500,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 +858,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 +931,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,15 +986,15 @@ 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 @@ -853,8 +1004,8 @@ minetest.register_node("celevator:machine",{ 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,8 +1013,8 @@ 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 = { not_in_creative_inventory = 1, }, @@ -896,8 +1047,8 @@ 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 = { not_in_creative_inventory = 1, }, @@ -929,8 +1080,8 @@ 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 = { not_in_creative_inventory = 1, }, @@ -962,7 +1113,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 +1124,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,46 +1139,47 @@ 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")) + 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 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))) + local carnodes = celevator.drives.entity.gathercar(carpos,core.dir_to_yaw(core.fourdir_to_dir(celevator.get_node(carpos).param2))) for hash in pairs(carnodes) do - local piecepos = minetest.get_position_from_hash(hash) + local piecepos = core.get_position_from_hash(hash) local piece = celevator.get_node(piecepos) - if piece.name == "celevator:car_010" then + local ndef = core.registered_nodes[piece.name] or {} + if ndef._cop then celevator.get_meta(piecepos):set_string("formspec",copformspec) - elseif piece.name == "celevator:car_000" then + elseif ndef._keyswitches then celevator.get_meta(piecepos):set_string("formspec",switchformspec) end end |
