2015-02-05 10:07:38 +01:00
local S = rawget ( _G , " intllib " ) and intllib.Getter ( ) or function ( s ) return s end
2014-03-31 01:32:13 +02:00
2015-02-07 20:42:23 +01:00
local pipeworks = rawget ( _G , " pipeworks " )
2017-04-11 10:41:26 +02:00
local fs_helpers = rawget ( _G , " fs_helpers " )
2019-02-01 21:20:03 +01:00
local has_protector_mod = minetest.get_modpath ( " protector " )
2017-04-11 10:41:26 +02:00
local allow_label = " "
2017-04-11 13:15:59 +02:00
local tube_entry = " "
2017-04-11 10:41:26 +02:00
local shift_edit_field = 0
2015-02-07 20:42:23 +01:00
if not minetest.get_modpath ( " pipeworks " ) then
-- Pipeworks is not installed. Simulate using a dummy table...
pipeworks = { }
2017-04-11 10:41:26 +02:00
fs_helpers = { }
2015-02-07 20:42:23 +01:00
local pipeworks_meta = { }
setmetatable ( pipeworks , pipeworks_meta )
local dummy = function ( )
end
pipeworks_meta.__index = function ( table , key )
print ( " [technic_chests] WARNING: variable or method ' " .. key .. " ' not present in dummy pipeworks table - assuming it is a method... " )
pipeworks [ key ] = dummy
return dummy
end
pipeworks.after_place = dummy
pipeworks.after_dig = dummy
2017-04-11 10:41:26 +02:00
fs_helpers.cycling_button = function ( ) return " " end
else
fs_helpers = pipeworks.fs_helpers
allow_label = " label[0.9,0.36;Allow splitting incoming stacks from tubes] "
shift_edit_field = 3
2017-04-11 13:15:59 +02:00
tube_entry = " ^pipeworks_tube_connection_metallic.png "
2015-02-07 20:42:23 +01:00
end
2013-12-18 01:15:20 +01:00
local chest_mark_colors = {
2014-03-31 01:32:13 +02:00
{ " black " , S ( " Black " ) } ,
{ " blue " , S ( " Blue " ) } ,
{ " brown " , S ( " Brown " ) } ,
2014-04-16 19:10:00 +02:00
{ " cyan " , S ( " Cyan " ) } ,
2014-03-31 01:32:13 +02:00
{ " dark_green " , S ( " Dark Green " ) } ,
{ " dark_grey " , S ( " Dark Grey " ) } ,
{ " green " , S ( " Green " ) } ,
{ " grey " , S ( " Grey " ) } ,
{ " magenta " , S ( " Magenta " ) } ,
{ " orange " , S ( " Orange " ) } ,
{ " pink " , S ( " Pink " ) } ,
{ " red " , S ( " Red " ) } ,
{ " violet " , S ( " Violet " ) } ,
{ " white " , S ( " White " ) } ,
{ " yellow " , S ( " Yellow " ) } ,
2013-12-18 01:15:20 +01:00
}
local function colorid_to_postfix ( id )
2014-03-31 01:32:13 +02:00
return chest_mark_colors [ id ] and " _ " .. chest_mark_colors [ id ] [ 1 ] or " "
2013-12-18 01:15:20 +01:00
end
2014-07-02 20:13:04 +02:00
local function get_color_buttons ( coleft , lotop )
2013-12-18 01:15:20 +01:00
local buttons_string = " "
for y = 0 , 3 do
for x = 0 , 3 do
local file_name = " technic_colorbutton " .. ( y * 4 + x ) .. " .png "
buttons_string = buttons_string .. " image_button[ "
2014-07-02 20:13:04 +02:00
.. ( coleft + 0.1 + x * 0.7 ) .. " , " .. ( lotop + 0.1 + y * 0.7 )
2013-12-18 01:15:20 +01:00
.. " ;0.8,0.8; " .. file_name .. " ;color_button "
.. ( y * 4 + x + 1 ) .. " ;] "
end
end
return buttons_string
end
local function check_color_buttons ( pos , meta , chest_name , fields )
for i = 1 , 16 do
if fields [ " color_button " .. i ] then
2014-07-26 20:33:48 +02:00
local node = minetest.get_node ( pos )
node.name = chest_name .. colorid_to_postfix ( i )
minetest.swap_node ( pos , node )
2014-03-31 01:32:13 +02:00
meta : set_string ( " color " , i )
2013-12-18 01:15:20 +01:00
return
end
end
end
2014-05-01 09:32:01 +02:00
local function set_formspec ( pos , data , page )
local meta = minetest.get_meta ( pos )
local node = minetest.get_node ( pos )
2014-07-02 20:13:04 +02:00
local formspec = data.base_formspec
2017-04-11 10:41:26 +02:00
formspec = formspec .. fs_helpers.cycling_button (
meta ,
" image_button[0,0.35;1,0.6 " ,
" splitstacks " ,
{
2017-04-12 01:16:50 +02:00
pipeworks.button_off ,
2017-04-12 02:54:30 +02:00
pipeworks.button_on
2017-04-11 10:41:26 +02:00
}
) .. allow_label
2014-05-01 09:32:01 +02:00
if data.autosort then
local status = meta : get_int ( " autosort " )
2014-07-02 20:13:04 +02:00
formspec = formspec .. " button[ " .. ( data.hileft + 2 ) .. " , " .. ( data.height + 1.1 ) .. " ;3,0.8;autosort_to_ " .. ( 1 - status ) .. " ; " .. S ( " Auto-sort is %s " ) : format ( status == 1 and S ( " On " ) or S ( " Off " ) ) .. " ] "
2014-05-01 09:32:01 +02:00
end
if data.infotext then
local formspec_infotext = minetest.formspec_escape ( meta : get_string ( " infotext " ) )
if page == " main " then
2017-04-11 10:41:26 +02:00
formspec = formspec .. " image_button[ " .. ( shift_edit_field + data.hileft + 2.1 ) .. " ,0.1;0.8,0.8; "
2014-05-01 09:32:01 +02:00
.. " technic_pencil_icon.png;edit_infotext;] "
2017-04-11 10:41:26 +02:00
.. " label[ " .. ( shift_edit_field + data.hileft + 3 ) .. " ,0; " .. formspec_infotext .. " ] "
2014-05-01 09:32:01 +02:00
elseif page == " edit_infotext " then
2017-04-11 10:41:26 +02:00
formspec = formspec .. " image_button[ " .. ( shift_edit_field + data.hileft + 2.1 ) .. " ,0.1;0.8,0.8; "
2014-05-01 09:32:01 +02:00
.. " technic_checkmark_icon.png;save_infotext;] "
2017-04-11 10:41:26 +02:00
.. " field[ " .. ( shift_edit_field + data.hileft + 3.3 ) .. " ,0.2;4.8,1; "
2014-05-01 09:32:01 +02:00
.. " infotext_box; " .. S ( " Edit chest description: " ) .. " ; "
.. formspec_infotext .. " ] "
end
end
if data.color then
local colorID = meta : get_int ( " color " )
local colorName
if chest_mark_colors [ colorID ] then
colorName = chest_mark_colors [ colorID ] [ 2 ]
else
colorName = S ( " None " )
end
2014-07-02 20:13:04 +02:00
formspec = formspec .. " label[ " .. ( data.coleft + 0.2 ) .. " , " .. ( data.lotop + 3 ) .. " ; " .. S ( " Color Filter: %s " ) : format ( colorName ) .. " ] "
2014-05-01 09:32:01 +02:00
end
meta : set_string ( " formspec " , formspec )
end
local function sort_inventory ( inv )
local inlist = inv : get_list ( " main " )
local typecnt = { }
local typekeys = { }
for _ , st in ipairs ( inlist ) do
if not st : is_empty ( ) then
local n = st : get_name ( )
local w = st : get_wear ( )
local m = st : get_metadata ( )
local k = string.format ( " %s %05d %s " , n , w , m )
if not typecnt [ k ] then
2017-09-02 15:57:32 +02:00
typecnt [ k ] = { st }
2014-05-01 09:32:01 +02:00
table.insert ( typekeys , k )
2017-09-02 15:57:32 +02:00
else
table.insert ( typecnt [ k ] , st )
2014-05-01 09:32:01 +02:00
end
end
end
table.sort ( typekeys )
2017-09-02 15:57:32 +02:00
inv : set_list ( " main " , { } )
2014-05-01 09:32:01 +02:00
for _ , k in ipairs ( typekeys ) do
2017-09-02 15:57:32 +02:00
for _ , item in ipairs ( typecnt [ k ] ) do
inv : add_item ( " main " , item )
2014-05-01 09:32:01 +02:00
end
end
end
2013-12-18 01:15:20 +01:00
local function get_receive_fields ( name , data )
local lname = name : lower ( )
return function ( pos , formname , fields , sender )
local meta = minetest.get_meta ( pos )
local page = " main "
2014-05-01 09:32:01 +02:00
if fields.sort or ( data.autosort and fields.quit and meta : get_int ( " autosort " ) == 1 ) then
sort_inventory ( meta : get_inventory ( ) )
end
2013-12-18 01:15:20 +01:00
if fields.edit_infotext then
page = " edit_infotext "
end
2014-05-01 09:32:01 +02:00
if fields.autosort_to_1 then meta : set_int ( " autosort " , 1 ) end
if fields.autosort_to_0 then meta : set_int ( " autosort " , 0 ) end
2014-04-24 18:42:35 +02:00
if fields.infotext_box then
2013-12-18 01:15:20 +01:00
meta : set_string ( " infotext " , fields.infotext_box )
end
if data.color then
-- This sets the node
local nn = " technic: " .. lname .. ( data.locked and " _locked " or " " ) .. " _chest "
check_color_buttons ( pos , meta , nn , fields )
end
2017-04-11 10:41:26 +02:00
if fields [ " fs_helpers_cycling:0:splitstacks " ]
or fields [ " fs_helpers_cycling:1:splitstacks " ] then
if not pipeworks.may_configure ( pos , sender ) then return end
fs_helpers.on_receive_fields ( pos , fields )
end
Buff chest sizes
Make the inventory sizes of all the technic chests larger, to provide
a more appreciable benefit from upgrading chests, more in keeping with
the resources spent on the upgrades.
Currently the game engine doesn't handle large forms well. The size
of an inventory slot is fixed relative to the screen height, and a
form that exceeds either screen dimension will extend off the screen,
making parts of it inaccessible. The tallest a form can get and remain
usable is 13 slots, and even that slightly overspills the screen height.
The maximum usable width depends on the screen aspect ratio. For the
narrowest common ratio, 5:4, the widest a form can usably get is 15 slots,
again slightly overspilling. Combined with the layout of the chest forms,
this implies a maximum practical chest inventory size of 15x7 (= 105),
slightly smaller than the largest Minecraft chests.
To provide roughly equal size steps in the five upgrades from wooden
chest (staying at 8x4 = 32) to mithril chest, the steps need to be of
about 15 slots instead of the former 4. The new sizes are:
wooden 8x4 32
iron 9x5 45
copper 12x5 60
silver 12x6 72
gold 15x6 90
mithril 15x7 105
To make upgrading from the old chest sizes to the new sizes more
convenient, the inventory size is now set not only upon chest construction
but also when accepting form input, at the same time as rewriting
the formspec. So after upgrading the technic mod, viewing an existing
chest upgrades it to the new size. The first time a pre-existing chest
is viewed its form will have the old dimensions, looking broken due
to the inventory background image now having the new number of slots.
The second time it is viewed the form will have the new dimensions,
and the full new number of slots will be usable.
2014-06-20 19:46:57 +02:00
meta : get_inventory ( ) : set_size ( " main " , data.width * data.height )
2014-05-01 09:32:01 +02:00
set_formspec ( pos , data , page )
2013-12-18 01:15:20 +01:00
end
end
2014-07-02 19:45:35 +02:00
function technic . chests : definition ( name , data )
2013-12-18 01:15:20 +01:00
local lname = name : lower ( )
2014-03-31 01:32:13 +02:00
name = S ( name )
2014-07-02 20:13:04 +02:00
local d = { }
for k , v in pairs ( data ) do d [ k ] = v end
data = d
data.lowidth = 8
data.ovwidth = math.max ( data.lowidth , data.width )
data.hileft = ( data.ovwidth - data.width ) / 2
data.loleft = ( data.ovwidth - data.lowidth ) / 2
if data.color then
if data.lowidth + 3 <= data.ovwidth then
data.coleft = data.ovwidth - 3
if data.loleft + data.lowidth > data.coleft then
data.loleft = data.coleft - data.lowidth
end
else
data.loleft = 0
data.coleft = data.lowidth
data.ovwidth = data.lowidth + 3
end
end
data.lotop = data.height + 2
data.ovheight = data.lotop + 4
2013-12-18 01:15:20 +01:00
local locked_after_place = nil
local front = { " technic_ " .. lname .. " _chest_front.png " }
2015-02-03 11:14:26 +01:00
data.base_formspec = " size[ " .. data.ovwidth .. " , " .. data.ovheight .. " ] " ..
2014-04-16 19:10:00 +02:00
" label[0,0; " .. S ( " %s Chest " ) : format ( name ) .. " ] " ..
2015-02-03 11:14:26 +01:00
" list[context;main; " .. data.hileft .. " ,1; " .. data.width .. " , " .. data.height .. " ;] " ..
2014-07-02 20:13:04 +02:00
" list[current_player;main; " .. data.loleft .. " , " .. data.lotop .. " ;8,4;] " ..
2015-05-03 21:13:45 +02:00
" background[-0.19,-0.25; " .. ( data.ovwidth + 0.4 ) .. " , " .. ( data.ovheight + 0.75 ) .. " ;technic_chest_form_bg.png] " ..
2014-07-02 20:13:04 +02:00
" background[ " .. data.hileft .. " ,1; " .. data.width .. " , " .. data.height .. " ;technic_ " .. lname .. " _chest_inventory.png] " ..
2015-06-18 04:09:27 +02:00
" background[ " .. data.loleft .. " , " .. data.lotop .. " ;8,4;technic_main_inventory.png] " ..
" listring[] "
2017-04-11 10:41:26 +02:00
2014-05-01 09:32:01 +02:00
if data.sort then
2014-07-02 20:13:04 +02:00
data.base_formspec = data.base_formspec .. " button[ " .. data.hileft .. " , " .. ( data.height + 1.1 ) .. " ;1,0.8;sort; " .. S ( " Sort " ) .. " ] "
2014-05-01 09:32:01 +02:00
end
2013-12-18 01:15:20 +01:00
if data.color then
2014-07-02 20:13:04 +02:00
data.base_formspec = data.base_formspec .. get_color_buttons ( data.coleft , data.lotop )
2013-12-18 01:15:20 +01:00
end
if data.locked then
locked_after_place = function ( pos , placer )
local meta = minetest.get_meta ( pos )
meta : set_string ( " owner " , placer : get_player_name ( ) or " " )
2014-03-31 01:32:13 +02:00
meta : set_string ( " infotext " ,
S ( " %s Locked Chest (owned by %s) " )
: format ( name , meta : get_string ( " owner " ) ) )
2015-02-07 18:07:17 +01:00
pipeworks.after_place ( pos )
2013-12-18 01:15:20 +01:00
end
2015-02-07 18:07:17 +01:00
else
locked_after_place = pipeworks.after_place
2013-12-18 01:15:20 +01:00
end
2019-02-01 21:20:03 +01:00
if data.locked then
table.insert ( front , " technic_ " .. lname .. " _chest_lock_overlay.png " )
end
if data.protected and has_protector_mod then
-- use overlay from protector mod
table.insert ( front , " protector_logo.png " )
end
2014-03-31 01:32:13 +02:00
local desc
if data.locked then
desc = S ( " %s Locked Chest " ) : format ( name )
2019-02-01 21:20:03 +01:00
elseif data.protected then
desc = S ( " %s Protected Chest " ) : format ( name )
2014-03-31 01:32:13 +02:00
else
desc = S ( " %s Chest " ) : format ( name )
end
2017-04-11 13:15:59 +02:00
local tentry = tube_entry
if tube_entry ~= " " then
if lname == " wooden " then
tentry = " ^pipeworks_tube_connection_wooden.png "
elseif lname == " mithril " then
tentry = " ^pipeworks_tube_connection_stony.png "
end
end
2013-12-18 01:15:20 +01:00
local def = {
2014-03-31 01:32:13 +02:00
description = desc ,
2017-04-11 13:15:59 +02:00
tiles = {
" technic_ " .. lname .. " _chest_top.png " .. tentry ,
" technic_ " .. lname .. " _chest_top.png " .. tentry ,
" technic_ " .. lname .. " _chest_side.png " .. tentry ,
" technic_ " .. lname .. " _chest_side.png " .. tentry ,
" technic_ " .. lname .. " _chest_side.png " .. tentry ,
table.concat ( front , " ^ " )
} ,
2013-12-18 01:15:20 +01:00
paramtype2 = " facedir " ,
groups = self.groups ,
tube = self.tube ,
legacy_facedir_simple = true ,
sounds = default.node_sound_wood_defaults ( ) ,
2015-02-07 18:07:17 +01:00
after_place_node = locked_after_place ,
2015-02-07 09:22:56 +01:00
after_dig_node = pipeworks.after_dig ,
2013-12-18 01:15:20 +01:00
on_construct = function ( pos )
local meta = minetest.get_meta ( pos )
2014-03-31 01:32:13 +02:00
meta : set_string ( " infotext " , S ( " %s Chest " ) : format ( name ) )
2014-05-01 09:32:01 +02:00
set_formspec ( pos , data , " main " )
2013-12-18 01:15:20 +01:00
local inv = meta : get_inventory ( )
Buff chest sizes
Make the inventory sizes of all the technic chests larger, to provide
a more appreciable benefit from upgrading chests, more in keeping with
the resources spent on the upgrades.
Currently the game engine doesn't handle large forms well. The size
of an inventory slot is fixed relative to the screen height, and a
form that exceeds either screen dimension will extend off the screen,
making parts of it inaccessible. The tallest a form can get and remain
usable is 13 slots, and even that slightly overspills the screen height.
The maximum usable width depends on the screen aspect ratio. For the
narrowest common ratio, 5:4, the widest a form can usably get is 15 slots,
again slightly overspilling. Combined with the layout of the chest forms,
this implies a maximum practical chest inventory size of 15x7 (= 105),
slightly smaller than the largest Minecraft chests.
To provide roughly equal size steps in the five upgrades from wooden
chest (staying at 8x4 = 32) to mithril chest, the steps need to be of
about 15 slots instead of the former 4. The new sizes are:
wooden 8x4 32
iron 9x5 45
copper 12x5 60
silver 12x6 72
gold 15x6 90
mithril 15x7 105
To make upgrading from the old chest sizes to the new sizes more
convenient, the inventory size is now set not only upon chest construction
but also when accepting form input, at the same time as rewriting
the formspec. So after upgrading the technic mod, viewing an existing
chest upgrades it to the new size. The first time a pre-existing chest
is viewed its form will have the old dimensions, looking broken due
to the inventory background image now having the new number of slots.
The second time it is viewed the form will have the new dimensions,
and the full new number of slots will be usable.
2014-06-20 19:46:57 +02:00
inv : set_size ( " main " , data.width * data.height )
2013-12-18 01:15:20 +01:00
end ,
can_dig = self.can_dig ,
on_receive_fields = get_receive_fields ( name , data ) ,
on_metadata_inventory_move = self.on_inv_move ,
on_metadata_inventory_put = self.on_inv_put ,
2017-09-02 15:57:32 +02:00
on_metadata_inventory_take = self.on_inv_take ,
2017-01-15 15:58:13 +01:00
on_blast = function ( pos )
local drops = { }
default.get_inventory_drops ( pos , " main " , drops )
2017-03-06 21:09:44 +01:00
drops [ # drops + 1 ] = " technic: " .. name : lower ( ) .. ( data.locked and " _locked " or " " ) .. " _chest "
2017-01-15 15:58:13 +01:00
minetest.remove_node ( pos )
return drops
end ,
2013-12-18 01:15:20 +01:00
}
if data.locked then
def.allow_metadata_inventory_move = self.inv_move
def.allow_metadata_inventory_put = self.inv_put
def.allow_metadata_inventory_take = self.inv_take
2017-03-06 20:32:18 +01:00
def.on_blast = function ( ) end
2017-03-06 21:09:44 +01:00
def.can_dig = function ( pos , player )
local meta = minetest.get_meta ( pos ) ;
local inv = meta : get_inventory ( )
return inv : is_empty ( " main " ) and default.can_interact_with_node ( player , pos )
2017-03-06 20:32:18 +01:00
end
2017-01-15 15:58:13 +01:00
def.on_skeleton_key_use = function ( pos , player , newsecret )
local meta = minetest.get_meta ( pos )
local owner = meta : get_string ( " owner " )
local name = player : get_player_name ( )
-- verify placer is owner of lockable chest
if owner ~= name then
minetest.record_protection_violation ( pos , name )
minetest.chat_send_player ( name , " You do not own this chest. " )
return nil
end
local secret = meta : get_string ( " key_lock_secret " )
if secret == " " then
secret = newsecret
meta : set_string ( " key_lock_secret " , secret )
end
return secret , " a locked chest " , owner
2017-03-06 20:32:18 +01:00
end
2019-02-01 21:20:03 +01:00
elseif data.protected then
def.allow_metadata_inventory_move = self.inv_move_protected
def.allow_metadata_inventory_put = self.inv_put_protected
def.allow_metadata_inventory_take = self.inv_take_protected
def.on_blast = function ( ) end
def.can_dig = function ( pos , player )
local meta = minetest.get_meta ( pos ) ;
local inv = meta : get_inventory ( )
return inv : is_empty ( " main " ) and not minetest.is_protected ( pos , player : get_player_name ( ) )
end
2013-12-18 01:15:20 +01:00
end
2014-07-02 19:45:35 +02:00
return def
end
2013-12-18 01:15:20 +01:00
2014-07-02 19:45:35 +02:00
function technic . chests : register ( name , data )
local def = technic.chests : definition ( name , data )
2013-12-18 01:15:20 +01:00
2019-02-01 21:20:03 +01:00
-- prefix
local nn = " technic: " .. name : lower ( )
if data.locked then
-- locked chest
nn = nn .. " _locked "
elseif data.protected then
-- protected chest
nn = nn .. " _protected "
end
-- suffix
nn = nn .. " _chest "
2013-12-18 01:15:20 +01:00
minetest.register_node ( " : " .. nn , def )
if data.color then
2014-07-02 19:45:35 +02:00
local mk_front
if string.find ( def.tiles [ 6 ] , " %^ " ) then
mk_front = function ( overlay ) return def.tiles [ 6 ] : gsub ( " %^ " , " ^ " .. overlay .. " ^ " ) end
else
mk_front = function ( overlay ) return def.tiles [ 6 ] .. " ^ " .. overlay end
end
2013-12-18 01:15:20 +01:00
for i = 1 , 15 do
local postfix = colorid_to_postfix ( i )
local colordef = { }
for k , v in pairs ( def ) do
colordef [ k ] = v
end
colordef.drop = nn
colordef.groups = self.groups_noinv
2014-07-02 19:45:35 +02:00
colordef.tiles = { def.tiles [ 1 ] , def.tiles [ 2 ] , def.tiles [ 3 ] , def.tiles [ 4 ] , def.tiles [ 5 ] , mk_front ( " technic_chest_overlay " .. postfix .. " .png " ) }
2013-12-18 01:15:20 +01:00
minetest.register_node ( " : " .. nn .. postfix , colordef )
end
end
end