changed serialize function to be deterministic

This commit is contained in:
StochasticMouse 2024-10-20 01:06:16 +02:00
parent d4d1211f13
commit 86d64d1583
2 changed files with 50 additions and 21 deletions

View File

@ -123,7 +123,7 @@ local function apiary_node_timer(pos,elapsed)
minetest.chat_send_all("prova")
local new_queen = forestry_bees.format_bee(monarchlist[1])
local drone_genes = forestry_bees.return_all_genes_double(string.sub(string.match(string.match(new_queen:get_name(),":.*"),".*_"),2,-2))
new_queen:get_meta():set_string("drone_genes", minetest.serialize(drone_genes))
new_queen:get_meta():set_string("drone_genes", forestry_bees.serialize(drone_genes))
inv:set_stack("monarch",1,new_queen)
monarchlist = inv:get_list("monarch")
end
@ -139,7 +139,7 @@ local function apiary_node_timer(pos,elapsed)
--if actionable check if things are ready
if actionable then
--ternary expression if can_breed it evals to breedtime else lifetime
needed_time = (can_breed and {breedtime} or { tonumber(forestry_bees.settings:get("lifespan_multiplier")) * minetest.deserialize(monarchlist[1]:get_meta():get_string("genes"))["lifespan"][1]})[1]
needed_time = (can_breed and {breedtime} or { tonumber(forestry_bees.settings:get("lifespan_multiplier")) * forestry_bees.deserialize(monarchlist[1]:get_meta():get_string("genes"))["lifespan"][1]})[1]
el = math.min(el, needed_time - src_time)
src_time = src_time + el
@ -289,12 +289,14 @@ minetest.register_node("forestry_bees:apiary", apply_logger({
insert_object = function(pos, node, stack, direction)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
minetest.get_node_timer(pos):start(1.0)
if minetest.get_item_group(stack:get_name(),"bee_drone") == 1 then
return inv:add_item('drone', stack)
end
if minetest.get_item_group(stack:get_name(),"bee_monarch") == 1 then
return inv:add_item('monarch', stack)
end
end,
can_insert = function(pos, node, stack, direction)
local meta = minetest.get_meta(pos)

View File

@ -1,23 +1,50 @@
--function forestry_bees.Bee(bee_type,active_type_gene,inactive_type_gene,active_fertility_gene,inactive_fertility_gene)
--local itemstack = ItemStack({name = forestry_bees.bee_name(bee_type,active_type_gene)})
--itemstack:get_meta():set_string("active_type_gene",active_type_gene)
--itemstack:get_meta():set_string("inactive_type_gene",inactive_type_gene)
--itemstack:get_meta():set_string("active_fertility_gene",active_fertility_gene)
--itemstack:get_meta():set_string("inactive_fertility_gene",inactive_fertility_gene)
--return itemstack
--end
function forestry_bees.serialize(t)
-- i know that core.serialize exists but it is non deterministic
-- for bees and thus creates bees with the same "genes" table but
-- a different "genes" string, thus making different itemstacks
-- for this reason this function is necessary
-- the tables in this mod are like {"a"={1,2},"b"={"c","d"}}
-- for this reason the function is much simpler
local function add_gene(str, tab, label)
local t2 = tab[label]
return str .. label .."\t"..tostring(t2[1]).."\t"..tostring(t2[2]).."\t\n"
end
local result = ""
for i, label in ipairs({"type_gene", "production", "fertility", "lifespan",
"nocturnal", "cave", "flyer", "flower", "radius"}) do
result = add_gene(result, t, label)
end
return result
end
function forestry_bees.deserialize(str)
--same as above
local function unravel(str1)
local first_gene_str = string.match(str1,"^(.-)\n")
local iter = string.gmatch(first_gene_str,"(.-)\t")
local label = iter()
local result_tab = {iter(), iter()}
return label, result_tab, string.match(str1,"\n(.+)")
end
local fin_tab = {}
local label, result_tab, rest_str = unravel(str)
fin_tab[label] = result_tab
while rest_str do
label, result_tab, rest_str = unravel(rest_str)
fin_tab[label] = result_tab
end
return fin_tab
end
function forestry_bees.Bee(bee_type,genes)
local itemstack = ItemStack({name = forestry_bees.bee_name(bee_type,genes["type_gene"][1])}) --the "1" is cuz the table genes["type_gene"] has 2 entries: active and inactive
itemstack:get_meta():set_string("genes", minetest.serialize(genes))
--for gene_type,gene in pairs(genes) do
-- itemstack:get_meta():set_string(gene_type,gene)
--end
itemstack:get_meta():set_string("genes", forestry_bees.serialize(genes))
return itemstack
end
function forestry_bees.can_queen_work(queen, pos)
local genes = minetest.deserialize(queen:get_meta():get_string("genes"))
local genes = forestry_bees.deserialize(queen:get_meta():get_string("genes"))
local biome_data = minetest.get_biome_data(pos)
local biome_name = minetest.get_biome_name(biome_data["biome"])
local humidity = biome_data["humidity"]
@ -34,7 +61,7 @@ function forestry_bees.can_queen_work(queen, pos)
end
function forestry_bees.calculate_drop(bee)
local genes = minetest.deserialize(bee:get_meta():get_string("genes"))
local genes = forestry_bees.deserialize(bee:get_meta():get_string("genes"))
local possible_drops = forestry_bees.bee_drops[genes["type_gene"][1]] --this gets us a table
local out_table = {}
for drop,chance in pairs(possible_drops) do
@ -68,8 +95,8 @@ function forestry_bees.format_bee(bee)
end
function forestry_bees.breed_princess_drone(princess,drone)
local princess_genes = minetest.deserialize(princess:get_meta():get_string("genes")) --princess_meta["genes"]
local drone_genes = minetest.deserialize(drone:get_meta():get_string("genes"))
local princess_genes = forestry_bees.deserialize(princess:get_meta():get_string("genes")) --princess_meta["genes"]
local drone_genes = forestry_bees.deserialize(drone:get_meta():get_string("genes"))
--fix for missing genes in bees, if we have bees with missing genes we just give them the default ones
if princess_genes == nil then
local princess_type = string.sub(string.match(string.match(princess:get_name(),":.*"),".*_"),2,-2)
@ -81,7 +108,7 @@ function forestry_bees.breed_princess_drone(princess,drone)
end
local queen = forestry_bees.Bee("queen",princess_genes)
local queen_meta = queen:get_meta()
queen_meta:set_string("drone_genes",minetest.serialize(drone_genes))
queen_meta:set_string("drone_genes",forestry_bees.serialize(drone_genes))
return queen
end
@ -173,8 +200,8 @@ end
function forestry_bees.apiary_result(queen, pos)
--given a queen calculates the correct princess + drone output
local meta = queen:get_meta()
local mother_genes = minetest.deserialize(meta:get_string("genes"))
local father_genes = minetest.deserialize(meta:get_string("drone_genes"))
local mother_genes = forestry_bees.deserialize(meta:get_string("genes"))
local father_genes = forestry_bees.deserialize(meta:get_string("drone_genes"))
local genes = output_genes(mother_genes,father_genes,pos)
--local genes = final_gene(mother_chosen_gene, father_chosen_gene)
local princess = forestry_bees.Bee("princess", genes)