From 9ad4b35bd9ed6ee30fa0b7fb75897af4794b249d Mon Sep 17 00:00:00 2001 From: Alois Wohlschlager Date: Fri, 5 Oct 2018 11:01:58 +0200 Subject: [PATCH] Code refactoring, in-game docs, vanadium more common. Version 0.3 --- CHANGELOG.txt | 5 + LICENSE.txt | 2 +- README.txt | 6 +- book.lua | 111 ++++++ crafting.lua | 6 + craftitems.lua | 10 + init.lua | 11 +- lab.lua | 672 +++++++++++------------------------- ores.lua | 6 +- reactions.lua | 476 +++++++++++++++++++++++++ textures/chemistry_book.png | Bin 0 -> 437 bytes 11 files changed, 836 insertions(+), 469 deletions(-) create mode 100644 book.lua create mode 100644 reactions.lua create mode 100644 textures/chemistry_book.png diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 83ea578..fd81111 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,8 @@ +0.3: +* Extensive code refactoring to prepare for an API (which is already used internally, but unstable and not exposed at the moment) +* Added in-game documentation ("Old Alchemy Textbook") +* Made vanadium more common to better reflect the situation in real life + 0.2: * Water can now be crafted by burning hydrogen * Updated README to reflect changes in the uses for some items diff --git a/LICENSE.txt b/LICENSE.txt index 83cdc85..2a14fd4 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,7 +1,7 @@ License for Code ---------------- -Copyright (C) 2017 Alois Wohlschlager +Copyright (C) 2017, 2018 Alois Wohlschlager This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by diff --git a/README.txt b/README.txt index dad2b8c..1fc438a 100644 --- a/README.txt +++ b/README.txt @@ -1,4 +1,4 @@ -Adds ores, a lab, various lab equipment, chemicals and more tools, building materials and lights. The most comprehensive chemistry mod for Minetest. +Adds ores, a lab, various lab equipment, chemicals and more tools, building materials and lights. Very comprehensive chemistry mod for Minetest. License: LGPLv2.1 or later for code, CC-BY-SA 3.0 for textures and sounds @@ -10,6 +10,7 @@ Other: copy the mod folder to minetest/mods/ in your installation folder Dependencies: Nothing outside of the Minetest game, so everything needed should be already in place. We need only default, vessels, bucket and fire. Mesecons will only add some support/compatibility features. +Minetest 0.4.17.1 is recommended. Contact: alois1@gmx-topmail.de @@ -65,10 +66,11 @@ Misc * Charcoal: Intermediate product to make coal from trees * Compressed Coal: Make diamond renewable * Refined lava: Make lava tools +* Old Alchemy Textbook: Contains all possible reactions (in-game documentation) Tools ----- -* Lava pickaxe, shovel, axe and sword: Lava tools are like steel tools, but smelt dropped items, also the sword deals more damage +* Lava pickaxe, shovel, axe and sword: Lava tools are like steel tools, but smelt most dropped items (and turn wood into charcoal), also the sword deals more damage * Stainless Steel pickaxe, shovel, axe and sword: More robust than steel tools Blocks diff --git a/book.lua b/book.lua new file mode 100644 index 0000000..a4faacf --- /dev/null +++ b/book.lua @@ -0,0 +1,111 @@ +local pages = {} +local product_indexes = {} + +local function representative(item_or_group_name) + if item_or_group_name:sub(1, 6) == "group:" then + local groupname = item_or_group_name:sub(7) + -- TODO this works well for the current purposes, but isn't robust at all + return "default:"..groupname + else + return item_or_group_name + end +end + +local function reactant_name_count(page, index) + local reactants = reactions[page].reactants + if reactants[index] then + return representative(reactants[index]:get_name()).." "..reactants[index]:get_count() + else + return "" + end +end + +local function catalyst_name(page) + local catalyst = reactions[page].catalyst + if catalyst then + return catalyst + else + return "" + end +end + +local function tool_name(page) + local tool = reactions[page].tool + if tool then + return tool + else + return "" + end +end + +local function product_name_count(page, product_index, index) + local output = reactions[page].possible_outputs[product_index] + if output then + if output.products[index] then + return representative(output.products[index]:get_name()).." "..output.products[index]:get_count() + else + return "" + end + else + return "" + end +end + +local function book_formspec(page, product_index) + return + "size[8,4]".. + "label[1,0;Reactants "..page.."/"..#reactions.."]".. + "label[5,0;Products "..product_index.."/"..#reactions[page].possible_outputs..": p="..reactions[page].possible_outputs[product_index].probability.."]".. + "button[0,1;1,3;back;<]".. + "button[7,1;1,3;forward;>]".. + "item_image_button[1,1;1,1;"..reactant_name_count(page, 1)..";;]".. + "item_image_button[2,1;1,1;"..reactant_name_count(page, 2)..";;]".. + "item_image_button[1,2;1,1;"..reactant_name_count(page, 3)..";;]".. + "item_image_button[2,2;1,1;"..reactant_name_count(page, 4)..";;]".. + "item_image_button[1,3;1,1;"..reactant_name_count(page, 5)..";;]".. + "item_image_button[2,3;1,1;"..reactant_name_count(page, 6)..";;]".. + "item_image_button[3.5,1;1,1;"..catalyst_name()..";;]".. + "item_image_button[3.5,3;1,1;"..tool_name()..";;]".. + "item_image_button[5,1;1,1;"..product_name_count(page, product_index, 1)..";;]".. + "item_image_button[6,1;1,1;"..product_name_count(page, product_index, 2)..";;]".. + "item_image_button[5,2;1,1;"..product_name_count(page, product_index, 3)..";;]".. + "item_image_button[6,2;1,1;"..product_name_count(page, product_index, 4)..";;]".. + "item_image_button[5,3;1,1;"..product_name_count(page, product_index, 5)..";;]".. + "item_image_button[6,3;1,1;"..product_name_count(page, product_index, 6)..";;]" +end + +function book_on_use(itemstack, user) + minetest.show_formspec(user:get_player_name(), "chemistry_book", book_formspec(1, 1)) +end + +minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname ~= "chemistry_book" then + return + else + local page = pages[player:get_player_name()] + local product_index = product_indexes[player:get_player_name()] + if fields.back then + if product_index == 1 then + page = page - 1 + product_index = #reactions[page].possible_outputs + else + product_index = product_index - 1 + end + elseif fields.forward then + if product_index == #reactions[page].possible_outputs then + page = page + 1 + product_index = 1 + else + product_index = product_index + 1 + end + end + if page == 0 then + page = #reactions + elseif page == #reactions + 1 then + page = 1 + end + pages[player:get_player_name()] = page + product_indexes[player:get_player_name()] = product_index + minetest.show_formspec(player:get_player_name(), "chemistry_book", book_formspec(page, product_index)) + end +end) diff --git a/crafting.lua b/crafting.lua index 5e7538b..355c3fb 100644 --- a/crafting.lua +++ b/crafting.lua @@ -270,6 +270,12 @@ minetest.register_craft({ recipe = {"default:lava_source", "default:steel_ingot"} }) +minetest.register_craft({ + type = "shapeless", + output = "chemistry:book", + recipe = {"default:book", "chemistry:sulfur_lump"} +}) + -- Mesecon compatibility/support if minetest.get_modpath("mesecons") ~= nil then minetest.register_craft({ diff --git a/craftitems.lua b/craftitems.lua index e43207a..2994077 100644 --- a/craftitems.lua +++ b/craftitems.lua @@ -147,3 +147,13 @@ minetest.register_craftitem("chemistry:refined_lava", { description = "Refined Lava", inventory_image = "chemistry_refined_lava.png", }) + +minetest.register_craftitem("chemistry:book", { + description = "Old Alchemy Textbook", + inventory_image = "chemistry_book.png", + stack_max = 1, + groups = {book = 1}, + on_use = function(itemstack, user) + book_on_use(itemstack, user) + end, +}) diff --git a/init.lua b/init.lua index 2086577..24f8cfe 100644 --- a/init.lua +++ b/init.lua @@ -1,11 +1,20 @@ +-- No API is exported yet, as it's unstable chemistry = {} local chemistry_path=minetest.get_modpath("chemistry") +--[[ + Dependencies: + reactions > lab + book > lab + craftitems > book +]]-- dofile(chemistry_path.."/nodes.lua") -dofile(chemistry_path.."/craftitems.lua") dofile(chemistry_path.."/ores.lua") dofile(chemistry_path.."/tools.lua") dofile(chemistry_path.."/lab.lua") +dofile(chemistry_path.."/reactions.lua") dofile(chemistry_path.."/crafting.lua") dofile(chemistry_path.."/abm.lua") +dofile(chemistry_path.."/book.lua") +dofile(chemistry_path.."/craftitems.lua") diff --git a/lab.lua b/lab.lua index 70e86ef..686df46 100644 --- a/lab.lua +++ b/lab.lua @@ -1,5 +1,5 @@ local formspec = - "size[8,8.5]".. + "size[8,8.5]".. default.gui_bg.. default.gui_bg_img.. default.gui_slots.. @@ -19,6 +19,77 @@ local formspec = "listring[current_player;main]".. default.get_hotbar_bg(0, 4.25) +EPSILON = 1e-7 + +reactions = {} + +--[[ + This is how a formula looks like: + { + tool: (itemstring of tool needed for the reaction, or nil) + catalyst: (--"--) + reactants: { + (ItemStack's of up to six reactants, indexes more than six are silently ignored; no duplicate itemstrings please) + } + possible_outputs: { + { + probability: (...) + products: { + (ItemStack's of up to six products) + } + } + } + sound: (description of a sound to be played, or nil) + } +--]] + +function register_reaction(formula) + local err = false + -- Basic checks of formula + if formula.reactants == nil then + minetest.log("error", "No reactants supplied to register_reaction() (nil)") + err = true + end + if #formula.reactants == 0 then + minetest.log("error", "No reactants supplied to register_reaction() (empty)") + err = true + end + local reactant_count = 0 + for i=1, 6 do + if not (formula.reactants[i] == nil) then + reactant_count = reactant_count + 1 + end + end + if not (#formula.reactants == reactant_count) then + minetest.log("error", "Extra reactants supplied to register_reaction() ") + err = true + end + if formula.possible_outputs == nil then + minetest.log("error", "No possible outputs supplied to register_reaction() (nil)") + err = true + end + if #formula.possible_outputs == 0 then + minetest.log("error", "No possible outputs supplied to register_reaction() (empty)") + err = true + end + local total_probability = 0.0 + for i=1, #formula.possible_outputs do + local output = formula.possible_outputs[i] + if output.probability <= 0 or output.probability > 1 then + minetest.log("error", "Invalid probability for output supplied to register_reaction()") + err = true + end + total_probability = total_probability + output.probability + end + if math.abs(total_probability - 1.0) > EPSILON then + minetest.log("error", "Probabilities which do not sum to one supplied to register_reaction()") + err = true + end + if not err then + reactions[#reactions + 1] = formula + end +end + local function can_dig(pos, player) local meta = minetest.get_meta(pos); local inv = meta:get_inventory() @@ -56,12 +127,20 @@ local function allow_metadata_inventory_take(pos, listname, index, stack, player return stack:get_count() end -local function reaction_possible(pos) +local function reaction_possible(pos, products) local meta = minetest.get_meta(pos) local inv = meta:get_inventory() - local p5 = inv:get_stack("product", 5) - local p6 = inv:get_stack("product", 6) - return p5:is_empty() and p6:is_empty() + -- Actually not quite, this checks whether the reaction would be possible if we needed an empty stack for every product + -- TODO do this properly + local needed_stacks = #products + local free_stacks = 0 + for i=1, 6 do + local prod = inv:get_stack("product", i) + if prod:is_empty() then + free_stacks = free_stacks + 1 + end + end + return free_stacks >= needed_stacks end local function get_node_group(name, group) @@ -74,13 +153,15 @@ end local function bunsen_sound(pos) minetest.sound_play("chemistry_bunsen", { pos = pos, - max_hear_distance = 32, + max_hear_distance = 16, gain = 1.0, }) end local function explosion_sound(pos) minetest.sound_play("chemistry_explosion", { + pos = pos, + max_hear_distance = 64, gain = 1.0, }) end @@ -88,7 +169,7 @@ end local function mortar_sound(pos) minetest.sound_play("chemistry_mortar", { pos = pos, - max_hear_distance = 32, + max_hear_distance = 8, gain = 1.0, }) end @@ -96,7 +177,7 @@ end local function pouring_sound(pos) minetest.sound_play("chemistry_pouring", { pos = pos, - max_hear_distance = 32, + max_hear_distance = 8, gain = 1.0, }) end @@ -104,470 +185,138 @@ end local function stirring_sound(pos) minetest.sound_play("chemistry_stirring", { pos = pos, - max_hear_distance = 32, + max_hear_distance = 8, gain = 1.0, }) end +local function check_item_match(item, stack) + if item == nil then + return stack:is_empty() + else + return stack:get_name() == item + end +end + +local function check_name_match(actual, needed) + if needed:sub(1, 6) == "group:" then + return get_node_group(actual, needed:sub(7)) ~= 0 + else + return actual == needed + end +end + local function lab_node_timer(pos, elapsed) local meta = minetest.get_meta(pos) local inv = meta:get_inventory() local result = false local catalyst = inv:get_stack("catalyst", 1) local tool = inv:get_stack("tool", 1) - local r1 = inv:get_stack("reactant", 1) - local r2 = inv:get_stack("reactant", 2) - local r3 = inv:get_stack("reactant", 3) - local r4 = inv:get_stack("reactant", 4) - local r5 = inv:get_stack("reactant", 5) - local r6 = inv:get_stack("reactant", 6) - if r6:is_empty() then - if r5:is_empty() then - if r4:is_empty() then - if r3:is_empty() then - if r2:is_empty() then - if r1:is_empty() then - else - if r1:get_name() == "chemistry:vanadium_ingot" and r1:get_count() >= 2 and tool:get_name() == "chemistry:bunsen" then - local item = ItemStack("chemistry:vanadium_v_oxide", 1) - if reaction_possible(pos) then - bunsen_sound(pos) - inv:add_item("product", item) - r1:set_count(r1:get_count() - 2) - inv:set_stack("reactant", 1, r1) - result = true - end - end - if r1:get_name() == "chemistry:sulfur_lump" and tool:get_name() == "chemistry:bunsen" then - local item = ItemStack("chemistry:sulfur_dioxide", 1) - if reaction_possible(pos) then - bunsen_sound(pos) - inv:add_item("product", item) - r1:set_count(r1:get_count() - 1) - inv:set_stack("reactant", 1, r1) - result = true - end - end - if r1:get_name() == "chemistry:sulfur_dioxide" and r1:get_count() >= 2 and tool:get_name() == "chemistry:bunsen" and catalyst:get_name() == "chemistry:vanadium_v_oxide" then - local item = ItemStack("chemistry:sulfur_trioxide", 1) -- just using two here doesn't work for some reason - if reaction_possible(pos) then - bunsen_sound(pos) - inv:add_item("product", item) - inv:add_item("product", item) - r1:set_count(r1:get_count() - 2) - inv:set_stack("reactant", 1, r1) - result = true - end - end - if r1:get_name() == "bucket:bucket_water" and tool:get_name() == "chemistry:bucket_emptying_system" then - local item = ItemStack("default:water_source", 1) - local bucket = ItemStack("bucket:bucket_empty", 1) - if reaction_possible(pos) then - pouring_sound(pos) - inv:add_item("product", item) - inv:set_stack("reactant", 1, bucket) - result = true - end - end - if r1:get_name() == "bucket:bucket_lava" and tool:get_name() == "chemistry:bucket_emptying_system" then - local item = ItemStack("default:lava_source", 1) - local bucket = ItemStack("bucket:bucket_empty", 1) - if reaction_possible(pos) then - pouring_sound(pos) - inv:add_item("product", item) - inv:set_stack("reactant", 1, bucket) - result = true - end - end - if r1:get_name() == "default:water_source" and r1:get_count() >= 2 and tool:get_name() == "chemistry:electrolytic_unit" then - local item = ItemStack("chemistry:hydrogen", 1) - local oxygen = ItemStack("chemistry:oxygen", 1) - if reaction_possible(pos) then - inv:add_item("product", item) - inv:add_item("product", item) - inv:add_item("product", oxygen) - r1:set_count(r1:get_count() - 2) - inv:set_stack("reactant", 1, r1) - result = true - end - end - if r1:get_name() == "chemistry:salt" and r1:get_count() >= 2 and tool:get_name() == "chemistry:electrolytic_unit" then - local sodium = ItemStack("chemistry:sodium", 1) - local chlorine = ItemStack("chemistry:chlorine", 1) - if reaction_possible(pos) then - inv:add_item("product", sodium) - inv:add_item("product", sodium) - inv:add_item("product", chlorine) - r1:set_count(r1:get_count() - 2) - inv:set_stack("reactant", 1, r1) - result = true - end - end - if r1:get_name() == "chemistry:hydrogen" and r1:get_count() >= 4 and tool:get_name() == "chemistry:star" then - local helium = ItemStack("chemistry:helium", 1) - if reaction_possible(pos) then - inv:add_item("product", helium) - r1:set_count(r1:get_count() - 4) - inv:set_stack("reactant", 1, r1) - result = true - end - end - if r1:get_name() == "chemistry:helium" and r1:get_count() >= 3 and tool:get_name() == "chemistry:star" then - local carbon = ItemStack("default:coal_lump", 1) - if reaction_possible(pos) then - inv:add_item("product", carbon) - r1:set_count(r1:get_count() - 3) - inv:set_stack("reactant", 1, r1) - result = true - end - end - if r1:get_name() == "default:coal_lump" and r1:get_count() >= 2 and tool:get_name() == "chemistry:star" then - local neon = ItemStack("chemistry:neon", 1) - local helium = ItemStack("chemistry:helium", 1) - if reaction_possible(pos) then - inv:add_item("product", neon) - inv:add_item("product", helium) - r1:set_count(r1:get_count() - 2) - inv:set_stack("reactant", 1, r1) - result = true - end - end - if r1:get_name() == "chemistry:oxygen" and r1:get_count() >= 2 and tool:get_name() == "chemistry:star" then - if math.random() < 0.5 then - local sulfur = ItemStack("chemistry:sulfur_lump", 1) - if reaction_possible(pos) then - inv:add_item("product", sulfur) - r1:set_count(r1:get_count() - 2) - inv:set_stack("reactant", 1, r1) - result = true - end - else - local silicon = ItemStack("chemistry:silicon", 1) - local helium = ItemStack("chemistry:helium", 1) - if reaction_possible(pos) then - inv:add_item("product", silicon) - inv:add_item("product", helium) - r1:set_count(r1:get_count() - 2) - inv:set_stack("reactant", 1, r1) - result = true - end - end - end - if r1:get_name() == "chemistry:silicon" and r1:get_count() >= 2 and tool:get_name() == "chemistry:star" then - local iron = ItemStack("default:iron_lump", 1) - if reaction_possible(pos) then - inv:add_item("product", iron) - r1:set_count(r1:get_count() - 2) - inv:set_stack("reactant", 1, r1) - result = true - end - end - if r1:get_name() == "chemistry:silicon" and tool:get_name() == "chemistry:bunsen" then - local item = ItemStack("default:sand", 1) - if reaction_possible(pos) then - bunsen_sound(pos) - inv:add_item("product", item) - r1:set_count(r1:get_count() - 1) - inv:set_stack("reactant", 1, r1) - result = true - end - end - if r1:get_name() == "default:cobble" and tool:get_name() == "chemistry:mortar" then - local item = ItemStack("default:gravel", 1) - if reaction_possible(pos) then - mortar_sound(pos) - inv:add_item("product", item) - r1:set_count(r1:get_count() - 1) - inv:set_stack("reactant", 1, r1) - result = true - end - end - if r1:get_name() == "default:sand" and tool:get_name() == "chemistry:mortar" then - local item = ItemStack("default:clay", 1) - if reaction_possible(pos) then - mortar_sound(pos) - inv:add_item("product", item) - r1:set_count(r1:get_count() - 1) - inv:set_stack("reactant", 1, r1) - result = true - end - end - if get_node_group(r1:get_name(), "tree") ~= 0 and tool:get_name() == "chemistry:mortar" then - local item = ItemStack("default:dirt", 1) - if reaction_possible(pos) then - mortar_sound(pos) - inv:add_item("product", item) - inv:add_item("product", item) - inv:add_item("product", item) - inv:add_item("product", item) - inv:add_item("product", item) - inv:add_item("product", item) - inv:add_item("product", item) - inv:add_item("product", item) - r1:set_count(r1:get_count() - 1) - inv:set_stack("reactant", 1, r1) - result = true - end - end - if get_node_group(r1:get_name(), "wood") ~= 0 and tool:get_name() == "chemistry:mortar" then - local item = ItemStack("default:dirt", 1) - if reaction_possible(pos) then - mortar_sound(pos) - inv:add_item("product", item) - inv:add_item("product", item) - r1:set_count(r1:get_count() - 1) - inv:set_stack("reactant", 1, r1) - result = true - end - end - if get_node_group(r1:get_name(), "tree") ~= 0 and tool:get_name() == "chemistry:bunsen" then - local item = ItemStack("chemistry:charcoal", 1) - if reaction_possible(pos) then - bunsen_sound(pos) - inv:add_item("product", item) - inv:add_item("product", item) - inv:add_item("product", item) - inv:add_item("product", item) - r1:set_count(r1:get_count() - 1) - inv:set_stack("reactant", 1, r1) - result = true - end - end - if get_node_group(r1:get_name(), "wood") ~= 0 and tool:get_name() == "chemistry:bunsen" then - local item = ItemStack("chemistry:charcoal", 1) - if reaction_possible(pos) then - bunsen_sound(pos) - inv:add_item("product", item) - r1:set_count(r1:get_count() - 1) - inv:set_stack("reactant", 1, r1) - result = true - end - end - -- The Completely Realistic Supernova™ - -- Masses don't work out, and the star continues to exist, but it's just to make the last few things renewable - if r1:get_name() == "default:diamond" and tool:get_name() == "chemistry:star" then - local value = math.random() - if (value < 0.4) then - if reaction_possible(pos) then - explosion_sound(pos) - local copper = ItemStack("default:copper_lump", 1) - inv:add_item("product", copper) - r1:set_count(r1:get_count() - 1) - inv:set_stack("reactant", 1, r1) - result = true - end - elseif (value < 0.8) then - if reaction_possible(pos) then - explosion_sound(pos) - local vanadium = ItemStack("chemistry:vanadium_lump", 1) - inv:add_item("product", vanadium) - r1:set_count(r1:get_count() - 1) - inv:set_stack("reactant", 1, r1) - result = true - end - elseif (value < 0.93) then - if reaction_possible(pos) then - explosion_sound(pos) - local gold = ItemStack("default:gold_lump", 1) - inv:add_item("product", gold) - r1:set_count(r1:get_count() - 1) - inv:set_stack("reactant", 1, r1) - result = true - end - else - if reaction_possible(pos) then - explosion_sound(pos) - local mese = ItemStack("default:mese_crystal", 1) - inv:add_item("product", mese) - r1:set_count(r1:get_count() - 1) - inv:set_stack("reactant", 1, r1) - result = true - end - end - end - if r1:get_name() == "chemistry:copper_sulfate_wet" and tool:get_name() == "chemistry:bunsen" then - local item = ItemStack("default:copper_sulfate_dry", 1) - if reaction_possible(pos) then - bunsen_sound(pos) - inv:add_item("product", item) - r1:set_count(r1:get_count() - 1) - inv:set_stack("reactant", 1, r1) - result = true - end - end - if r1:get_name() == "default:water_source" and r1:get_count() >= 10 and tool:get_name() == "chemistry:bunsen" then - local item = ItemStack("chemistry:salt", 1) - if reaction_possible(pos) then - bunsen_sound(pos) - inv:add_item("product", item) - r1:set_count(r1:get_count() - 10) - inv:set_stack("reactant", 1, r1) - result = true - end - end - if r1:get_name() == "chemistry:hydrogen" and tool:get_name() == "chemistry:bunsen" then - local item = ItemStack("default:water_source", 1) - if reaction_possible(pos) then - explosion_sound(pos) - inv:add_item("product", item) - r1:set_count(r1:get_count() - 1) - inv:set_stack("reactant", 1, r1) - result = true - end - end - end -- r1 switch - else - if r1:get_name() == "chemistry:sulfur_trioxide" and r2:get_name() == "default:water_source" and tool:get_name() == "chemistry:stir_stick" then - local item = ItemStack("chemistry:sulfur_trioxide_water", 1) - if reaction_possible(pos) then - inv:add_item("product", item) - r1:set_count(r1:get_count() - 1) - r2:set_count(r2:get_count() - 1) - inv:set_stack("reactant", 1, r1) - inv:set_stack("reactant", 2, r2) - result = true - end + local r = {} + r[1] = inv:get_stack("reactant", 1) + r[2] = inv:get_stack("reactant", 2) + r[3] = inv:get_stack("reactant", 3) + r[4] = inv:get_stack("reactant", 4) + r[5] = inv:get_stack("reactant", 5) + r[6] = inv:get_stack("reactant", 6) + + local reaction = nil + for i=1, #reactions do + local formula = reactions[i] + local needed_tool = formula.tool + local needed_catalyst = formula.catalyst + local needed_reactants = formula.reactants + local reaction_works = true + for j=1, 6 do + local needed_reactant = needed_reactants[j] + local ok = false + if needed_reactant == nil then + ok = true + else + for k=1, 6 do + local supplied_reactant = r[k] + if check_name_match(supplied_reactant:get_name(), needed_reactant:get_name()) and supplied_reactant:get_count() >= needed_reactant:get_count() then + ok = true + end + end + end + if not ok then + reaction_works = false + end + end + local reactant_count = 0 + for k = 1, 6 do + local supplied_reactant = r[k] + if not r[k]:is_empty() then + reactant_count = reactant_count + 1 + end + end + if reactant_count ~= #needed_reactants then + reaction_works = false + end + if not check_item_match(needed_tool, tool) then + reaction_works = false + end + if not check_item_match(needed_catalyst, catalyst) then + reaction_works = false + end + if reaction_works then + reaction = formula + end + end + + if not (reaction == nil) then + local rand = math.random() + local total_probability = 0.0 + local selected_output = nil + while selected_output == nil do + for i=1, #reaction.possible_outputs do + local output = reaction.possible_outputs[i] + total_probability = total_probability + output.probability + if total_probability > rand then + selected_output = output + break + end + end + if selected_output == nil then + minetest.log("info", "Hit epsilon, retry") + end + end + local products = selected_output.products + if reaction_possible(pos, products) then + local reactants = reaction.reactants + for j=1, 6 do + local reactant = reactants[j] + if not (reactant == nil) then + for k=1, 6 do + if check_name_match(r[k]:get_name(), reactant:get_name()) then + r[k]:set_count(r[k]:get_count() - reactant:get_count()) + inv:set_stack("reactant", k, r[k]) end - if r1:get_name() == "chemistry:sulfur_trioxide" and r2:get_name() == "chemistry:sulfuric_acid" and tool:get_name() == "chemistry:stir_stick" then - local item = ItemStack("chemistry:disulfuric_acid", 1) - if reaction_possible(pos) then - inv:add_item("product", item) - r1:set_count(r1:get_count() - 1) - r2:set_count(r2:get_count() - 1) - inv:set_stack("reactant", 1, r1) - inv:set_stack("reactant", 2, r2) - result = true - end - end - if r1:get_name() == "chemistry:disulfuric_acid" and r2:get_name() == "default:water_source" and tool:get_name() == "chemistry:stir_stick" then - local item = ItemStack("chemistry:sulfuric_acid", 1) - if reaction_possible(pos) then - inv:add_item("product", item) - inv:add_item("product", item) - r1:set_count(r1:get_count() - 1) - r2:set_count(r2:get_count() - 1) - inv:set_stack("reactant", 1, r1) - inv:set_stack("reactant", 2, r2) - result = true - end - end - if r1:get_name() == "chemistry:hydrogen" and r2:get_name() == "chemistry:chlorine" and tool:get_name() == "chemistry:bunsen" then - local item = ItemStack("chemistry:hydrogen_chloride", 1) - if reaction_possible(pos) then - explosion_sound(pos) - inv:add_item("product", item) - inv:add_item("product", item) - r1:set_count(r1:get_count() - 1) - r2:set_count(r2:get_count() - 1) - inv:set_stack("reactant", 1, r1) - inv:set_stack("reactant", 2, r2) - result = true - end - end - if r1:get_name() == "chemistry:hydrogen_chloride" and r2:get_name() == "default:water_source" and tool:get_name() == "chemistry:stir_stick" then - local item = ItemStack("chemistry:hydrochloric_acid", 1) - if reaction_possible(pos) then - stirring_sound(pos) - inv:add_item("product", item) - r1:set_count(r1:get_count() - 1) - r2:set_count(r2:get_count() - 1) - inv:set_stack("reactant", 1, r1) - inv:set_stack("reactant", 2, r2) - result = true - end - end - if r1:get_name() == "chemistry:sodium" and r1:get_count() >= 2 and r2:get_name() == "default:water_source" and r2:get_count() >= 2 and tool:get_name() == "chemistry:stir_stick" then - local item = ItemStack("chemistry:sodium_hydroxide", 1) - local hydrogen = ItemStack("chemistry:hydrogen", 1) - if reaction_possible(pos) then - stirring_sound(pos) - inv:add_item("product", item) - inv:add_item("product", item) - inv:add_item("product", hydrogen) - r1:set_count(r1:get_count() - 2) - r2:set_count(r2:get_count() - 2) - inv:set_stack("reactant", 1, r1) - inv:set_stack("reactant", 2, r2) - result = true - end - end - if r1:get_name() == "chemistry:sodium_hydroxide" and r2:get_name() == "default:water_source" and tool:get_name() == "chemistry:stir_stick" then - local item = ItemStack("chemistry:caustic_soda", 1) - if reaction_possible(pos) then - stirring_sound(pos) - inv:add_item("product", item) - r1:set_count(r1:get_count() - 1) - r2:set_count(r2:get_count() - 1) - inv:set_stack("reactant", 1, r1) - inv:set_stack("reactant", 2, r2) - result = true - end - end - if r1:get_name() == "default:coal_lump" and r2:get_name() == "chemistry:helium" and tool:get_name() == "chemistry:star" then - local oxygen = ItemStack("chemistry:oxygen", 1) - if reaction_possible(pos) then - inv:add_item("product", oxygen) - r1:set_count(r1:get_count() - 1) - r2:set_count(r2:get_count() - 1) - inv:set_stack("reactant", 1, r1) - inv:set_stack("reactant", 2, r2) - result = true - end - end - if r1:get_name() == "chemistry:neon" and r2:get_name() == "chemistry:helium" and tool:get_name() == "chemistry:star" then - local magnesium = ItemStack("chemistry:magnesium", 1) - if reaction_possible(pos) then - inv:add_item("product", magnesium) - r1:set_count(r1:get_count() - 1) - r2:set_count(r2:get_count() - 1) - inv:set_stack("reactant", 1, r1) - inv:set_stack("reactant", 2, r2) - result = true - end - end - if r1:get_name() == "chemistry:oxygen" and r2:get_name() == "chemistry:helium" and tool:get_name() == "chemistry:star" then - local neon = ItemStack("chemistry:neon", 1) - if reaction_possible(pos) then - inv:add_item("product", neon) - r1:set_count(r1:get_count() - 1) - r2:set_count(r2:get_count() - 1) - inv:set_stack("reactant", 1, r1) - inv:set_stack("reactant", 2, r2) - result = true - end - end - if (r1:get_name() == "default:copper_lump" or r1:get_name() == "default:copper_ingot") and r2:get_name() == "chemistry:sulfuric_acid" and tool:get_name() == "chemistry:stir_stick" and catalyst:get_name() == "chemistry:bunsen" then - local cuso4 = ItemStack("chemistry:copper_ii_sulfate_dry", 1) - local hydrogen = ItemStack("chemistry:hydrogen", 1) - if reaction_possible(pos) then - stirring_sound(pos) - inv:add_item("product", cuso4) - inv:add_item("product", hydrogen) - r1:set_count(r1:get_count() - 1) - r2:set_count(r2:get_count() - 1) - inv:set_stack("reactant", 1, r1) - inv:set_stack("reactant", 2, r2) - result = true - end - end - if (get_node_group(r1:get_name(), "stone") ~= 0 or r1:get_name() == "default:gravel") and r2:get_name() == "chemistry:sulfuric_acid" and tool:get_name() == "chemistry:stir_stick" then - local gypsum = ItemStack("chemistry:gypsum", 1) - if reaction_possible(pos) then - stirring_sound(pos) - inv:add_item("product", gypsum) - r1:set_count(r1:get_count() - 1) - r2:set_count(r2:get_count() - 1) - inv:set_stack("reactant", 1, r1) - inv:set_stack("reactant", 2, r2) - result = true - end - end - end -- r2 switch - end -- r3 switch - end -- r4 switch - end -- r5 switch - end -- r6 switch - + end + end + end + for k=1, #products do + inv:add_item("product", products[k]) + end + if reaction.sound then + local sound = reaction.sound + if sound == "bunsen" then + bunsen_sound() + elseif sound == "explosion" then + explosion_sound() + elseif sound == "mortar" then + mortar_sound() + elseif sound == "pouring" then + pouring_sound() + elseif sound == "stirring" then + stirring_sound() + end + end + result = true + end + end + return result end @@ -611,4 +360,3 @@ minetest.register_node("chemistry:lab", { allow_metadata_inventory_move = allow_metadata_inventory_move, allow_metadata_inventory_take = allow_metadata_inventory_take, }) - diff --git a/ores.lua b/ores.lua index 872ed49..ffd06b8 100644 --- a/ores.lua +++ b/ores.lua @@ -55,7 +55,7 @@ function chemistry.register_ores() ore_type = "scatter", ore = "chemistry:stone_with_vanadium", wherein = "default:stone", - clust_scarcity = 9 * 9 * 9, + clust_scarcity = 7 * 7 * 7, clust_num_ores = 5, clust_size = 3, y_min = 1025, @@ -66,7 +66,7 @@ function chemistry.register_ores() ore_type = "scatter", ore = "chemistry:stone_with_vanadium", wherein = "default:stone", - clust_scarcity = 12 * 12 * 12, + clust_scarcity = 9 * 9 * 9, clust_num_ores = 4, clust_size = 3, y_min = -63, @@ -77,7 +77,7 @@ function chemistry.register_ores() ore_type = "scatter", ore = "chemistry:stone_with_vanadium", wherein = "default:stone", - clust_scarcity = 9 * 9 * 9, + clust_scarcity = 7 * 7 * 7, clust_num_ores = 5, clust_size = 3, y_min = -31000, diff --git a/reactions.lua b/reactions.lua new file mode 100644 index 0000000..366c921 --- /dev/null +++ b/reactions.lua @@ -0,0 +1,476 @@ +register_reaction({ + tool = "chemistry:bunsen", + reactants = {ItemStack("chemistry:vanadium_ingot 2")}, + possible_outputs = { + { + probability = 1.0, + products = {ItemStack("chemistry:vanadium_v_oxide 1")} + } + }, + sound = "bunsen" +}) + +register_reaction({ + tool = "chemistry:bunsen", + reactants = {ItemStack("chemistry:sulfur_lump 1")}, + possible_outputs = { + { + probability = 1.0, + products = {ItemStack("chemistry:sulfur_dioxide 1")} + } + }, + sound = "bunsen" +}) + +register_reaction({ + tool = "chemistry:bunsen", + catalyst = "chemistry:vanadium_v_oxide", + reactants = {ItemStack("chemistry:sulfur_dioxide 2")}, + possible_outputs = { + { + probability = 1.0, + products = {ItemStack("chemistry:sulfur_trioxide 2")} + } + }, + sound = "bunsen" +}) + +register_reaction({ + tool = "chemistry:bucket_emptying_system", + reactants = {ItemStack("bucket:bucket_water 1")}, + possible_outputs = { + { + probability = 1.0, + products = {ItemStack("default:water_source 1"), ItemStack("bucket:bucket_empty 1")} + } + }, + sound = "pouring" +}) + +register_reaction({ + tool = "chemistry:bucket_emptying_system", + reactants = {ItemStack("bucket:bucket_lava 1")}, + possible_outputs = { + { + probability = 1.0, + products = {ItemStack("default:lava_source 1"), ItemStack("bucket:bucket_empty 1")} + } + }, + sound = "pouring" +}) + +register_reaction({ + tool = "chemistry:electrolytic_unit", + reactants = {ItemStack("default:water_source 2")}, + possible_outputs = { + { + probability = 1.0, + products = {ItemStack("chemistry:hydrogen 2"), ItemStack("chemistry:oxygen 1")} + } + } +}) + +register_reaction({ + tool = "chemistry:electrolytic_unit", + reactants = {ItemStack("chemistry:salt 2")}, + possible_outputs = { + { + probability = 1.0, + products = {ItemStack("chemistry:sodium 2"), ItemStack("chemistry:chlorine 1")} + } + } +}) + +register_reaction({ + tool = "chemistry:star", + reactants = {ItemStack("chemistry:hydrogen 4")}, + possible_outputs = { + { + probability = 1.0, + products = {ItemStack("chemistry:helium 1")} + } + } +}) + +register_reaction({ + tool = "chemistry:star", + reactants = {ItemStack("chemistry:helium 3")}, + possible_outputs = { + { + probability = 1.0, + products = {ItemStack("default:coal_lump 1")} + } + } +}) + +register_reaction({ + tool = "chemistry:star", + reactants = {ItemStack("default:coal_lump 2")}, + possible_outputs = { + { + probability = 1.0, + products = {ItemStack("chemistry:neon 1"), ItemStack("chemistry:helium 1")} + } + } +}) + +register_reaction({ + tool = "chemistry:star", + reactants = {ItemStack("chemistry:oxygen 2")}, + possible_outputs = { + { + probability = 0.5, + products = {ItemStack("chemistry:sulfur_lump 1")} + }, + { + probability = 0.5, + products = {ItemStack("chemistry:silicon 1"), ItemStack("chemistry:helium 1")} + } + } +}) + +register_reaction({ + tool = "chemistry:star", + reactants = {ItemStack("chemistry:silicon 2")}, + possible_outputs = { + { + probability = 1.0, + products = {ItemStack("default:iron_lump 1")} + } + } +}) + +register_reaction({ + tool = "chemistry:bunsen", + reactants = {ItemStack("chemistry:silicon 1")}, + possible_outputs = { + { + probability = 1.0, + products = {ItemStack("default:sand 1")} + } + }, + sound = "bunsen" +}) + +register_reaction({ + tool = "chemistry:mortar", + reactants = {ItemStack("default:cobble 1")}, + possible_outputs = { + { + probability = 1.0, + products = {ItemStack("default:gravel 1")} + } + }, + sound = "mortar" +}) + +register_reaction({ + tool = "chemistry:mortar", + reactants = {ItemStack("default:gravel 1")}, + possible_outputs = { + { + probability = 1.0, + products = {ItemStack("default:sand 1")} + } + }, + sound = "mortar" +}) + +register_reaction({ + tool = "chemistry:mortar", + reactants = {ItemStack("default:sand 1")}, + possible_outputs = { + { + probability = 1.0, + products = {ItemStack("default:clay 1")} + } + }, + sound = "mortar" +}) + +register_reaction({ + tool = "chemistry:mortar", + reactants = {ItemStack("group:tree 1")}, + possible_outputs = { + { + probability = 1.0, + products = {ItemStack("default:dirt 8")} + } + }, + sound = "mortar" +}) + +register_reaction({ + tool = "chemistry:mortar", + reactants = {ItemStack("group:wood 1")}, + possible_outputs = { + { + probability = 1.0, + products = {ItemStack("default:dirt 2")} + } + }, + sound = "mortar" +}) + +register_reaction({ + tool = "chemistry:bunsen", + reactants = {ItemStack("group:tree 1")}, + possible_outputs = { + { + probability = 1.0, + products = {ItemStack("chemistry:charcoal 4")} + } + }, + sound = "bunsen" +}) + +register_reaction({ + tool = "chemistry:bunsen", + reactants = {ItemStack("group:wood 1")}, + possible_outputs = { + { + probability = 1.0, + products = {ItemStack("chemistry:charcoal 1")} + } + }, + sound = "bunsen" +}) + +register_reaction({ + tool = "chemistry:star", + reactants = {ItemStack("default:iron_lump 1")}, + possible_outputs = { -- The probabilities are approximately proportional to the occurence at very low y + { + probability = 0.351, + products = {ItemStack("default:iron_lump 1")} + }, + { + probability = 0.309, + products = {ItemStack("chemistry:vanadium_lump 1")} + }, + { + probability = 0.146, + products = {ItemStack("default:copper_lump 1")} + }, + { + probability = 0.106, + products = {ItemStack("default:tin_lump 1")} + }, + { + probability = 0.048, + products = {ItemStack("default:gold_lump 1")} + }, + { + probability = 0.039, + products = {ItemStack("default:mese_crystal 1")} + }, + { + probability = 0.001, + products = {ItemStack("default:mese 1")} + } + } +}) + +register_reaction({ + tool = "chemistry:bunsen", + reactants = {ItemStack("chemistry:copper_ii_sulfate_wet 1")}, + possible_outputs = { + { + probability = 1.0, + products = {ItemStack("chemistry:copper_ii_sulfate_dry 1")} + } + }, + sound = "bunsen" +}) + +register_reaction({ + tool = "chemistry:bunsen", + reactants = {ItemStack("default:water_source 10")}, + possible_outputs = { + { + probability = 1.0, + products = {ItemStack("chemistry:salt 1")} + } + }, + sound = "bunsen" +}) + +register_reaction({ + tool = "chemistry:bunsen", + reactants = {ItemStack("chemistry:hydrogen 1")}, + possible_outputs = { + { + probability = 1.0, + products = {ItemStack("default:water_source 1")} + } + }, + sound = "explosion" +}) + +register_reaction({ + tool = "chemistry:stir_stick", + reactants = {ItemStack("chemistry:sulfur_trioxide 1"), ItemStack("default:water_source 1")}, + possible_outputs = { + { + probability = 1.0, + products = {ItemStack("chemistry:sulfur_trioxide_water 1")} + } + }, + sound = "stirring" +}) + +register_reaction({ + tool = "chemistry:stir_stick", + reactants = {ItemStack("chemistry:sulfur_trioxide 1"), ItemStack("chemistry:sulfuric_acid 1")}, + possible_outputs = { + { + probability = 1.0, + products = {ItemStack("chemistry:disulfuric_acid 1")} + } + }, + sound = "stirring" +}) + +register_reaction({ + tool = "chemistry:stir_stick", + reactants = {ItemStack("chemistry:disulfuric_acid 1"), ItemStack("default:water_source 1")}, + possible_outputs = { + { + probability = 1.0, + products = {ItemStack("chemistry:sulfuric_acid 2")} + } + }, + sound = "stirring" +}) + +register_reaction({ + tool = "chemistry:bunsen", + reactants = {ItemStack("chemistry:hydrogen 1"), ItemStack("chemistry:chlorine 1")}, + possible_outputs = { + { + probability = 1.0, + products = {ItemStack("chemistry:hydrogen_chloride 2")} + } + }, + sound = "explosion" +}) + +register_reaction({ + tool = "chemistry:stir_stick", + reactants = {ItemStack("chemistry:hydrogen_chloride 1"), ItemStack("default:water_source 1")}, + possible_outputs = { + { + probability = 1.0, + products = {ItemStack("chemistry:hydrochloric_acid 1")} + } + }, + sound = "stirring" +}) + +register_reaction({ + tool = "chemistry:stir_stick", + reactants = {ItemStack("chemistry:sodium 2"), ItemStack("default:water_source 2")}, + possible_outputs = { + { + probability = 1.0, + products = {ItemStack("chemistry:sodium_hydroxide 2"), ItemStack("chemistry:hydrogen 1")} + } + }, + sound = "stirring" +}) + +register_reaction({ + tool = "chemistry:stir_stick", + reactants = {ItemStack("chemistry:sodium_hydroxide 1"), ItemStack("default:water_source 1")}, + possible_outputs = { + { + probability = 1.0, + products = {ItemStack("chemistry:caustic_soda 1")} + } + }, + sound = "stirring" +}) + +register_reaction({ + tool = "chemistry:star", + reactants = {ItemStack("default:coal_lump 1"), ItemStack("chemistry:helium 1")}, + possible_outputs = { + { + probability = 1.0, + products = {ItemStack("chemistry:oxygen 1")} + } + } +}) + +register_reaction({ + tool = "chemistry:star", + reactants = {ItemStack("chemistry:neon 1"), ItemStack("chemistry:helium 1")}, + possible_outputs = { + { + probability = 1.0, + products = {ItemStack("chemistry:magnesium 1")} + } + } +}) + +register_reaction({ + tool = "chemistry:star", + reactants = {ItemStack("chemistry:oxygen 1"), ItemStack("chemistry:helium 1")}, + possible_outputs = { + { + probability = 1.0, + products = {ItemStack("chemistry:neon 1")} + } + } +}) + +register_reaction({ + tool = "chemistry:stir_stick", + catalyst = "chemistry:bunsen", + reactants = {ItemStack("default:copper_lump 1"), ItemStack("chemistry:sulfuric_acid 1")}, + possible_outputs = { + { + probability = 1.0, + products = {ItemStack("chemistry:copper_ii_sulfate_dry 1"), ItemStack("chemistry:hydrogen 1")} + } + }, + sound = "bunsen" +}) + +register_reaction({ + tool = "chemistry:stir_stick", + catalyst = "chemistry:bunsen", + reactants = {ItemStack("default:copper_ingot 1"), ItemStack("chemistry:sulfuric_acid 1")}, + possible_outputs = { + { + probability = 1.0, + products = {ItemStack("chemistry:copper_ii_sulfate_dry 1"), ItemStack("chemistry:hydrogen 1")} + } + }, + sound = "bunsen" +}) + +register_reaction({ + tool = "chemistry:stir_stick", + reactants = {ItemStack("group:stone 1"), ItemStack("chemistry:sulfuric_acid 1")}, + possible_outputs = { + { + probability = 1.0, + products = {ItemStack("chemistry:gypsum 1")} + } + }, + sound = "stirring" +}) + +register_reaction({ + tool = "chemistry:stir_stick", + reactants = {ItemStack("default:gravel 1"), ItemStack("chemistry:sulfuric_acid 1")}, + possible_outputs = { + { + probability = 1.0, + products = {ItemStack("chemistry:gypsum 1")} + } + }, + sound = "stirring" +}) + diff --git a/textures/chemistry_book.png b/textures/chemistry_book.png new file mode 100644 index 0000000000000000000000000000000000000000..43ecfd5ac1085996b83bdf3f9dbf8f0518cf9ffb GIT binary patch literal 437 zcmV;m0ZRUfP)LQ4^LfZ9>|({mAK<1-HWvf# zMJl*Bm4b-iT2pgNK@#{n$c0>!RG|-U2zT%E-hH`9M1*-%n6Z_amc?|n)F zz_JvqZJl9tc?Io*bpgbai<$<{Z3*Vo5X(jxN5>BUfQ#-1d_P3B(Lqtu;9l>h%)&d^ zb`}W$4%?3afN?O!>-!s2RZZ0vL`1@>*GzJn6?%GkrrSH0>NS(5&m>pwhSRM4X(pol ff8oE9F{ge2k