From 20a1171144039e57cdab8f048077bb7027805726 Mon Sep 17 00:00:00 2001 From: orwell96 Date: Wed, 2 Nov 2016 11:17:42 +0100 Subject: [PATCH] rework entity handling some modularization, clarify 'initialized' property, some re-implementations --- advtrains.zip | Bin 1326055 -> 1326241 bytes trainlogic.lua | 13 ++-- wagons.lua | 163 ++++++++++++++++++++++++++----------------------- 3 files changed, 93 insertions(+), 83 deletions(-) diff --git a/advtrains.zip b/advtrains.zip index 38995c6edf1ddf925f44ca2fef672b894b25b6b3..f8ae5e737dda59fa1a341974129e98efde9149e9 100644 GIT binary patch delta 13625 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 Ng9EAn?tlFH{{g;N9ESh^ diff --git a/trainlogic.lua b/trainlogic.lua index f16e1e2..a372b19 100644 --- a/trainlogic.lua +++ b/trainlogic.lua @@ -1,7 +1,8 @@ --trainlogic.lua --controls train entities stuff about connecting/disconnecting/colliding trains and other things -local print=function(t, ...) minetest.log("action", table.concat({t, ...}, " ")) minetest.chat_send_all(table.concat({t, ...}, " ")) end +--local print=function(t, ...) minetest.log("action", table.concat({t, ...}, " ")) minetest.chat_send_all(table.concat({t, ...}, " ")) end +local print=function() end local benchmark=false --printbm=function(str, t) print("[advtrains]"..str.." "..((os.clock()-t)*1000).."ms") end @@ -95,7 +96,7 @@ advtrains.save = function() -- update wagon saves for _,wagon in pairs(minetest.luaentities) do if wagon.is_wagon and wagon.initialized then - advtrains.wagon_save[wagon.unique_id]=advtrains.merge_tables(wagon)--so, will only copy non_metatable elements + wagon:get_staticdata() end end --cross out userdata @@ -140,6 +141,7 @@ minetest.register_globalstep(function(dtime) for k,v in pairs(advtrains.trains) do --advtrains.update_trainpart_properties(k) if #v.trainparts==0 then + print("[advtrains][train "..k.."] has empty trainparts, removing.") advtrains.trains[k]=nil end end @@ -248,6 +250,7 @@ function advtrains.train_step(id, train, dtime) local node_range=(math.max((minetest.setting_get("active_block_range") or 0),1)*16) if train.check_trainpartload<=0 then local ori_pos=advtrains.get_real_index_position(path, train.index) --not much to calculate + print("[advtrains][train "..id.."] at "..minetest.pos_to_string(vector.round(ori_pos))) local should_check=false for _,p in ipairs(minetest.get_connected_players()) do @@ -276,11 +279,7 @@ function advtrains.train_step(id, train, dtime) --print(w_id.." not loaded, but save available") --spawn a new and initialize it with the properties from wagon_save local le=minetest.env:add_entity(ori_pos, advtrains.wagon_save[w_id].entity_name):get_luaentity() - for k,v in pairs(advtrains.wagon_save[w_id]) do - le[k]=v - end - advtrains.wagon_save[w_id].name=nil - advtrains.wagon_save[w_id].object=nil + le:init_from_wagon_save(w_id) else print(w_id.." not loaded and no save available") --what the hell... diff --git a/wagons.lua b/wagons.lua index 287b723..d8e5034 100644 --- a/wagons.lua +++ b/wagons.lua @@ -1,5 +1,6 @@ --atan2 counts angles clockwise, minetest does counterclockwise -local print=function(t) minetest.log("action", t) minetest.chat_send_all(t) end +--local print=function(t) minetest.log("action", t) minetest.chat_send_all(t) end +local print=function() end local wagon={ collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5}, @@ -44,51 +45,36 @@ function wagon:train() return advtrains.trains[self.train_id] end -function wagon:on_activate(staticdata, dtime_s) - --print("[advtrains][wagon "..(self.unique_id or "no-id").."] activated") +--[[about 'initalized': + when initialized is false, the entity hasn't got any data yet and should wait for these to be set before doing anything + when loading an existing object (with staticdata), it will be set + when instanciating a new object via add_entity, it is not set at the time on_activate is called. + then, wagon:initialize() will be called + + wagon will save only uid in staticdata, no serialized table +]] +function wagon:on_activate(sd_uid, dtime_s) + print("[advtrains][wagon "..((sd_uid and sd_uid~="" and sd_uid) or "no-id").."] activated") self.object:set_armor_groups({immortal=1}) - if staticdata then - local tmp = minetest.deserialize(staticdata) - if tmp then - self.unique_id=tmp.unique_id - self.train_id=tmp.train_id - self.wagon_flipped=tmp.wagon_flipped - self.owner=tmp.owner - self.seatp=tmp.seatp + if sd_uid and sd_uid~="" then + --legacy + --expect this to be a serialized table and handle + if minetest.deserialize(sd_uid) then + self:init_from_wagon_save(minetest.deserialize(sd_uid).unique_id) + else + self:init_from_wagon_save(sd_uid) end - end - self.old_pos = self.object:getpos() - self.old_velocity = self.velocity - self.initialized_pre=true self.entity_name=self.name - --same code is in on_step - --does this object already have an ID? - if not self.unique_id then - self.unique_id=os.time()..os.clock()--should be random enough. - else - for _,wagon in pairs(minetest.luaentities) do - if wagon.is_wagon and wagon.initialized and wagon.unique_id==self.unique_id then--i am a duplicate! - self.object:remove() - return - end - end - end - --is my train still here - if not self.train_id or not self:train() then - if self.initialized then - print("[advtrains][wagon "..self.unique_id.."] missing train_id, destroying") + --duplicates? + for _,wagon in pairs(minetest.luaentities) do + if wagon.is_wagon and wagon.initialized and wagon.unique_id==self.unique_id and wagon~=self then--i am a duplicate! + print("[advtrains][wagon "..((sd_uid and sd_uid~="" and sd_uid) or "no-id").."] duplicate found, removing") self.object:remove() return end - print("[advtrains][wagon "..self.unique_id.."] missing train_id, but not yet initialized, returning") - return - elseif not self.initialized then - self.initialized=true end - advtrains.update_trainpart_properties(self.train_id) - minetest.after(1, function() self:reattach_all() end) if self.custom_on_activate then self:custom_on_activate(staticdata_table, dtime_s) @@ -96,19 +82,57 @@ function wagon:on_activate(staticdata, dtime_s) end function wagon:get_staticdata() + if not self:ensure_init() then return end + print("[advtrains][wagon "..((self.unique_id and self.unique_id~="" and self.unique_id) or "no-id").."]: saving to wagon_save") --save to table before being unloaded advtrains.wagon_save[self.unique_id]=advtrains.merge_tables(self) - return minetest.serialize({ - unique_id=self.unique_id, - train_id=self.train_id, - wagon_flipped=self.wagon_flipped, - owner=self.owner, - seatp=self.seatp, - }) + advtrains.wagon_save[self.unique_id].entity_name=self.name + advtrains.wagon_save[self.unique_id].name=nil + advtrains.wagon_save[self.unique_id].object=nil + return self.unique_id +end +--returns: uid of wagon +function wagon:init_new_instance(train_id, properties) + self.unique_id=os.time()..os.clock() + self.train_id=train_id + for k,v in pairs(properties) do + if k~="name" and k~="object" then + self[k]=v + end + end + minetest.after(1, function() self:reattach_all() end) + self.initialized=true + print("init_new_instance "..self.unique_id.." ("..self.train_id..")") + return self.unique_id +end +function wagon:init_from_wagon_save(uid) + if not advtrains.wagon_save[uid] then + self.object:remove() + return + end + self.unique_id=uid + for k,v in pairs(advtrains.wagon_save[uid]) do + if k~="name" and k~="object" then + self[k]=v + end + end + if not self.train_id or not self:train() then + self.object:remove() + return + end + self.initialized=true + print("init_from_wagon_save "..self.unique_id.." ("..self.train_id..")") + advtrains.update_trainpart_properties(self.train_id) +end +function wagon:ensure_init() + if self.initialized then return true end + self.object:setvelocity({x=0,y=0,z=0}) + return false end -- Remove the wagon function wagon:on_punch(puncher, time_from_last_punch, tool_capabilities, direction) + if not self:ensure_init() then return end if not puncher or not puncher:is_player() then return end @@ -159,10 +183,10 @@ function wagon:destroy() self.custom_on_destroy(self, puncher, time_from_last_punch, tool_capabilities, direction) end + print("[advtrains][wagon "..((self.unique_id and self.unique_id~="" and self.unique_id) or "no-id").."]: destroying") + self.object:remove() - if not self.initialized then return end - table.remove(self:train().trainparts, self.pos_in_trainparts) advtrains.update_trainpart_properties(self.train_id) advtrains.wagon_save[self.unique_id]=nil @@ -172,6 +196,8 @@ end function wagon:on_step(dtime) + if not self:ensure_init() then return end + local t=os.clock() local pos = self.object:getpos() @@ -179,18 +205,9 @@ function wagon:on_step(dtime) print("["..self.unique_id.."][fatal] missing position (object:getpos() returned nil)") return end - - if not self.initialized_pre then - print("[advtrains] wagon stepping while not yet initialized_pre, returning") - self.object:setvelocity({x=0,y=0,z=0}) - return - end self.entity_name=self.name - --does this object already have an ID? - if not self.unique_id then - self.unique_id=os.time()..os.clock()--should be random enough. - end + --is my train still here if not self.train_id or not self:train() then print("[advtrains][wagon "..self.unique_id.."] missing train_id, destroying") @@ -203,17 +220,6 @@ function wagon:on_step(dtime) self.seatp={} end - --re-attach driver if he got lost - --if not self.driver and self.driver_name then - -- local clicker=minetest.get_player_by_name(self.driver_name) - -- if clicker then - -- self.driver = clicker - -- advtrains.player_to_wagon_mapping[clicker:get_player_name()]=self - -- clicker:set_attach(self.object, "", self.attach_offset, {x=0,y=0,z=0}) - -- clicker:set_eye_offset(self.view_offset, self.view_offset) - -- end - --end - --custom on_step function if self.custom_on_step then self:custom_on_step(self, dtime) @@ -444,6 +450,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) end end) function wagon:reattach_all() + if not self.seatp then self.seatp={} end for seatno, pname in pairs(self.seatp) do local p=minetest.get_player_by_name(pname) if p then @@ -473,6 +480,17 @@ function advtrains.register_wagon(sysname, traintype, prototype, desc, inv_img) if not pointed_thing.type == "node" then return end + + local node=minetest.env:get_node_or_nil(pointed_thing.under) + if not node then print("[advtrains]Ignore at placer position") return itemstack end + local nodename=node.name + if(not advtrains.is_track_and_drives_on(nodename, advtrains.all_traintypes[traintype].drives_on)) then + print("[advtrains]no track here, not placing.") + return itemstack + end + local conn1=advtrains.get_track_connections(node.name, node.param2) + local id=advtrains.create_new_train_at(pointed_thing.under, advtrains.dirCoordSet(pointed_thing.under, conn1), traintype) + local ob=minetest.env:add_entity(pointed_thing.under, "advtrains:"..sysname) if not ob then print("[advtrains]couldn't add_entity, aborting") @@ -482,15 +500,8 @@ function advtrains.register_wagon(sysname, traintype, prototype, desc, inv_img) le.owner=placer:get_player_name() le.infotext=desc..", owned by "..placer:get_player_name() - local node=minetest.env:get_node_or_nil(pointed_thing.under) - if not node then print("[advtrains]Ignore at placer position") return itemstack end - local nodename=node.name - if(not advtrains.is_track_and_drives_on(nodename, advtrains.all_traintypes[traintype].drives_on)) then - print("[advtrains]no trck here, not placing.") - return itemstack - end - local conn1=advtrains.get_track_connections(node.name, node.param2) - local id=advtrains.create_new_train_at(pointed_thing.under, advtrains.dirCoordSet(pointed_thing.under, conn1), traintype) + local wagon_uid=le:init_new_instance(id, {}) + advtrains.add_wagon_to_train(le, id) if not minetest.setting_getbool("creative_mode") then itemstack:take_item()