From 86d64d15836aa39160a052c5a5f25859c083c548 Mon Sep 17 00:00:00 2001 From: StochasticMouse Date: Sun, 20 Oct 2024 01:06:16 +0200 Subject: [PATCH] changed serialize function to be deterministic --- forestry_bees/apiary.lua | 6 ++-- forestry_bees/helper.lua | 65 ++++++++++++++++++++++++++++------------ 2 files changed, 50 insertions(+), 21 deletions(-) diff --git a/forestry_bees/apiary.lua b/forestry_bees/apiary.lua index dd32f8b..e69c996 100644 --- a/forestry_bees/apiary.lua +++ b/forestry_bees/apiary.lua @@ -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) diff --git a/forestry_bees/helper.lua b/forestry_bees/helper.lua index 3602901..8bdbf19 100644 --- a/forestry_bees/helper.lua +++ b/forestry_bees/helper.lua @@ -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)