collectgarbage hammer fix, and add some asserts to crash before corrupting anything in impossible situations.

This commit is contained in:
FaceDeer 2019-01-13 03:02:02 -07:00
parent 03beff0d33
commit 8ea6d7eb70
3 changed files with 45 additions and 26 deletions

@ -16,8 +16,20 @@ local get_node_image = function(pos, node)
node_image.meta.fields.formspec = node_def._digtron_formspec(pos, meta) -- causes formspec to be automatically upgraded whenever Digtron moves node_image.meta.fields.formspec = node_def._digtron_formspec(pos, meta) -- causes formspec to be automatically upgraded whenever Digtron moves
end end
local group = minetest.get_item_group(node.name, "digtron")
-- group 1 has no special metadata
if group > 1 and group < 10 then
assert(node_image ~= nil and node_image.meta ~= nil, "[Digtron] Digtron failed to get a metadata table for a Digtron node in group "
.. tostring(group) .. ". This error should not be possible. Please see https://github.com/minetest/minetest/issues/8067")
-- These groups have inventories
if group == 2 or (group > 3 and group < 8) then
assert(node_image.meta.inventory ~= nil, "[Digtron] Digtron failed to get a metadata inventory table for a Digtron node in group "
.. tostring(group) .. ". This error should not be possible. Please see https://github.com/minetest/minetest/issues/8067")
end
end
-- Record what kind of thing we've got in a builder node so its facing can be rotated properly -- Record what kind of thing we've got in a builder node so its facing can be rotated properly
if minetest.get_item_group(node.name, "digtron") == 4 then if group == 4 then
local build_item = "" local build_item = ""
if node_image.meta.inventory.main then if node_image.meta.inventory.main then
build_item = node_image.meta.inventory.main[1] build_item = node_image.meta.inventory.main[1]
@ -37,13 +49,13 @@ local to_test = Pointset.create()
local tested = Pointset.create() local tested = Pointset.create()
function DigtronLayout.create(pos, player) function DigtronLayout.create(pos, player)
collectgarbage()
local self = {} local self = {}
setmetatable(self, DigtronLayout) setmetatable(self, DigtronLayout)
--initialize. We're assuming that the start position is a controller digtron, should be a safe assumption since only the controller node should call this --initialize. We're assuming that the start position is a controller digtron, should be a safe assumption since only the controller node should call this
self.traction = 0 self.traction = 0
self.all = {} self.all = {}
self.extents = {}
self.water_touching = false self.water_touching = false
self.lava_touching = false self.lava_touching = false
self.protected = Pointset.create() -- if any nodes we look at are protected, make note of that. That way we don't need to keep re-testing protection state later. self.protected = Pointset.create() -- if any nodes we look at are protected, make note of that. That way we don't need to keep re-testing protection state later.
@ -54,12 +66,12 @@ function DigtronLayout.create(pos, player)
table.insert(self.all, get_node_image(pos, minetest.get_node(pos))) -- We never visit the source node, so insert it into the all table a priori. Revisit this design decision if a controller node is created that contains fuel or inventory or whatever. table.insert(self.all, get_node_image(pos, minetest.get_node(pos))) -- We never visit the source node, so insert it into the all table a priori. Revisit this design decision if a controller node is created that contains fuel or inventory or whatever.
self.extents.max_x = pos.x self.extents_max_x = pos.x
self.extents.min_x = pos.x self.extents_min_x = pos.x
self.extents.max_y = pos.y self.extents_max_y = pos.y
self.extents.min_y = pos.y self.extents_min_y = pos.y
self.extents.max_z = pos.z self.extents_max_z = pos.z
self.extents.min_z = pos.z self.extents_min_z = pos.z
tested:set(pos.x, pos.y, pos.z, true) tested:set(pos.x, pos.y, pos.z, true)
to_test:set(pos.x + 1, pos.y, pos.z, true) to_test:set(pos.x + 1, pos.y, pos.z, true)
@ -143,12 +155,12 @@ function DigtronLayout.create(pos, player)
end end
-- update extents -- update extents
self.extents.max_x = math.max(self.extents.max_x, testpos.x) self.extents_max_x = math.max(self.extents_max_x, testpos.x)
self.extents.min_x = math.min(self.extents.min_x, testpos.x) self.extents_min_x = math.min(self.extents_min_x, testpos.x)
self.extents.max_y = math.max(self.extents.max_y, testpos.y) self.extents_max_y = math.max(self.extents_max_y, testpos.y)
self.extents.min_y = math.min(self.extents.min_y, testpos.y) self.extents_min_y = math.min(self.extents_min_y, testpos.y)
self.extents.max_z = math.max(self.extents.max_z, testpos.z) self.extents_max_z = math.max(self.extents_max_z, testpos.z)
self.extents.min_z = math.min(self.extents.min_z, testpos.z) self.extents_min_z = math.min(self.extents_min_z, testpos.z)
--queue up potential new test points adjacent to this digtron node --queue up potential new test points adjacent to this digtron node
to_test:set_if_not_in(tested, testpos.x + 1, testpos.y, testpos.z, true) to_test:set_if_not_in(tested, testpos.x + 1, testpos.y, testpos.z, true)
@ -302,6 +314,12 @@ local top = {
} }
-- Rotates 90 degrees widdershins around the axis defined by facedir (which in this case is pointing out the front of the node, so it needs to be converted into an upward-pointing axis internally) -- Rotates 90 degrees widdershins around the axis defined by facedir (which in this case is pointing out the front of the node, so it needs to be converted into an upward-pointing axis internally)
function DigtronLayout.rotate_layout_image(self, facedir) function DigtronLayout.rotate_layout_image(self, facedir)
if self == nil or self.all == nil or self.controller == nil or self.old_pos_pointset == nil then
-- this should not be possible, but if it is then abort.
return false
end
-- To convert this into the direction the "top" of the axle node is pointing in: -- To convert this into the direction the "top" of the axle node is pointing in:
-- 0, 1, 2, 3 == (0,1,0) -- 0, 1, 2, 3 == (0,1,0)
-- 4, 5, 6, 7 == (0,0,1) -- 4, 5, 6, 7 == (0,0,1)
@ -322,14 +340,12 @@ end
-- Translation -- Translation
function DigtronLayout.move_layout_image(self, dir) function DigtronLayout.move_layout_image(self, dir)
local extents = self.extents self.extents_max_x = self.extents_max_x + dir.x
self.extents_min_x = self.extents_min_x + dir.x
extents.max_x = extents.max_x + dir.x self.extents_max_y = self.extents_max_y + dir.y
extents.min_x = extents.min_x + dir.x self.extents_min_y = self.extents_min_y + dir.y
extents.max_y = extents.max_y + dir.y self.extents_max_z = self.extents_max_z + dir.z
extents.min_y = extents.min_y + dir.y self.extents_min_z = self.extents_min_z + dir.z
extents.max_z = extents.max_z + dir.z
extents.min_z = extents.min_z + dir.z
for k, node_image in pairs(self.all) do for k, node_image in pairs(self.all) do
self.old_pos_pointset:set(node_image.pos.x, node_image.pos.y, node_image.pos.z, true) self.old_pos_pointset:set(node_image.pos.x, node_image.pos.y, node_image.pos.z, true)

@ -43,7 +43,10 @@ minetest.register_node("digtron:axle", {
return return
end end
local image = DigtronLayout.create(pos, clicker) local image = DigtronLayout.create(pos, clicker)
image:rotate_layout_image(node.param2) if image:rotate_layout_image(node.param2) == false then
-- This should be impossible, but if self-validation fails abort.
return
end
if image:can_write_layout_image() then if image:can_write_layout_image() then
if image:write_layout_image(clicker) then if image:write_layout_image(clicker) then
minetest.sound_play("whirr", {gain=1.0, pos=pos}) minetest.sound_play("whirr", {gain=1.0, pos=pos})

@ -72,9 +72,9 @@ end
-- Checks if a player is within a layout's extents. -- Checks if a player is within a layout's extents.
local function move_player_test(layout, player) local function move_player_test(layout, player)
local player_pos = player:getpos() local player_pos = player:getpos()
if player_pos.x >= layout.extents.min_x - 1 and player_pos.x <= layout.extents.max_x + 1 and if player_pos.x >= layout.extents_min_x - 1 and player_pos.x <= layout.extents_max_x + 1 and
player_pos.y >= layout.extents.min_y - 1 and player_pos.y <= layout.extents.max_y + 1 and player_pos.y >= layout.extents_min_y - 1 and player_pos.y <= layout.extents_max_y + 1 and
player_pos.z >= layout.extents.min_z - 1 and player_pos.z <= layout.extents.max_z + 1 then player_pos.z >= layout.extents_min_z - 1 and player_pos.z <= layout.extents_max_z + 1 then
return true return true
end end
return false return false