init.lua 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548
  1. local modpath = minetest.get_modpath(minetest.get_current_modname())
  2. minetest.register_alias("commoditymarket:kings_market", "commoditymarket_fantasy:kings_market")
  3. minetest.register_alias("commoditymarket:gold_coins", "commoditymarket_fantasy:gold_coins")
  4. minetest.register_alias("commoditymarket:night_market", "commoditymarket_fantasy:night_market")
  5. minetest.register_alias("commoditymarket:goblin_market", "commoditymarket_fantasy:goblin_market")
  6. minetest.register_alias("commoditymarket:under_market", "commoditymarket_fantasy:under_market")
  7. minetest.register_alias("commoditymarket:caravan_post", "commoditymarket_fantasy:caravan_post")
  8. minetest.register_alias("commoditymarket:caravan_market_1", "commoditymarket_fantasy:caravan_market_1")
  9. minetest.register_alias("commoditymarket:caravan_market_2", "commoditymarket_fantasy:caravan_market_2")
  10. minetest.register_alias("commoditymarket:caravan_market_3", "commoditymarket_fantasy:caravan_market_3")
  11. minetest.register_alias("commoditymarket:caravan_market_4", "commoditymarket_fantasy:caravan_market_4")
  12. minetest.register_alias("commoditymarket:caravan_market_5", "commoditymarket_fantasy:caravan_market_5")
  13. minetest.register_alias("commoditymarket:caravan_market_permanent", "commoditymarket_fantasy:caravan_market_permanent")
  14. local S = minetest.get_translator(minetest.get_current_modname())
  15. dofile(modpath.."/mapgen_dungeon_markets.lua")
  16. local coins_per_ingot = math.floor(tonumber(minetest.settings:get("commoditymarket_coins_per_ingot")) or 1000)
  17. -- Only register gold coins once, if required
  18. local gold_coins_registered = false
  19. local register_gold_coins = function()
  20. if not gold_coins_registered then
  21. minetest.register_craftitem("commoditymarket_fantasy:gold_coins", {
  22. description = S("Gold Coins"),
  23. _doc_items_longdesc = S("A gold ingot is far too valuable to use as a basic unit of value, so it has become common practice to divide the standard gold bar into @1 small disks to make trade easier.", coins_per_ingot),
  24. _doc_items_usagehelp = S("Gold coins can be deposited and withdrawn from markets that accept them as currency. These markets can make change if you have @1 coins and would like them back in ingot form again.", coins_per_ingot),
  25. inventory_image = "commoditymarket_gold_coins.png",
  26. stack_max = coins_per_ingot,
  27. })
  28. gold_coins_registered = true
  29. end
  30. end
  31. local default_items = {"default:axe_bronze","default:axe_diamond","default:axe_mese","default:axe_steel","default:axe_steel","default:axe_stone","default:axe_wood","default:pick_bronze","default:pick_diamond","default:pick_mese","default:pick_steel","default:pick_stone","default:pick_wood","default:shovel_bronze","default:shovel_diamond","default:shovel_mese","default:shovel_steel","default:shovel_stone","default:shovel_wood","default:sword_bronze","default:sword_diamond","default:sword_mese","default:sword_steel","default:sword_stone","default:sword_wood", "default:blueberries", "default:book", "default:bronze_ingot", "default:clay_brick", "default:clay_lump", "default:coal_lump", "default:copper_ingot", "default:copper_lump", "default:diamond", "default:flint", "default:gold_ingot", "default:gold_lump", "default:iron_lump", "default:mese_crystal", "default:mese_crystal_fragment", "default:obsidian_shard", "default:paper", "default:steel_ingot", "default:stick", "default:tin_ingot", "default:tin_lump", "default:acacia_tree", "default:acacia_wood", "default:apple", "default:aspen_tree", "default:aspen_wood", "default:blueberry_bush_sapling", "default:bookshelf", "default:brick", "default:bronzeblock", "default:bush_sapling", "default:cactus", "default:clay", "default:coalblock", "default:cobble", "default:copperblock", "default:desert_cobble", "default:desert_sand", "default:desert_sandstone", "default:desert_sandstone_block", "default:desert_sandstone_brick", "default:desert_stone", "default:desert_stone_block", "default:desert_stonebrick", "default:diamondblock", "default:dirt", "default:glass", "default:goldblock", "default:gravel", "default:ice", "default:junglegrass", "default:junglesapling", "default:jungletree", "default:junglewood", "default:ladder_steel", "default:ladder_wood", "default:large_cactus_seedling", "default:mese", "default:mese_post_light", "default:meselamp", "default:mossycobble", "default:obsidian", "default:obsidian_block", "default:obsidian_glass", "default:obsidianbrick", "default:papyrus", "default:pine_sapling", "default:pine_tree", "default:pine_wood", "default:sand", "default:sandstone", "default:sandstone_block", "default:sandstonebrick", "default:sapling", "default:silver_sand", "default:silver_sandstone", "default:silver_sandstone_block", "default:silver_sandstone_brick", "default:snow", "default:snowblock", "default:steelblock", "default:stone", "default:stone_block", "default:stonebrick", "default:tinblock", "default:tree", "default:wood",}
  32. local usage_help = S("Right-click on this to open the market interface.")
  33. ------------------------------------------------------------------------------
  34. -- King's Market
  35. if minetest.settings:get_bool("commoditymarket_enable_kings_market", true) then
  36. local kings_def = {
  37. description = S("King's Market"),
  38. long_description = S("The largest and most accessible market for the common man, the King's Market uses gold coins as its medium of exchange (or the equivalent in gold ingots - @1 coins to the ingot). However, as a respectable institution of the surface world, the King's Market operates only during the hours of daylight. The purchase and sale of swords and explosives is prohibited in the King's Market. Gold coins are represented by a '☼' symbol.", coins_per_ingot),
  39. currency = {
  40. ["default:gold_ingot"] = coins_per_ingot,
  41. ["commoditymarket_fantasy:gold_coins"] = 1
  42. },
  43. currency_symbol = "☼", -- "\u{263C}" Alchemical symbol for gold
  44. allow_item = function(item)
  45. if item:sub(1,13) == "default:sword" or item:sub(1,4) == "tnt:" then
  46. return false
  47. end
  48. return true
  49. end,
  50. inventory_limit = 100000,
  51. --sell_limit =, -- no sell limit for the King's Market
  52. initial_items = default_items,
  53. }
  54. register_gold_coins()
  55. commoditymarket.register_market("kings", kings_def)
  56. local kings_protect = minetest.settings:get_bool("commoditymarket_protect_kings_market", true)
  57. local on_blast
  58. if kings_protect then
  59. on_blast = function() end
  60. end
  61. minetest.register_node("commoditymarket_fantasy:kings_market", {
  62. description = kings_def.description,
  63. _doc_items_longdesc = kings_def.long_description,
  64. _doc_items_usagehelp = usage_help,
  65. tiles = {"default_chest_top.png","default_chest_top.png",
  66. "default_chest_side.png","default_chest_side.png",
  67. "commoditymarket_empty_shelf.png","default_chest_side.png^commoditymarket_crown.png",},
  68. paramtype2 = "facedir",
  69. is_ground_content = false,
  70. groups = {choppy = 2, oddly_breakable_by_hand = 1,},
  71. sounds = default.node_sound_wood_defaults(),
  72. on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
  73. local timeofday = minetest.get_timeofday()
  74. if timeofday > 0.2 and timeofday < 0.8 then
  75. commoditymarket.show_market("kings", clicker:get_player_name())
  76. else
  77. minetest.chat_send_player(clicker:get_player_name(), S("At this time of day the King's Market is closed."))
  78. minetest.sound_play({name = "commoditymarket_error", gain = 0.1}, {to_player=clicker:get_player_name()})
  79. end
  80. end,
  81. can_dig = function(pos, player)
  82. return not kings_protect or minetest.check_player_privs(player, "protection_bypass")
  83. end,
  84. on_blast = on_blast,
  85. })
  86. end
  87. -------------------------------------------------------------------------------
  88. -- Night Market
  89. if minetest.settings:get_bool("commoditymarket_enable_night_market", true) then
  90. local night_def = {
  91. description = S("Night Market"),
  92. long_description = S("When the sun sets and the stalls of the King's Market close, other vendors are just waking up to share their wares. The Night Market is not as voluminous as the King's Market but accepts a wider range of wares. It accepts the same gold coinage of the realm, @1 coins to the gold ingot.", coins_per_ingot),
  93. currency = {
  94. ["default:gold_ingot"] = coins_per_ingot,
  95. ["commoditymarket_fantasy:gold_coins"] = 1
  96. },
  97. currency_symbol = "☼", --"\u{263C}"
  98. inventory_limit = 10000,
  99. --sell_limit =, -- no sell limit for the Night Market
  100. initial_items = default_items,
  101. anonymous = true,
  102. }
  103. register_gold_coins()
  104. commoditymarket.register_market("night", night_def)
  105. local night_protect = minetest.settings:get_bool("commoditymarket_protect_night_market", true)
  106. local on_blast
  107. if night_protect then
  108. on_blast = function() end
  109. end
  110. minetest.register_node("commoditymarket_fantasy:night_market", {
  111. description = night_def.description,
  112. _doc_items_longdesc = night_def.long_description,
  113. _doc_items_usagehelp = usage_help,
  114. tiles = {"default_chest_top.png","default_chest_top.png",
  115. "default_chest_side.png","default_chest_side.png",
  116. "commoditymarket_empty_shelf.png","default_chest_side.png^commoditymarket_moon.png",},
  117. paramtype2 = "facedir",
  118. is_ground_content = false,
  119. groups = {choppy = 2, oddly_breakable_by_hand = 1,},
  120. sounds = default.node_sound_wood_defaults(),
  121. on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
  122. local timeofday = minetest.get_timeofday()
  123. if timeofday < 0.2 or timeofday > 0.8 then
  124. commoditymarket.show_market("night", clicker:get_player_name())
  125. else
  126. minetest.chat_send_player(clicker:get_player_name(), S("At this time of day the Night Market is closed."))
  127. minetest.sound_play({name = "commoditymarket_error", gain = 0.1}, {to_player=clicker:get_player_name()})
  128. end
  129. end,
  130. can_dig = function(pos, player)
  131. return not night_protect or minetest.check_player_privs(player, "protection_bypass")
  132. end,
  133. on_blast = on_blast,
  134. })
  135. end
  136. -------------------------------------------------------------------------------
  137. if minetest.settings:get_bool("commoditymarket_enable_caravan_market", true) then
  138. -- "Trader's Caravan" - small-capacity market that players can summon
  139. local time_until_caravan = 120 -- caravan arrives in two minutes
  140. local dwell_time = 600 -- caravan leaves ten minutes after last usage
  141. local caravan_def = {
  142. description = S("Trader's Caravan"),
  143. long_description = S("Unlike most markets that have well-known fixed locations that travelers congregate to, the network of Trader's Caravans is fluid and dynamic in their locations. A Trader's Caravan can show up anywhere, make modest trades, and then be gone the next time you visit them. These caravans accept gold and gold coins as a currency (one gold ingot to @1 gold coins exchange rate). Any reasonably-wealthy person can create a signpost marking a location where Trader's Caravans will make a stop.", coins_per_ingot),
  144. currency = {
  145. ["default:gold_ingot"] = coins_per_ingot,
  146. ["commoditymarket_fantasy:gold_coins"] = 1
  147. },
  148. currency_symbol = "☼", --"\u{263C}"
  149. inventory_limit = 1000,
  150. sell_limit = 1000,
  151. initial_items = default_items,
  152. }
  153. register_gold_coins()
  154. minetest.register_craft({
  155. output = "commoditymarket_fantasy:caravan_post",
  156. recipe = {
  157. {'group:wood', 'group:wood', ''},
  158. {'group:wood', "default:gold_ingot", ''},
  159. {'group:wood', "default:chest_locked", ''},
  160. }
  161. })
  162. commoditymarket.register_market("caravan", caravan_def)
  163. local create_caravan_def = function(override_table)
  164. local def = {
  165. description = caravan_def.description,
  166. _doc_items_longdesc = caravan_def.long_description,
  167. _doc_items_usagehelp = usage_help,
  168. drawtype = "mesh",
  169. mesh = "commoditymarket_wagon.obj",
  170. tiles = {
  171. { name = "commoditymarket_door_wood.png", backface_culling = true }, -- door
  172. { name = "default_wood.png", backface_culling = true }, -- base wood
  173. { name = "default_fence_rail_wood.png", backface_culling = true }, -- wheel sides
  174. { name = "default_coal_block.png", backface_culling = true }, -- wheel tyre
  175. { name = "commoditymarket_shingles_wood.png", backface_culling = true }, -- roof
  176. { name = "default_junglewood.png", backface_culling = true }, -- corner wood
  177. },
  178. collision_box = {
  179. type = "fixed",
  180. fixed = {
  181. -- Note: this nodebox should have a height of 1.5, but using 95/64 as a workaround for
  182. -- https://github.com/minetest/minetest/issues/9322
  183. {-0.75, -0.5, -1.25, 0.75, 95/64, 1.25},
  184. },
  185. },
  186. selection_box = {
  187. type = "fixed",
  188. fixed = {
  189. {-0.75, -0.5, -1.25, 0.75, 95/64, 1.25},
  190. },
  191. },
  192. paramtype2 = "facedir",
  193. drop = "",
  194. groups = {choppy = 2, oddly_breakable_by_hand = 1, not_in_creative_inventory = 1},
  195. sounds = default.node_sound_wood_defaults(),
  196. on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
  197. commoditymarket.show_market("caravan", clicker:get_player_name())
  198. local timer = minetest.get_node_timer(pos)
  199. timer:start(dwell_time)
  200. end,
  201. after_destruct = function(pos, oldnode)
  202. local facedir = oldnode.param2
  203. local dir = minetest.facedir_to_dir(facedir)
  204. local target = vector.add(pos, vector.multiply(dir,-3))
  205. local target_node = minetest.get_node(target)
  206. if target_node.name == "commoditymarket_fantasy:caravan_post" then
  207. local meta = minetest.get_meta(target)
  208. meta:set_string("infotext", S("Right-click to summon a trader's caravan"))
  209. end
  210. end,
  211. on_timer = function(pos, elapsed)
  212. minetest.set_node(pos, {name="air"})
  213. minetest.sound_play("commoditymarket_register_closed", {
  214. pos = pos,
  215. gain = 1.0, -- default
  216. max_hear_distance = 32, -- default, uses an euclidean metric
  217. })
  218. end,
  219. }
  220. if override_table then
  221. for k, v in pairs(override_table) do
  222. def[k] = v
  223. end
  224. end
  225. return def
  226. end
  227. -- Create five caravans with different textures, randomly pick which one shows up.
  228. minetest.register_node("commoditymarket_fantasy:caravan_market_1", create_caravan_def())
  229. minetest.register_node("commoditymarket_fantasy:caravan_market_2", create_caravan_def({
  230. tiles = {
  231. { name = "commoditymarket_door_wood.png^[multiply:#CCCCFF", backface_culling = true }, -- door
  232. { name = "default_acacia_wood.png", backface_culling = true }, -- base wood
  233. { name = "default_fence_rail_wood.png", backface_culling = true }, -- wheel sides
  234. { name = "default_copper_block.png", backface_culling = true }, -- wheel tyre
  235. { name = "commoditymarket_shingles_wood.png^[multiply:#CC8888", backface_culling = true }, -- roof
  236. { name = "default_wood.png", backface_culling = true }, -- corner wood
  237. }
  238. }))
  239. minetest.register_node("commoditymarket_fantasy:caravan_market_3", create_caravan_def({
  240. tiles = {
  241. { name = "commoditymarket_door_wood.png", backface_culling = true }, -- door
  242. { name = "default_aspen_wood.png", backface_culling = true }, -- base wood
  243. { name = "default_fence_aspen_wood.png", backface_culling = true }, -- wheel sides
  244. { name = "default_cobble.png", backface_culling = true }, -- wheel tyre
  245. { name = "default_stone_brick.png", backface_culling = true }, -- roof
  246. { name = "default_pine_tree.png", backface_culling = true }, -- corner wood
  247. }
  248. }))
  249. minetest.register_node("commoditymarket_fantasy:caravan_market_4", create_caravan_def({
  250. tiles = {
  251. { name = "commoditymarket_door_wood.png", backface_culling = true }, -- door
  252. { name = "default_junglewood.png", backface_culling = true }, -- base wood
  253. { name = "default_fence_rail_junglewood.png", backface_culling = true }, -- wheel sides
  254. { name = "default_obsidian.png", backface_culling = true }, -- wheel tyre
  255. { name = "commoditymarket_shingles_wood.png^[multiply:#88FF88", backface_culling = true }, -- roof
  256. { name = "default_tree.png", backface_culling = true }, -- corner wood
  257. }
  258. }))
  259. minetest.register_node("commoditymarket_fantasy:caravan_market_5", create_caravan_def({
  260. tiles = {
  261. { name = "commoditymarket_door_wood.png", backface_culling = true }, -- door
  262. { name = "default_pine_wood.png", backface_culling = true }, -- base wood
  263. { name = "default_chest_lock.png", backface_culling = true }, -- wheel sides
  264. { name = "default_chest_top.png", backface_culling = true }, -- wheel tyre
  265. { name = "default_furnace_top.png", backface_culling = true }, -- roof
  266. { name = "default_wood.png", backface_culling = true }, -- corner wood
  267. }
  268. }))
  269. local caravan_protect = minetest.settings:get_bool("commoditymarket_protect_caravan_market", true)
  270. local on_blast
  271. if caravan_protect then
  272. on_blast = function() end
  273. end
  274. -- This one doesn't delete itself, server admins can place a permanent instance of it that way. Maybe inside towns next to bigger stationary markets.
  275. minetest.register_node("commoditymarket_fantasy:caravan_market_permanent", {
  276. description = caravan_def.description,
  277. _doc_items_longdesc = caravan_def.long_description,
  278. _doc_items_usagehelp = usage_help,
  279. drawtype = "mesh",
  280. light_source = 10,
  281. mesh = "commoditymarket_wagon.obj",
  282. tiles = {
  283. { name = "commoditymarket_door_wood.png", backface_culling = true }, -- door
  284. { name = "default_wood.png", backface_culling = true }, -- base wood
  285. { name = "default_fence_rail_wood.png", backface_culling = true }, -- wheel sides
  286. { name = "default_coal_block.png", backface_culling = true }, -- wheel tyre
  287. { name = "commoditymarket_shingles_wood.png", backface_culling = true }, -- roof
  288. { name = "default_junglewood.png", backface_culling = true }, -- corner wood
  289. },
  290. collision_box = {
  291. type = "fixed",
  292. fixed = {
  293. -- Note: this nodebox should have a height of 1.5, but using 95/64 as a workaround for
  294. -- https://github.com/minetest/minetest/issues/9322
  295. {-0.75, -0.5, -1.25, 0.75, 95/64, 1.25},
  296. },
  297. },
  298. selection_box = {
  299. type = "fixed",
  300. fixed = {
  301. {-0.75, -0.5, -1.25, 0.75, 95/64, 1.25},
  302. },
  303. },
  304. paramtype2 = "facedir",
  305. is_ground_content = false,
  306. groups = {choppy = 2, oddly_breakable_by_hand = 1,},
  307. sounds = default.node_sound_wood_defaults(),
  308. on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
  309. commoditymarket.show_market("caravan", clicker:get_player_name())
  310. end,
  311. can_dig = function(pos, player)
  312. return not caravan_protect or minetest.check_player_privs(player, "protection_bypass")
  313. end,
  314. on_blast = on_blast,
  315. })
  316. -- is a 5x3 area centered around pos clear of obstruction and has usable ground?
  317. local is_suitable_caravan_space = function(pos, facedir)
  318. local x_dim = 2
  319. local z_dim = 2
  320. local dir = minetest.facedir_to_dir(facedir)
  321. if dir.x ~= 0 then
  322. z_dim = 1
  323. elseif dir.z ~= 0 then
  324. x_dim = 1
  325. end
  326. -- walkable ground?
  327. for x = pos.x - x_dim, pos.x + x_dim, 1 do
  328. for z = pos.z - z_dim, pos.z + z_dim, 1 do
  329. local node = minetest.get_node({x=x, y=pos.y-1, z=z})
  330. local node_def = minetest.registered_nodes[node.name]
  331. if node_def == nil or node_def.walkable ~= true then return false end
  332. end
  333. end
  334. -- buildable_to in the rest?
  335. for y = pos.y, pos.y+2, 1 do
  336. for x = pos.x - x_dim, pos.x + x_dim, 1 do
  337. for z = pos.z - z_dim, pos.z + z_dim, 1 do
  338. local node = minetest.get_node({x=x, y=y, z=z})
  339. local node_def = minetest.registered_nodes[node.name]
  340. if node_def == nil or node_def.buildable_to ~= true then return false end
  341. end
  342. end
  343. end
  344. return true
  345. end
  346. minetest.register_node("commoditymarket_fantasy:caravan_post", {
  347. description = S("Trading Post"),
  348. _long_items_longdesc = S("This post signals passing caravan traders that customers can be found here, and signals to customers that caravan traders can be found here. If no caravan is present, right-click to summon one."),
  349. _doc_items_usagehelp = S("The trader's caravan requires a suitable open space next to the trading post for it to arrive, and takes some time to arrive after being summoned. The post gives a countdown to the caravan's arrival when moused over."),
  350. tiles = {"commoditymarket_sign.png^[transformR90", "commoditymarket_sign.png^[transformR270",
  351. "commoditymarket_sign.png^commoditymarket_caravan_sign.png", "commoditymarket_sign.png^commoditymarket_caravan_sign.png^[transformFX",
  352. "commoditymarket_sign_post.png", "commoditymarket_sign_post.png"},
  353. groups = {choppy = 2, oddly_breakable_by_hand = 1,},
  354. sounds = default.node_sound_wood_defaults(),
  355. inventory_image = "commoditymarket_caravan_sign_inventory.png",
  356. paramtype= "light",
  357. paramtype2 = "facedir",
  358. drawtype = "nodebox",
  359. node_box = {
  360. type = "fixed",
  361. fixed = {
  362. {-0.125,-0.5,-0.5,0.125,2.0625,-0.25},
  363. {-0.0625,1.4375,-0.25,0.0625,2.0,0.5},
  364. },
  365. },
  366. on_construct = function(pos)
  367. local timer = minetest.get_node_timer(pos)
  368. timer:start(1.0)
  369. end,
  370. on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
  371. local timer = minetest.get_node_timer(pos)
  372. timer:start(1.0)
  373. end,
  374. on_timer = function(pos, elapsed)
  375. local node = minetest.get_node(pos)
  376. local meta = minetest.get_meta(pos)
  377. if node.name ~= "commoditymarket_fantasy:caravan_post" then
  378. return -- the node was removed
  379. end
  380. local facedir = node.param2
  381. local dir = minetest.facedir_to_dir(facedir)
  382. local target = vector.add(pos, vector.multiply(dir,3))
  383. local target_node = minetest.get_node(target)
  384. if target_node.name:sub(1,string.len("commoditymarket_fantasy:caravan_market")) == "commoditymarket_fantasy:caravan_market" then
  385. -- It's already here somehow, shut down timer.
  386. meta:set_string("infotext", "")
  387. meta:set_float("wait_time", 0)
  388. return
  389. end
  390. local is_suitable_space = is_suitable_caravan_space(target, facedir)
  391. if not is_suitable_space then
  392. meta:set_string("infotext", S("Indicated parking area isn't suitable.\nA 5x3 open space with solid ground\nis required for a caravan."))
  393. meta:set_float("wait_time", 0)
  394. local timer = minetest.get_node_timer(pos)
  395. timer:start(1.0)
  396. return
  397. end
  398. local wait_time = (meta:get_float("wait_time") or 0) + elapsed
  399. meta:set_float("wait_time", wait_time)
  400. if wait_time < time_until_caravan then
  401. meta:set_string("infotext", S("Caravan summoned\nETA: @1 seconds.", math.floor(time_until_caravan - wait_time)))
  402. local timer = minetest.get_node_timer(pos)
  403. timer:start(1.0)
  404. return
  405. end
  406. -- spawn the caravan. We've already established that the target pos is clear.
  407. minetest.set_node(target, {name="commoditymarket_fantasy:caravan_market_"..math.random(1,5), param2=facedir})
  408. minetest.sound_play("commoditymarket_register_opened", {
  409. pos = target,
  410. gain = 1.0, -- default
  411. max_hear_distance = 32, -- default, uses an euclidean metric
  412. })
  413. local timer = minetest.get_node_timer(target)
  414. timer:start(dwell_time)
  415. meta:set_string("infotext", "")
  416. meta:set_float("wait_time", 0)
  417. end,
  418. })
  419. end
  420. -------------------------------------------------------------------------------
  421. -- "Goblin Exchange"
  422. if minetest.settings:get_bool("commoditymarket_enable_goblin_market", true) then
  423. local goblin_def = {
  424. description = S("Goblin Exchange"),
  425. long_description = S("One does not usually associate Goblins with the sort of sophistication that running a market requires. Usually one just associates Goblins with savagery and violence. But they understand the principle of tit-for-tat exchange, and if approached correctly they actually respect the concepts of ownership and debt. However, for some peculiar reason they understand this concept in the context of coal lumps. Goblins deal in the standard coal lump as their form of currency, conceptually divided into 100 coal centilumps (though Goblin brokers prefer to \"keep the change\" when giving back actual coal lumps)."),
  426. currency = {
  427. ["default:coal_lump"] = 100
  428. },
  429. currency_symbol = "¢", --"\u{00A2}" cent symbol
  430. inventory_limit = 1000,
  431. --sell_limit =, -- no sell limit
  432. }
  433. commoditymarket.register_market("goblin", goblin_def)
  434. local goblin_protect = minetest.settings:get_bool("commoditymarket_protect_goblin_market", true)
  435. local on_blast
  436. if goblin_protect then
  437. on_blast = function() end
  438. end
  439. minetest.register_node("commoditymarket_fantasy:goblin_market", {
  440. description = goblin_def.description,
  441. _doc_items_longdesc = goblin_def.long_description,
  442. _doc_items_usagehelp = usage_help,
  443. tiles = {"default_chest_top.png^(default_coal_block.png^[opacity:128)","default_chest_top.png^(default_coal_block.png^[opacity:128)",
  444. "default_chest_side.png^(default_coal_block.png^[opacity:128)","default_chest_side.png^(default_coal_block.png^[opacity:128)",
  445. "commoditymarket_empty_shelf.png^(default_coal_block.png^[opacity:128)","default_chest_side.png^(default_coal_block.png^[opacity:128)^commoditymarket_goblin.png",},
  446. paramtype2 = "facedir",
  447. is_ground_content = false,
  448. groups = {choppy = 2, oddly_breakable_by_hand = 1,},
  449. sounds = default.node_sound_wood_defaults(),
  450. on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
  451. commoditymarket.show_market("goblin", clicker:get_player_name())
  452. end,
  453. can_dig = function(pos, player)
  454. return not goblin_protect or minetest.check_player_privs(player, "protection_bypass")
  455. end,
  456. on_blast = on_blast,
  457. })
  458. end
  459. --------------------------------------------------------------------------------
  460. if minetest.settings:get_bool("commoditymarket_enable_under_market", true) then
  461. local undermarket_def = {
  462. description = S("Undermarket"),
  463. long_description = S("Deep in the bowels of the world, below even the goblin-infested warrens and ancient delvings of the dwarves, dark and mysterious beings once dwelt. A few still linger to this day, and facilitate barter for those brave souls willing to travel in their lost realms. The Undermarket uses Mese chips ('₥') as a currency - twenty chips to the Mese fragment. Though traders are loathe to physically break Mese crystals up into units that small, as it renders it useless for other purposes."),
  464. currency = {
  465. ["default:mese"] = 9*9*20,
  466. ["default:mese_crystal"] = 9*20,
  467. ["default:mese_crystal_fragment"] = 20
  468. },
  469. currency_symbol = "₥", --"\u{20A5}" mill sign
  470. inventory_limit = 10000,
  471. --sell_limit =, -- no sell limit
  472. }
  473. commoditymarket.register_market("under", undermarket_def)
  474. local under_protect = minetest.settings:get_bool("commoditymarket_protect_under_market", true)
  475. local on_blast
  476. if under_protect then
  477. on_blast = function() end
  478. end
  479. minetest.register_node("commoditymarket_fantasy:under_market", {
  480. description = undermarket_def.description,
  481. _doc_items_longdesc = undermarket_def.long_description,
  482. _doc_items_usagehelp = usage_help,
  483. tiles = {"commoditymarket_under_top.png","commoditymarket_under_top.png",
  484. "commoditymarket_under.png","commoditymarket_under.png","commoditymarket_under.png","commoditymarket_under.png"},
  485. paramtype2 = "facedir",
  486. is_ground_content = false,
  487. groups = {choppy = 2, oddly_breakable_by_hand = 1,},
  488. sounds = default.node_sound_stone_defaults(),
  489. on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
  490. commoditymarket.show_market("under", clicker:get_player_name())
  491. end,
  492. can_dig = function(pos, player)
  493. return not under_protect or minetest.check_player_privs(player, "protection_bypass")
  494. end,
  495. on_blast = on_blast,
  496. })
  497. end
  498. ------------------------------------------------------------------