Harden a number of minetest.after player checks
[MineClone/MineClone2.git] / mods / ITEMS / mcl_jukebox / init.lua
blob2ee8f8c113cfbf073b7d7f57a2910f38a71e517d
1 -- Player name-indexed table containing the currently heard track
2 local active_tracks = {}
4 -- Player name-indexed table containing the current used HUD ID for the “Now playing” message.
5 local active_huds = {}
7 -- Player name-indexed table for the “Now playing” message.
8 -- Used to make sure that minetest.after only applies to the latest HUD change event
9 local hud_sequence_numbers = {}
11 -- List of music
12 local recorddata = {
13 -- { title, author, identifier }
14 { "The Evil Sister (Jordach's Mix)", "SoundHelix", "13" } ,
15 { "The Energetic Rat (Jordach's Mix)", "SoundHelix", "wait" },
16 { "Eastern Feeling", "Jordach", "blocks"},
17 { "Minetest", "Jordach", "far" },
18 { "Credit Roll (Jordach's HD Mix)", "Junichi Masuda", "chirp" },
19 { "Winter Feeling", "Tom Peter", "strad" },
20 { "Synthgroove (Jordach's Mix)", "HeroOfTheWinds", "mellohi" },
21 { "The Clueless Frog (Jordach's Mix)", "SoundHelix", "mall" },
23 local records = #recorddata
25 for r=1, records do
26 local doc = false
27 local entryname, longdesc, usagehelp
28 if r == 1 then
29 doc = true
30 entryname = "Music Disc"
31 longdesc = "A music disc holds a single music track which can be used in a jukebox to play music."
32 usagehelp = "Rightclick an empty jukebox with the music disc in your hand to play the music. Rightclick the jukebox again to retrieve the music disc. The music can only be heard by you, not by other players."
33 end
34 minetest.register_craftitem("mcl_jukebox:record_"..r, {
35 description =
36 core.colorize("#55FFFF", "Music Disc") .. "\n" ..
37 core.colorize("#989898", recorddata[r][2] .. "—" .. recorddata[r][1]),
38 _doc_items_create_entry = doc,
39 _doc_items_entry_name = entryname,
40 _doc_items_longdesc = longdesc,
41 _doc_items_usagehelp = usagehelp,
42 inventory_image = "mcl_jukebox_record_"..recorddata[r][3]..".png",
43 stack_max = 1,
44 groups = { music_record = r },
46 end
48 local function now_playing(player, track_id)
49 local playername = player:get_player_name()
50 local hud = active_huds[playername]
51 local text = "Now playing: " .. recorddata[track_id][2] .. "—" .. recorddata[track_id][1]
53 if not hud_sequence_numbers[playername] then
54 hud_sequence_numbers[playername] = 1
55 else
56 hud_sequence_numbers[playername] = hud_sequence_numbers[playername] + 1
57 end
59 local id
60 if hud ~= nil then
61 id = hud
62 player:hud_change(id, "text", text)
63 else
64 id = player:hud_add({
65 hud_elem_type = "text",
66 position = { x=0.5, y=0.8 },
67 offset = { x=0, y = 0 },
68 size = { x=100, y=100},
69 number = 0x55FFFF,
70 text = text,
72 active_huds[playername] = id
73 end
74 minetest.after(5, function(tab)
75 local playername = tab[1]
76 local player = minetest.get_player_by_name(playername)
77 local id = tab[2]
78 local seq = tab[3]
79 if not player or not player:is_player() or not active_huds[playername] or not hud_sequence_numbers[playername] or seq ~= hud_sequence_numbers[playername] then
80 return
81 end
82 if id == active_huds[playername] then
83 player:hud_remove(active_huds[playername])
84 active_huds[playername] = nil
85 end
86 end, {playername, id, hud_sequence_numbers[playername]})
88 end
90 minetest.register_on_leaveplayer(function(player)
91 active_tracks[player:get_player_name()] = nil
92 active_huds[player:get_player_name()] = nil
93 hud_sequence_numbers[player:get_player_name()] = nil
94 end)
96 -- Jukebox crafting
97 minetest.register_craft({
98 output = 'mcl_jukebox:jukebox',
99 recipe = {
100 {'group:wood', 'group:wood', 'group:wood'},
101 {'group:wood', 'mcl_core:diamond', 'group:wood'},
102 {'group:wood', 'group:wood', 'group:wood'},
106 local play_record = function(pos, itemstack, player)
107 local record_id = minetest.get_item_group(itemstack:get_name(), "music_record")
108 if record_id ~= 0 then
109 local cname = player:get_player_name()
110 if active_tracks[cname] ~= nil then
111 minetest.sound_stop(active_tracks[cname])
112 active_tracks[cname] = nil
114 active_tracks[cname] = minetest.sound_play("mcl_jukebox_track_"..record_id, {
115 to_player = cname,
116 gain = 1,
118 now_playing(player, record_id)
119 return true
121 return false
124 -- Jukebox
125 minetest.register_node("mcl_jukebox:jukebox", {
126 description = "Jukebox",
127 _doc_items_longdesc = "Jukeboxes play music when they're supplied with a music disc.",
128 _doc_items_usagehelp = "Place a music disc into an empty jukebox to insert the music disc and play music. If the jukebox already has a music disc, you will retrieve this music disc first. The music can only be heard by you, not by other players.",
129 tiles = {"mcl_jukebox_top.png", "mcl_jukebox_side.png", "mcl_jukebox_side.png"},
130 sounds = mcl_sounds.node_sound_wood_defaults(),
131 groups = {handy=1,axey=1, container=7, deco_block=1, material_wood=1},
132 is_ground_content = false,
133 on_construct = function(pos)
134 local meta = minetest.get_meta(pos)
135 local inv = meta:get_inventory()
136 inv:set_size("main", 1)
137 end,
138 on_rightclick= function(pos, node, clicker, itemstack, pointed_thing)
139 if not clicker then return end
140 local cname = clicker:get_player_name()
142 local meta = minetest.get_meta(pos)
143 local inv = meta:get_inventory()
144 if not inv:is_empty("main") then
145 -- Jukebox contains a disc: Stop music and remove disc
146 if active_tracks[cname] ~= nil then
147 minetest.sound_stop(active_tracks[cname])
149 local lx = pos.x
150 local ly = pos.y+1
151 local lz = pos.z
152 local record = inv:get_stack("main", 1)
153 local dropped_item = minetest.add_item({x=lx, y=ly, z=lz}, record)
154 -- Rotate record to match with “slot” texture
155 dropped_item:set_yaw(math.pi/2)
156 inv:set_stack("main", 1, "")
157 if active_tracks[cname] ~= nil then
158 minetest.sound_stop(active_tracks[cname])
159 clicker:hud_remove(active_huds[cname])
160 active_tracks[cname] = nil
161 active_huds[cname] = nil
163 else
164 -- Jukebox is empty: Play track if player holds music record
165 local playing = play_record(pos, itemstack, clicker)
166 if playing then
167 local put_itemstack = ItemStack(itemstack)
168 put_itemstack:set_count(1)
169 inv:set_stack("main", 1, put_itemstack)
170 itemstack:take_item()
173 return itemstack
174 end,
175 after_dig_node = function(pos, oldnode, oldmetadata, digger)
176 local name = digger:get_player_name()
177 local meta = minetest.get_meta(pos)
178 local meta2 = meta
179 meta:from_table(oldmetadata)
180 local inv = meta:get_inventory()
181 local stack = inv:get_stack("main", 1)
182 if not stack:is_empty() then
183 local p = {x=pos.x+math.random(0, 10)/10-0.5, y=pos.y, z=pos.z+math.random(0, 10)/10-0.5}
184 local dropped_item = minetest.add_item(p, stack)
185 -- Rotate record to match with “slot” texture
186 dropped_item:set_yaw(math.pi/2)
187 if active_tracks[name] ~= nil then
188 minetest.sound_stop(active_tracks[name])
189 digger:hud_remove(active_huds[name])
190 active_tracks[name] = nil
191 active_huds[name] = nil
194 meta:from_table(meta2:to_table())
195 end,
196 _mcl_blast_resistance = 30,
197 _mcl_hardness = 2,
200 minetest.register_craft({
201 type = "fuel",
202 recipe = "mcl_jukebox:jukebox",
203 burntime = 15,