- added dependency for formspecs and ownership mods
- introduced packages with specialized behavior
- created textures for newly registered items
- fixed regex during validation of recipient names
- fixed erroneous checks against unowned nodes
- general code refactoring and reformatting
This commit is contained in:
Leslie Krause 2018-12-25 07:34:00 -05:00
parent 67827270e6
commit df4356d978
9 changed files with 275 additions and 53 deletions

View File

@ -1,15 +1,97 @@
==========================================================
Giftbox Mod v2.1 by sorcerykid
Giftbox Mod v2.2
By Leslie E. Krause
https://forum.minetest.net/viewtopic.php?f=9&t=19133
Repository
----------------------
License of source code
Browse source code:
https://bitbucket.org/sorcerykid/giftbox
Download archive:
https://bitbucket.org/sorcerykid/giftbox/get/master.zip
https://bitbucket.org/sorcerykid/giftbox/get/master.tar.gz
Revision History
----------------------
Version 1.0b (12-Jan-2018)
- initial version within doors mod
Version 2.0 (31-Aug-2018)
- separated common routines into standalone mod
- included support files for public release
Version 1.0a (Build 01)
- initial build
Version 1.1a (Build 02)
- moved configuration settings into separate file
- made infotext of admin giftbox configurable
- made background of admin giftbox configurable
- changed debug log messages into tokenized strings
Version 2.0b (Build 03)
- merged colored giftboxes from mt_seasons mod
- added aliases for original colored giftboxes
- improved end-user customizations of giftbox
Version 2.0 (Build 04)
- renamed admin giftbox to "present" for distinction
- created textures for newly registered nodes
- renamed associated texture files of present
- replaced owner meta for present with sender instead
- added protection check to inventory take of present
- disabled formspec for recipient of empty present
- added sender/receiver checks when digging giftbox
- made default infotext of giftbox configurable
- changed owner of giftbox to placer for simplicity
- set default receiver of giftbox during placement
- switched all prior references of owner to receiver
- registered alias for original admin giftbox
Version 2.1 (Build 05)
- escaped giftbox message in formspec string
- improved validation of giftbox message input
Version 2.2 (Build 06)
- added dependency for formspecs and ownership mods
- introduced packages with specialized behavior
- created textures for newly registered items
- fixed regex during validation of recipient names
- fixed erroneous checks against unowned nodes
- general code refactoring and reformatting
Dependencies
----------------------
Default Mod (required)
https://github.com/minetest/minetest_game/default
ActiveFormspecs Mod (required)
https://bitbucket.org/sorcerykid/formspecs
Basic Ownership Mod (required)
https://bitbucket.org/sorcerykid/ownership
Compatability
----------------------
Minetest 0.4.15+ required
Installation
----------------------
1) Unzip the archive into the mods directory of your game
2) Rename the giftbox-master directory to "giftbox"
Source Code License
----------------------------------------------------------
GNU Lesser General Public License v3 (LGPL-3.0)
Copyright (c) 2016-2017, Leslie E. Krause
Copyright (c) 2016-2018, Leslie E. Krause
Original source code by maikerumine:
https://github.com/maikerumine/just_test_tribute/blob/master/mods/mt_seasons/nodes.lua
@ -24,9 +106,7 @@ See the GNU Lesser General Public License for more details.
http://www.gnu.org/licenses/lgpl-2.1.html
License of media (textures, sounds, and models)
Multimedia License (textures, sounds, and models)
----------------------------------------------------------
Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)

View File

@ -2,6 +2,7 @@
giftbox.present_infotext = "Christmas Present"
giftbox.present_greeting = "present_greeting.png"
giftbox.package_viewer = "package_viewer.png"
giftbox.present_items = {
"default:torch 60",
@ -35,8 +36,9 @@ giftbox.present_items = {
"default:meselamp 10",
}
giftbox.giftbox_message_length_min = 5
giftbox.giftbox_message_length_max = 150
giftbox.parcel_public_description = "Parcel"
giftbox.parcel_private_description = "Parcel for %s"
giftbox.giftbox_public_infotext1 = "Gift Box"
giftbox.giftbox_public_infotext2 = "'%s'"
giftbox.giftbox_private_infotext1 = "Gift Box for %s"
@ -44,27 +46,16 @@ giftbox.giftbox_private_infotext2 = "Dear %s: '%s'"
giftbox.giftbox_drops = {
-- digging gift box allows for a single drop of items with a given a rarity
{ items = { "default:mese" }, rarity = 75 },
{ items = { "protector:protect" }, rarity = 75 },
{ items = { "default:sword_diamond" }, rarity = 50 },
{ items = { "default:sword_bronze" }, rarity = 25 },
{ items = { "default:diamondblock" }, rarity = 50 },
{ items = { "default:goldblock" }, rarity = 50 },
{ items = { "default:pick_diamond" }, rarity = 50 },
{ items = { "default:pick_bronze" }, rarity = 25 },
{ items = { "default:coalblock 10" }, rarity = 25 },
{ items = { "default:obsidian 20" }, rarity = 25 },
{ items = { "default:sword_diamond" }, rarity = 20 },
{ items = { "default:sword_bronze" }, rarity = 10 },
{ items = { "default:pick_diamond" }, rarity = 20 },
{ items = { "default:pick_bronze" }, rarity = 10 },
{ items = { "default:gold_lump 10" }, rarity = 5 },
{ items = { "default:coal_lump 20" }, rarity = 5 },
{ items = { "default:orange 20" }, rarity = 5 },
{ items = { "default:apple 30" }, rarity = 5 },
{ items = { "default:gold_lump 5" }, rarity = 10 },
{ items = { "default:coal_lump 10" }, rarity = 10 },
-- default drop must be placed last and have rarity of 0 to avoid empty drops
{ items = { "farming:gingerbread_cookie 5", "farming:candycane 10" }, rarity = 0 },
}

View File

@ -1 +1,3 @@
default
formspecs
ownership

201
init.lua
View File

@ -1,10 +1,10 @@
--------------------------------------------------------
-- Minetest :: Giftbox Mod v2.1 (giftbox)
-- Minetest :: Giftbox Mod v2.2 (giftbox)
--
-- See README.txt for licensing and other information.
-- Copyright (c) 2016-2017, Leslie Ellen Krause
-- Copyright (c) 2016-2018, Leslie E. Krause
--
-- ./games/just_test_tribute/mods/giftbox/init.lua
-- ./games/minetest_game/mods/giftbox/init.lua
--------------------------------------------------------
giftbox = { }
@ -30,18 +30,18 @@ local box_colors = { "black", "blue", "cyan", "green", "magenta", "red", "white"
minetest.register_node( "giftbox:present", {
description = "Gift Box",
tiles = { "present_top.png", "present_bottom.png", "present_side.png",
"present_side.png", "present_side.png", "present_side.png" },
is_ground_content = false,
groups = { choppy = 2, oddly_breakable_by_hand = 2 },
sounds = default.node_sound_wood_defaults( ),
tiles = { "present_top.png", "present_bottom.png", "present_side.png",
"present_side.png", "present_side.png", "present_side.png" },
is_ground_content = false,
groups = { choppy = 2, oddly_breakable_by_hand = 2 },
sounds = default.node_sound_wood_defaults( ),
drop = { },
after_place_node = function( pos, player )
after_place_node = function ( pos, player )
minetest.get_meta( pos ):set_string( "infotext", giftbox.present_infotext .. " (placed by " .. player:get_player_name( ) .. ")" )
end,
on_construct = function ( pos )
on_construct = function ( pos )
local meta = minetest.get_meta( pos )
meta:get_inventory( ):set_size( "main", 1 )
meta:set_string( "oldtime", os.time( ) )
@ -50,7 +50,7 @@ minetest.register_node( "giftbox:present", {
can_dig = function ( pos, player )
return not minetest.is_protected( pos, player:get_player_name( ) ) and default.is_empty( pos )
end,
allow_metadata_inventory_take = function( pos, listname, index, stack, player )
allow_metadata_inventory_take = function ( pos, listname, index, stack, player )
-- only allow receiver to take item and remove node
-- of course, placer can already bypass protection
@ -59,16 +59,16 @@ minetest.register_node( "giftbox:present", {
end
return stack:get_count( )
end,
allow_metadata_inventory_put = function( pos, listname, index, stack, player )
allow_metadata_inventory_put = function ( pos, listname, index, stack, player )
return 0
end,
on_metadata_inventory_take = function( pos, listname, index, stack, player )
on_metadata_inventory_take = function ( pos, listname, index, stack, player )
if default.is_empty( pos ) then
minetest.remove_node( pos )
end
minetest.log( "action", string.format( default.STATUS_CONTAINER_GET, player:get_player_name( ), "giftbox", minetest.pos_to_string( pos ) ) )
end,
on_open = function( pos, clicker )
on_open = function ( pos, clicker )
local pname = clicker:get_player_name( )
local spos = pos.x .. "," .. pos.y .. "," .. pos.z
@ -83,10 +83,10 @@ minetest.register_node( "giftbox:present", {
"list[nodemeta:%s;main;6,0.5;1,1;]"
slot = 0
for _, name in ipairs( giftbox.present_items ) do
for _, name in ipairs( giftbox.present_items ) do
formspec = formspec .. "item_image_button[ " .. ( slot % 8 ) .. "," .. ( math.floor ( slot / 8 ) + 2 ) .. ";1,1;" .. name .. ";add " .. name .. ";]"
slot = slot + 1
end
end
return string.format( formspec, spos )
elseif not minetest.is_protected( pos, pname ) and not default.is_empty( pos ) then
-- only show formspec if placer remembered to select item
@ -100,11 +100,11 @@ minetest.register_node( "giftbox:present", {
default.gui_slots ..
"list[nodemeta:%s;main;7,4;1,1;]" ..
"list[current_player;main;1,5.5;8,1;]" ..
default.get_hotbar_bg(1,5.5)
default.get_hotbar_bg( 1, 5.5 )
return string.format( formspec, spos )
end
end,
on_close = function( pos, player, fields )
on_close = function ( pos, player, fields )
local fname, item
fname = next( fields, nil ) -- use next since we only care about the name of a single button
@ -116,7 +116,156 @@ minetest.register_node( "giftbox:present", {
end
end
end,
})
} )
minetest.register_craftitem( "giftbox:package_unsealed", {
description = "Package (To seal, point to an object and use)",
inventory_image = "package_unsealed.png",
wield_image = "package_unsealed2.png",
groups = { flammable = 3 },
on_use = function( cur_stack, player, pointed_thing )
if pointed_thing.type == "object" and not pointed_thing.ref:is_player( ) then
local player_name = player:get_player_name( )
local player_inv = player:get_inventory( )
-- ignore objects that are not builtin-item (sanity check)
local entity = pointed_thing.ref:get_luaentity( )
if entity.name ~= "__builtin:item" then return end
local item_name = ItemStack( entity.itemstring ):get_name( )
if item_name == "giftbox:package_unsealed" or item_name == "giftbox:package_sealed" then
minetest.chat_send_player( player_name, "This item cannot be stored inside a package." )
return
end
cur_stack:take_item( )
pointed_thing.ref:remove( )
-- produce a sealed package containing pointed_thing
local new_stack = ItemStack( "giftbox:package_sealed" )
local meta = new_stack:get_meta( )
meta:set_string( "description", giftbox.parcel_public_description ..
" (from " .. player_name .. " on " .. os.date( "%x" ) .. ")" )
meta:set_string( "timestamp", os.time( ) )
meta:set_string( "receiver", default.OWNER_NOBODY )
meta:set_string( "owner", player_name )
meta:set_string( "is_anonymous", "false" )
meta:set_string( "itemstring", entity.itemstring )
if player_inv:room_for_item( "main", new_stack ) then
player_inv:add_item( "main", new_stack )
else
minetest.add_item( player:getpos( ), new_stack )
end
end
return cur_stack
end
} )
minetest.register_craftitem( "giftbox:package_sealed", {
inventory_image = "package_sealed.png",
wield_image = "package_sealed2.png",
groups = { flammable = 3, not_in_creative_inventory = 1 },
on_use = function( itemstack, player, pointed_thing )
local player_name = player:get_player_name( )
local meta = itemstack:get_meta( )
local receiver = meta:get_string( "receiver" )
local owner = meta:get_string( "owner" )
if owner == player_name or minetest.check_player_privs( player_name, { give = true } ) then
local formspec =
"size[8,3.5]" ..
default.gui_bg ..
default.gui_bg_img ..
"checkbox[4.8,1.8;is_anonymous;Anonymous Sender;" .. meta:get_string( "is_anonymous" ) .. "]" ..
"label[0.1,2.0;Recipient:]" ..
"field[1.8,2.4;3.0,0.25;receiver;;" .. receiver .. "]" ..
"label[2.9,0.0;Package Contents:]" ..
"image[3.5,0.6;1,1;gui_furnace_arrow_bg.png^[transformR270]" ..
"item_image_button[2.5,0.6;1,1;giftbox:package_sealed;restore;]" ..
"item_image_button[4.5,0.6;1,1;" .. ItemStack( meta:get_string( "itemstring" ) ):get_name( ) .. ";revert;]" ..
"label[0.1,2.9;Stored on " .. os.date( "%x %X", tonumber( meta:get_string( "timestamp" ) ) ) .. "]" ..
"button_exit[6.0,3.0;2,0.3;save;Save]"
minetest.create_form( nil, player_name, formspec, function ( _, player, fields )
if fields.is_anonymous then
meta:set_string( "is_anonymous", fields.is_anonymous )
elseif fields.revert then
local itemstring = meta:get_string( "itemstring" )
player:set_wielded_item( ItemStack( itemstring ) )
minetest.destroy_form( player_name )
elseif fields.restore then
player:set_wielded_item( "giftbox:package_unsealed" )
minetest.destroy_form( player_name )
elseif fields.save and fields.receiver then
if fields.receiver == owner then
minetest.chat_send_player( owner, "You cannot send a parcel to yourself." )
return
elseif fields.receiver ~= default.OWNER_NOBODY and not string.find( fields.receiver, "^[-_A-Za-z0-9]+$" ) then
minetest.chat_send_player( owner, "The specified recipient is invalid." )
return
end
-- public vs. private letters and parcels
local description = fields.receiver == default.OWNER_NOBODY and
giftbox.parcel_public_description or
string.format( giftbox.parcel_private_description, fields.receiver )
if meta:get_string( "is_anonymous" ) == "false" then
description = description .. " (from " .. owner .. " on " .. os.date( "%x", tonumber( meta:get_string( "timestamp" ) ) ) .. ")"
end
meta:set_string( "description", description )
meta:set_string( "receiver", fields.receiver )
player:set_wielded_item( itemstack )
end
end )
elseif receiver == player_name or receiver == default.OWNER_NOBODY then
local formspec =
"size[9,7]" ..
default.gui_bg ..
default.gui_bg_img ..
"background[0,0;9,6;" .. giftbox.package_viewer .. "]" ..
"label[0.5,0.5;" .. minetest.colorize( "#000000", os.date( "%x %X", tonumber( meta:get_string( "timestamp" ) ) ) ) .. "]" ..
"button_exit[3.0,6.5;3.0,0.3;open;Open Package]"
if meta:get_string( "is_anonymous" ) == "false" then
formspec = formspec .. "label[3.5,2.5;" .. minetest.colorize( "#000000", owner ) .. "]"
end
if receiver ~= default.OWNER_NOBODY then
formspec = formspec .. "label[3.5,3.0;" .. minetest.colorize( "#000000", receiver ) .. "]"
end
minetest.create_form( nil, player_name, formspec, function ( _, player, fields )
if fields.open then
local itemstring = meta:get_string( "itemstring" )
player:set_wielded_item( ItemStack( itemstring ) )
-- TODO: record deliveries of letters and parcels in debug log
end
end )
else
minetest.chat_send_player( player_name, "Access denied. This parcel does not belong to you." )
end
return itemstack
end
} )
minetest.register_craft( {
output = "giftbox:package_opened",
recipe = {
{ "default:paper", "default:paper", "default:paper" },
{ "default:paper", "", "default:paper" },
{ "default:paper", "default:paper", "default:paper" },
}
} )
for i, color in ipairs( box_colors ) do
minetest.register_node( "giftbox:giftbox_" .. color, {
@ -142,7 +291,7 @@ for i, color in ipairs( box_colors ) do
drop = { max_items = 1, items = giftbox.giftbox_drops },
on_dig = function( pos, node, player )
on_dig = function ( pos, node, player )
local digger = player:get_player_name( )
local receiver = minetest.get_meta( pos ):get_string( "receiver" )
-- local is_protected = minetest.get_meta( pos ):get_string( "is_protected" ) == "true"
@ -161,25 +310,25 @@ for i, color in ipairs( box_colors ) do
minetest.remove_node( pos )
end
end,
after_place_node = function( pos, player )
after_place_node = function ( pos, player )
local placer = player:get_player_name( ) or "singleplayer"
local meta = minetest.get_meta( pos )
default.set_owner( pos, placer )
meta:set_string( "receiver", "" )
meta:set_string( "receiver", default.OWNER_NOBODY )
meta:set_string( "is_anonymous", "false" )
-- initial item string: Gift Box (placed by sorcerykid)
meta:set_string( "infotext", giftbox.giftbox_public_infotext1 .. " (from " .. placer .. ")" )
end,
on_open = function( pos, player, fields )
on_open = function ( pos, player, fields )
local meta = minetest.get_meta( pos )
local formspec =
"size[8,3]" ..
default.gui_bg ..
default.gui_bg_img ..
"button_exit[6,2.5;2,0.3;save;Save]" ..
"checkbox[4.5,1.3;is_anonymous;Anonymous Gift;" .. meta:get_string( "is_anonymous" ) .. "]" ..
"checkbox[4.5,1.3;is_anonymous;Anonymous Sender;" .. meta:get_string( "is_anonymous" ) .. "]" ..
"label[0.1,0;Personalize your holiday greeting (or leave blank for the default):]" ..
"field[0.4,1;7.8,0.25;message;;" .. minetest.formspec_escape( meta:get_string( "message" ) ) .. "]" ..
"label[0.1,1.5;Recipient:]" ..
@ -190,7 +339,7 @@ for i, color in ipairs( box_colors ) do
return formspec
end
end,
on_close = function( pos, player, fields )
on_close = function ( pos, player, fields )
local owner = player:get_player_name( )
local meta = minetest.get_meta( pos )
@ -214,7 +363,7 @@ for i, color in ipairs( box_colors ) do
elseif fields.receiver == owner then
minetest.chat_send_player( owner, "You cannot give a gift to yourself." )
return
elseif fields.receiver ~= "" and not string.find( fields.receiver, "^[_A-Za-z0-9]+$" ) then
elseif fields.receiver ~= default.OWNER_NOBODY and not string.find( fields.receiver, "^[-_A-Za-z0-9]+$" ) then
minetest.chat_send_player( owner, "The specified recipient is invalid." )
return
end

BIN
textures/package_sealed.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 317 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 246 B

BIN
textures/package_viewer.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB