308 lines
10 KiB
Lua
308 lines
10 KiB
Lua
--[[
|
|
Copyright (c) 2015, Robert 'Bobby' Zenz
|
|
All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions are met:
|
|
|
|
* Redistributions of source code must retain the above copyright notice, this
|
|
list of conditions and the following disclaimer.
|
|
|
|
* Redistributions in binary form must reproduce the above copyright notice,
|
|
this list of conditions and the following disclaimer in the documentation
|
|
and/or other materials provided with the distribution.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
--]]
|
|
|
|
|
|
--- artisanryui is a static, global object that allows to replace the inventory
|
|
-- with the Artisanry one.
|
|
artisanryui = {
|
|
artisanry = nil,
|
|
last_blueprints_cache = {},
|
|
inventory = nil,
|
|
output_size = 7 * 5,
|
|
pages = {}
|
|
}
|
|
|
|
|
|
--- Activates the ArtinsaryUI.
|
|
--
|
|
-- This function replaces all inventories of all currently coneccted players
|
|
-- and also registers a callback to replace the inventory of every new player.
|
|
--
|
|
-- @param artisanry The Artisanry instance to use.
|
|
function artisanryui.activate(artisanry)
|
|
artisanryui.artisanry = artisanry
|
|
artisanryui.inventory = artisanryui.create_inventory()
|
|
|
|
artisanryui.replace_inventories()
|
|
|
|
minetest.register_on_joinplayer(artisanryui.replace_inventory)
|
|
minetest.register_on_player_receive_fields(artisanryui.scroll_page)
|
|
end
|
|
|
|
--- Builds the formspec for the artisanryui inventory.
|
|
--
|
|
-- @param player The player.
|
|
-- @return The formspec for the inventory.
|
|
function artisanryui.build_formspec(player)
|
|
local window = "size[15,12;]"
|
|
window = window .. "bgcolor[#00000000;true]"
|
|
window = window .. "listcolors[#00000000;#FFFFFF33]"
|
|
|
|
local input_background = ""
|
|
|
|
for y = 4, 0, -1 do
|
|
for x = 0, 4, 1 do
|
|
input_background = input_background .. "background[" .. x .. "," .. y .. ";3,3;artisanry_craft_bg.png]"
|
|
end
|
|
end
|
|
|
|
local result_background = ""
|
|
|
|
for y = 4, 0, -1 do
|
|
for x = 0, 6, 1 do
|
|
result_background = result_background .. "background[" .. (x + 6) .. "," .. y .. ";3,3;artisanry_output_bg.png]"
|
|
end
|
|
end
|
|
|
|
local inventory_background = ""
|
|
|
|
for y = 9, 7, -1 do
|
|
for x = 2, 9, 1 do
|
|
inventory_background = inventory_background .. "background[" .. x .. "," .. y .. ";3,3;artisanry_inventory_bg.png]"
|
|
end
|
|
end
|
|
|
|
for x = 2, 9, 1 do
|
|
inventory_background = inventory_background .. "background[" .. x .. ",6;3,3;artisanry_inventory_bg.png]"
|
|
end
|
|
|
|
local input = "list[detached:artisanryui;" .. player:get_player_name() .. "-input;1,1;5,5;]"
|
|
local result = "list[detached:artisanryui;" .. player:get_player_name() .. "-output;7,1;7,5;]"
|
|
|
|
local previous_button = "button[7,6;2,1;artisanry-" .. player:get_player_name() .. "-previous-page;<<]"
|
|
local next_button = "button[12,6;2,1;artisanry-" .. player:get_player_name() .. "-next-page;>>]"
|
|
|
|
local inventory = "list[current_player;main;3,7;8,4;]"
|
|
|
|
local ring = "listring[current_player;main]"
|
|
ring = ring .. "listring[detached:artisanryui;" .. player:get_player_name() .. "-input]"
|
|
ring = ring .. "listring[current_player;main]"
|
|
ring = ring .. "listring[detached:artisanryui;" .. player:get_player_name() .. "-output]"
|
|
ring = ring .. "listring[current_player;main]"
|
|
|
|
local formspec = window
|
|
.. input_background
|
|
.. result_background
|
|
.. previous_button
|
|
.. next_button
|
|
.. inventory_background
|
|
.. input
|
|
.. result
|
|
.. inventory
|
|
.. ring
|
|
|
|
return formspec
|
|
end
|
|
|
|
--- Creates a detached inventory that is used.
|
|
--
|
|
-- @return The detached inventory.
|
|
function artisanryui.create_inventory()
|
|
return minetest.create_detached_inventory("artisanryui", {
|
|
allow_move = function(inventory, from_list, from_index, to_list, to_index, count, player)
|
|
-- Disallow putting if this is an output inventory.
|
|
if stringutil.endswith(to_list, "-output") then
|
|
return 0
|
|
else
|
|
return count
|
|
end
|
|
end,
|
|
|
|
allow_put = function(inventory, listname, index, stack, player)
|
|
-- Disallow putting if this is an output inventory.
|
|
if stringutil.endswith(listname, "-output") then
|
|
return 0
|
|
else
|
|
return stack:get_count()
|
|
end
|
|
end,
|
|
|
|
allow_take = function(inventory, listname, index, stack, player)
|
|
return stack:get_count()
|
|
end,
|
|
|
|
on_move = function(inventory, from_list, from_index, to_list, to_index, count, player)
|
|
if stringutil.endswith(from_list, "-output") then
|
|
artisanryui.update_player_inventory(player, inventory:get_stack(to_list, to_index))
|
|
end
|
|
|
|
artisanryui.update_from_input_inventory(player)
|
|
end,
|
|
|
|
on_put = function(inventory, listname, index, stack, player)
|
|
artisanryui.update_from_input_inventory(player)
|
|
end,
|
|
|
|
on_take = function(inventory, listname, index, stack, player)
|
|
if stringutil.endswith(listname, "-output") then
|
|
artisanryui.update_player_inventory(player, stack)
|
|
end
|
|
|
|
artisanryui.update_from_input_inventory(player)
|
|
end
|
|
})
|
|
end
|
|
|
|
--- Replaces the inventory of every currently connected player with
|
|
-- the artisanryui one.
|
|
function artisanryui.replace_inventories()
|
|
for index, player in ipairs(minetest.get_connected_players()) do
|
|
artisanryui.replace_inventory(player)
|
|
end
|
|
end
|
|
|
|
--- Replaces the inventory of the given player with the artisanryui one.
|
|
--
|
|
-- @param player The player for which to replace the inventory.
|
|
function artisanryui.replace_inventory(player)
|
|
artisanryui.inventory:set_size(player:get_player_name() .. "-input", 5 * 5)
|
|
artisanryui.inventory:set_size(player:get_player_name() .. "-output", artisanryui.output_size)
|
|
|
|
player:set_inventory_formspec(artisanryui.build_formspec(player))
|
|
|
|
artisanryui.last_blueprints_cache[player:get_player_name()] = List:new()
|
|
|
|
artisanryui.pages[player:get_player_name()] = {
|
|
current = 1,
|
|
max = 1
|
|
}
|
|
|
|
artisanryui.update_from_input_inventory(player)
|
|
end
|
|
|
|
--- Callback for when the scroll buttons are pressed.
|
|
--
|
|
-- @param player The Player object from which the event originated.
|
|
-- @param formname The name of the form.
|
|
-- @param fields The fields.
|
|
function artisanryui.scroll_page(player, formname, fields)
|
|
if fields["artisanry-" .. player:get_player_name() .. "-next-page"] ~= nil then
|
|
local pages = artisanryui.pages[player:get_player_name()]
|
|
pages.current = math.min(pages.current + 1, pages.max)
|
|
|
|
artisanryui.update_from_input_inventory(player)
|
|
elseif fields["artisanry-" .. player:get_player_name() .. "-previous-page"] ~= nil then
|
|
local pages = artisanryui.pages[player:get_player_name()]
|
|
pages.current = math.max(pages.current - 1, 1)
|
|
|
|
artisanryui.update_from_input_inventory(player)
|
|
end
|
|
end
|
|
|
|
--- Updates from the input inventory of the given player.
|
|
--
|
|
-- @param player The player for which to update the inventories.
|
|
function artisanryui.update_from_input_inventory(player)
|
|
local input = artisanryui.inventory:get_list(player:get_player_name() .. "-input")
|
|
local index = 1
|
|
|
|
local blueprints = artisanryui.last_blueprints_cache[player:get_player_name()]
|
|
blueprints:clear()
|
|
|
|
local page = artisanryui.pages[player:get_player_name()]
|
|
local result, decremented_input = minetest.get_craft_result({
|
|
method = "normal",
|
|
width = 5,
|
|
items = input
|
|
})
|
|
|
|
if not result.item:is_empty() and page.current == 1 then
|
|
artisanryui.inventory:set_stack(player:get_player_name() .. "-output", index, result.item)
|
|
blueprints:add({
|
|
decremented_input = decremented_input,
|
|
result = result
|
|
})
|
|
|
|
index = index + 1
|
|
end
|
|
|
|
input = artisanryutil.flat_to_grid(input)
|
|
|
|
local start_index = (page.current - 1) * artisanryui.output_size
|
|
local output_blueprints = artisanryui.artisanry:get_blueprints(input)
|
|
|
|
page.max = math.ceil(output_blueprints:size() / artisanryui.output_size)
|
|
|
|
output_blueprints:sub_list(start_index, artisanryui.output_size):foreach(function(blueprint)
|
|
artisanryui.inventory:set_stack(player:get_player_name() .. "-output", index, blueprint:get_result())
|
|
blueprints:add(blueprint)
|
|
|
|
index = index + 1
|
|
end)
|
|
|
|
while index <= artisanryui.output_size do
|
|
artisanryui.inventory:set_stack(player:get_player_name() .. "-output", index, nil)
|
|
index = index + 1
|
|
end
|
|
end
|
|
|
|
--- Updates the players inventory based on the taken stack.
|
|
--
|
|
-- @param player The player for which to update the inventories.
|
|
-- @param taken_stack The ItemStack that was taken.
|
|
function artisanryui.update_player_inventory(player, taken_stack)
|
|
local input = artisanryui.inventory:get_list(player:get_player_name() .. "-input")
|
|
local input_grid = artisanryutil.flat_to_grid(input)
|
|
|
|
local blueprints = artisanryui.last_blueprints_cache[player:get_player_name()]
|
|
|
|
blueprints:foreach(function(blueprint)
|
|
if blueprint:get_result():get_name() == taken_stack:get_name() then
|
|
if blueprint.decremented_input ~= nil then
|
|
-- This is an item registered with the default Minetest system.
|
|
artisanryui.inventory:set_list(player:get_player_name() .. "-input", blueprint.decremented_input.items)
|
|
else
|
|
local start_row = arrayutil.next_matching_row(input_grid, nil, function(item)
|
|
return not artisanryutil.is_empty_item(item)
|
|
end)
|
|
local start_column = arrayutil.next_matching_column(input_grid, nil, function(item)
|
|
return not artisanryutil.is_empty_item(item)
|
|
end)
|
|
|
|
local blueprint_input = blueprint:get_input()
|
|
|
|
for row_index = start_row, start_row + #blueprint_input - 1, 1 do
|
|
local blueprint_row = blueprint_input[row_index - start_row + 1]
|
|
|
|
for column_index = start_column, start_column + #blueprint_row - 1, 1 do
|
|
local inventory_index = (row_index - 1) * 5 + column_index
|
|
|
|
local current_stack = input_grid[row_index][column_index]
|
|
local blueprint_stack = blueprint_row[column_index - start_column + 1]
|
|
|
|
current_stack:set_count(current_stack:get_count() - blueprint_stack:get_count())
|
|
|
|
artisanryui.inventory:set_stack(player:get_player_name() .. "-input", inventory_index, current_stack)
|
|
end
|
|
end
|
|
end
|
|
|
|
return true
|
|
end
|
|
end)
|
|
end
|
|
|