rework entity handling

some modularization, clarify 'initialized' property, some re-implementations
master
orwell96 2016-11-02 11:17:42 +01:00
parent ee6b7494bb
commit 20a1171144
3 changed files with 93 additions and 83 deletions

Binary file not shown.

View File

@ -1,7 +1,8 @@
--trainlogic.lua --trainlogic.lua
--controls train entities stuff about connecting/disconnecting/colliding trains and other things --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 local benchmark=false
--printbm=function(str, t) print("[advtrains]"..str.." "..((os.clock()-t)*1000).."ms") end --printbm=function(str, t) print("[advtrains]"..str.." "..((os.clock()-t)*1000).."ms") end
@ -95,7 +96,7 @@ advtrains.save = function()
-- update wagon saves -- update wagon saves
for _,wagon in pairs(minetest.luaentities) do for _,wagon in pairs(minetest.luaentities) do
if wagon.is_wagon and wagon.initialized then 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
end end
--cross out userdata --cross out userdata
@ -140,6 +141,7 @@ minetest.register_globalstep(function(dtime)
for k,v in pairs(advtrains.trains) do for k,v in pairs(advtrains.trains) do
--advtrains.update_trainpart_properties(k) --advtrains.update_trainpart_properties(k)
if #v.trainparts==0 then if #v.trainparts==0 then
print("[advtrains][train "..k.."] has empty trainparts, removing.")
advtrains.trains[k]=nil advtrains.trains[k]=nil
end end
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) local node_range=(math.max((minetest.setting_get("active_block_range") or 0),1)*16)
if train.check_trainpartload<=0 then if train.check_trainpartload<=0 then
local ori_pos=advtrains.get_real_index_position(path, train.index) --not much to calculate 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 local should_check=false
for _,p in ipairs(minetest.get_connected_players()) do 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") --print(w_id.." not loaded, but save available")
--spawn a new and initialize it with the properties from wagon_save --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() 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:init_from_wagon_save(w_id)
le[k]=v
end
advtrains.wagon_save[w_id].name=nil
advtrains.wagon_save[w_id].object=nil
else else
print(w_id.." not loaded and no save available") print(w_id.." not loaded and no save available")
--what the hell... --what the hell...

View File

@ -1,5 +1,6 @@
--atan2 counts angles clockwise, minetest does counterclockwise --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={ local wagon={
collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5}, 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] return advtrains.trains[self.train_id]
end end
function wagon:on_activate(staticdata, dtime_s) --[[about 'initalized':
--print("[advtrains][wagon "..(self.unique_id or "no-id").."] activated") when initialized is false, the entity hasn't got any data yet and should wait for these to be set before doing anything
self.object:set_armor_groups({immortal=1}) when loading an existing object (with staticdata), it will be set
if staticdata then when instanciating a new object via add_entity, it is not set at the time on_activate is called.
local tmp = minetest.deserialize(staticdata) then, wagon:initialize() will be called
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
end
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 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 end
self.old_pos = self.object:getpos()
self.old_velocity = self.velocity
self.initialized_pre=true
self.entity_name=self.name self.entity_name=self.name
--same code is in on_step --duplicates?
--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 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! 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() self.object:remove()
return return
end end
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")
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 if self.custom_on_activate then
self:custom_on_activate(staticdata_table, dtime_s) self:custom_on_activate(staticdata_table, dtime_s)
@ -96,19 +82,57 @@ function wagon:on_activate(staticdata, dtime_s)
end end
function wagon:get_staticdata() 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 --save to table before being unloaded
advtrains.wagon_save[self.unique_id]=advtrains.merge_tables(self) advtrains.wagon_save[self.unique_id]=advtrains.merge_tables(self)
return minetest.serialize({ advtrains.wagon_save[self.unique_id].entity_name=self.name
unique_id=self.unique_id, advtrains.wagon_save[self.unique_id].name=nil
train_id=self.train_id, advtrains.wagon_save[self.unique_id].object=nil
wagon_flipped=self.wagon_flipped, return self.unique_id
owner=self.owner, end
seatp=self.seatp, --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 end
-- Remove the wagon -- Remove the wagon
function wagon:on_punch(puncher, time_from_last_punch, tool_capabilities, direction) 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 if not puncher or not puncher:is_player() then
return return
end end
@ -159,9 +183,9 @@ function wagon:destroy()
self.custom_on_destroy(self, puncher, time_from_last_punch, tool_capabilities, direction) self.custom_on_destroy(self, puncher, time_from_last_punch, tool_capabilities, direction)
end end
self.object:remove() print("[advtrains][wagon "..((self.unique_id and self.unique_id~="" and self.unique_id) or "no-id").."]: destroying")
if not self.initialized then return end self.object:remove()
table.remove(self:train().trainparts, self.pos_in_trainparts) table.remove(self:train().trainparts, self.pos_in_trainparts)
advtrains.update_trainpart_properties(self.train_id) advtrains.update_trainpart_properties(self.train_id)
@ -172,6 +196,8 @@ end
function wagon:on_step(dtime) function wagon:on_step(dtime)
if not self:ensure_init() then return end
local t=os.clock() local t=os.clock()
local pos = self.object:getpos() local pos = self.object:getpos()
@ -180,17 +206,8 @@ function wagon:on_step(dtime)
return return
end 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 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 --is my train still here
if not self.train_id or not self:train() then if not self.train_id or not self:train() then
print("[advtrains][wagon "..self.unique_id.."] missing train_id, destroying") print("[advtrains][wagon "..self.unique_id.."] missing train_id, destroying")
@ -203,17 +220,6 @@ function wagon:on_step(dtime)
self.seatp={} self.seatp={}
end 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 --custom on_step function
if self.custom_on_step then if self.custom_on_step then
self:custom_on_step(self, dtime) self:custom_on_step(self, dtime)
@ -444,6 +450,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end end
end) end)
function wagon:reattach_all() function wagon:reattach_all()
if not self.seatp then self.seatp={} end
for seatno, pname in pairs(self.seatp) do for seatno, pname in pairs(self.seatp) do
local p=minetest.get_player_by_name(pname) local p=minetest.get_player_by_name(pname)
if p then if p then
@ -473,6 +480,17 @@ function advtrains.register_wagon(sysname, traintype, prototype, desc, inv_img)
if not pointed_thing.type == "node" then if not pointed_thing.type == "node" then
return return
end 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) local ob=minetest.env:add_entity(pointed_thing.under, "advtrains:"..sysname)
if not ob then if not ob then
print("[advtrains]couldn't add_entity, aborting") 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.owner=placer:get_player_name()
le.infotext=desc..", owned by "..placer:get_player_name() le.infotext=desc..", owned by "..placer:get_player_name()
local node=minetest.env:get_node_or_nil(pointed_thing.under) local wagon_uid=le:init_new_instance(id, {})
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)
advtrains.add_wagon_to_train(le, id) advtrains.add_wagon_to_train(le, id)
if not minetest.setting_getbool("creative_mode") then if not minetest.setting_getbool("creative_mode") then
itemstack:take_item() itemstack:take_item()