433 lines
19 KiB
Lua
433 lines
19 KiB
Lua
local suffixes = {"", "K", "M", "B", "T"}
|
|
|
|
local function get_amount_label(itemstring, player_emc)
|
|
if not minetest.registered_items[itemstring] then return "" end
|
|
if player_emc <= 0 then return "0" end
|
|
local item_emc = exchangeclone.get_item_emc(itemstring)
|
|
local amount = math.floor(player_emc/item_emc)
|
|
if player_emc <= 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_emc = exchangeclone.get_player_emc(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..";"..get_amount_label(itemstring, player_emc).."]"
|
|
else
|
|
buttons = buttons.."image_button["..tostring(x+column)..","..tostring(y+row)..";1,1;blank.png;empty_button"..tostring(i)..";]"
|
|
end
|
|
end
|
|
buttons = buttons.."label[5.75,5.25;"..tostring(page).."/"..tostring(#pages).."]"
|
|
player:get_meta():set_int("exchangeclone_transmutation_page", page)
|
|
return buttons
|
|
end
|
|
|
|
--<copied from MineClone>
|
|
local function filter_item(name, description, lang, filter)
|
|
local desc
|
|
if not lang then
|
|
desc = string.lower(description)
|
|
else
|
|
desc = string.lower(minetest.get_translated_string(lang, description))
|
|
end
|
|
return string.find(name, filter, nil, true) or string.find(desc, filter, nil, true)
|
|
end
|
|
|
|
function exchangeclone.reload_transmutation_list(player, search)
|
|
local meta = player:get_meta()
|
|
local player_emc = exchangeclone.get_player_emc(player)
|
|
local items_to_show = minetest.deserialize(meta:get_string("exchangeclone_transmutation_learned_items")) or {}
|
|
local lang = minetest.get_player_information(player:get_player_name()).lang_code
|
|
local pages = {}
|
|
local page_num
|
|
local i = 0
|
|
if not search or search == "" then search = player:get_meta():get_string("exchangeclone_transmutation_search") or "" end
|
|
if search and search ~= "" then
|
|
local filtered_items = {}
|
|
for _, name in pairs(items_to_show) do
|
|
local def = minetest.registered_items[name]
|
|
if def and def.description and def.description ~= "" then
|
|
if filter_item(string.lower(def.name), def.description, lang, search) then
|
|
table.insert(filtered_items, name)
|
|
end
|
|
end
|
|
items_to_show = table.copy(filtered_items)
|
|
end
|
|
end
|
|
local no_duplicates = {}
|
|
for _, item in pairs(items_to_show) do
|
|
if type(item) == "string" then
|
|
local emc_value = exchangeclone.get_item_emc(item)
|
|
if emc_value and emc_value <= player_emc and emc_value > 0 then
|
|
no_duplicates[exchangeclone.handle_alias(item)] = true -- gets rid of duplicates
|
|
end
|
|
end
|
|
end
|
|
|
|
items_to_show = {}
|
|
for item, _ in pairs(no_duplicates) do
|
|
table.insert(items_to_show, item)
|
|
end
|
|
table.sort(items_to_show)
|
|
|
|
for _, item in ipairs(items_to_show) do
|
|
page_num = math.floor(i/16) + 1
|
|
if not pages[page_num] then pages[page_num] = {} end
|
|
pages[page_num][(i % 16) + 1] = item
|
|
i = i + 1
|
|
end
|
|
player:get_meta():set_string("exchangeclone_transmutation", minetest.serialize(pages))
|
|
return pages
|
|
end
|
|
|
|
local function add_to_output(player, amount, show)
|
|
local item = player:get_meta():get_string("exchangeclone_transmutation_selection")
|
|
if minetest.registered_items[item] then
|
|
local emc_value = exchangeclone.get_item_emc(item)
|
|
if not emc_value then return end
|
|
local player_emc = exchangeclone.get_player_emc(player)
|
|
local stack_max = ItemStack(item):get_stack_max()
|
|
if amount == true then amount = stack_max end
|
|
local max_amount = math.min(amount, stack_max, math.floor(player_emc/emc_value))
|
|
local inventory = minetest.get_inventory({type = "detached", name = "exchangeclone_transmutation_"..player:get_player_name()})
|
|
local added_amount = max_amount - inventory:add_item("output", ItemStack(item.." "..max_amount)):get_count()
|
|
exchangeclone.set_player_emc(player, math.min(player_emc, player_emc - (emc_value * added_amount))) -- not sure if "math.min()" is necessary
|
|
if show then exchangeclone.show_transmutation_table_formspec(player) end
|
|
end
|
|
end
|
|
|
|
local function handle_inventory(player, inventory, to_list)
|
|
local stack = inventory:get_stack(to_list, 1)
|
|
local itemstring = stack:get_name()
|
|
local single_item = stack:peek_item(1)
|
|
itemstring = exchangeclone.emc_aliases[itemstring] or itemstring
|
|
if to_list == "learn" then
|
|
local list = minetest.deserialize(player:get_meta():get_string("exchangeclone_transmutation_learned_items")) or {}
|
|
if itemstring == "exchangeclone:tome_of_knowledge" then
|
|
list = {}
|
|
local i = 0
|
|
for name, def in pairs(minetest.registered_items) do
|
|
local emc_value = exchangeclone.get_item_emc(name)
|
|
if emc_value and emc_value > 0 then
|
|
i = i + 1
|
|
list[i] = name
|
|
end
|
|
end
|
|
table.sort(list)
|
|
player:get_meta():set_string("exchangeclone_transmutation_learned_items", minetest.serialize(list))
|
|
inventory:set_stack(to_list, 1, nil)
|
|
else
|
|
local individual_emc_value = exchangeclone.get_item_emc(single_item)
|
|
if not individual_emc_value or individual_emc_value <= 0 then return end
|
|
local player_emc = exchangeclone.get_player_emc(player)
|
|
-- How many items can be added?
|
|
local max_count = math.floor((exchangeclone.limit - player_emc)/individual_emc_value)
|
|
-- How many items will be added?
|
|
local add_count = math.min(max_count, stack:get_count())
|
|
-- How much EMC is that?
|
|
local emc_value = individual_emc_value * add_count
|
|
exchangeclone.add_player_emc(player, emc_value)
|
|
local item_index = table.indexof(list, itemstring)
|
|
if item_index == -1 then
|
|
list[#list+1] = itemstring
|
|
table.sort(list)
|
|
player:get_meta():set_string("exchangeclone_transmutation_learned_items", minetest.serialize(list))
|
|
end
|
|
stack:set_count(stack:get_count() - add_count)
|
|
if stack:get_count() == 0 then stack = ItemStack("") end
|
|
inventory:set_stack(to_list, 1, stack)
|
|
end
|
|
exchangeclone.show_transmutation_table_formspec(player)
|
|
elseif to_list == "forget" then
|
|
return
|
|
elseif to_list == "charge" then
|
|
local player_emc = exchangeclone.get_player_emc(player)
|
|
local star_emc = exchangeclone.get_star_itemstack_emc(stack)
|
|
local charge_amount = math.min(exchangeclone.get_star_max(stack) - star_emc, player_emc)
|
|
if charge_amount > 0 then
|
|
exchangeclone.add_player_emc(player, -charge_amount)
|
|
exchangeclone.add_star_emc(inventory, to_list, 1, charge_amount)
|
|
exchangeclone.show_transmutation_table_formspec(player)
|
|
end
|
|
end
|
|
end
|
|
|
|
local function check_for_table(player, inv)
|
|
-- Keeps player from accessing someone else's transmutation inventory
|
|
if inv and inv:get_location().name ~= "exchangeclone_transmutation_"..player:get_player_name() then return false end
|
|
-- Allow creative players to do whatever
|
|
if minetest.is_creative_enabled(player:get_player_name()) then return true end
|
|
-- Check for nearby/wielded table(t)
|
|
local def = player:get_wielded_item():get_definition()
|
|
local range = def and def.range
|
|
if not range then range = player:get_inventory():get_stack("hand", 1):get_definition().range end
|
|
if range then range = range + 1 else range = 5 end
|
|
if player:get_wielded_item():get_name() ~= "exchangeclone:transmutation_tablet"
|
|
and not minetest.find_node_near(player:get_pos(), range, "exchangeclone:transmutation_table", true) then return false end
|
|
return true
|
|
end
|
|
|
|
local function allow_inventory_action(player, stack, to_list, count, move, inventory)
|
|
if not check_for_table(player, inventory) then return 0 end
|
|
if to_list == "output" then
|
|
return 0
|
|
elseif to_list == "charge" and minetest.get_item_group(stack:get_name(), "klein_star") < 1 then
|
|
return 0
|
|
elseif to_list == "learn" then
|
|
if stack:get_name() == "exchangeclone:tome_of_knowledge" then return count end
|
|
local emc_value = exchangeclone.get_item_emc(exchangeclone.handle_alias(stack))
|
|
if not emc_value then return 0 end
|
|
if emc_value <= 0 then
|
|
return 0
|
|
else
|
|
return count
|
|
end
|
|
elseif to_list == "forget" then
|
|
-- Kind of a weird way of doing this, but I couldn't make it work in the "on_inventory_* functions"
|
|
local list = minetest.deserialize(player:get_meta():get_string("exchangeclone_transmutation_learned_items")) or {}
|
|
local item_index = table.indexof(list, exchangeclone.handle_alias(stack:get_name()))
|
|
if item_index > -1 then
|
|
list[item_index] = list[#list]
|
|
list[#list] = nil
|
|
table.sort(list)
|
|
player:get_meta():set_string("exchangeclone_transmutation_learned_items", minetest.serialize(list))
|
|
local selection = player:get_meta():get_string("exchangeclone_transmutation_selection")
|
|
if selection == stack:get_name() then
|
|
player:get_meta():set_string("exchangeclone_transmutation_selection", "")
|
|
end
|
|
end
|
|
exchangeclone.show_transmutation_table_formspec(player)
|
|
return 0
|
|
else
|
|
return count
|
|
end
|
|
end
|
|
|
|
function exchangeclone.show_transmutation_table_formspec(player, data)
|
|
exchangeclone.reload_transmutation_list(player, data and data.search)
|
|
if not data then data = {} end
|
|
local player_emc = exchangeclone.get_player_emc(player)
|
|
local selection = data.selection or player:get_meta():get_string("exchangeclone_transmutation_selection")
|
|
local player_name = player:get_player_name()
|
|
local inventory_name = "detached:exchangeclone_transmutation_"..player_name
|
|
local label = "Transmutation\n"..exchangeclone.format_number(player_emc).." EMC"
|
|
|
|
local formspec =
|
|
"size[9,11]"..
|
|
"label[0,0;"..label.."]"..
|
|
"list["..inventory_name..";charge;0,1;1,1]"..
|
|
"label[0,2;Charge]"..
|
|
"list["..inventory_name..";forget;1,1;1,1]"..
|
|
"label[1,2;Forget]"..
|
|
"list["..inventory_name..";learn;2,1;1,1]"..
|
|
"label[2,2;Learn]"..
|
|
"list["..inventory_name..";output;2,3.5;2,2]"..
|
|
"label[2.5,3;Output]"..
|
|
get_transmutation_buttons(player, (data.page or player:get_meta():get_int("exchangeclone_transmutation_page")), 4, 1)..
|
|
"button[4,5;1,1;left_arrow;<]"..
|
|
"button[7,5;1,1;right_arrow;>]"..
|
|
"button[0,3.5;1,1;plus1;+1]"..
|
|
"button[1,3.5;1,1;plus5;+5]"..
|
|
"button[0,4.5;1,1;plus10;+10]"..
|
|
"button[1,4.5;1,1;plusstack;+Stack]"..
|
|
"field[4.25,0.25;4,1;search_box;;"..minetest.formspec_escape(data.search or player:get_meta():get_string("exchangeclone_transmutation_search") or "").."]"..
|
|
"field_close_on_enter[search_box;false]"..
|
|
"button[8,0;1,1;search_button;Search]"..
|
|
exchangeclone.inventory_formspec(0,6.25)..
|
|
"listring["..inventory_name..";output]"..
|
|
"listring[current_player;main]"..
|
|
"listring["..inventory_name..";learn]"..
|
|
"listring[current_player;main]"
|
|
|
|
if minetest.registered_items[selection] then
|
|
formspec = formspec.."item_image[0.5,2.5;0.8,0.8;"..selection.."]"
|
|
end
|
|
|
|
if exchangeclone.mcl then
|
|
formspec = formspec..
|
|
mcl_formspec.get_itemslot_bg(0,1,1,1)..
|
|
mcl_formspec.get_itemslot_bg(1,1,1,1)..
|
|
mcl_formspec.get_itemslot_bg(2,1,1,1)..
|
|
mcl_formspec.get_itemslot_bg(2,3.5,2,2)
|
|
end
|
|
|
|
minetest.show_formspec(player_name, "exchangeclone_transmutation_table", formspec)
|
|
end
|
|
|
|
minetest.register_on_joinplayer(function(ref, last_login)
|
|
local playername = ref:get_player_name()
|
|
minetest.create_detached_inventory("exchangeclone_transmutation_"..playername, {
|
|
allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
|
|
local stack = inv:get_stack(from_list, from_index)
|
|
stack:set_count(count)
|
|
return allow_inventory_action(player, stack, to_list, count, true, inv)
|
|
end,
|
|
on_move = function(inv, from_list, from_index, to_list, to_index, count, player)
|
|
local stack = inv:get_stack(to_list, to_index)
|
|
handle_inventory(player, inv, to_list, to_index, stack)
|
|
end,
|
|
allow_put = function(inv, listname, index, stack, player)
|
|
local count = stack:get_count()
|
|
return allow_inventory_action(player, stack, listname, count, false, inv)
|
|
end,
|
|
on_put = function(inv, listname, index, stack, player)
|
|
handle_inventory(player, inv, listname, index, stack)
|
|
end
|
|
}, playername)
|
|
local inventory = minetest.get_inventory({type = "detached", name = "exchangeclone_transmutation_"..playername})
|
|
inventory:set_size("charge", 1)
|
|
inventory:set_size("output", 4)
|
|
inventory:set_width("output", 2)
|
|
inventory:set_size("learn", 1)
|
|
inventory:set_size("forget", 1)
|
|
exchangeclone.reload_transmutation_list(ref)
|
|
end)
|
|
|
|
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|
if formname == "exchangeclone_transmutation_table" then
|
|
if not check_for_table(player) then return end
|
|
for field, value in pairs(fields) do
|
|
if field == "search_box" or field == "quit" then
|
|
-- do nothing
|
|
elseif field == "right_arrow" then
|
|
exchangeclone.show_transmutation_table_formspec(player, {page = player:get_meta():get_int("exchangeclone_transmutation_page") + 1})
|
|
elseif field == "left_arrow" then
|
|
exchangeclone.show_transmutation_table_formspec(player, {page = player:get_meta():get_int("exchangeclone_transmutation_page") - 1})
|
|
elseif field == "search_button" or (field == "key_enter_field" and value == "search_box") then
|
|
local search = fields.search_box or ""
|
|
player:get_meta():set_string("exchangeclone_transmutation_search", search)
|
|
exchangeclone.show_transmutation_table_formspec(player, {page = 1})
|
|
elseif field == "plus1" then
|
|
add_to_output(player, 1, true)
|
|
elseif field == "plus5" then
|
|
add_to_output(player, 5, true)
|
|
elseif field == "plus10" then
|
|
add_to_output(player, 10, true)
|
|
elseif field == "plusstack" then
|
|
add_to_output(player, true, true)
|
|
elseif minetest.registered_items[field] then
|
|
player:get_meta():set_string("exchangeclone_transmutation_selection", field)
|
|
exchangeclone.show_transmutation_table_formspec(player, {selection = field})
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
|
|
minetest.register_tool("exchangeclone:transmutation_tablet", {
|
|
description = "Transmutation Tablet",
|
|
groups = {disable_repair = 1, fire_immune = 1},
|
|
wield_image = "exchangeclone_transmutation_tablet.png",
|
|
inventory_image = "exchangeclone_transmutation_tablet.png",
|
|
on_secondary_use = function(itemstack, player, pointed_thing)
|
|
local click_test = exchangeclone.check_on_rightclick(itemstack, player, pointed_thing)
|
|
if click_test ~= false then
|
|
return click_test
|
|
end
|
|
exchangeclone.show_transmutation_table_formspec(player)
|
|
end,
|
|
on_place = function(itemstack, player, pointed_thing)
|
|
local click_test = exchangeclone.check_on_rightclick(itemstack, player, pointed_thing)
|
|
if click_test ~= false then
|
|
return click_test
|
|
end
|
|
exchangeclone.show_transmutation_table_formspec(player)
|
|
end
|
|
})
|
|
|
|
minetest.register_node("exchangeclone:transmutation_table", {
|
|
description = "Transmutation Table",
|
|
paramtype2 = "wallmounted",
|
|
tiles = {
|
|
"exchangeclone_transmutation_table_top.png",
|
|
"exchangeclone_transmutation_table_bottom.png",
|
|
"exchangeclone_transmutation_table_side.png"
|
|
},
|
|
groups = {cracky = 3, pickaxey = 1, handy = 1, oddly_breakable_by_hand = 1},
|
|
drawtype = "nodebox",
|
|
node_box = {
|
|
type = "fixed",
|
|
fixed = {-0.5, -0.5, -0.5, 0.5, -0.3, 0.5},
|
|
},
|
|
sounds = exchangeclone.sound_mod.node_sound_stone_defaults(),
|
|
on_rightclick = function(pos, node, player, itemstack, pointed_thing)
|
|
exchangeclone.show_transmutation_table_formspec(player)
|
|
end,
|
|
_mcl_hardness = 10,
|
|
_mcl_blast_resistance = 6,
|
|
})
|
|
|
|
minetest.register_tool("exchangeclone:tome_of_knowledge", {
|
|
description = "Tome of Knowledge\nKlein Star Omegas in crafting recipe must be full\nLearns all items when put into Transmutation Table(t)",
|
|
inventory_image = "exchangeclone_tome_of_knowledge.png",
|
|
groups = {disable_repair = 1, fire_immune = 1}
|
|
})
|
|
|
|
minetest.register_alias("exchangeclone:tome_of_knowledge", "exchangeclone:tome_of_knowledge")
|
|
|
|
local book = "default:book"
|
|
local obsidian = "default:obsidian"
|
|
local stone = "default:stone"
|
|
if exchangeclone.mcl then
|
|
book = "mcl_books:book"
|
|
obsidian = "mcl_core:obsidian"
|
|
stone = "mcl_core:stone"
|
|
end
|
|
|
|
minetest.register_craft({
|
|
output = "exchangeclone:transmutation_table",
|
|
recipe = {
|
|
{obsidian, stone, obsidian},
|
|
{stone, "exchangeclone:philosophers_stone", stone},
|
|
{obsidian, stone, obsidian}
|
|
},
|
|
replacements = {{"exchangeclone:philosophers_stone", "exchangeclone:philosophers_stone"}}
|
|
})
|
|
|
|
minetest.register_craft({
|
|
output = "exchangeclone:transmutation_tablet",
|
|
recipe = {
|
|
{"exchangeclone:dark_matter_block", stone, "exchangeclone:dark_matter_block"},
|
|
{stone, "exchangeclone:transmutation_table", stone},
|
|
{"exchangeclone:dark_matter_block", stone, "exchangeclone:dark_matter_block"}
|
|
},
|
|
})
|
|
|
|
if minetest.settings:get_bool("exchangeclone.allow_crafting_alchemical_tome", false) then
|
|
minetest.register_craft({
|
|
output = "exchangeclone:tome_of_knowledge",
|
|
recipe = {
|
|
{"", book, ""},
|
|
{"exchangeclone:klein_star_omega", "exchangeclone:philosophers_stone", "exchangeclone:klein_star_omega"},
|
|
{"", "exchangeclone:red_matter", ""}
|
|
},
|
|
replacements = {{"exchangeclone:philosophers_stone", "exchangeclone:philosophers_stone"}}
|
|
})
|
|
end
|
|
|
|
minetest.register_craft_predict(function(itemstack, player, old_craft_grid, craft_inv)
|
|
if itemstack == ItemStack("exchangeclone:tome_of_knowledge") then
|
|
for _, i in pairs({4,6}) do
|
|
local stack = old_craft_grid[i]
|
|
if exchangeclone.get_star_itemstack_emc(stack) < exchangeclone.get_star_max(stack) then
|
|
return ItemStack("")
|
|
end
|
|
end
|
|
end
|
|
end) |