sorcery  Artifact [7838002de4]

Artifact 7838002de4e8ed2f81b4250c7854c2450c3d485bb5a37559e1b64a381dc831a7:


local constants = {
	keg_volume = sorcery.liquid.constants.glasses_per_bottle * 600
}

local hitbox = {
	type = 'fixed';
	fixed = {
		-0.4, -0.5, -0.5;
		 0.4,  0.2,  0.5;
	};
}
local kegcaption = function(m)
	local liqid = m:get_string('liquid')
	if liqid ~= '' then
		local liq = sorcery.register.liquid.db[liqid]
		if not liq then log.err('missing entry for liquid',liqid) return end
		return {
			title = string.format('%s Keg', sorcery.lib.str.capitalize(liq.name));
			color = sorcery.lib.color(liq.color);
			desc = string.format('%s of %s', liq.measure(m:get_int('charge')), liq.name);
		};
	else return { title = 'Empty Keg', props = {} } end
end
local log = sorcery.logger('keg')
minetest.register_node('sorcery:keg', {
	description = 'Keg';
	drawtype = 'mesh';
	mesh = 'sorcery-keg.obj';
	sunlight_propagates = true;
	paramtype = 'light';
	paramtype2 = 'facedir';
	groups = { choppy = 2; sorcery_container = 2 }; -- 2=liquid
	tiles = {
		'default_bronze_block.png';
		'default_wood.png';
		'default_steel_block.png';
	};
	selection_box = hitbox;
	collision_box = hitbox;
	drop = {
		-- preserve_metadata will not work without this!
		max_items = 1;
		items = {
			{ items = { 'sorcery:keg' } };
		};
	};
	preserve_metadata = function(pos,node,meta,drops)
		if meta.liquid and meta.liquid ~= '' then
			local m = drops[1]:get_meta()
			m:from_table({fields = meta})
			local cap = kegcaption(m)
			m:set_string('description', sorcery.lib.ui.tooltip(cap))
			m:set_string('short_description', cap.title)
		end
	end;
	after_place_node = function(pos, placer, stack, tgt)
		local meta = minetest.get_meta(pos)
		local stackmeta = stack:get_meta()
		meta:from_table(stackmeta:to_table())
		if not meta:contains('infotext') then
			meta:set_string('infotext', 'Empty Keg')
		end
	end;
	on_rightclick = function(pos, node, user, stack)
		local m = minetest.get_meta(pos)
		local update = function()
			local c = kegcaption(m)
			local str = c.title
			if c.desc then str = str .. '\n(' .. c.desc .. ')' end
			if c.props then for _,p in pairs(c.props) do -- future-proofing
				str = str .. string.format('\n(%s: %s)', p.title, p.desc)
			end end
			m:set_string('infotext', str)
		end

		if stack:is_empty() then return end

		local ctr = sorcery.itemclass.get(stack, 'container')
		if (not ctr) or not ctr.hold == 'liquid' then return end

		local liqid = m:get_string('liquid')
		if ctr.has and -- add liquid to keg
			(liqid == ctr.has or not m:contains('liquid')) then
			if not ctr.empty then log.err(stack:get_name(), 'does not specify its empty counterpart container') return end

			local add = ctr.charge * stack:get_count()
			local chg = m:get_int('charge')
			if chg + add > constants.keg_volume then
				log.act(string.format('%s tried to overfill a %s keg at %s',
					user:get_player_name(),
					ctr.has, minetest.pos_to_string(pos)))
				return
			end
			m:set_int('charge', chg + add)
			m:set_string('liquid', ctr.has)
			sorcery.liquid.sound_pour(add,chg,pos)

			local liq = sorcery.register.liquid.db[ctr.has]
			if liq then
				update()
				log.act(string.format('%s added %u units of %s to a keg at %s',
					user:get_player_name(), add,
					ctr.has, minetest.pos_to_string(pos)))
			else log.err('no liquid entry for',ctr.has) end

			return ItemStack {
				name = ctr.empty;
				count = stack:get_count();
			}
		elseif not ctr.has and liqid ~= '' then -- take liquid
			local liq = sorcery.register.liquid.db[m:get_string('liquid')]
			if not liq then log.err('missing definition for liquid', liqid) return end

			local basin = m:get_int('charge')
			local filled, amtleft = sorcery.liquid.fill_from_basin(stack, liqid, basin)
			if filled then
				local chg = basin - amtleft
				log.act(string.format('%s removed %u units of %s from a keg at %s',
					user:get_player_name(), chg, liqid,
					minetest.pos_to_string(pos)))
				if amtleft == 0 then
					m:set_string('liquid','')
					m:set_int('charge',0)
				else m:set_int('charge', amtleft) end
				sorcery.liquid.sound_dip(chg,avail,pos)
				update()

				-- fancy visuals
				local color = sorcery.lib.color(liq.color or {255,255,255})
				local spritz = sorcery.lib.image('sorcery_droplet.png')
				local drop = sorcery.lib.image('sorcery_drop.png')
				spritz = spritz:blit(spritz:multiply(color))
				drop   = drop:blit  (drop:multiply  (color))
				local facing = minetest.facedir_to_dir(minetest.get_node(pos).param2)
				local noz = vector.add(pos, vector.rotate(
					vector.new(0.0,0,-0.48),
					vector.dir_to_rotation(facing)
				))
				local minnoz = vector.offset(noz, -0.03, -0.32, -0.03);
				local maxnoz = vector.offset(noz,  0.03, -0.32,  0.03);
				minetest.add_particlespawner {
					amount = 15 * chg, time = 0.1*chg;
					texture = spritz:render();
					minpos = minnoz, maxpos = maxnoz;
					minvel = vector.new(0,0,0);
					maxvel = vector.new(0,-0.1,0);
					minacc = vector.new(0,-0.1,0);
					maxacc = vector.new(0,-0.13,0);
					minsize = 0.4, maxsize = 1;
					glow = 14; -- FIXME liquid glow prop
					minexptime = 0.5, maxexptime = 0.5;
					animation = {
						type = 'sheet_2d';
						frames_w = 14;
						frames_h = 1;
						frame_length = 0.5/14;
					}
				}
				minetest.after(0.2, function()
					minetest.add_particlespawner {
						amount = math.random(5,11) * chg, time = 0.13 * chg;
						texture = drop:render();
						minpos = vector.offset(minnoz, 0,-0.05,0);
						maxpos = vector.offset(maxnoz, 0,-0.05,0);
						minvel = vector.new(0,-0.1,0);
						maxvel = vector.new(0,-0.4,0);
						minacc = vector.new(0,-0.15,0);
						maxacc = vector.new(0,-0.18,0);
						minsize = 0.3, maxsize = 0.5;
						glow = 14; -- FIXME liquid glow prop
						minexptime = 1, maxexptime = 1.5;
						animation = {
							type = 'sheet_2d';
							frames_w = 10;
							frames_h = 1;
							frame_length = 1.5/10;
						}
					}
				end)

				return filled
			end
		end
	end;
})

minetest.register_craft {
	output = "sorcery:keg";
	recipe = {
		{'','screwdriver:screwdriver',''};
		{'sorcery:screw_bronze', 'sorcery:tap', 'sorcery:screw_bronze'};
		{'', 'xdecor:barrel', ''};
	};
	replacements = {
		{'screwdriver:screwdriver', 'screwdriver:screwdriver'};
	};
}