diff options
Diffstat (limited to 'advtrains/wagons.lua')
-rw-r--r-- | advtrains/wagons.lua | 180 |
1 files changed, 125 insertions, 55 deletions
diff --git a/advtrains/wagons.lua b/advtrains/wagons.lua index f9b29bb..cf15871 100644 --- a/advtrains/wagons.lua +++ b/advtrains/wagons.lua @@ -13,7 +13,13 @@ local GETOFF_TP_DELAY = 0.5 local IGNORE_WORLD = advtrains.IGNORE_WORLD advtrains.wagons = {} -advtrains.wagon_prototypes = {} +advtrains.wagon_alias = {} +advtrains.wagon_prototypes = setmetatable({}, { + __index = function(t, k) + local _, proto = advtrains.resolve_wagon_alias(k) + return proto + end +}) advtrains.wagon_objects = {} local unload_wgn_range = advtrains.wagon_load_range + 32 @@ -280,7 +286,7 @@ function wagon:on_step(dtime) local data = advtrains.wagons[self.id] if not pos then - --atdebug("["..self.id.."][fatal] missing position (object:getpos() returned nil)") + --atdebug("["..self.id.."][fatal] missing position (object:get_pos() returned nil)") return end @@ -814,8 +820,8 @@ function wagon:get_off(seatno) end --if not door_entry, or paths missing, fall back to old method --atdebug("using fallback") - local objpos=advtrains.round_vector_floor_y(self.object:getpos()) - local yaw=self.object:getyaw() + local objpos=advtrains.round_vector_floor_y(self.object:get_pos()) + local yaw=self.object:get_yaw() local isx=(yaw < math.pi/4) or (yaw > 3*math.pi/4 and yaw < 5*math.pi/4) or (yaw > 7*math.pi/4) local offp --abuse helper function @@ -868,6 +874,7 @@ function wagon:show_wagon_properties(pname) ]] local data = advtrains.wagons[self.id] local form="size[5,5]" + form=form.."label[0.2,0;"..attrans("This Wagon ID")..": "..self.id.."]" form = form .. "field[0.5,1;4.5,1;whitelist;Allow these players to access your wagon:;"..minetest.formspec_escape(data.whitelist or "").."]" form = form .. "field[0.5,2;4.5,1;roadnumber;Wagon road number:;"..minetest.formspec_escape(data.roadnumber or "").."]" local fc = "" @@ -892,7 +899,7 @@ end --BordCom local function checkcouple(ent) - if not ent or not ent:getyaw() then + if not ent or not ent:get_yaw() then return nil end local le = ent:get_luaentity() @@ -971,6 +978,7 @@ function wagon:show_bordcom(pname) local linhei local form = "size[11,9]label[0.5,0;AdvTrains Boardcom v0.1]" + form=form.."textarea[7.5,0.05;10,1;;"..attrans("Train ID")..": "..(minetest.formspec_escape(train.id or ""))..";]" form=form.."textarea[0.5,1.5;7,1;text_outside;"..attrans("Text displayed outside on train")..";"..(minetest.formspec_escape(train.text_outside or "")).."]" form=form.."textarea[0.5,3;7,1;text_inside;"..attrans("Text displayed inside train")..";"..(minetest.formspec_escape(train.text_inside or "")).."]" form=form.."field[7.5,1.75;3,1;line;"..attrans("Line")..";"..(minetest.formspec_escape(train.line or "")).."]" @@ -1088,12 +1096,11 @@ function wagon:handle_bordcom_fields(pname, formname, fields) for i, tpid in ipairs(train.trainparts) do if fields["dcpl_"..i] then advtrains.safe_decouple_wagon(tpid, pname) - elseif fields["wgprp"..i] then - for _,wagon in pairs(minetest.luaentities) do - if wagon.is_wagon and wagon.initialized and wagon.id==tpid and data.owner==pname then - wagon:show_wagon_properties(pname) - return - end + elseif fields["wgprp"..i] and data.owner==pname then + local wagon = advtrains.get_wagon_entity(tpid) + if wagon then + wagon:show_wagon_properties(pname) + return end end end @@ -1139,44 +1146,48 @@ end minetest.register_on_player_receive_fields(function(player, formname, fields) local uid=string.match(formname, "^advtrains_geton_(.+)$") if uid then - for _,wagon in pairs(minetest.luaentities) do - if wagon.is_wagon and wagon.initialized and wagon.id==uid then - local data = advtrains.wagons[wagon.id] - if fields.inv then - if wagon.has_inventory and wagon.get_inventory_formspec then - minetest.show_formspec(player:get_player_name(), "advtrains_inv_"..uid, wagon:get_inventory_formspec(player:get_player_name(), make_inv_name(uid))) - end - elseif fields.seat then - local val=minetest.explode_textlist_event(fields.seat) - if val and val.type~="INV" and not data.seatp[player:get_player_name()] then - --get on - wagon:get_on(player, val.index) - --will work with the new close_formspec functionality. close exactly this formspec. - minetest.show_formspec(player:get_player_name(), formname, "") - end + local wagon = advtrains.get_wagon_entity(uid) + if wagon then + local data = advtrains.wagons[wagon.id] + if fields.inv then + if wagon.has_inventory and wagon.get_inventory_formspec then + minetest.show_formspec(player:get_player_name(), "advtrains_inv_"..uid, wagon:get_inventory_formspec(player:get_player_name(), make_inv_name(uid))) + end + elseif fields.seat then + local val=minetest.explode_textlist_event(fields.seat) + if val and val.type~="INV" and not data.seatp[player:get_player_name()] then + --get on + wagon:get_on(player, val.index) + --will work with the new close_formspec functionality. close exactly this formspec. + minetest.show_formspec(player:get_player_name(), formname, "") end end end + return true end + uid=string.match(formname, "^advtrains_seating_(.+)$") if uid then - for _,wagon in pairs(minetest.luaentities) do - if wagon.is_wagon and wagon.initialized and wagon.id==uid then - local pname=player:get_player_name() - local no=wagon:get_seatno(pname) - if no then - if wagon.seat_groups then - wagon:seating_from_key_helper(pname, fields, no) - end + local wagon = advtrains.get_wagon_entity(uid) + if wagon then + local pname=player:get_player_name() + local no=wagon:get_seatno(pname) + if no then + if wagon.seat_groups then + wagon:seating_from_key_helper(pname, fields, no) end end end + return true end + uid=string.match(formname, "^advtrains_prop_(.+)$") if uid then local pname=player:get_player_name() local data = advtrains.wagons[uid] - if pname~=data.owner and not minetest.check_player_privs(pname, {train_admin = true}) then + if not data then + return true + elseif pname~=data.owner and not minetest.check_player_privs(pname, {train_admin = true}) then return true end if fields.save or not fields.quit then @@ -1198,29 +1209,32 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) wagon.show_wagon_properties({id=uid}, pname) end end + return true end uid=string.match(formname, "^advtrains_bordcom_(.+)$") if uid then - for _,wagon in pairs(minetest.luaentities) do - if wagon.is_wagon and wagon.initialized and wagon.id==uid then - wagon:handle_bordcom_fields(player:get_player_name(), formname, fields) - end + local wagon = advtrains.get_wagon_entity(uid) + if wagon then + wagon:handle_bordcom_fields(player:get_player_name(), formname, fields) end + return true end + uid=string.match(formname, "^advtrains_inv_(.+)$") if uid then local pname=player:get_player_name() local data = advtrains.wagons[uid] if fields.prop and data.owner==pname then - for _,wagon in pairs(minetest.luaentities) do - if wagon.is_wagon and wagon.initialized and wagon.id==uid and data.owner==pname then - wagon:show_wagon_properties(pname) - --wagon:handle_bordcom_fields(player:get_player_name(), formname, fields) - end + local wagon = advtrains.get_wagon_entity(uid) + if wagon then + wagon:show_wagon_properties(pname) + --wagon:handle_bordcom_fields(player:get_player_name(), formname, fields) end end + return true end end) + function wagon:seating_from_key_helper(pname, fields, no) local data = advtrains.wagons[self.id] local sgr=self.seats[no].group @@ -1259,7 +1273,7 @@ function wagon:check_seat_group_access(pname, sgr) return false, attrans("You are not allowed to access the driver stand.") end if self.seat_groups[sgr].driving_ctrl_access then - advtrains.log("Drive", pname, self.object:getpos(), self:train().text_outside) + advtrains.log("Drive", pname, self.object:get_pos(), self:train().text_outside) end return true end @@ -1317,11 +1331,33 @@ function advtrains.get_wagon_prototype(data) data.type = data.entity_name data.entity_name = nil end - if not wt or not advtrains.wagon_prototypes[wt] then + local rt, proto = advtrains.resolve_wagon_alias(wt) + if not rt then atwarn("Unable to load wagon type",wt,", using placeholder") - wt="advtrains:wagon_placeholder" + rt = "advtrains:wagon_placeholder" + proto = advtrains.wagon_prototypes[rt] end - return wt, advtrains.wagon_prototypes[wt] + return rt, proto +end + +function advtrains.register_wagon_alias(src, dst) + advtrains.wagon_alias[src] = dst +end + +local function recursive_resolve_alias(name, seen) + local prototype = rawget(advtrains.wagon_prototypes, name) + if prototype then + return name, prototype + end + local resolved = advtrains.wagon_alias[name] + if resolved and not seen[resolved] then + seen[name] = true + return recursive_resolve_alias(resolved, seen) + end +end + +function advtrains.resolve_wagon_alias(name) + return recursive_resolve_alias(name, {}) end function advtrains.standard_inventory_formspec(self, pname, invname) @@ -1368,13 +1404,23 @@ function advtrains.register_wagon(sysname_p, prototype, desc, inv_img, nincreati groups = wagon_groups, on_place = function(itemstack, placer, pointed_thing) - if not pointed_thing.type == "node" then + if pointed_thing.type ~= "node" then return end + + local pos = pointed_thing.under + local node = minetest.get_node(pos) + local pointed_def = minetest.registered_nodes[node.name] + if pointed_def and pointed_def.on_rightclick then + local controls = placer:get_player_control() + if not controls.sneak then + return pointed_def.on_rightclick(pos, node, placer, itemstack, pointed_thing) + end + end + local pname = placer:get_player_name() - local node=minetest.get_node_or_nil(pointed_thing.under) - if not node then atprint("[advtrains]Ignore at placer position") return itemstack end + if node.name == "ignore" then atprint("[advtrains]Ignore at placer position") return itemstack end local nodename=node.name if(not advtrains.is_track_and_drives_on(nodename, prototype.drives_on)) then atprint("no track here, not placing.") @@ -1384,14 +1430,14 @@ function advtrains.register_wagon(sysname_p, prototype, desc, inv_img, nincreati minetest.chat_send_player(pname, "You don't have the train_operator privilege.") return itemstack end - if not minetest.check_player_privs(placer, {train_admin = true }) and minetest.is_protected(pointed_thing.under, placer:get_player_name()) then + if not minetest.check_player_privs(placer, {train_admin = true }) and minetest.is_protected(pos, placer:get_player_name()) then return itemstack end local tconns=advtrains.get_track_connections(node.name, node.param2) local yaw = placer:get_look_horizontal() local plconnid = advtrains.yawToClosestConn(yaw, tconns) - local prevpos = advtrains.get_adjacent_rail(pointed_thing.under, tconns, plconnid, prototype.drives_on) + local prevpos = advtrains.get_adjacent_rail(pos, tconns, plconnid, prototype.drives_on) if not prevpos then minetest.chat_send_player(pname, "The track you are trying to place the wagon on is not long enough!") return @@ -1399,7 +1445,7 @@ function advtrains.register_wagon(sysname_p, prototype, desc, inv_img, nincreati local wid = advtrains.create_wagon(sysname, pname) - local id=advtrains.create_new_train_at(pointed_thing.under, plconnid, 0, {wid}) + local id=advtrains.create_new_train_at(pos, plconnid, 0, {wid}) if not advtrains.is_creative(pname) then itemstack:take_item() @@ -1487,4 +1533,28 @@ function advtrains.get_wagon_at_index(train_id, w_index) end -- nothing found, dist must be further back return nil -end
\ No newline at end of file +end + +function advtrains.get_wagon_entity(wagon_id) + if not advtrains.wagons[wagon_id] then return end + local object = advtrains.wagon_objects[wagon_id] + if object then + return object:get_luaentity() + end +end + +function advtrains.next_wagon_entity_in_train(train, i) + local wagon_id = train.trainparts[i + 1] + if wagon_id then + local wagon = advtrains.get_wagon_entity(wagon_id) + if wagon then + return i + 1, wagon + end + end +end + +function advtrains.wagon_entity_pairs_in_train(train_id) + local train = advtrains.trains[train_id] + if not train then return function() end end + return advtrains.next_wagon_entity_in_train, train, 0 +end |