From 08cbd3adfe523ae8ad4e7263f11ff5ae1d521230 Mon Sep 17 00:00:00 2001 From: cheapie Date: Tue, 8 Aug 2023 22:16:42 -0500 Subject: Add initial car motion functionality Place a machine (no texture yet) above the car somewhere when the car is at the lowest floor, then pair it to the drive with the pairing tool. Not much error checking yet, it'll probably crash if you do anything weird. --- car.lua | 24 ++++++++++++- controllerfw.lua | 5 +++ drive_entity.lua | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- pairingtool.lua | 43 +++++++++++++++++++++++ 4 files changed, 169 insertions(+), 5 deletions(-) diff --git a/car.lua b/car.lua index c89015e..5211ecb 100644 --- a/car.lua +++ b/car.lua @@ -314,11 +314,33 @@ local pieces = { for _,def in ipairs(pieces) do def.groups = { dig_immediate = 2, + _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 - def.light_source = minetest.LIGHT_MAX + def.light_source = 9 minetest.register_node("celevator:car_"..def._position,def) end diff --git a/controllerfw.lua b/controllerfw.lua index 2640af2..4ac888c 100644 --- a/controllerfw.lua +++ b/controllerfw.lua @@ -19,6 +19,10 @@ if not mem.drive.status then } end +if mem.drive.state == "uninit" then + fault("driveuninit",true) +end + local juststarted = false local modenames = { @@ -48,6 +52,7 @@ local doorstates = { local faultnames = { drivecomm = "Lost Communication With Drive", + driveuninit = "Drive Not Configured", } local function drivecmd(command) diff --git a/drive_entity.lua b/drive_entity.lua index 79a3990..ace5dd6 100644 --- a/drive_entity.lua +++ b/drive_entity.lua @@ -57,6 +57,7 @@ minetest.register_node("celevator:drive",{ description = celevator.drives.entity.name, groups = { cracky = 1, + _celevator_drive = 1, }, tiles = { "celevator_cabinet_sides.png", @@ -84,9 +85,8 @@ minetest.register_node("celevator:drive",{ meta:set_string("dpos","0") meta:set_string("vel","0") meta:set_string("maxvel","0.2") - meta:set_string("state","stopped") + meta:set_string("state","uninit") meta:set_string("startpos","0") - meta:set_string("origin",minetest.pos_to_string(vector.new(-726,9,77))) update_ui(pos) end, on_destruct = stopbuzz, @@ -98,9 +98,36 @@ minetest.register_entity("celevator:car_moving",{ visual_size = vector.new(0.667,0.667,0.667), wield_item = "default:dirt", static_save = false, + glow = minetest.LIGHT_MAX, }, }) +function celevator.drives.entity.gathercar(pos,yaw,nodes) + if not nodes then nodes = {} end + local hash = minetest.hash_node_position(pos) + if nodes[hash] then return nodes end + nodes[hash] = true + if minetest.get_item_group(minetest.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(minetest.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(minetest.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(minetest.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(minetest.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(minetest.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 +end + function celevator.drives.entity.nodestoentities(nodes) local refs = {} for _,pos in ipairs(nodes) do @@ -156,7 +183,18 @@ function celevator.drives.entity.step() end if state == "start" then sound = true - local handles = celevator.drives.entity.nodestoentities({vector.add(origin,vector.new(0,startpos,0))}) + 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(minetest.get_node(startv).param2))) + local nodes = {} + for carhash in pairs(hashes) do + local carpos = minetest.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 + table.insert(nodes,carpos) + end + end + local handles = celevator.drives.entity.nodestoentities(nodes) celevator.drives.entity.entityinfo[hash] = { handles = handles, } @@ -207,6 +245,7 @@ minetest.register_globalstep(celevator.drives.entity.step) function celevator.drives.entity.moveto(pos,target) local meta = minetest.get_meta(pos) + if meta:get_string("state") ~= "stopped" then return end meta:set_string("dpos",tostring(target)) meta:set_string("state","start") meta:set_string("startpos",meta:get_string("apos")) @@ -233,7 +272,7 @@ end function celevator.drives.entity.estop(pos) local meta = minetest.get_meta(pos) - if meta:get_string("state") == "stopped" then return end + if meta:get_string("state") ~= "running" then return end local apos = math.floor(tonumber(meta:get_string("apos"))+0.5) meta:set_string("dpos",tostring(apos)) local hash = minetest.hash_node_position(pos) @@ -270,6 +309,61 @@ function celevator.drives.entity.getstatus(pos,call2) ret.dpos = tonumber(meta:get_string("dpos")) or 0 ret.vel = tonumber(meta:get_string("vel")) or 0 ret.maxvel = tonumber(meta:get_string("maxvel")) or 0.2 + ret.state = meta:get_string("state") return ret end end + +local function carsearch(pos) + for i=1,500,1 do + local searchpos = vector.subtract(pos,vector.new(0,i,0)) + local node = minetest.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 + local xoffset = tonumber(string.sub(offsettext,1,1)) + local yoffset = tonumber(string.sub(offsettext,2,2)) + local zoffset = tonumber(string.sub(offsettext,3,3)) + local offset = vector.new(xoffset,yoffset,zoffset) + offset = vector.rotate_around_axis(offset,vector.new(0,1,0),yaw) + return vector.subtract(searchpos,offset) + end + end +end + +local function updatecarpos(pos) + local meta = minetest.get_meta(pos) + local carpos = carsearch(pos) + if carpos then + meta:set_string("origin",minetest.pos_to_string(carpos)) + meta:set_string("infotext",string.format("Using car with origin %s",minetest.pos_to_string(carpos))) + else + meta:set_string("infotext","No car found! Punch to try again") + end +end + +minetest.register_node("celevator:machine",{ + description = "Hoist Machine", + groups = { + dig_immediate = 2, + _celevator_machine = 1, + }, + paramtype = "light", + paramtype2 = "4dir", + tiles = { + "default_dirt.png", + }, + after_place_node = updatecarpos, + on_punch = function(pos,_,player) + if not player:is_player() 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,"Can't open cabinet - cabinet is locked.") + minetest.record_protection_violation(pos,name) + return + end + updatecarpos(pos) + end, +}) diff --git a/pairingtool.lua b/pairingtool.lua index 9bea461..7a48f31 100644 --- a/pairingtool.lua +++ b/pairingtool.lua @@ -50,6 +50,49 @@ minetest.register_tool("celevator:pairingtool",{ local stackmeta = itemstack:get_meta() stackmeta:set_string("controllerpos",minetest.pos_to_string(pos)) minetest.chat_send_player(name,"Now pairing with controller at "..minetest.pos_to_string(pos)) + elseif minetest.get_item_group(node.name,"_celevator_drive") == 1 then + local stackmeta = itemstack:get_meta() + stackmeta:set_string("drivepos",minetest.pos_to_string(pos)) + minetest.chat_send_player(name,"Now pairing with drive at "..minetest.pos_to_string(pos)) + elseif minetest.get_item_group(node.name,"_celevator_machine") == 1 then + local stackmeta = itemstack:get_meta() + local nodemeta = minetest.get_meta(pos) + local oldpairing = minetest.string_to_pos(nodemeta:get_string("drivepos")) + local drivepos = minetest.string_to_pos(stackmeta:get_string("drivepos")) + local origin = minetest.string_to_pos(nodemeta:get_string("origin")) + if not origin then + minetest.chat_send_player(name,"Car has not been located! Try punching the machine to search for one.") + elseif not drivepos then + minetest.chat_send_player(name,"Nothing has been selected to pair with! Punch a drive first.") + elseif oldpairing then + local drivemeta = minetest.get_meta(oldpairing) + drivemeta:set_string("machinepos","") + drivemeta:set_string("apos","0") + drivemeta:set_string("dpos","0") + drivemeta:set_string("vel","0") + drivemeta:set_string("maxvel","0.2") + drivemeta:set_string("state","uninit") + drivemeta:set_string("startpos","0") + drivemeta:set_string("origin",minetest.pos_to_string(origin)) + nodemeta:set_string("drivepos","") + minetest.chat_send_player(player:get_player_name(),"Unpaired from "..minetest.pos_to_string(oldpairing)) + elseif minetest.get_item_group(minetest.get_node(drivepos).name,"_celevator_drive") ~= 1 then + minetest.chat_send_player(name,"Drive has been removed. Punch a new drive to pair to that one.") + else + if minetest.is_protected(drivepos,name) and not minetest.check_player_privs(name,{protection_bypass=true}) then + minetest.chat_send_player(name,"Unable to pair - drive at "..minetest.pos_to_string(drivepos).." is protected!") + minetest.record_protection_violation(drivepos,name) + elseif minetest.is_protected(pos,name) and not minetest.check_player_privs(name,{protection_bypass=true}) then + minetest.chat_send_player(name,"Unable to pair - item to be paired is protected!") + minetest.record_protection_violation(pos,name) + else + local drivemeta = minetest.get_meta(drivepos) + nodemeta:set_string("drivepos",minetest.pos_to_string(drivepos)) + drivemeta:set_string("machinepos",minetest.pos_to_string(pos)) + drivemeta:set_string("state","stopped") + minetest.chat_send_player(player:get_player_name(),"Machine paired to "..minetest.pos_to_string(drivepos)) + end + end elseif minetest.get_item_group(node.name,"_celevator_callbutton") == 1 then local stackmeta = itemstack:get_meta() local nodemeta = minetest.get_meta(pos) -- cgit v1.2.3