diff --git a/README.md b/README.md index ac22276..b2486e0 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,15 @@ # ExchangeClone +[![ContentDB](https://content.minetest.net/packages/ThePython10110/ExchangeClone/shields/downloads)](https://content.minetest.net/packages/ThePython10110/ExchangeClone) Allows players to turn items into energy, and energy into items. Supports all items in Minetest Game and MineClone 2, and anything that can be made from them! Also adds a whole bunch of other stuff. Welcome to the dev branch! This is the branch I'm currently working on, so it's likely that there are bugs. +ExchangeClone is tested with the latest release of Minetest, Minetest Game, MineClone2, and Mineclonia. + ## ExchangeClone's Features: +* Energy * Philosopher's Stone * Transmutation Table -* Energy * Alchemical Tome * Exchange Orb * Deconstructor @@ -17,7 +20,7 @@ Welcome to the dev branch! This is the branch I'm currently working on, so it's * Dark and Red Matter Tools * Dark and Red Matter Armor * Dark and Red Matter Furnaces -* PESA (deprecated) +* PESA (deprecated, WILL BE REMOVED in 7.0) See the [wiki](https://github.com/ThePython10110/ExchangeClone/wiki) for more information @@ -35,10 +38,9 @@ Dependencies: Minetest Game or MineClone. ## Known issues: -* It is impossible to die from most things when wearing DM/RM armor... MineClone's damage system is annoying. +* It is impossible to die from most things when wearing DM/RM armor in MineClon(e/ia)... There's some rounding thing that happens when the player has 1 health or something. I can't figur it out. * When machines are exploded, they (and the items inside) do not drop. I can't figure out why. * Dark/Red matter shears will sometimes (randomly) be treated as normal shears when used by MineClone dispensers. This will not be fixed. -* Nodes destroyed by special abilities will not usually update surrounding nodes (so you may end up with floating gravel, flowers, torches, etc.). This will *probably* not be fixed, unless a change to Minetest makes it easier. **If you have a suggestion or notice a bug, visit the [GitHub issues page](https://github.com/thepython10110/exchangeclone/issues).** @@ -57,65 +59,78 @@ Dependencies: Minetest Game or MineClone. ## Changelog
Look at this fancy expanding changelog -TODO: -Written/writable book alias -Campfire copy value -Philosopher's Stone/copper -Map aliases -Sponge aliases -Auto coral -Stripped stuff (kinda already works but still) -Bamboo block is automatically too much (tree group). -Bamboo mosaic (MCLA) actually has no energy value -Labels on Transmutation Table(t) items showing amount left (1.4K, 999.9M, 25.9B, etc.) - +### TODO: +* Written/writable book alias (MTG) +* Campfire copy value +* Philosopher's Stone/copper +* Map aliases +* Sponge aliases +* Stripped stuff (kinda already works but still) +* Bamboo block is automatically too much (tree group). +* Figure out what's going to happen with Technic (the PR probably won't be merged) +* Fix tools (after switching to bulk_remove, haven't been dropping) +* Add commands for setting custom energy values (set_item_energy), load after group values. +* Texture for Advanced Alchemical Chests +* Textures/code for covalence dust +* Mind, Life, Body, and Soul Stones +* Improve multidig +* Add more Energy Collectors \* Not actually added yet -### v6.0 (The Automation Update) +### v6.0 (The Compatibility Update) + +**Summary:** + +I'm going to name all major updates from now on, unless and until I change my mind. I'm also going to have short summaries before the long list of changes. The biggest thing in this update is AUTOMATIC ENERGY VALUES! This means I no longer have to add energy values for every single item, meaning it's easier to add support for more mods. Also, players' personal energy limit has been increased from about two billion to *one trillion*. ExchangeClone is now also compatible with the Hopper and Pipeworks mods. + +**The PESA will be removed in version 7.0.** + * New Features: * Automatically generated energy values! Based on crafting and cooking recipes. - * Depending on the number of items you have, this could increase loading time. - * For reasons beyond my control, things kind of vary a bit between loads because of which items are added to the `minetest.registered_items` first (which is somewhat random). For instance, the Lookup Tool in MineClone2 might sometimes have an energy value of 5 (1 stick + 1 glass) or 16 (4 sticks) depending on whether the energy value for glass is added first or not. At least, I assume that's the reason. - * Technic recipe types (grinding, alloying, etc.) will also work, as long as their `output_size` is 1 and my PR gets merged. + * Depending on the number of crafting recipes you have, this could increase load times. This is definitely a bit of an issue in MineClone2, probably due to the number of banner/dye recipes. Eventually (hopefully), loom functionality will be added and this will improve quite a bit. + * Technic recipe types (grinding, alloying, etc.) will also work, as long as their `output_size` is 1 (meaning they only output one item at a time, so not the centrifuge or separator). * Also supports Mineclonia's stonecutter recipes, Netherite upgrades, and more. - * Added energy values for Basic Materials\* and Technic - * Infinite food (costs 64 energy to use, but doesn't disappear, equal to MCL steak) + * Added various ways of adding custom energy values or energy recipes (`exchangeclone.register_energy_alias`, `exchangeclone.register_craft_type`, and `exchangeclone.register_craft`) + * Added energy values for More Ores and Technic. + * Infinite food (costs 64 energy to use, but isn't consumed, equal to MCL steak) * Alchemical Chests, Alchemical Bags, and Advanced Alchemical Chests + * Labels on items in the Transmutation GUI showing how many items can be created. + * Added comma separators when energy is shown (to make it easier to identify large numbers) * Support for Pipeworks and Hopper mods! (MCL hoppers already worked) * Covalence Dust (left-click with Philosopher's Stone to open repairing menu; only tools with an energy value can be repaired)\* * Mind, Life, Body, and Soul Stones (although MTG only has the soul stone).\* - * Mercurial Eye (maybe)\* + * More Energy Collectors (to go with the increased energy limit) * Chat commands to set/add/remove energy from a player (requires `privs` privilege): - * `/add_energy [player] value` (player defaults to self, value can be negative) - * `/set_energy [player] value` (player defaults to self) - * Added `exchangeclone.register_energy_alias(alias, itemstring)` function, which allow items to be treated as other items. + * `/add_player_energy [player] value` (player defaults to self, value can be negative) + * `/set_player_energy [player] value` (player defaults to self) * Changes: * Energy values are now in `_exchangeclone_energy/energy_values.lua`, and are laid out differently, and aliases now work. * ExchangeClone is now a modpack for [annoying reasons](https://forum.minetest.net/viewtopic.php?f=47&p=429775s). *Every single mod* in the modpack is required, regardless of what it says the dependencies are. You may need to disable and then enable it for everything to work correctly. * The default energy value is no longer 1 but none. - * The 2.14-billion-ish personal energy limit is has been increased to 1,000,000,000,000 (1 trillion). Any higher (literally ANY higher) and there are precision-based exploits like being able to create infinite glass panes (or really anything with an energy value less than 1) when you have enough energy. - * MineClone(ia/2) energy values now (mostly) match ProjectE's, with a few minor differences. - * Emeralds are still worth less than diamonds, because villager trades make then *way* easier to get than diamonds. + * The 2.14-billion-ish personal energy limit is has been increased to 1,000,000,000,000 (1 trillion). Any higher (literally ANY higher) and there are precision-based exploits like being able to create an unlimited amount of anything with an energy value less than 1. I considered finding some library for arbitrary precision in Lua, but decided it was too much work (and nobody really needs more than a trillion energy anyway). + * MineClon(e2/ia) energy values now (mostly) match ProjectE's, with a few minor differences. + * Emeralds are still worth less than diamonds because of villager trades (in my opinion, this should be changed in ProjectE as well) * Bamboo is worth less so things make more sense. * Dyes are worth different amounts based on their crafting recipes, so different colors of things are worth different amounts. * Since fractional energy values are allowed, some energy values may be slightly different. * Energy values are now multiples of 0.05 instead of 0.25, for no real reason. - * Added comma separators when energy is shown (to make it easier to identify large numbers) * Tools that break multiple nodes at once (hammers, hoes, katar, and morningstar) use a better method that may (?) slightly decrease lag.\* * A couple changes involving the Philosopher's Stone: * Ender pearls can now be crafted with 4 iron and the Philosopher's Stone (MCL). * Copper's energy value has been changed (128 instead of 85), and the recipe has been changed accordingly.\* * Ice and obsidian can now be transmuted into water and lava, respectively. * It is now impossible to transmute between bedrock and barriers (MCL). I thought it was funny originally, but now I'm realizing that I don't want this to be annoying to people who run servers (are there any servers with this mod?) - * It now costs 4 dark/red matter to make a block, which is great news if you already have some (because they're now worth more), but not so great if you don't. - * Tool abilities now cost nothing (to match ProjectE). - * Tool abilities now take upgrades into account (silk touch, fortune, etc.) except for the sword AOE ability (which is annoying). + * It now costs 4 dark/red matter to make a block, which is great news if you already have some (because they're now worth more), but not so great if you don't. Sorry and you're welcome. + * Tool abilities now have no energy cost (to match ProjectE). + * Tool abilities now take upgrades into account (silk touch, fortune, etc.) except for the sword AOE ability (which would require more irritating hacky workarounds). + * Several neutral mobs (endermen, spiders, piglins) are now affected by the dark/red matter sword in "slay all" mode, to match ProjectE. * Bugfixes: * Fixed potion energy values * Fixed Red Matter Shield recipe * Fixed other modes of DM/RM tools not having energy values - * Deconstructors and Constructors now (sort of) use node timers again, meaning they won't stop trying to work. + * Deconstructors and Constructors now use node timers again (but better than before), meaning they won't ever stop. (Previously, they would stop if there was too much energy to deconstruct or too little energy to construct.) + * Tool abilities now update nodes that require support (torches, sand, etc.)\*. ### v5.4 * Fixed a minor bug with the Energy Collector (thanks @programmerjake!) diff --git a/_exchangeclone_energy/init.lua b/_exchangeclone_energy/init.lua deleted file mode 100644 index a76b32f..0000000 --- a/_exchangeclone_energy/init.lua +++ /dev/null @@ -1,365 +0,0 @@ --- Registers all energy values - --- Gets lists of energy values -dofile(minetest.get_modpath("_exchangeclone_energy").."/energy_values.lua") - -local function get_cheapest_recipe(itemstring, log) - itemstring = ItemStack(itemstring):get_name() - local recipes = exchangeclone.recipes[itemstring] - if not recipes then return end - local cheapest - for _, recipe in ipairs(recipes) do - local ingredient_cost = 0 - local output_count = ItemStack(recipe.output):get_count() - local output_name = ItemStack(recipe.output):get_name() - local skip = false - if not recipe.type or recipe.type == "shaped" then - for _, row in ipairs(recipe.recipe) do - for _, item in ipairs(row) do - if item ~= "" then - if item == output_name then - output_count = math.max(0, output_count - 1) - else - local cost = exchangeclone.get_item_energy(item) - if (not cost) or cost == 0 then - skip = item - else - ingredient_cost = ingredient_cost + cost - end - end - end - end - end - elseif (recipe.type == "shapeless") or (recipe.type == "technic") or recipe.type == "preserving" then - for _, item in ipairs(recipe.recipe) do - if item == output_name then - output_count = math.max(0, output_count - 1) - else - local cost = exchangeclone.get_item_energy(item) - if (not cost) or cost == 0 then - skip = item - else - ingredient_cost = ingredient_cost + cost - end - end - end - elseif recipe.type == "cooking" or recipe.type == "stonecutting" or recipe.type == "decaychain" then - local cost = exchangeclone.get_item_energy(recipe.recipe) - if (not cost) or cost == 0 then - skip = recipe.recipe - if recipe.recipe == "mcl_core:cobble" then minetest.log(dump({recipe, cost})) end - else - ingredient_cost = cost - end - end - if recipe.replacements and not skip then - for _, item in ipairs(recipe.replacements) do - local cost = exchangeclone.get_item_energy(item[2]) - if (not cost) or cost == 0 then - skip = item - else - ingredient_cost = ingredient_cost - cost - end - end - end - if output_count < 1 then skip = true end - if not skip then - local total_cost = math.floor(ingredient_cost*20/math.max(1, output_count))/20 -- allow .05, won't work with huge numbers - if (not cheapest) or (cheapest[1] > total_cost) then - cheapest = {total_cost, recipe} - end - end - if log then minetest.log(dump({ - recipe = recipe, - ingredient_cost = ingredient_cost, - output_count = output_count - })) end - end - return cheapest and cheapest[1] -end - -local function set_item_energy(itemstring, energy_value) - if not (energy_value and itemstring) then return end - energy_value = math.floor(energy_value*20)/20 -- floor to nearest .05 - if energy_value < 0 then return end - local def = minetest.registered_items[itemstring] - if not def then return end - local description = def.description or "" - local existing_energy_value = description:find("Energy Value: ([%d%.,]+)") - if existing_energy_value then - description = description:gsub("Energy Value: ([%d%.,]+)", "Energy Value: "..exchangeclone.format_number(energy_value)) - else - if description[#description] ~= "\n" then - description = description.."\n" - end - description = description.."Energy Value: "..exchangeclone.format_number(energy_value) - end - minetest.override_item(itemstring, { - description = description, - energy_value = energy_value, - }) -end - -local function add_potion_energy(info) - local base_cost = exchangeclone.get_item_energy("mcl_potions:water") or 1 --cost of water bottle - -- TODO: Change dragon's breath when MineClone does. - local dragon_breath_cost = exchangeclone.get_item_energy("mcl_potions:dragon_breath") or 8.5 - base_cost = math.floor(base_cost + (info.ingredient_cost / 3)) -- /3 because 3 potions/ingredient - base_cost = base_cost + (info.custom_base_cost or (exchangeclone.get_item_energy("mcl_nether:nether_wart_item") or 24)/3) - local splash_cost = base_cost + (exchangeclone.get_item_energy("mcl_mobitems:gunpowder") or 192)/3 - local lingering_cost = math.floor(base_cost + (dragon_breath_cost / 3)) - set_item_energy("mcl_potions:"..info.name, base_cost) - set_item_energy("mcl_potions:"..info.name.."_splash", splash_cost) - set_item_energy("mcl_potions:"..info.name.."_lingering", lingering_cost) - if not info.no_arrow then - local arrow_cost = math.floor(lingering_cost/8 + (exchangeclone.get_item_energy("mcl_bows:arrow") or 14)) - set_item_energy("mcl_potions:"..info.name.."_arrow", arrow_cost) - end - if info.plus then - local plus_base_cost = base_cost + (exchangeclone.get_item_energy("mesecons:redstone") or 64)/3 - local plus_splash_cost = splash_cost + (exchangeclone.get_item_energy("mesecons:redstone") or 64)/3 - local plus_lingering_cost = lingering_cost + (exchangeclone.get_item_energy("mesecons:redstone") or 64)/3 - set_item_energy("mcl_potions:"..info.name.."_plus", plus_base_cost) - set_item_energy("mcl_potions:"..info.name.."_plus_splash", plus_splash_cost) - set_item_energy("mcl_potions:"..info.name.."_plus_lingering", plus_lingering_cost) - if not info.no_arrow then - local plus_arrow_cost = math.floor(plus_lingering_cost/8 + (exchangeclone.get_item_energy("mcl_bows:arrow") or 14)) - set_item_energy("mcl_potions:"..info.name.."_plus_arrow", plus_arrow_cost) - end - end - if info.two then - local two_base_cost = base_cost + (exchangeclone.get_item_energy("mcl_nether:glowstone_dust") or 384)/3 - local two_splash_cost = splash_cost + (exchangeclone.get_item_energy("mcl_nether:glowstone_dust") or 384)/3 - local two_lingering_cost = lingering_cost + (exchangeclone.get_item_energy("mcl_nether:glowstone_dust") or 384)/3 - set_item_energy("mcl_potions:"..info.name.."_2", two_base_cost) - set_item_energy("mcl_potions:"..info.name.."_2_splash", two_splash_cost) - set_item_energy("mcl_potions:"..info.name.."_2_lingering", two_lingering_cost) - if not info.no_arrow then - local two_arrow_cost = math.floor(two_lingering_cost/8 + (exchangeclone.get_item_energy("mcl_bows:arrow") or 14)) - set_item_energy("mcl_potions:"..info.name.."_2_arrow", two_arrow_cost) - end - end -end - --- Wait until all mods are loaded (to make sure all items have been registered) -minetest.register_on_mods_loaded(function() - minetest.log("action", "ExchangeClone: Registering energy values") - local auto = {} - - -- handle aliases in exchangeclone.recipes - for itemstring, recipes in pairs(exchangeclone.recipes) do - local new_name = ItemStack(itemstring):get_name() - if new_name and new_name ~= "" and new_name ~= itemstring then - exchangeclone.recipes[new_name] = recipes - end - end - - -- Register group energy values - local groupnames = {} - for index, group in ipairs(exchangeclone.group_values) do - groupnames[#groupnames + 1] = group[1] --Get list of group names - end - local grouped_items = exchangeclone.get_group_items(groupnames, true, true) - for index, group in ipairs(exchangeclone.group_values) do - for i, item in pairs(grouped_items[group[1]]) do - set_item_energy(item, group[2]) - end - end - - for itemstring, energy_value in pairs(exchangeclone.energy_values) do - set_item_energy(itemstring, energy_value) - end - - if exchangeclone.mineclonia then - -- Handle stonecutter recipes - -- TODO: Check recipe_yield for every Mineclonia update - local recipe_yield = { --maps itemgroup to the respective recipe yield, default is 1 - ["slab"] = 2, - } - for result, def in pairs(minetest.registered_items) do - if minetest.get_item_group(result,"not_in_creative_inventory") == 0 then - if def._mcl_stonecutter_recipes then - for _, source in pairs(def._mcl_stonecutter_recipes) do - local yield = 1 - for k,v in pairs(recipe_yield) do if minetest.get_item_group(result,k) > 0 then yield = v end end - if not exchangeclone.recipes[result] then exchangeclone.recipes[result] = {} end - table.insert(exchangeclone.recipes[result],{output = result.." "..yield, type = "stonecutting", recipe = source}) - minetest.log(dump({output = result.." "..yield, type = "stonecutting", recipe = source})) - end - end - end - end - -- Handle decaychains - if mcl_copper then - local decaychains = mcl_copper.registered_decaychains - for name, data in pairs(decaychains) do - for i, itemstring in ipairs(data.nodes) do - if minetest.get_item_group(name,"not_in_creative_inventory") == 0 then - local preserved_itemstring = itemstring.."_preserved" - if not exchangeclone.recipes[preserved_itemstring] then exchangeclone.recipes[preserved_itemstring] = {} end - table.insert(exchangeclone.recipes[preserved_itemstring], {output = preserved_itemstring, type = "preserving", recipe = {itemstring, "group:"..data.preserve_group}}) - if i > 1 then - if not exchangeclone.recipes[itemstring] then exchangeclone.recipes[itemstring] = {} end - table.insert(exchangeclone.recipes[itemstring],{output = itemstring, type = "decaychain", recipe = data.nodes[i-1]}) - end - end - end - end - end - end - - -- Register energy aliases and certain energy values that would be annoying to include in exchangeclone.energy_values - if exchangeclone.mcl then - for i = 0, 31 do - exchangeclone.register_energy_alias("mcl_compass:18", "mcl_compass:"..i) - exchangeclone.register_energy_alias("mcl_compass:18", "mcl_compass:"..i.."_lodestone") - end - for i = 0, 63 do - exchangeclone.register_energy_alias("mcl_clock:clock", "mcl_clock:clock_"..i) - end - exchangeclone.register_energy_alias("doc_identifier:identifier_solid", "doc_identifier:identifier_liquid") - exchangeclone.register_energy_alias("mcl_books:writable_book", "mcl_books:written_book") - - for _, coral_type in ipairs({"brain", "bubble", "fire", "horn", "tube"}) do - for thing, value in pairs({[coral_type.."_coral"] = 16, [coral_type.."_coral_block"] = 64, [coral_type.."_coral_fan"] = 16}) do - set_item_energy("mcl_ocean:"..thing, value) - set_item_energy("mcl_ocean:dead_"..thing, value/16) - end - end - end - - -- Register base energy values - for itemstring, energy_value in pairs(exchangeclone.energy_values) do - set_item_energy(itemstring, energy_value) - end - - -- Register copper block energy values (has to be done before automatic stuff but after base stuff) - if exchangeclone.mcl then - local cheapest = get_cheapest_recipe("mcl_copper:block") - if cheapest then - set_item_energy("mcl_copper:block", cheapest) - end - for _, state in ipairs({"exposed", "weathered", "oxidized"}) do - set_item_energy("mcl_copper:block_"..state, exchangeclone.get_item_energy("mcl_copper:block")) - end - end - - -- Register `exchangeclone_custom_energy` values and decide whether to automatically register energy values - for itemstring, def in pairs(minetest.registered_items) do - if def.exchangeclone_custom_energy then - set_item_energy(itemstring, def.exchangeclone_custom_energy) - else - itemstring = exchangeclone.handle_alias(itemstring) or itemstring - def = minetest.registered_items[itemstring] -- in case itemstring changed - local _, _, mod_name, item_name = itemstring:find("([%d_%l]+):([%d_%l]+)") - if ( - def - and item_name - and mod_name - and def.description - and def.description ~= "" - -- I hate recovery compasses. - and ((minetest.get_item_group(itemstring, "not_in_creative_inventory") < 1) or (mod_name == "mcl_compass")) - and (not exchangeclone.get_item_energy(itemstring)) - and exchangeclone.recipes[itemstring] - ) then - auto[itemstring] = true - end - end - end - - local old_auto - local same = false - local i = 1 - -- Automatically register energy values - while not same do - minetest.log("action", "ExchangeClone: \tPASS #"..i) - if auto == {} then break end - if old_auto then - same = true - for itemstring, _ in pairs(old_auto) do - if itemstring ~= "" and not auto[itemstring] then - same = false - break - end - end - end - if same then - minetest.log("action", "ExchangeClone:\tNo change, stopping.") - break - end - old_auto = table.copy(auto) - for itemstring, _ in pairs(auto) do - local cheapest = get_cheapest_recipe(itemstring) - if cheapest then - set_item_energy(itemstring, cheapest) - auto[itemstring] = nil - end - end - i = i + 1 - end - - --minetest.log(dump(auto)) - - if exchangeclone.mcl then - exchangeclone.mcl_potion_data = exchangeclone.mcl_potion_data or {} - table.insert_all(exchangeclone.mcl_potion_data, { -- automatically assumes base cost is awkward potion if not specified - {name = "water", ingredient_cost = 0, custom_base_cost = 0, no_arrow = true}, - {name = "awkward", ingredient_cost = 0, no_arrow = true}, - {name = "fire_resistance", ingredient_cost = 768, plus = true}, - {name = "poison", ingredient_cost = 128, plus = true, two = true}, - {name = "harming", ingredient_cost = 192, custom_base_cost = 52, two = true}, - {name = "healing", ingredient_cost = 1852, two = true}, - {name = "leaping", ingredient_cost = 64, plus = true, two = true}, - {name = "mundane", ingredient_cost = 32, no_arrow = true, custom_base_cost = 0}, - {name = "night_vision", ingredient_cost = 1840, plus = true}, - {name = "regeneration", ingredient_cost = 4096, plus = true, two = true}, - {name = "slowness", ingredient_cost = 192, custom_base_cost = 20, plus = true, two = true}, - {name = "swiftness", ingredient_cost = 32, plus = true, two = true}, - {name = "thick", ingredient_cost = 384, no_arrow = true, custom_base_cost = 0}, - {name = "water_breathing", ingredient_cost = 64, plus = true}, - {name = "invisibility", ingredient_cost = 192, custom_base_cost = 623, plus = true}, - {name = "withering", ingredient_cost = 128, plus = true, two = true} - }) - for _, info in ipairs(exchangeclone.mcl_potion_data) do - add_potion_energy(info) - end - -- Concrete and banners/shields (don't remember why the shields don't work) - for _, color in ipairs({"red", "orange", "yellow", "lime", "dark_green", "cyan", "light_blue", "blue", "purple", "magenta", "pink", "black", "white", "silver", "grey", "brown"}) do - set_item_energy("mcl_colorblocks:concrete_"..color, exchangeclone.get_item_energy("mcl_colorblocks:concrete_powder_"..color) or 2) - set_item_energy("mcl_stairs:stair_concrete_"..color, get_cheapest_recipe("mcl_stairs:stair_concrete_"..color)) - set_item_energy("mcl_stairs:slab_concrete_"..color, get_cheapest_recipe("mcl_stairs:slab_concrete_"..color)) - set_item_energy("mcl_shields:shield_"..color, (exchangeclone.get_item_energy("mcl_banners:banner_item_"..color) or 340) + (exchangeclone.get_item_energy("mcl_shields:shield") or 304)) - end - -- Enchanted/netherite tools - for name, def in pairs(minetest.registered_items) do - if def._mcl_enchanting_enchanted_tool then - exchangeclone.register_energy_alias(name, def._mcl_enchanting_enchanted_tool) - end - if def._mcl_upgrade_item then - if not name:find("enchanted") then - set_item_energy(def._mcl_upgrade_item, (exchangeclone.get_item_energy(name) or 0)+(exchangeclone.get_item_energy("mcl_nether:netherite_ingot") or 73728)) - end - end - end - -- Recovery compasses use a random compass frame for the crafting recipe... Incredibly irritating. - for i = 0, 31 do - if exchangeclone.get_item_energy("mcl_compass:"..i.."_recovery") then - for j = 0, 31 do - exchangeclone.register_energy_alias("mcl_compass:"..i.."_recovery", "mcl_compass:"..j.."_recovery") - end - break - end - end - end - - -- Adds energy values to aliased items, even though they're not used (just so it's displayed) - for alias, itemstring in pairs(exchangeclone.energy_aliases) do - set_item_energy(alias, exchangeclone.get_item_energy(itemstring)) - end - - -- Free up memory (I assume this will do that?) - exchangeclone.recipes = nil - exchangeclone.energy_values = nil - minetest.log("action", "ExchangeClone: Done registering energy values.") -end) \ No newline at end of file diff --git a/_exchangeclone_energy/mod.conf b/_exchangeclone_energy/mod.conf deleted file mode 100644 index fc297a0..0000000 --- a/_exchangeclone_energy/mod.conf +++ /dev/null @@ -1,4 +0,0 @@ -name = _exchangeclone_energy -title = ExchangeClone Energy -depends = exchangeclone, zzzz_exchangeclone_crafthook -optional_depends = 3d_armor, mcl_item_id, mcl_core, default, moreswords, mcl_stairs, meat_blocks, sticky_things, fake_liquids, sound_machine, stairs, mcl_dispensers, farming, mobs_mc, screwdriver, _mcl_autogroup, unified_inventory \ No newline at end of file diff --git a/exchangeclone/axes.lua b/exchangeclone/axes.lua index 3e886f3..d615016 100644 --- a/exchangeclone/axes.lua +++ b/exchangeclone/axes.lua @@ -11,6 +11,7 @@ exchangeclone.axe_action = { exchangeclone.play_ability_sound(player) end data.itemstack = itemstack + data.remove_positions = {} return data end, action = function(player, pos, node, data) @@ -26,13 +27,14 @@ exchangeclone.axe_action = { else local drops = minetest.get_node_drops(node.name, data.itemstack) exchangeclone.drop_items_on_player(pos, drops, player) - minetest.set_node(pos, {name = "air"}) + table.insert(data.remove_positions, pos) end end end return data end, end_action = function(player, center, range, data) + exchangeclone.remove_nodes(data.remove_positions) if range > 0 or not data.strip then exchangeclone.start_cooldown(player, "axe", range/6) end diff --git a/exchangeclone/energy_collector.lua b/exchangeclone/energy_collector.lua index 8d8ee29..930a9fa 100644 --- a/exchangeclone/energy_collector.lua +++ b/exchangeclone/energy_collector.lua @@ -22,18 +22,9 @@ minetest.register_lbm({ end, }) -local check_positions = { - {x=0,y=0,z=1}, - {x=0,y=0,z=-1}, - {x=0,y=1,z=0}, - {x=0,y=-1,z=0}, - {x=1,y=0, z=0}, - {x=-1,y=0,z=0}, -} - local function check_for_furnaces(pos, set_furnace, start) local found = false - for _, check_pos in ipairs(check_positions) do + for _, check_pos in ipairs(exchangeclone.neighbors) do local new_pos = vector.add(pos, check_pos) local node = minetest.get_node(new_pos) local furnace = minetest.get_item_group(node.name, "exchangeclone_furnace") diff --git a/exchangeclone/hammers.lua b/exchangeclone/hammers.lua index 3b852ba..ddc55f6 100644 --- a/exchangeclone/hammers.lua +++ b/exchangeclone/hammers.lua @@ -12,6 +12,7 @@ exchangeclone.hammer_action = { exchangeclone.multidig[player:get_player_name()] = true -- to prevent doing 3x3 as well as AOE exchangeclone.play_ability_sound(player) data.itemstack = itemstack + data.remove_positions = {} return data end, action = function(player, pos, node, data) @@ -21,12 +22,13 @@ exchangeclone.hammer_action = { else local drops = minetest.get_node_drops(node.name, data.itemstack) exchangeclone.drop_items_on_player(pos, drops, player) - minetest.set_node(pos, {name = "air"}) + table.insert(data.remove_positions, pos) end end return data end, end_action = function(player, center, range, data) + exchangeclone.remove_nodes(data.remove_positions) exchangeclone.multidig[player:get_player_name()] = nil exchangeclone.start_cooldown(player, "hammer", range/2) -- The hammer has by far the most lag potential and therefore a long cooldown. end diff --git a/exchangeclone/infinite_food.lua b/exchangeclone/infinite_food.lua index 6fe60cd..6f6f210 100644 --- a/exchangeclone/infinite_food.lua +++ b/exchangeclone/infinite_food.lua @@ -16,9 +16,12 @@ end minetest.register_tool("exchangeclone:infinite_food", { description = S("Infinite Food").."\n"..S("Consumes 64 energy when eaten"), + wield_image = "farming_bread.png^[screen:#555500", + inventory_image = "farming_bread.png^[screen:#555500", groups = { food = 2, eatable = 8, disable_repair = 1, fire_immune = 1}, - on_place = infinite_food_function, - on_secondary_use = infinite_food_function, + on_place = exchangeclone.mcl and infinite_food_function, + on_secondary_use = exchangeclone.mcl and infinite_food_function, + on_use = (not exchangeclone.mcl) and infinite_food_function, _mcl_saturation = 12.8, }) @@ -27,4 +30,15 @@ minetest.register_on_item_eat(function(hp_change, replace_with_item, itemstack, if itemstack:get_name() == "exchangeclone:infinite_food" then exchangeclone.set_player_energy(player, player_energy - 64) end -end) \ No newline at end of file +end) + +local bread_itemstring = exchangeclone.mcl and "mcl_farming:bread" or "farming:bread" + +minetest.register_craft({ + output = "exchangeclone:infinite_food", + recipe = { + {bread_itemstring, bread_itemstring, bread_itemstring,}, + {bread_itemstring, "exchangeclone:transmutation_tablet", bread_itemstring,}, + {bread_itemstring, bread_itemstring, bread_itemstring,}, + } +}) \ No newline at end of file diff --git a/exchangeclone/init.lua b/exchangeclone/init.lua index 0d23f81..71aa8a0 100644 --- a/exchangeclone/init.lua +++ b/exchangeclone/init.lua @@ -1,26 +1,14 @@ -if not (exchangeclone and minetest.get_modpath("_exchangeclone_energy")) then +if not exchangeclone then error("Disable and re-enable the ExchangeClone modpack.") end -if (not minetest.get_modpath("mcl_core")) and (not minetest.get_modpath("default")) then - error("ExchangeClone requires Minetest Game, MineClone2, or MineClonia (and possibly other spinoffs).\nPlease use one of those games.") -else - exchangeclone.mcl = minetest.get_modpath("mcl_core") -end +minetest.log("action", "ExchangeClone: Registering own stuff") -exchangeclone.mineclonia = minetest.get_game_info().id == "mineclonia" -- if exchangeclone.mineclonia, exchangeclone.mcl is also defined. - -exchangeclone.pipeworks = minetest.get_modpath("pipeworks") - -exchangeclone.orb_max = 51200000 -- Max capacity of Klein Star Omega in ProjectE +-- Decides what mod to use for sounds +exchangeclone.sound_mod = exchangeclone.mcl and mcl_sounds or default local modpath = minetest.get_modpath("exchangeclone") -exchangeclone.orb_max = minetest.settings:get("exchangeclone.orb_max") or 51200000 - -minetest.log("action", "ExchangeClone: Registering own stuff") - -dofile(modpath.."/lib.lua") dofile(modpath.."/constructor.lua") dofile(modpath.."/deconstructor.lua") dofile(modpath.."/energy_collector.lua") @@ -53,4 +41,12 @@ dofile(modpath.."/alchemical_chests.lua") dofile(modpath.."/transmutation_table.lua") dofile(modpath.."/furnaces.lua") -minetest.log("action", "ExchangeClone: Done.") \ No newline at end of file +minetest.log("action", "ExchangeClone: Done.") + +minetest.register_on_mods_loaded(function() + local start_time = minetest.get_us_time() + minetest.log("action", "ExchangeClone: Registering energy values") + dofile(modpath.."/register_energy.lua") + local total_time = minetest.get_us_time() - start_time + minetest.log("action", "ExchangeClone: Done registering energy values ("..total_time.." microseconds)") +end) \ No newline at end of file diff --git a/exchangeclone/mod.conf b/exchangeclone/mod.conf index e024f62..e09941d 100644 --- a/exchangeclone/mod.conf +++ b/exchangeclone/mod.conf @@ -1,6 +1,6 @@ name = exchangeclone title = ExchangeClone description = The main part of the modpack (depends on both the other mods) -min_minetest_version = 5.5 +depends = zzzz_exchangeclone_init optional_depends = mcl_core, default, mcl_armor, 3d_armor, mcl_item_id, mobs_mc, hopper, pipeworks, mcl_dispensers author = ThePython10110 \ No newline at end of file diff --git a/exchangeclone/philosophers_stone.lua b/exchangeclone/philosophers_stone.lua index 50261c2..17da0df 100644 --- a/exchangeclone/philosophers_stone.lua +++ b/exchangeclone/philosophers_stone.lua @@ -1,5 +1,7 @@ local S = minetest.get_translator() +local phil = "exchangeclone:philosophers_stone" + local function show_enchanting(player) local player_meta = player:get_meta() player_meta:set_int("mcl_enchanting:num_bookshelves", 8) -- 15 for max enchantments @@ -304,14 +306,8 @@ minetest.register_tool("exchangeclone:philosophers_stone", { }) local diamond = exchangeclone.itemstrings.diamond -local corner = "default:tin_ingot" -local side = "default:obsidian" - -if exchangeclone.mcl then - diamond = "mcl_core:diamond" - corner = "mcl_nether:glowstone_dust" - side = "mesecons:redstone" -end +local corner = exchangeclone.itemstrings.glowstoneworth +local side = exchangeclone.itemstrings.redstoneworth minetest.register_craft({ output = "exchangeclone:philosophers_stone", @@ -326,166 +322,123 @@ minetest.register_craft({ output = "mcl_core:coal_lump", type = "shapeless", recipe = { - "exchangeclone:philosophers_stone", + phil, "mcl_core:charcoal_lump", "mcl_core:charcoal_lump", "mcl_core:charcoal_lump", "mcl_core:charcoal_lump" }, - replacements = {{"exchangeclone:philosophers_stone", "exchangeclone:philosophers_stone"}} + replacements = {{phil, phil}} }) minetest.register_craft({ output = "mcl_core:charcoal_lump 4", type = "shapeless", recipe = { - "exchangeclone:philosophers_stone", + phil, "mcl_core:coal_lump" }, - replacements = {{"exchangeclone:philosophers_stone", "exchangeclone:philosophers_stone"}} + replacements = {{phil, phil}} }) minetest.register_craft({ output = exchangeclone.itemstrings.iron, type = "shapeless", recipe = { - "exchangeclone:philosophers_stone", + phil, exchangeclone.itemstrings.coal, exchangeclone.itemstrings.coal, }, - replacements = {{"exchangeclone:philosophers_stone", "exchangeclone:philosophers_stone"}} + replacements = {{phil, phil}} }) minetest.register_craft({ output = exchangeclone.itemstrings.coal.." 2", type = "shapeless", recipe = { - "exchangeclone:philosophers_stone", + phil, exchangeclone.itemstrings.iron }, - replacements = {{"exchangeclone:philosophers_stone", "exchangeclone:philosophers_stone"}} + replacements = {{phil, phil}} }) minetest.register_craft({ - output = "mcl_copper:copper_ingot 6", + output = exchangeclone.itemstrings.copper.." 2", type = "shapeless", recipe = { - "exchangeclone:philosophers_stone", - "mcl_core:iron_ingot", - "mcl_core:iron_ingot", + phil, + exchangeclone.itemstrings.iron, + exchangeclone.itemstrings.iron, }, - replacements = {{"exchangeclone:philosophers_stone", "exchangeclone:philosophers_stone"}} + replacements = {{phil, phil}} }) minetest.register_craft({ - output = "default:copper_ingot 4", + output = exchangeclone.itemstrings.iron.." 2", type = "shapeless", recipe = { - "exchangeclone:philosophers_stone", - "default:steel_ingot", - "default:steel_ingot", - "default:steel_ingot", - "default:steel_ingot", - "default:steel_ingot", + phil, + exchangeclone.itemstrings.copper, + exchangeclone.itemstrings.copper, }, - replacements = {{"exchangeclone:philosophers_stone", "exchangeclone:philosophers_stone"}} -}) - -minetest.register_craft({ - output = "mcl_core:iron_ingot", - type = "shapeless", - recipe = { - "exchangeclone:philosophers_stone", - "mcl_copper:copper_ingot", - "mcl_copper:copper_ingot", - "mcl_copper:copper_ingot", - }, - replacements = {{"exchangeclone:philosophers_stone", "exchangeclone:philosophers_stone"}} + replacements = {{phil, phil}} }) minetest.register_craft({ output = "mcl_throwing:ender_pearl", type = "shapeless", recipe = { - "exchangeclone:philosophers_stone", + phil, "mcl_core:iron_ingot", "mcl_core:iron_ingot", "mcl_core:iron_ingot", "mcl_core:iron_ingot", }, - replacements = {{"exchangeclone:philosophers_stone", "exchangeclone:philosophers_stone"}} -}) - - -minetest.register_craft({ - output = "mcl_core:iron_ingot 2", - type = "shapeless", - recipe = { - "exchangeclone:philosophers_stone", - "mcl_copper:copper_ingot", - "mcl_copper:copper_ingot", - "mcl_copper:copper_ingot", - "mcl_copper:copper_ingot", - "mcl_copper:copper_ingot", - "mcl_copper:copper_ingot", - }, - replacements = {{"exchangeclone:philosophers_stone", "exchangeclone:philosophers_stone"}} -}) -minetest.register_craft({ - output = "default:steel_ingot 5", - type = "shapeless", - recipe = { - "exchangeclone:philosophers_stone", - "default:copper_ingot", - "default:copper_ingot", - "default:copper_ingot", - "default:copper_ingot", - }, - replacements = {{"exchangeclone:philosophers_stone", "exchangeclone:philosophers_stone"}} + replacements = {{phil, phil}} }) minetest.register_craft({ output = "default:tin_ingot 4", type = "shapeless", recipe = { - "exchangeclone:philosophers_stone", + phil, "default:copper_ingot", "default:copper_ingot", "default:copper_ingot", "default:copper_ingot", "default:copper_ingot", }, - replacements = {{"exchangeclone:philosophers_stone", "exchangeclone:philosophers_stone"}} + replacements = {{phil, phil}} }) minetest.register_craft({ output = "default:copper_ingot 5", type = "shapeless", recipe = { - "exchangeclone:philosophers_stone", + phil, "default:tin_ingot", "default:tin_ingot", "default:tin_ingot", "default:tin_ingot", }, - replacements = {{"exchangeclone:philosophers_stone", "exchangeclone:philosophers_stone"}} + replacements = {{phil, phil}} }) minetest.register_craft({ output = exchangeclone.itemstrings.iron.." 8", type = "shapeless", recipe = { - "exchangeclone:philosophers_stone", + phil, exchangeclone.itemstrings.gold }, - replacements = {{"exchangeclone:philosophers_stone", "exchangeclone:philosophers_stone"}} + replacements = {{phil, phil}} }) minetest.register_craft({ output = exchangeclone.itemstrings.gold, type = "shapeless", recipe = { - "exchangeclone:philosophers_stone", + phil, exchangeclone.itemstrings.iron, exchangeclone.itemstrings.iron, exchangeclone.itemstrings.iron, @@ -495,107 +448,107 @@ minetest.register_craft({ exchangeclone.itemstrings.iron, exchangeclone.itemstrings.iron, }, - replacements = {{"exchangeclone:philosophers_stone", "exchangeclone:philosophers_stone"}} + replacements = {{phil, phil}} }) minetest.register_craft({ output = exchangeclone.itemstrings.emeraldworth, type = "shapeless", recipe = { - "exchangeclone:philosophers_stone", + phil, exchangeclone.itemstrings.gold, exchangeclone.itemstrings.gold, }, - replacements = {{"exchangeclone:philosophers_stone", "exchangeclone:philosophers_stone"}} + replacements = {{phil, phil}} }) minetest.register_craft({ output = exchangeclone.itemstrings.gold.." 2", type = "shapeless", recipe = { - "exchangeclone:philosophers_stone", + phil, exchangeclone.itemstrings.emeraldworth, }, - replacements = {{"exchangeclone:philosophers_stone", "exchangeclone:philosophers_stone"}} + replacements = {{phil, phil}} }) minetest.register_craft({ output = exchangeclone.itemstrings.diamond, type = "shapeless", recipe = { - "exchangeclone:philosophers_stone", + phil, exchangeclone.itemstrings.emeraldworth, exchangeclone.itemstrings.emeraldworth, }, - replacements = {{"exchangeclone:philosophers_stone", "exchangeclone:philosophers_stone"}} + replacements = {{phil, phil}} }) minetest.register_craft({ output = exchangeclone.itemstrings.emeraldworth.." 2", type = "shapeless", recipe = { - "exchangeclone:philosophers_stone", + phil, exchangeclone.itemstrings.diamond }, - replacements = {{"exchangeclone:philosophers_stone", "exchangeclone:philosophers_stone"}} + replacements = {{phil, phil}} }) minetest.register_craft({ output = "mcl_nether:ancient_debris", type = "shapeless", recipe = { - "exchangeclone:philosophers_stone", + phil, "mcl_core:diamond", "mcl_core:diamond", }, - replacements = {{"exchangeclone:philosophers_stone", "exchangeclone:philosophers_stone"}} + replacements = {{phil, phil}} }) minetest.register_craft({ output = "mcl_core:diamond 2", type = "shapeless", recipe = { - "exchangeclone:philosophers_stone", + phil, "mcl_nether:ancient_debris" }, - replacements = {{"exchangeclone:philosophers_stone", "exchangeclone:philosophers_stone"}} + replacements = {{phil, phil}} }) minetest.register_craft({ output = "mcl_core:diamond 2", type = "shapeless", recipe = { - "exchangeclone:philosophers_stone", + phil, "mcl_nether:netherite_scrap" }, - replacements = {{"exchangeclone:philosophers_stone", "exchangeclone:philosophers_stone"}} + replacements = {{phil, phil}} }) minetest.register_craft({ output = "mcl_core:diamond 9", type = "shapeless", recipe = { - "exchangeclone:philosophers_stone", + phil, "mcl_nether:netherite_ingot" }, - replacements = {{"exchangeclone:philosophers_stone", "exchangeclone:philosophers_stone"}} + replacements = {{phil, phil}} }) minetest.register_craft({ output = "mcl_nether:netherite_ingot", type = "shapeless", recipe = { - "exchangeclone:philosophers_stone", + phil, "mcl_core:diamondblock" }, - replacements = {{"exchangeclone:philosophers_stone", "exchangeclone:philosophers_stone"}} + replacements = {{phil, phil}} }) minetest.register_craft({ output = "mcl_nether:glowstone_dust", type = "shapeless", recipe = { - "exchangeclone:philosophers_stone", + phil, "mesecons:redstone", "mesecons:redstone", "mesecons:redstone", @@ -603,105 +556,105 @@ minetest.register_craft({ "mesecons:redstone", "mesecons:redstone", }, - replacements = {{"exchangeclone:philosophers_stone", "exchangeclone:philosophers_stone"}} + replacements = {{phil, phil}} }) minetest.register_craft({ output = "mesecons:redstone 6", type = "shapeless", recipe = { - "exchangeclone:philosophers_stone", + phil, "mcl_nether:glowstone_dust", }, - replacements = {{"exchangeclone:philosophers_stone", "exchangeclone:philosophers_stone"}} + replacements = {{phil, phil}} }) minetest.register_craft({ output = "mcl_core:lapis", type = "shapeless", recipe = { - "exchangeclone:philosophers_stone", + phil, "mcl_nether:glowstone_dust", "mcl_nether:glowstone_dust" }, - replacements = {{"exchangeclone:philosophers_stone", "exchangeclone:philosophers_stone"}} + replacements = {{phil, phil}} }) minetest.register_craft({ output = "mcl_nether:glowstone_dust 2", type = "shapeless", recipe = { - "exchangeclone:philosophers_stone", + phil, "mcl_core:lapis", }, - replacements = {{"exchangeclone:philosophers_stone", "exchangeclone:philosophers_stone"}} + replacements = {{phil, phil}} }) minetest.register_craft({ output = "exchangeclone:alchemical_coal", type = "shapeless", recipe = { - "exchangeclone:philosophers_stone", + phil, exchangeclone.itemstrings.coal, exchangeclone.itemstrings.coal, exchangeclone.itemstrings.coal, exchangeclone.itemstrings.coal, }, - replacements = {{"exchangeclone:philosophers_stone", "exchangeclone:philosophers_stone"}} + replacements = {{phil, phil}} }) minetest.register_craft({ output = exchangeclone.itemstrings.coal.." 4", type = "shapeless", recipe = { - "exchangeclone:philosophers_stone", + phil, "exchangeclone:alchemical_coal", }, - replacements = {{"exchangeclone:philosophers_stone", "exchangeclone:philosophers_stone"}} + replacements = {{phil, phil}} }) minetest.register_craft({ output = "exchangeclone:mobius_fuel", type = "shapeless", recipe = { - "exchangeclone:philosophers_stone", + phil, "exchangeclone:alchemical_coal", "exchangeclone:alchemical_coal", "exchangeclone:alchemical_coal", "exchangeclone:alchemical_coal", }, - replacements = {{"exchangeclone:philosophers_stone", "exchangeclone:philosophers_stone"}} + replacements = {{phil, phil}} }) minetest.register_craft({ output = "exchangeclone:alchemical_coal 4", type = "shapeless", recipe = { - "exchangeclone:philosophers_stone", + phil, "exchangeclone:mobius_fuel", }, - replacements = {{"exchangeclone:philosophers_stone", "exchangeclone:philosophers_stone"}} + replacements = {{phil, phil}} }) minetest.register_craft({ output = "exchangeclone:aeternalis_fuel", type = "shapeless", recipe = { - "exchangeclone:philosophers_stone", + phil, "exchangeclone:mobius_fuel", "exchangeclone:mobius_fuel", "exchangeclone:mobius_fuel", "exchangeclone:mobius_fuel", }, - replacements = {{"exchangeclone:philosophers_stone", "exchangeclone:philosophers_stone"}} + replacements = {{phil, phil}} }) minetest.register_craft({ output = "exchangeclone:mobius_fuel 4", type = "shapeless", recipe = { - "exchangeclone:philosophers_stone", + phil, "exchangeclone:aeternalis_fuel", }, - replacements = {{"exchangeclone:philosophers_stone", "exchangeclone:philosophers_stone"}} + replacements = {{phil, phil}} }) \ No newline at end of file diff --git a/exchangeclone/red_matter_multitools.lua b/exchangeclone/red_matter_multitools.lua index 5264edf..11c0b45 100644 --- a/exchangeclone/red_matter_multitools.lua +++ b/exchangeclone/red_matter_multitools.lua @@ -131,6 +131,7 @@ exchangeclone.morningstar_action = { local data = {} data.itemstack = itemstack exchangeclone.play_ability_sound(player) + data.remove_positions = {} return data end, action = function(player, pos, node, data) @@ -141,12 +142,13 @@ exchangeclone.morningstar_action = { else local drops = minetest.get_node_drops(node.name, data.itemstack) exchangeclone.drop_items_on_player(pos, drops, player) - minetest.set_node(pos, {name = "air"}) + table.insert(data.remove_positions, pos) end end return data end, end_action = function(player, center, range, data) + exchangeclone.remove_nodes(data.remove_positions) exchangeclone.start_cooldown(player, "shovel", range/4) -- Longish cooldown exchangeclone.start_cooldown(player, "hammer", range/2) end diff --git a/exchangeclone/register_energy.lua b/exchangeclone/register_energy.lua new file mode 100644 index 0000000..93adceb --- /dev/null +++ b/exchangeclone/register_energy.lua @@ -0,0 +1,329 @@ +local function get_cheapest_recipe(itemstring, log) + itemstring = ItemStack(itemstring):get_name() + local recipes = exchangeclone.recipes[itemstring] + if not recipes then return end + local cheapest + for _, recipe in ipairs(recipes) do + local ingredient_cost = 0 + local output_count = ItemStack(recipe.output):get_count() + local output_name = ItemStack(recipe.output):get_name() + local skip = false + if not recipe.type or exchangeclone.craft_types[recipe.type].type == "shaped" then + for _, row in ipairs(recipe.recipe) do + for _, item in ipairs(row) do + if item ~= "" then + if item == output_name then + output_count = math.max(0, output_count - 1) + else + local cost = exchangeclone.get_item_energy(item) + if (not cost) or cost == 0 then + skip = item + else + ingredient_cost = ingredient_cost + cost + end + end + end + end + end + elseif exchangeclone.craft_types[recipe.type].type == "shapeless" then + for _, item in ipairs(recipe.recipe) do + if item == output_name then + output_count = math.max(0, output_count - 1) + else + local cost = exchangeclone.get_item_energy(item) + if (not cost) or cost == 0 then + skip = item + else + ingredient_cost = ingredient_cost + cost + end + end + end + elseif exchangeclone.craft_types[recipe.type].type == "cooking" then + local cost = exchangeclone.get_item_energy(recipe.recipe) + if (not cost) or cost == 0 then + skip = recipe.recipe + else + ingredient_cost = cost + end + end + if recipe.replacements and not skip then + for _, item in ipairs(recipe.replacements) do + local cost = exchangeclone.get_item_energy(item[2]) + if (not cost) or cost == 0 then + skip = item + else + ingredient_cost = ingredient_cost - cost + end + end + end + if output_count < 1 then skip = true end + if not skip then + local total_cost = math.floor(ingredient_cost*20/math.max(1, output_count))/20 -- allow .05, won't work with huge numbers + if (not cheapest) or (cheapest[1] > total_cost) then + cheapest = {total_cost, recipe} + end + end + if log then minetest.log(dump({ + recipe = recipe, + ingredient_cost = ingredient_cost, + output_count = output_count + })) end + end + return cheapest and cheapest[1] +end + +-- Sets the energy value of an item, must be called during load time. +local function set_item_energy(itemstring, energy_value) + if not (energy_value and itemstring) then return end + energy_value = math.floor(energy_value*20)/20 -- floor to nearest .05 + if energy_value < 0 then return end + local def = minetest.registered_items[itemstring] + if not def then return end + local description = def.description or "" + + -- Override energy value if it already exists + local existing_energy_value = description:find("Energy Value: ([%d%.,]+)") + if existing_energy_value then + description = description:gsub("Energy Value: ([%d%.,]+)", "Energy Value: "..exchangeclone.format_number(energy_value)) + else + if description[#description] ~= "\n" then + description = description.."\n" + end + description = description.."Energy Value: "..exchangeclone.format_number(energy_value) + end + minetest.override_item(itemstring, { + description = description, + energy_value = energy_value, + }) +end + +local auto = {} + +-- Register group energy values +local groupnames = {} +for index, group in ipairs(exchangeclone.group_values) do + groupnames[#groupnames + 1] = group[1] --Get list of group names +end +local grouped_items = exchangeclone.get_group_items(groupnames, true, true) +for index, group in ipairs(exchangeclone.group_values) do + for i, item in pairs(grouped_items[group[1]]) do + set_item_energy(item, group[2]) + end +end + +-- Handle stonecutter recipes and decaychains in Mineclonia +if exchangeclone.mineclonia then + exchangeclone.register_craft_type("stonecutting", "cooking") + -- TODO: Check recipe_yield for every Mineclonia update + local recipe_yield = { --maps itemgroup to the respective recipe yield, default is 1 + ["slab"] = 2, + ["cut_copper"] = 4, + } + for result, def in pairs(minetest.registered_items) do + if minetest.get_item_group(result,"not_in_creative_inventory") == 0 then + if def._mcl_stonecutter_recipes then + for _, source in pairs(def._mcl_stonecutter_recipes) do + local yield = 1 + for k,v in pairs(recipe_yield) do if minetest.get_item_group(result,k) > 0 then yield = v end end + exchangeclone.register_craft({output = result.." "..yield, type = "stonecutting", recipe = source}) + end + end + end + end + + if mcl_copper then + exchangeclone.register_craft_type("decaychain", "cooking") + exchangeclone.register_craft_type("preserving", "cooking") + local decaychains = mcl_copper.registered_decaychains + for name, data in pairs(decaychains) do + for i, itemstring in ipairs(data.nodes) do + if minetest.get_item_group(name,"not_in_creative_inventory") == 0 then + local preserved_itemstring = itemstring.."_preserved" + exchangeclone.register_craft({output = preserved_itemstring, type = "preserving", recipe = {itemstring, "group:"..data.preserve_group}}) + if i > 1 then + exchangeclone.register_craft({output = itemstring, type = "decaychain", recipe = data.nodes[i-1]}) + end + end + end + end + end +end + +-- Register clock/compass aliases, handle enchanted/netherite stuff, potions, and concrete, and register coral energy values +if exchangeclone.mcl then + for i = 0, 31 do + exchangeclone.register_energy_alias("mcl_compass:18", "mcl_compass:"..i) + exchangeclone.register_energy_alias("mcl_compass:18", "mcl_compass:"..i.."_lodestone") + end + for i = 0, 63 do + exchangeclone.register_energy_alias("mcl_clock:clock", "mcl_clock:clock_"..i) + end + exchangeclone.register_energy_alias("doc_identifier:identifier_solid", "doc_identifier:identifier_liquid") + exchangeclone.register_energy_alias("mcl_books:writable_book", "mcl_books:written_book") + + for _, coral_type in ipairs({"brain", "bubble", "fire", "horn", "tube"}) do + for thing, value in pairs({[coral_type.."_coral"] = 16, [coral_type.."_coral_block"] = 64, [coral_type.."_coral_fan"] = 16}) do + set_item_energy("mcl_ocean:"..thing, value) + set_item_energy("mcl_ocean:dead_"..thing, value/16) + end + end + + + exchangeclone.register_craft_type("brewing", "shapeless") + local function add_potion_recipe(info) + if not info.bases then info.bases = {"mcl_potions:awkward"} end + for _, base in ipairs(info.bases) do + local ingredient = info.ingredient + local normal = "mcl_potions:"..info.name + local splash = normal.."_splash" + local lingering = normal.."_lingering" + exchangeclone.register_craft({output = normal.." 3", type = "brewing", recipe = {base, base, base, ingredient}}) + exchangeclone.register_craft({output = normal.."_splash 3", type = "brewing", recipe = {normal, normal, normal, "mcl_mobitems:gunpowder"}}) + exchangeclone.register_craft({output = normal.."_lingering 3", type = "brewing", recipe = {normal, normal, normal, "mcl_potions:dragon_breath"}}) + if info.plus then + exchangeclone.register_craft({output = normal.."_plus 3", type = "brewing", recipe = {normal, normal, normal, "mcl_nether:glowstone_dust"}}) + exchangeclone.register_craft({output = normal.."_plus_splash 3", type = "brewing", recipe = {splash, splash, splash, "mcl_nether:glowstone_dust"}}) + exchangeclone.register_craft({output = normal.."_plus_lingering 3", type = "brewing", recipe = {lingering, lingering, lingering, "mcl_nether:glowstone_dust"}}) + end + if info.two then + exchangeclone.register_craft({output = normal.."_2 3", type = "brewing", recipe = {normal, normal, normal, "mesecons:redstone"}}) + exchangeclone.register_craft({output = normal.."_2_splash 3", type = "brewing", recipe = {splash, splash, splash, "mesecons:redstone"}}) + exchangeclone.register_craft({output = normal.."_2_lingering 3", type = "brewing", recipe = {lingering, lingering, lingering, "mesecons:redstone"}}) + end + end + end + for _, info in ipairs(exchangeclone.mcl_potion_data) do + add_potion_recipe(info) + end + + exchangeclone.register_craft_type("upgrading", "shapeless") + -- Enchanted/netherite tools + for name, def in pairs(minetest.registered_items) do + if def._mcl_enchanting_enchanted_tool then + exchangeclone.register_energy_alias(name, def._mcl_enchanting_enchanted_tool) + end + if def._mcl_upgrade_item then + if not name:find("enchanted") then + exchangeclone.register_craft({output = def._mcl_upgrade_item, type = "upgrading", recipe = {name, "mcl_nether:netherite_ingot"}}) + end + end + end + + exchangeclone.register_craft_type("hardening", "cooking") + -- Concrete and banners/shields (don't remember why the shields don't work) + for _, color in ipairs({"red", "orange", "yellow", "lime", "dark_green", "cyan", "light_blue", "blue", "purple", "magenta", "pink", "black", "white", "silver", "grey", "brown"}) do + exchangeclone.register_craft({output = "mcl_colorblocks:concrete_"..color, type = "hardening", recipe = "mcl_colorblocks:concrete_powder_"..color}) + exchangeclone.register_craft({output = "mcl_shields:shield_"..color, type = "shapeless", recipe = {"mcl_banners:banner_item_"..color, "mcl_shields:shield"}}) + end +end + +-- Register copper block/stonecutting energy recipes in MineClone2 +if exchangeclone.mcl and not exchangeclone.mineclonia then + exchangeclone.register_craft_type("oxidation", "cooking") + local cheapest = get_cheapest_recipe("mcl_copper:block") + if cheapest then + set_item_energy("mcl_copper:block", cheapest) + end + local states = {"", "_exposed", "_weathered", "_oxidized"} + for i = 2, #states do + exchangeclone.register_craft({output = "mcl_copper:block"..states[i], type = "oxidation", recipe = "mcl_copper:block"..states[i-1]}) + end + exchangeclone.register_craft_type("stonecutting", "cooking") + for input, outputs in pairs(mcl_stonecutter.registered_recipes) do + for output, amount in pairs(outputs) do + exchangeclone.register_craft({output = output.." "..amount, type = "stonecutting", recipe = input}) + end + end +end + +-- Register base energy values +for itemstring, energy_value in pairs(exchangeclone.base_energy_values) do + set_item_energy(itemstring, energy_value) +end + +-- Register `exchangeclone_custom_energy` values and decide whether to automatically register energy values +for itemstring, def in pairs(minetest.registered_items) do + if def.exchangeclone_custom_energy then + set_item_energy(itemstring, def.exchangeclone_custom_energy) + else + itemstring = exchangeclone.handle_alias(itemstring) or itemstring + def = minetest.registered_items[itemstring] -- in case itemstring changed + local _, _, mod_name, item_name = itemstring:find("([%d_%l]+):([%d_%l]+)") + if ( + def + and item_name + and mod_name + and def.description + and def.description ~= "" + and ((minetest.get_item_group(item_name, "not_in_creative_inventory") < 1) or mod_name == "mcl_compass") + and (not exchangeclone.get_item_energy(itemstring)) + and exchangeclone.recipes[itemstring] + ) then + auto[itemstring] = true + end + end +end + +-- handle aliases in exchangeclone.recipes +for itemstring, recipes in pairs(exchangeclone.recipes) do + local new_name = ItemStack(itemstring):get_name() + if new_name and new_name ~= "" and new_name ~= itemstring then + exchangeclone.recipes[new_name] = recipes + end +end + +local old_auto +local same = false +local i = 1 +-- Automatically register energy values +while not same do + minetest.log("action", "ExchangeClone: \tIteration #"..i) + if auto == {} then break end + if old_auto then + same = true + for itemstring, _ in pairs(old_auto) do + if itemstring ~= "" and not auto[itemstring] then + same = false + break + end + end + end + if same then + minetest.log("action", "ExchangeClone:\tNo change, stopping.") + break + end + old_auto = table.copy(auto) + for itemstring, _ in pairs(auto) do + local cheapest = get_cheapest_recipe(itemstring) + if cheapest then + set_item_energy(itemstring, cheapest) + auto[itemstring] = nil + end + end + i = i + 1 +end + +--minetest.log(dump(auto)) + +if exchangeclone.mcl then + set_item_energy("mcl_campfires:campfire", exchangeclone.get_item_energy("mcl_campfires:campfire_lit")) + set_item_energy("mcl_campfires:soul_campfire", exchangeclone.get_item_energy("mcl_campfires:soul_campfire_lit")) + -- Recovery compasses use a random compass frame for the crafting recipe... Incredibly irritating. + for i = 0, 31 do + if exchangeclone.get_item_energy("mcl_compass:"..i.."_recovery") then + for j = 0, 31 do + exchangeclone.register_energy_alias("mcl_compass:"..i.."_recovery", "mcl_compass:"..j.."_recovery") + end + break + end + end +end + +-- Adds energy values to aliased items, even though they're not used (just so it's displayed) +for alias, itemstring in pairs(exchangeclone.energy_aliases) do + set_item_energy(alias, exchangeclone.get_item_energy(itemstring)) +end + +-- Free up memory (I assume this will do that?) +exchangeclone.recipes = nil +exchangeclone.base_energy_values = nil \ No newline at end of file diff --git a/exchangeclone/shears.lua b/exchangeclone/shears.lua index 43c7451..dd1fa6f 100644 --- a/exchangeclone/shears.lua +++ b/exchangeclone/shears.lua @@ -1,9 +1,14 @@ +-- TODO: Before releasing, check the shears. Just do it. +-- I know you don't want to... but test EVERY SINGLE FUNCTION. +-- MineClonia probably broke them. + exchangeclone.shear_action = { start_action = function(player, center, range, itemstack) if exchangeclone.check_cooldown(player, "shears") then return end local data = {} exchangeclone.play_ability_sound(player) data.itemstack = itemstack + data.remove_positions = {} return data end, action = function(player, pos, node, data) @@ -18,15 +23,15 @@ exchangeclone.shear_action = { if node.name:sub(1,18) == "mcl_ocean:seagrass" then minetest.set_node(pos, {name="sand"}) else - minetest.set_node(pos, {name="air"}) + table.insert(data.remove_positions, pos) end end end return data end, end_action = function(player, center, range, data) + exchangeclone.remove_nodes(data.remove_positions) exchangeclone.start_cooldown(player, "shears", (range+1)/7) - return data end } diff --git a/exchangeclone/shovels.lua b/exchangeclone/shovels.lua index f779cd7..b9f52f7 100644 --- a/exchangeclone/shovels.lua +++ b/exchangeclone/shovels.lua @@ -9,6 +9,7 @@ exchangeclone.shovel_action = { exchangeclone.play_ability_sound(player) end data.itemstack = itemstack + data.remove_positions = {} return data end, action = function(player, pos, node, data) @@ -28,13 +29,14 @@ exchangeclone.shovel_action = { else local drops = minetest.get_node_drops(node.name, data.itemstack) exchangeclone.drop_items_on_player(pos, drops, player) - minetest.set_node(pos, {name = "air"}) + table.insert(data.remove_positions, pos) end end end return data end, end_action = function(player, center, range, data) + exchangeclone.remove_nodes(data.remove_positions) if range > 0 or not data.path then exchangeclone.start_cooldown(player, "shovel", range/4) -- Longish cooldown end diff --git a/exchangeclone/swords.lua b/exchangeclone/swords.lua index 219ed37..5d9e3d3 100644 --- a/exchangeclone/swords.lua +++ b/exchangeclone/swords.lua @@ -9,42 +9,47 @@ local aoe_exclude = { --any entity not including "mobs" is automatically added t ["mobs_mc:llamaspit"] = true, } -local hostile_mobs = { --for Red Matter Sword - ["mobs_mc:blaze"] = true, - ["mobs_mc:villager_zombie"] = true, - ["mobs_mc:endermite"] = true, - ["mobs_mc:killer_bunny"] = true, - ["mobs_mc:ghast"] = true, - ["mobs_mc:witch"] = true, - ["mobs_mc:zombie"] = true, - ["mobs_mc:baby_zombie"] = true, - ["mobs_mc:stray"] = true, - ["mobs_mc:enderdragon"] = true, - ["mobs_mc:magma_cube_big"] = true, - ["mobs_mc:piglin_brute"] = true, - ["mobs_mc:wither"] = true, - ["mobs_mc:skeleton"] = true, - ["mobs_mc:witherskeleton"] = true, - ["mobs_mc:slime_big"] = true, - ["mobs_mc:husk"] = true, - ["mobs_mc:evoker"] = true, - ["mobs_mc:creeper_charged"] = true, - ["mobs_mc:guardian_elder"] = true, - ["mobs_mc:guardian"] = true, - ["mobs_mc:creeper"] = true, - ["mobs_mc:vindicator"] = true, - ["mobs_mc:zoglin"] = true, +local hostile_mobs = { --for Red Matter Sword/Katar ["mobs_mc:baby_hoglin"] = true, - ["mobs_mc:silverfish"] = true, - ["mobs_mc:magma_cube_small"] = true, - ["mobs_mc:pillager"] = true, - ["mobs_mc:magma_cube_tiny"] = true, - ["mobs_mc:shulker"] = true, ["mobs_mc:baby_husk"] = true, + ["mobs_mc:baby_zombie"] = true, + ["mobs_mc:blaze"] = true, + ["mobs_mc:cave_spider"] = true, + ["mobs_mc:creeper"] = true, + ["mobs_mc:creeper_charged"] = true, + ["mobs_mc:enderdragon"] = true, + ["mobs_mc:enderman"] = true, + ["mobs_mc:endermite"] = true, + ["mobs_mc:evoker"] = true, + ["mobs_mc:ghast"] = true, + ["mobs_mc:guardian"] = true, + ["mobs_mc:guardian_elder"] = true, ["mobs_mc:hoglin"] = true, - ["mobs_mc:slime_tiny"] = true, - ["mobs_mc:vex"] = true, + ["mobs_mc:husk"] = true, ["mobs_mc:illusioner"] = true, + ["mobs_mc:killer_bunny"] = true, + ["mobs_mc:magma_cube_big"] = true, + ["mobs_mc:magma_cube_small"] = true, + ["mobs_mc:magma_cube_tiny"] = true, + ["mobs_mc:piglin"] = true, + ["mobs_mc:piglin_brute"] = true, + ["mobs_mc:pillager"] = true, + ["mobs_mc:shulker"] = true, + ["mobs_mc:skeleton"] = true, + ["mobs_mc:silverfish"] = true, + ["mobs_mc:slime_big"] = true, + ["mobs_mc:slime_tiny"] = true, + ["mobs_mc:spider"] = true, + ["mobs_mc:stray"] = true, + ["mobs_mc:vex"] = true, + ["mobs_mc:villager_zombie"] = true, + ["mobs_mc:vindicator"] = true, + ["mobs_mc:witch"] = true, + ["mobs_mc:wither"] = true, + ["mobs_mc:witherskeleton"] = true, + ["mobs_mc:zombified_piglin"] = true, + ["mobs_mc:zoglin"] = true, + ["mobs_mc:zombie"] = true, } minetest.register_on_mods_loaded(function() diff --git a/exchangeclone/tool_upgrades.lua b/exchangeclone/tool_upgrades.lua index 81b3230..301ae66 100644 --- a/exchangeclone/tool_upgrades.lua +++ b/exchangeclone/tool_upgrades.lua @@ -709,6 +709,8 @@ exchangeclone.register_upgrade( } ) +-- Intentionally NOT making a Curse of Binding upgrade (because if Keep Inventory is enabled, they will never break) + exchangeclone.register_upgrade( "exchangeclone:curse_of_vanishing_upgrade", "Curse of Vanishing \"Upgrade\"", diff --git a/exchangeclone/transmutation_table.lua b/exchangeclone/transmutation_table.lua index 6cfe1c0..3d1b7d1 100644 --- a/exchangeclone/transmutation_table.lua +++ b/exchangeclone/transmutation_table.lua @@ -1,17 +1,35 @@ -local function get_transmutation_buttons(player, page, x, y) - local pages = minetest.deserialize(player:get_meta():get_string("exchangeclone_transmutation")) or {} - if page > #pages then page = #pages end - if page < 1 then page = 1 end - if not pages[page] and page == 1 then - pages[page] = {} +local suffixes = {"", "K", "M", "B", "T"} + +local function get_amount_label(itemstring, player_energy) + if not minetest.registered_items[itemstring] then return "" end + if player_energy <= 0 then return "0" end + local item_energy = exchangeclone.get_item_energy(itemstring) + local amount = math.floor(player_energy/item_energy) + if player_energy <= 0 then return "0" end + for _, suffix in ipairs(suffixes) do + if amount < 1000 then + return amount..suffix + else + amount = math.floor(amount/1000) + end end +end + +local function get_transmutation_buttons(player, page, x, y) + local player_energy = exchangeclone.get_player_energy(player) + local pages = minetest.deserialize(player:get_meta():get_string("exchangeclone_transmutation")) or {} + if page < 1 then page = 1 end + if not pages[1] then + pages[1] = {} + end + if page > #pages then page = #pages end local buttons = "" for i = 0, 15 do local itemstring = pages[page][i+1] local column = (i%4) local row = math.floor(i/4) if itemstring then - buttons = buttons.."item_image_button["..tostring(x+column)..","..tostring(y+row)..";1,1;"..itemstring..";"..itemstring..";]" + buttons = buttons.."item_image_button["..tostring(x+column)..","..tostring(y+row)..";1,1;"..itemstring..";"..itemstring..";"..get_amount_label(itemstring, player_energy).."]" else buttons = buttons.."image_button["..tostring(x+column)..","..tostring(y+row)..";1,1;blank.png;empty_button"..tostring(i)..";]" end diff --git a/zzzz_exchangeclone_crafthook/init.lua b/zzzz_exchangeclone_crafthook/init.lua deleted file mode 100644 index edceefe..0000000 --- a/zzzz_exchangeclone_crafthook/init.lua +++ /dev/null @@ -1,33 +0,0 @@ -exchangeclone = {recipes = {}, energy_values = {}, group_values = {}} - -local old_func = minetest.register_craft -function minetest.register_craft(data, ...) - if data and data.output then - local itemstring = ItemStack(data.output):get_name() - exchangeclone.recipes[itemstring] = exchangeclone.recipes[itemstring] or {} - table.insert(exchangeclone.recipes[itemstring], table.copy(data)) - --[[ -- reverse cooking recipes too - if arg.type == "cooking" then - itemstring = ItemStack(arg.recipe):get_name() - local reverse_arg = table.copy(arg) - reverse_arg.recipe, reverse_arg.output = reverse_arg.output, reverse_arg.recipe - exchangeclone.recipes[itemstring] = exchangeclone.recipes[itemstring] or {} - table.insert(exchangeclone.recipes[itemstring], table.copy(reverse_arg)) - end --]] - end - old_func(data, ...) -end - -if minetest.get_modpath("technic") then - function exchangeclone.register_technic_recipe(typename, recipe) - local data = technic.recipes[typename] - if (data.output_size == 1) then - if data.output_size == 1 then - local result = {recipe = recipe.input, output = recipe.output, type = "technic"} - local output_itemstring = ItemStack(recipe.output):get_name() - exchangeclone.recipes[output_itemstring] = exchangeclone.recipes[output_itemstring] or {} - table.insert(exchangeclone.recipes[output_itemstring], result) - end - end - end -end \ No newline at end of file diff --git a/zzzz_exchangeclone_crafthook/mod.conf b/zzzz_exchangeclone_crafthook/mod.conf deleted file mode 100644 index 72a2687..0000000 --- a/zzzz_exchangeclone_crafthook/mod.conf +++ /dev/null @@ -1,3 +0,0 @@ -name = zzzz_exchangeclone_crafthook -title = ExchangeClone Craft Hook -description = Wraps the minetest.register_craft function to allow ExchangeClone to access crafting recipe information. \ No newline at end of file diff --git a/_exchangeclone_energy/energy_values.lua b/zzzz_exchangeclone_init/base_energy_values.lua similarity index 77% rename from _exchangeclone_energy/energy_values.lua rename to zzzz_exchangeclone_init/base_energy_values.lua index 6374269..d198c78 100644 --- a/_exchangeclone_energy/energy_values.lua +++ b/zzzz_exchangeclone_init/base_energy_values.lua @@ -8,6 +8,7 @@ if exchangeclone.mcl then {"flower", 8}, {"mushroom", 32}, {"decorated_pot_recipe", 4}, -- has to be 4 because of brick. + {"music_record", 2048}, }) for itemstring, energy_value in pairs({ @@ -50,9 +51,9 @@ if exchangeclone.mcl then ["mcl_buckets:bucket_tropical_fish"] = 832, ["mcl_buckets:bucket_water"] = 768, - ["mcl_cocoas:cocoa_beans"] = 64, + ["mcl_cherry_blossom:pink_petals"] = 4, - ["mcl_copper:copper_ingot"] = 128, + ["mcl_cocoas:cocoa_beans"] = 64, ["mcl_core:andesite"] = 16, ["mcl_core:apple"] = 128, @@ -60,24 +61,20 @@ if exchangeclone.mcl then ["mcl_core:cactus"] = 8, ["mcl_core:charcoal_lump"] = 32, ["mcl_core:clay_lump"] = 16, - ["mcl_core:coal_lump"] = 128, ["mcl_core:cobble"] = 1, ["mcl_core:cobweb"] = 12, ["mcl_core:crying_obsidian"] = 768, - ["mcl_core:dead_bush"] = 1, -- don't know which one of these is right + ["mcl_core:dead_bush"] = 1, -- don't know which one of these is right; maybe both? ["mcl_core:deadbush"] = 1, ["mcl_core:diamond"] = 8192, ["mcl_core:diorite"] = 16, ["mcl_core:dirt"] = 1, ["mcl_core:emerald"] = 4096, ["mcl_core:flint"] = 4, - ["mcl_core:gold_ingot"] = 2048, ["mcl_core:granite"] = 16, ["mcl_core:grass"] = 1, ["mcl_core:gravel"] = 4, ["mcl_core:ice"] = 1, - ["mcl_core:iron_ingot"] = 256, - ["mcl_core:lapis"] = 864, ["mcl_core:mycelium"] = 2, ["mcl_core:obsidian"] = 64, ["mcl_core:redsand"] = 1, @@ -85,9 +82,12 @@ if exchangeclone.mcl then ["mcl_core:sand"] = 1, ["mcl_core:vine"] = 8, + ["mcl_crimson:crimson_roots"] = 1, + ["mcl_crimson:nether_sprouts"] = 1, ["mcl_crimson:shroomlight"] = 416, ["mcl_crimson:twisting_vines"] = 8, ["mcl_crimson:warped_wart_block"] = 216, + ["mcl_crimson:warped_roots"] = 1, ["mcl_crimson:weeping_vines"] = 8, ["mcl_deepslate:deepslate_cobbled"] = 2, @@ -115,6 +115,8 @@ if exchangeclone.mcl then ["mcl_fishing:pufferfish_raw"] = 64, ["mcl_fishing:salmon_raw"] = 64, + ["mcl_flowers:fern"] = 1, + ["mcl_flowers:tallgrass"] = 1, ["mcl_flowers:waterlily"] = 16, ["mcl_flowers:wither_rose"] = 128, @@ -128,6 +130,8 @@ if exchangeclone.mcl then ["mcl_lush_caves:cave_vines"] = 16, ["mcl_lush_caves:glow_berry"] = 16, + ["mcl_lush_caves:moss_carpet"] = 8, + ["mcl_lush_caves:rooted_dirt"] = 5, ["mcl_lush_caves:spore_blossom"] = 64, ["mcl_mangrove:mangrove_roots"] = 4, @@ -168,13 +172,12 @@ if exchangeclone.mcl then ["mcl_mud:mud"] = 1, ["mcl_nether:ancient_debris"] = 12288, - ["mcl_nether:glowstone_dust"] = 384, ["mcl_nether:nether_wart_item"] = 24, ["mcl_nether:netherrack"] = 1, ["mcl_nether:quartz"] = 256, ["mcl_nether:soul_sand"] = 49, - ["mcl_ocean:kelp"] = 1, + ["mcl_ocean:kelp"] = 16, ["mcl_ocean:prismarine_crystals"] = 512, ["mcl_ocean:prismarine_shard"] = 256, ["mcl_ocean:sea_pickle_1_dead_brain_coral_block"] = 16, @@ -182,6 +185,10 @@ if exchangeclone.mcl then ["mcl_pottery_sherds:pot"] = 16, + ["mcl_sculk:vein"] = 4, + ["mcl_sculk:sculk"] = 16, + ["mcl_sculk:catalyst"] = 8040, + ["mcl_sponges:sponge"] = 128, ["mcl_throwing:egg"] = 32, @@ -194,9 +201,34 @@ if exchangeclone.mcl then ["useful_green_potatoes:useful_green_potato"] = 256, }) do - exchangeclone.energy_values[itemstring] = exchangeclone.energy_values[itemstring] or energy_value + exchangeclone.base_energy_values[itemstring] = exchangeclone.base_energy_values[itemstring] or energy_value end + -- TODO: Check after every update + exchangeclone.mcl_potion_data = exchangeclone.mcl_potion_data or {} + table.insert_all(exchangeclone.mcl_potion_data, { -- automatically assumes base is awkward potion if not specified + {name = "water", bases = {"mcl_potions:glass_bottle"}, no_arrow = true}, + {name = "awkward", bases = {"mcl_potions:water"}, ingredient = "mcl_nether:nether_wart_item", no_arrow = true}, + {name = "mundane", ingredient_cost = 32, no_arrow = true, custom_base_cost = 0}, + {name = "thick", ingredient_cost = 384, no_arrow = true, custom_base_cost = 0}, + {name = "fire_resistance", ingredient = "mcl_mobitems:magma_cream", plus = true}, + {name = "harming", bases = {"mcl_potions:poison", "mcl_potions:healing"}, ingredient = "mcl_potions:fermented_spider_eye", two = true}, + {name = "healing", ingredient = "mcl_potions:speckled_melon", two = true}, + {name = "leaping", ingredient = "mcl_mobitems:rabbit_foot", plus = true, two = true}, + {name = "night_vision", ingredient = "mcl_farming:carrot_item_gold", plus = true}, + {name = "poison", ingredient = "mcl_mobitems:spider_eye", plus = true, two = true}, + {name = "regeneration", ingredient = "mcl_mobitems:ghast_tear", plus = true, two = true}, + {name = "slowness", bases = {"mcl_potions:swiftness", "mcl_potions:leaping"}, ingredient = "mcl_potions:fermented_spider_eye", plus = true, two = true}, + {name = "swiftness", ingredient = "mcl_core:sugar", plus = true, two = true}, + {name = "water_breathing", ingredient = "mcl_fishing:pufferfish_raw", plus = true}, + {name = "invisibility", bases = {"mcl_potions:night_vision"}, ingredient = "mcl_potions:fermented_spider_eye", custom_base_cost = 623, plus = true}, + {name = "withering", ingredient = "mcl_flowers:wither_rose", plus = true, two = true} + }) else + exchangeclone.group_values = { + {"flower", 32}, + --{"dye", 8}, + } + for itemstring, energy_value in pairs({ ["bones:bones"] = 4, @@ -212,7 +244,6 @@ else ["default:blueberry_bush_leaves"] = 1, ["default:blueberry_bush_leaves_with_berries"] = 9, ["default:blueberry_bush_sapling"] = 32, - ["default:book_written"] = 96, ["default:bush_leaves"] = 1, ["default:bush_sapling"] = 32, ["default:bush_stem"] = 8, @@ -220,7 +251,6 @@ else ["default:clay_lump"] = 4, ["default:coal_lump"] = 128, ["default:cobble"] = 1, - ["default:copper_ingot"] = 320, ["default:coral_brown"] = 8, ["default:coral_cyan"] = 8, ["default:coral_green"] = 8, @@ -229,7 +259,6 @@ else ["default:coral_skeleton"] = 8, ["default:desert_cobble"] = 1, ["default:desert_sand"] = 1, - ["default:diamond"] = 8192, ["default:dirt"] = 1, ["default:dirt_with_grass"] = 1, ["default:dry_dirt"] = 1, @@ -237,13 +266,10 @@ else ["default:dry_dirt_with_grass"] = 1, ["default:emergent_jungle_sapling"] = 32, ["default:flint"] = 4, - ["default:gold_ingot"] = 2048, ["default:grass"] = 1, ["default:gravel"] = 4, ["default:ice"] = 1, - ["default:iron_ingot"] = 256, ["default:large_cactus_seedling"] = 32, - ["default:mese_crystal"] = 4096, ["default:mossycobble"] = 32, ["default:obsidian"] = 64, ["default:papyrus"] = 32, @@ -254,7 +280,6 @@ else ["default:sand_with_kelp"] = 1, ["default:silver_sand"] = 1, ["default:snow"] = 1, - ["default:tin_ingot"] = 384, ["farming:cotton"] = 12, ["farming:cotton_wild"] = 12, @@ -275,14 +300,9 @@ else ["useful_green_potatoes:useful_green_potato"] = 256 }) do - exchangeclone.energy_values[itemstring] = exchangeclone.energy_values[itemstring] or energy_value + exchangeclone.base_energy_values[itemstring] = exchangeclone.base_energy_values[itemstring] or energy_value end - exchangeclone.group_values = { - {"flower", 32}, - --{"dye", 8}, - } - end -- For things that are the same in both games: @@ -290,7 +310,7 @@ end for itemstring, energy_value in pairs ({ ["exchangeclone:alchemical_tome"] = 0, }) do - exchangeclone.energy_values[itemstring] = energy_value + exchangeclone.base_energy_values[itemstring] = energy_value end table.insert_all(exchangeclone.group_values, { diff --git a/zzzz_exchangeclone_init/init.lua b/zzzz_exchangeclone_init/init.lua new file mode 100644 index 0000000..3d116de --- /dev/null +++ b/zzzz_exchangeclone_init/init.lua @@ -0,0 +1,51 @@ +exchangeclone = {recipes = {}, base_energy_values = {}, group_values = {}} + +-- Override crafting +local old_func = minetest.register_craft +function minetest.register_craft(data, ...) + if data and data.output then + local itemstring = ItemStack(data.output):get_name() + exchangeclone.recipes[itemstring] = exchangeclone.recipes[itemstring] or {} + table.insert(exchangeclone.recipes[itemstring], table.copy(data)) + --[[ -- reverse cooking recipes too + if arg.type == "cooking" then + itemstring = ItemStack(arg.recipe):get_name() + local reverse_arg = table.copy(arg) + reverse_arg.recipe, reverse_arg.output = reverse_arg.output, reverse_arg.recipe + exchangeclone.recipes[itemstring] = exchangeclone.recipes[itemstring] or {} + table.insert(exchangeclone.recipes[itemstring], table.copy(reverse_arg)) + end --]] + end + old_func(data, ...) +end + +if (not minetest.get_modpath("mcl_core")) and (not minetest.get_modpath("default")) then + error("ExchangeClone requires Minetest Game, MineClone2, or MineClonia (and possibly other spinoffs).\nPlease use one of those games.") +else + exchangeclone.mcl = minetest.get_modpath("mcl_core") +end + +exchangeclone.mineclonia = minetest.get_game_info().id == "mineclonia" -- if exchangeclone.mineclonia, exchangeclone.mcl is also defined. +exchangeclone.pipeworks = minetest.get_modpath("pipeworks") +exchangeclone.orb_max = 51200000 -- Max capacity of Klein Star Omega in ProjectE +exchangeclone.orb_max = minetest.settings:get("exchangeclone.orb_max") or 51200000 + +local modpath = minetest.get_modpath("zzzz_exchangeclone_init") +dofile(modpath.."/lib.lua") + +exchangeclone.register_craft_type("shaped", "shaped") +exchangeclone.register_craft_type("shapeless", "shapeless") +exchangeclone.register_craft_type("cooking", "cooking") + +if minetest.get_modpath("technic") then + exchangeclone.register_craft_type("technic", "shapeless") + function exchangeclone.register_technic_recipe(typename, recipe) + local data = technic.recipes[typename] + if data.output_size == 1 then + local result = {recipe = recipe.input, output = recipe.output, type = "technic"} + exchangeclone.register_craft(result) + end + end +end + +dofile(modpath.."/base_energy_values.lua") \ No newline at end of file diff --git a/exchangeclone/lib.lua b/zzzz_exchangeclone_init/lib.lua similarity index 86% rename from exchangeclone/lib.lua rename to zzzz_exchangeclone_init/lib.lua index 778b3aa..9871ce5 100644 --- a/exchangeclone/lib.lua +++ b/zzzz_exchangeclone_init/lib.lua @@ -11,9 +11,6 @@ function exchangeclone.round(num) end end --- Decides what mod to use for sounds -if exchangeclone.mcl then exchangeclone.sound_mod = mcl_sounds else exchangeclone.sound_mod = default end - -- Don't think this even works correctly. function exchangeclone.get_inventory_drops(pos, inventory, drops) local inv = minetest.get_meta(pos):get_inventory() @@ -175,7 +172,6 @@ function exchangeclone.set_player_energy(player, amount) amount = tonumber(amount) if not (player and amount) then return end if amount < 0 or amount > exchangeclone.limit then return end - amount = math.floor(amount*4)/4 -- Floor to nearest .25 player:get_meta():set_string("exchangeclone_stored_energy", tonumber(amount)) exchangeclone.update_hud(player) end @@ -315,23 +311,19 @@ function exchangeclone.range_update(itemstack, player, max) end -- Make ExchangeClone tools slightly larger... -exchangeclone.wield_scale = {x=1,y=1,z=1} -if exchangeclone.mcl then - exchangeclone.wield_scale = mcl_vars.tool_wield_scale -end - -exchangeclone.wield_scale = vector.multiply(exchangeclone.wield_scale, 1.3) +exchangeclone.wield_scale = {x=1.3,y=1.3,z=1.3} -- Itemstrings for various items used in crafting recipes. exchangeclone.itemstrings = { - cobble = exchangeclone.mcl and "mcl_core:cobble" or "default:cobble", - redstoneworth = exchangeclone.mcl and "mesecons:redstone" or "default:obsidian", - glowstoneworth = exchangeclone.mcl and "mcl_nether:glowstone_dust" or "default:tin_ingot", - coal = exchangeclone.mcl and "mcl_core:coal_lump" or "default:coal_lump", - iron = exchangeclone.mcl and "mcl_core:iron_ingot" or "default:steel_ingot", - gold = exchangeclone.mcl and "mcl_core:gold_ingot" or "default:gold_ingot", - emeraldworth = exchangeclone.mcl and "mcl_core:emerald" or "default:mese_crystal", - diamond = exchangeclone.mcl and "mcl_core:diamond" or "default:diamond", + cobble = exchangeclone.mcl and "mcl_core:cobble" or "default:cobble", + redstoneworth = exchangeclone.mcl and "mesecons:redstone" or "default:obsidian", + glowstoneworth = exchangeclone.mcl and "mcl_nether:glowstone_dust" or "default:tin_ingot", + coal = exchangeclone.mcl and "mcl_core:coal_lump" or "default:coal_lump", + iron = exchangeclone.mcl and "mcl_core:iron_ingot" or "default:steel_ingot", + copper = exchangeclone.mcl and "mcl_copper:copper_ingot" or "default:copper_ingot", + gold = exchangeclone.mcl and "mcl_core:gold_ingot" or "default:gold_ingot", + emeraldworth = exchangeclone.mcl and "mcl_core:emerald" or "default:mese_crystal", + diamond = exchangeclone.mcl and "mcl_core:diamond" or "default:diamond", } exchangeclone.energy_aliases = {} @@ -619,7 +611,7 @@ function exchangeclone.check_cooldown(player, name) end -- Chat commands: -minetest.register_chatcommand("add_energy", { +minetest.register_chatcommand("add_player_energy", { params = "[player] ", description = "Add to a player's personal energy (player is self if not included, value can be negative)", privs = {privs = true}, @@ -640,10 +632,11 @@ minetest.register_chatcommand("add_energy", { return end exchangeclone.add_player_energy(player, tonumber(value)) + minetest.chat_send_player(name, "Added "..value.." to "..name.."'s personal energy.") end }) -minetest.register_chatcommand("set_energy", { +minetest.register_chatcommand("set_player_energy", { params = "[player] ", description = "Set a player's personal energy (player is self if not included; use 'limit' as value to set it to maximum)", privs = {privs = true}, @@ -665,5 +658,80 @@ minetest.register_chatcommand("set_energy", { end if value == "limit" then value = exchangeclone.limit end exchangeclone.set_player_energy(player, tonumber(value)) + minetest.chat_send_player(name, "Personal energy of "..name.." set to "..value) end -}) \ No newline at end of file +}) + +exchangeclone.neighbors = { + {x=-1, y=0, z=0}, + {x=1, y=0, z=0}, + {x=0, y=-1, z=0}, + {x=0, y=1, z=0}, + {x=0, y=0, z=-1}, + {x=0, y=0, z=1}, +} + +function exchangeclone.check_nearby_falling(pos) + for i=1, #exchangeclone.neighbors do + local new_pos = vector.add(pos, exchangeclone.neighbors[i]) + if exchangeclone.mcl then + local node = minetest.get_node(new_pos) + if node.name == "mcl_core:vine" then + mcl_core.check_vines_supported(new_pos, node) + end + end + minetest.check_single_for_falling(new_pos) + end +end + +function exchangeclone.remove_nodes(positions) + for _, pos in ipairs(positions) do + exchangeclone.check_nearby_falling(pos) + end + minetest.bulk_set_node(positions, {name = "air"}) +end + +--[[ +Recipes are registered with the same format that they are in minetest.register_craft: +{ + type = + recipe = + output = + replacements = {{, }, {, }} +} + +You do NOT have to call exchangeclone.register_craft if you use minetest.register_craft. +]] + +--[[ +name (string): The name of the crafting type. +recipe_type (string): One of the following: + shaped (default): Recipe is given in an array of arrays of ingredients. + shapeless: Recipe is given as a array of ingredients + cooking: Recipe is a single item +reverse (bool): Only applies for "cooking" recipe_type. If set to true, all recipes of this + type will be registered twice: once normally, and once with the recipe and output swapped. +]] + +exchangeclone.craft_types = {} + +function exchangeclone.register_craft_type(name, recipe_type, reverse) + exchangeclone.craft_types[name] = {type = recipe_type, reverse = true} +end + +function exchangeclone.register_craft(data) + if not data.output then return end + local itemstring = ItemStack(data.output):get_name() + exchangeclone.recipes[itemstring] = exchangeclone.recipes[itemstring] or {} + table.insert(exchangeclone.recipes[itemstring], table.copy(data)) + if data.type then + local type_data = exchangeclone.craft_types[data.type] + if type_data.type == "cooking" and type_data.reverse then + local flipped_data = table.copy(data) + flipped_data.output, flipped_data.recipe = flipped_data.recipe, flipped_data.output + local itemstring = ItemStack(flipped_data.output):get_name() + exchangeclone.recipes[itemstring] = exchangeclone.recipes[itemstring] or {} + table.insert(exchangeclone.recipes[itemstring], table.copy(flipped_data)) + end + end +end \ No newline at end of file diff --git a/zzzz_exchangeclone_init/mod.conf b/zzzz_exchangeclone_init/mod.conf new file mode 100644 index 0000000..b33db39 --- /dev/null +++ b/zzzz_exchangeclone_init/mod.conf @@ -0,0 +1,3 @@ +name = zzzz_exchangeclone_init +title = ExchangeClone Initilization +description = Some necessary things that need to happen first. \ No newline at end of file