File: skyblock.feats.lua

package info (click to toggle)
minetest-mod-skyblock 0.2.4-1.1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, sid
  • size: 384 kB
  • sloc: makefile: 14
file content (459 lines) | stat: -rw-r--r-- 15,366 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
--[[

Skyblock for Minetest

Copyright (c) 2015 cornernote, Brett O'Donnell <cornernote@gmail.com>
Source Code: https://github.com/cornernote/minetest-skyblock
License: GPLv3

]]--

-- expose api
skyblock.feats = {}

-- file to save players feat
local filepath = minetest.get_worldpath()..'/feats'


-- local variable to save players feats
local players_feat = {}

-- get players current level
function skyblock.feats.get_level(player_name)
	return skyblock.feats.get(0, player_name, 'level')
end

-- set players current level
function skyblock.feats.set_level(player_name, level)
	if skyblock.levels[level] then
		skyblock.feats.set(0, player_name, 'level', level)
		players_feat[player_name][level] = {}
		skyblock.levels[level].init(player_name)
		skyblock.feats.update(player_name)
		return true
	end
end

-- reset feats
function skyblock.feats.reset(player_name)
	skyblock.log('skyblock.feats.reset('..player_name..')')
	players_feat[player_name] = {}
	skyblock.feats.save(players_feat[player_name], player_name)
	skyblock.feats.update(player_name)
	skyblock.levels[1].init(player_name)
end

-- reset level
function skyblock.feats.reset_level(player_name)
	skyblock.log('skyblock.feats.reset_level('..player_name..')')
	local level = skyblock.feats.get_level(player_name)
	players_feat[player_name][level] = {}
	skyblock.feats.save(players_feat[player_name], player_name)
	skyblock.feats.update(player_name)
	skyblock.levels[level].init(player_name)
end

-- update feats
function skyblock.feats.update(player_name)
	skyblock.log('skyblock.feats.update('..player_name..')')
	local level = skyblock.feats.get_level(player_name)
	local pos = skyblock.get_spawn(player_name)
	if not pos or not skyblock.levels[level] then return end
	local info = skyblock.levels[level].get_info(player_name)

	-- next level
	if info.count==info.total then
		--minetest.chat_send_player(player_name, 'You completed level '..level)
		minetest.chat_send_all(player_name..' completed level '..level)
		for _, ref in pairs(minetest.get_connected_players()) do
			if not (ref:get_player_name() == player_name) then
				minetest.sound_play("skyblock_finish_other", {
					to_player = ref:get_player_name(),
					gain = 1.0,
				})
			else
				minetest.sound_play("skyblock_finish_level_player", {
					to_player = player_name,
					gain = 1.0,
				})
			end
		end
		minetest.log('action', player_name..' completed level '..level)
		
		skyblock.feats.add(0,info.player_name,'level')
		skyblock.levels[level+1].init(info.player_name)
		info = skyblock.levels[level+1].get_info(info.player_name)
	end
	
	-- update formspecs
	local player = minetest.get_player_by_name(player_name)
	if player then
		player:set_inventory_formspec(info.formspec)
	end
	local meta = minetest.env:get_meta(pos)
	meta:set_string('formspec', info.formspec_quest)
	meta:set_string('infotext', info.infotext)
end

-- get feat
function skyblock.feats.get(level,player_name,feat)
	--skyblock.log('skyblock.feats.get('..level..','..player_name..','..feat..')')
	if players_feat[player_name] == nil then
		players_feat[player_name] = skyblock.feats.load(player_name) or {}
	end
	if players_feat[player_name][level] == nil then
		players_feat[player_name][level] = {}
	end
	if players_feat[player_name][level][feat] == nil then
		players_feat[player_name][level][feat] = 0
		if feat=='level' then
			players_feat[player_name][level][feat] = 1
		end
	end
	return players_feat[player_name][level][feat]
end

-- add feat
function skyblock.feats.add(level,player_name,feat)
	skyblock.log('skyblock.feats.add('..level..','..player_name..','..feat..')')
	local player_feat = skyblock.feats.get(level,player_name,feat)
	players_feat[player_name][level][feat] = player_feat + 1
	if level~=0 or feat~='level' then
		local rewarded = skyblock.levels[level].reward_feat(player_name,feat)
		if rewarded then
			minetest.chat_send_all(player_name..' completed the quest "'..feat..'" on level '..level)
			minetest.sound_play("skyblock_finish_quest", {
				to_player = player_name,
				gain = 1.0,
			})
			minetest.log('action', player_name..' completed the quest "'..feat..'" on level '..level)
		end
	end
	skyblock.feats.save(players_feat[player_name], player_name)
	skyblock.feats.update(player_name)
end

-- set feat
function skyblock.feats.set(level,player_name,feat,value)
	skyblock.log('skyblock.feats.set('..level..','..player_name..','..feat..')')
	players_feat[player_name][level][feat] = value
	if level~=0 or feat~='level' then
		local rewarded = skyblock.levels[level].reward_feat(player_name,feat)
		if rewarded then
			minetest.chat_send_all(player_name..' completed the quest "'..feat..'" on level '..level)
			minetest.sound_play("skyblock_finish_quest", {
				to_player = player_name,
				gain = 1.0,
			})
			minetest.log('action', player_name..' completed the quest "'..feat..'" on level '..level)
		end
	end
	skyblock.feats.save(players_feat[player_name], player_name)
	skyblock.feats.update(player_name)
end

-- give reward
function skyblock.feats.give_reward(level,player_name,item_name)
	skyblock.log('skyblock.feats.give_reward('..level..','..player_name..','..item_name..')')
	local player = minetest.get_player_by_name(player_name)
	player:get_inventory():add_item('rewards', item_name)
	--player:set_inventory_formspec(skyblock.levels.get_formspec(player_name))
end

-- track eating
function skyblock.feats.on_item_eat(hp_change, replace_with_item, itemstack, user, pointed_thing)
	if not user then return end
	local player_name = user:get_player_name()
	local level = skyblock.feats.get_level(player_name)
	if skyblock.levels[level].on_item_eat then
		skyblock.levels[level].on_item_eat(player_name, itemstack)
	end
end
minetest.register_on_item_eat(skyblock.feats.on_item_eat)

-- track crafting
function skyblock.feats.on_craft(itemstack, player, old_craft_grid, craft_inv)
	local player_name = player:get_player_name()
	local level = skyblock.feats.get_level(player_name)
	if skyblock.levels[level].on_craft then
		skyblock.levels[level].on_craft(player_name, itemstack)
	end
end
minetest.register_on_craft(skyblock.feats.on_craft)

-- track node digging
function skyblock.feats.on_dignode(pos, oldnode, digger)
	if not digger then return end -- needed to prevent server crash when falling.lua runs callback (L:97)
	local player_name = digger:get_player_name()
	local level = skyblock.feats.get_level(player_name)
	if skyblock.levels[level].on_dignode then
		skyblock.levels[level].on_dignode(pos, oldnode, digger)
	end
end
minetest.register_on_dignode(skyblock.feats.on_dignode)

-- track node placing
function skyblock.feats.on_placenode(pos, newnode, placer, oldnode)
	--if not placer then return end -- needed to prevent server crash when player leaves
	local player_name = placer:get_player_name()
	local level = skyblock.feats.get_level(player_name)
	if skyblock.levels[level].on_placenode then
		skyblock.levels[level].on_placenode(pos, newnode, placer, oldnode)
	end
end
minetest.register_on_placenode(skyblock.feats.on_placenode)

-- track on_place of items with their own on_place
local function on_place(v, is_craftitem)
	local entity = minetest.registered_items[v]
	if entity and entity.on_place then
		local old_on_place = entity.on_place;
		function entity.on_place(itemstack, placer, pointed_thing)
			local old_count = itemstack:get_count()
			local res = old_on_place(itemstack, placer, pointed_thing)
			if itemstack and itemstack:get_count() == old_count-1 then
				skyblock.feats.on_placenode(pointed_thing, {name=v,param2=0}, placer, nil)
			end
			return res;
		end
		if( is_craftitem == 1 ) then
			minetest.register_craftitem(':'..v, entity)
		else
			minetest.register_node(':'..v, entity)
		end
	end
end
for _,v in ipairs({'doors:door_wood','doors:door_glass','doors:door_steel','doors:door_obsidian_glass'}) do
	on_place(v,1);
end
for _,v in ipairs({
		'default:cactus', 
		'farming:seed_wheat', 
		'farming:seed_cotton', 
		'default:sign_wall',
		'default:sign_wall_wood', 
		'default:apple'}) do
	on_place(v,0);
end

-- track bucket feats
function skyblock.feats.bucket_on_use(itemstack, user, pointed_thing)
	--if not user then return end -- needed to prevent server crash when player leaves
	local player_name = user:get_player_name()
	local level = skyblock.feats.get_level(player_name)
	if skyblock.levels[level].bucket_on_use then
		skyblock.levels[level].bucket_on_use(player_name, pointed_thing)
	end
end

-- track bucket_water feats
function skyblock.feats.bucket_water_on_use(itemstack, user, pointed_thing)
	--if not user then return end -- needed to prevent server crash when player leaves
	local player_name = user:get_player_name()
	local level = skyblock.feats.get_level(player_name)
	if skyblock.levels[level].bucket_water_on_use then
		skyblock.levels[level].bucket_water_on_use(player_name, pointed_thing)
	end
end

-- track bucket_lava feats
function skyblock.feats.bucket_lava_on_use(itemstack, user, pointed_thing)
	--if not user then return end -- needed to prevent server crash when player leaves
	local player_name = user:get_player_name()
	local level = skyblock.feats.get_level(player_name)
	if skyblock.levels[level].bucket_lava_on_use then
		skyblock.levels[level].bucket_lava_on_use(player_name, pointed_thing)
	end
end

-- bucket_empty
local function bucket_on_use(itemstack, user, pointed_thing)
	-- Must be pointing to node
	if pointed_thing.type ~= 'node' then
		return
	end
	-- Check if protected
	if minetest.is_protected(pointed_thing.under, user:get_player_name()) then
		return
	end
	-- Get the Node and Registered Item
	local n = minetest.get_node_or_nil(pointed_thing.under)
 	local ndef
 	if n then
 		ndef = minetest.registered_items[n.name]
 	end
 	-- Call on_rightclick if the pointed node defines it
 	if ndef and ndef.on_rightclick and user and not user:get_player_control().sneak then
 		return ndef.on_rightclick(pointed_thing.under, n, user, itemstack) or itemstack
 	end
 	-- Check if pointing to a liquid source
	local liquid = bucket.liquids[n.name]
	if liquid ~= nil and liquid.source == n.name and liquid.itemname ~= nil then
		
		-- begin track bucket feats
		skyblock.feats.bucket_on_use(itemstack, user, pointed_thing)
		-- end track bucket feats
	
		minetest.env:add_node(pointed_thing.under, {name='air'})
		return {name=liquid.itemname}
	end
end
minetest.override_item('bucket:bucket_empty', {
	on_place = bucket_on_use,
	on_use = bucket_on_use,
})

-- bucket_water
local function bucket_water_on_use(itemstack, user, pointed_thing)
	-- Must be pointing to node
	if pointed_thing.type ~= 'node' then
		return
	end
	-- Check if protected
	if minetest.is_protected(pointed_thing.under, user:get_player_name()) then
		return
	end
	-- Get the Node and Registered Item
	local n = minetest.get_node_or_nil(pointed_thing.under)
	local ndef
	if n then
		ndef = minetest.registered_items[n.name]
	end
	-- Call on_rightclick if the pointed node defines it
	if ndef and ndef.on_rightclick and user and not user:get_player_control().sneak then
		return ndef.on_rightclick(pointed_thing.under, n, user, itemstack) or itemstack
	end
 	-- Check if pointing to a liquid
	if bucket.liquids[n.name] == nil then
		-- Not a liquid

		-- begin anti-grief change
		local player_name = user:get_player_name()
		local spawn = skyblock.get_spawn(player_name)
		local range = tonumber(minetest.setting_get("bucket_use_range")) or false -- how far from spawn you can use water
		local pos = pointed_thing.under
		if range and (spawn==nil
			or (pos.x-spawn.x > range or pos.x-spawn.x < range*-1) 
			or (pos.y-spawn.y > range/2 or pos.y-spawn.y < range*-1/2) 
			or (pos.z-spawn.z > range or pos.z-spawn.z < range*-1)) then
			minetest.chat_send_player(player_name, 'Cannot use bucket so far from your home.')
			return
		end
		-- end anti-grief change

		minetest.env:add_node(pointed_thing.above, {name='default:water_source'})
	elseif n.name ~= 'default:water_source' then
		-- It's a liquid
		minetest.env:add_node(pointed_thing.under, {name='default:water_source'})
	end

	-- begin track bucket feats
	skyblock.feats.bucket_water_on_use(itemstack, user, pointed_thing)
	-- end track bucket feats

	return {name='bucket:bucket_empty'}
end
minetest.override_item('bucket:bucket_water', {
	on_place = bucket_water_on_use,
	on_use = bucket_water_on_use,
})

-- bucket_lava
local function bucket_lava_on_use(itemstack, user, pointed_thing)
	-- Must be pointing to node
	if pointed_thing.type ~= 'node' then
		return
	end
	-- Check if protected
	if minetest.is_protected(pointed_thing.under, user:get_player_name()) then
		return
	end
	-- Get the Node and Registered Item
	local n = minetest.get_node_or_nil(pointed_thing.under)
	local ndef
	if n then
		ndef = minetest.registered_items[n.name]
	end
	-- Call on_rightclick if the pointed node defines it
	if ndef and ndef.on_rightclick and user and not user:get_player_control().sneak then
		return ndef.on_rightclick(pointed_thing.under, n, user, itemstack) or itemstack
	end
	-- Check if pointing to a liquid
	if bucket.liquids[n.name] == nil then
		-- Not a liquid

		-- begin anti-grief change
		local player_name = user:get_player_name()
		local spawn = skyblock.get_spawn(player_name)
		local range = tonumber(minetest.setting_get("bucket_use_range")) or false -- how far from spawn you can use lava
		local pos = pointed_thing.under
		if range and (spawn==nil
			or (pos.x-spawn.x > range or pos.x-spawn.x < range*-1)
			or (pos.z-spawn.z > range or pos.z-spawn.z < range*-1)) then
			--if (pos.y-spawn.y > range/2 or pos.y-spawn.y < range*-1/2) then
				minetest.chat_send_player(player_name, 'Cannot use bucket so far from your home.')
				return
			--end
		end
		-- end anti-grief change

		minetest.env:add_node(pointed_thing.above, {name='default:lava_source'})
	elseif n.name ~= 'default:lava_source' then
		-- It's a liquid
		minetest.env:add_node(pointed_thing.under, {name='default:lava_source'})
	end

	-- begin track bucket feats
	skyblock.feats.bucket_lava_on_use(itemstack, user, pointed_thing)
	-- end track bucket feats

	return {name='bucket:bucket_empty'}
end
minetest.override_item('bucket:bucket_lava', {
	on_place = bucket_lava_on_use,
	on_use = bucket_lava_on_use,
})

-- add protection to hoes
for _, material in pairs({"wood", "stone", "steel", "bronze", "mese", "diamond"}) do
	local old_use = minetest.registered_items["farming:hoe_" .. material].on_use
	minetest.override_item("farming:hoe_" .. material, {
		on_use = function(itemstack, user, pointed_thing)
			if not minetest.is_protected(pointed_thing.above, user:get_player_name()) then
				old_use(itemstack, user, pointed_thing)
			end
		end
	})
end

-- make directory
local function mkdir(path)
	if minetest.mkdir then
		minetest.mkdir(path)
	else
		os.execute('mkdir "' .. path .. '"')
	end
end

-- save data
function skyblock.feats.save(data,player_name)
	local file = io.open(filepath..'/'..player_name, 'wb')
	if not file then
		mkdir(filepath)
		file = io.open(filepath..'/'..player_name, 'wb')
		if not file then 
			skyblock.log('cannot open feat file for writing "'..filepath..'/'..player_name..'"')
		end
	end
	file:write(minetest.serialize(data))
	file:close()
end

-- load data
function skyblock.feats.load(player_name)
	local file,err = io.open(filepath..'/'..player_name, 'rb')
	if err then return nil end
	local data = file:read('*a')
	file:close()
	return minetest.deserialize(data)
end