Lots of random stuff (only 2 mods now)

This commit is contained in:
ThePython 2023-12-14 15:09:59 -08:00
parent 40cf7088da
commit 002b5da71e
23 changed files with 750 additions and 677 deletions

View File

@ -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
<details><summary>Look at this fancy expanding changelog</summary>
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!)

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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")

View File

@ -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

View File

@ -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)
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,},
}
})

View File

@ -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.")
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)

View File

@ -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

View File

@ -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}}
})

View File

@ -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

View File

@ -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

View File

@ -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
}

View File

@ -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

View File

@ -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()

View File

@ -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\"",

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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, {

View File

@ -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")

View File

@ -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] <value>",
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] <value>",
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
})
})
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 = <type>
recipe = <recipe>
output = <itemstring>
replacements = {{<itemstring>, <replace_itemstring>}, {<itemstring>, <replace_itemstring>}}
}
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

View File

@ -0,0 +1,3 @@
name = zzzz_exchangeclone_init
title = ExchangeClone Initilization
description = Some necessary things that need to happen first.