2018-11-10 14:16:52 -08:00
--- Returns true if given value is a finite number; otherwise false or nil if value is not of type string nor number.
function x_marketplace . isfinite ( value )
if type ( value ) == " string " then
value = tonumber ( value )
if value == nil then return nil end
elseif type ( value ) ~= " number " then
return nil
end
return value > - math.huge and value < math.huge
end
--- Returns true if given value is not a number (NaN); otherwise false or nil if value is not of type string nor number.
function x_marketplace . isnan ( value )
if type ( value ) == " string " then
value = tonumber ( value )
if value == nil then return nil end
elseif type ( value ) ~= " number " then
return nil
end
return value ~= value
end
2018-12-01 08:13:24 -08:00
--- rounds a number to the nearest decimal places
-- @local
local function round ( val , decimal )
if ( decimal ) then
return math.floor ( ( val * 10 ^ decimal ) + 0.5 ) / ( 10 ^ decimal )
else
return math.floor ( val + 0.5 )
end
2018-11-13 15:48:25 -08:00
end
2018-12-01 08:13:24 -08:00
local function string_endswith ( full , part )
return full : find ( part , 1 , true ) == # full - # part + 1
2018-11-10 14:16:52 -08:00
end
2018-12-01 08:13:24 -08:00
--- Normalize nodename string without mod prefix and return nodename with mod prefix. This function was borrowed from WorldEdit mod.
-- @param nodename name of the node as a string, can be without the mod prefix
-- @return nil if node doesn't exists or nodename with mode prefix
-- @see https://github.com/Uberi/Minetest-WorldEdit
function x_marketplace . normalize_nodename ( nodename )
2018-12-02 08:25:25 -08:00
if not nodename then
return false
end
2018-12-01 08:13:24 -08:00
nodename = nodename : gsub ( " ^%s*(.-)%s*$ " , " %1 " ) -- strip spaces
if nodename == " " then return nil end
local fullname = ItemStack ( { name = nodename } ) : get_name ( ) -- resolve aliases
if minetest.registered_nodes [ fullname ] or fullname == " air " then -- full name
return fullname
end
for key , value in pairs ( minetest.registered_nodes ) do
if string_endswith ( key , " : " .. nodename ) then -- matches name (w/o mod part)
return key
end
end
end
--- Search items in marketplace object
2018-11-02 13:24:33 -07:00
-- @param string the string
-- @return string with found items, if no items found returns boolean false
function x_marketplace . store_find ( string )
local found = " "
2018-12-01 09:13:25 -08:00
local str = x_marketplace.normalize_nodename ( string )
2018-12-01 08:13:24 -08:00
if not str then
return false
end
2018-11-13 16:29:24 -08:00
2018-11-02 13:24:33 -07:00
for k , v in pairs ( x_marketplace.store_list ) do
2018-11-13 15:48:25 -08:00
if string.find ( k , str ) then
2018-11-02 13:24:33 -07:00
found = found .. k .. " buy: " .. string.format ( " %.2f " , v.buy ) .. " sell: " .. string.format ( " %.2f " , v.sell ) .. " \n "
end
end
if found == " " then
found = false
end
return found
end
2018-12-01 08:13:24 -08:00
--- Get random items from the store
2018-11-02 13:24:33 -07:00
-- @param number the integer
-- @return string with found items
function x_marketplace . store_get_random ( number )
local keys , i , suggest = { } , 1 , " "
local how_many = number or 5
for k , v in pairs ( x_marketplace.store_list ) do
keys [ i ] = k
i = i + 1
end
for i = 1 , how_many do
suggest = suggest .. " \n " .. keys [ math.random ( 1 , # keys ) ]
end
return suggest
end
2018-12-01 08:13:24 -08:00
--- Get players balance of BitGold
2018-11-02 13:24:33 -07:00
-- @param name the string of player name
-- @return string the current balance
function x_marketplace . get_player_balance ( name )
if not name then
return " "
end
local player = minetest.get_player_by_name ( name )
local balance = player : get_attribute ( " balance " ) or 0
return balance
end
2018-12-01 08:13:24 -08:00
--- Set players balance of BitGold
2018-11-02 13:24:33 -07:00
-- @param name the string of player name
-- @param amount the number of what should be added/deducted (if negative) from players balance
-- @return string the balance info message, returns false if not enough funds
function x_marketplace . set_player_balance ( name , amount )
if not name or not amount then
return " "
end
local player = minetest.get_player_by_name ( name )
local balance = player : get_attribute ( " balance " ) or 0
local new_balance = balance + amount
if new_balance < 0 then
2018-11-09 16:15:04 -08:00
return false , " below "
end
if new_balance > x_marketplace.max_balance then
return false , " above "
2018-11-02 13:24:33 -07:00
end
player : set_attribute ( " balance " , new_balance )
return new_balance
end
2018-11-10 14:16:52 -08:00
2018-11-25 10:04:44 -08:00
function x_marketplace . find_signs ( player_pos , text , sign )
2018-11-10 14:16:52 -08:00
local pos0 = vector.subtract ( player_pos , 2 )
local pos1 = vector.add ( player_pos , 2 )
2018-11-25 10:04:44 -08:00
local positions = minetest.find_nodes_in_area ( pos0 , pos1 , sign )
2018-11-10 14:16:52 -08:00
local found = false
if # positions <= 0 then
return false
end
for k , v in pairs ( positions ) do
local sign_meta = minetest.get_meta ( v )
local sign_text = sign_meta : get_string ( " text " ) : trim ( )
if sign_text == text then
found = true
break
end
end
return found
end
minetest.register_craftitem ( " x_marketplace:head " , {
description = " head " ,
inventory_image = " x_marketplace_head-front.png " ,
wield_image = " x_marketplace_head-front.png " ,
stack_max = 1 ,
wield_scale = { x = 1.5 , y = 1.5 , z = 6 } ,
on_use = function ( itemstack , user , pointed_thing )
if pointed_thing.type == " node " then
local node = minetest.get_node ( pointed_thing.under )
2018-11-25 10:04:44 -08:00
if node.name == " x_marketplace:sign_wall_bones " then
2018-11-10 14:16:52 -08:00
local node_meta = minetest.get_meta ( pointed_thing.under )
if node_meta : get_string ( " text " ) : trim ( ) == " /mp sellhead " then
local stack_meta = itemstack : to_table ( ) . meta
local stack_meta_value = tonumber ( stack_meta.value )
local stack_meta_owner = stack_meta.owner
2018-11-17 10:37:10 -08:00
if not stack_meta_value then
2018-11-17 11:13:21 -08:00
itemstack : take_item ( )
return itemstack
2018-11-17 10:37:10 -08:00
end
2018-11-10 14:16:52 -08:00
-- sell item
local new_balance = x_marketplace.set_player_balance ( user : get_player_name ( ) , stack_meta_value )
if new_balance then
minetest.sound_play ( " x_marketplace_gold " , {
object = user ,
max_hear_distance = 10 ,
gain = 1.0
} )
minetest.chat_send_player ( user : get_player_name ( ) , minetest.colorize ( x_marketplace.colors . green , " MARKET PLACE: You sold " .. stack_meta_owner .. " head for " .. stack_meta_value .. " BitGold. Your new balance is: " .. new_balance .. " BitGold " ) )
itemstack : take_item ( )
else
minetest.chat_send_player ( user : get_player_name ( ) , minetest.colorize ( x_marketplace.colors . yellow , " MARKET PLACE: You will go above the maximum balance if you sell this item. Transaction cancelled. " ) )
end
end
2018-11-25 10:04:44 -08:00
else
2018-11-25 10:11:06 -08:00
minetest.chat_send_player ( user : get_player_name ( ) , minetest.colorize ( x_marketplace.colors . yellow , " MARKET PLACE: If you want to sell the head, you have to punch Bones Sign with text '/mp sellhead' on it. " ) )
2018-11-10 14:16:52 -08:00
end
end
return itemstack
end ,
} )
minetest.register_on_dieplayer ( function ( player )
local player_name = player : get_player_name ( )
local balance = tonumber ( x_marketplace.get_player_balance ( player_name ) )
local lost_value , new_balance
if balance then
-- no money, nothing to loose
if balance == 0 then
return
-- almost no money, drop everything
elseif balance <= 10 then
lost_value = balance
-- loose between 5-10% from balance
else
lost_value = ( balance / 100 ) * math.random ( 5 , 10 )
end
lost_value = round ( lost_value , 2 )
new_balance = x_marketplace.set_player_balance ( player_name , lost_value * - 1 )
local pos = vector.round ( player : getpos ( ) )
local itemstack = ItemStack ( " x_marketplace:head " )
local meta = itemstack : get_meta ( )
local item_description = minetest.registered_items [ " x_marketplace:head " ] [ " description " ]
meta : set_string ( " owner " , player_name )
meta : set_string ( " value " , lost_value )
meta : set_string ( " description " , player_name .. " " .. item_description .. " \n value: " .. lost_value .. " BitGold " )
local obj = minetest.add_item ( pos , itemstack )
if obj then
obj : set_velocity ( {
x = math.random ( - 10 , 10 ) / 9 ,
y = 5 ,
z = math.random ( - 10 , 10 ) / 9 ,
} )
end
minetest.chat_send_player ( player_name , minetest.colorize ( x_marketplace.colors . yellow , " MARKET PLACE: When you died you lost " .. lost_value .. " BitGold " ) )
end
end )