summaryrefslogtreecommitdiff
path: root/mods/vzxv_itemstacks/container.lua
blob: a8fb4d9918c224bffd6b60e41d3b29397cfeadcf (plain)
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

local container_entities = {}

local function update_container_entity(entity, stack)
	entity:set_properties {
		physical = false,
		pointable = false,
		collide_with_objects = false,
		visual = "wielditem",
		visual_size = {x = 0.4, y = 0.4},
		wield_item = stack:get_name(),
		static_save = false,
	}
end

minetest.register_entity("vzxv_itemstacks:itemstack",{
	initial_properties = {
		physical = false,
		pointable = false,
		static_save = false,
	},
	on_activate = function(self)
		local ent = self.object
		local pos = vzxv.round_pos(ent:get_pos())
		container_entities[minetest.hash_node_position(pos)] = ent
	end,
	on_step = function(self,dt)
		local ent = self.object
		local pos = vzxv.round_pos(ent:get_pos())
		pos.y = pos.y - 1
		if minetest.get_node(pos).name == "air" then
			pos.y = pos.y + 1
			vzxv.drop_loose(pos,vzxv.get_container_stack(pos))
			minetest.set_node(pos,{name="air"})
		end
	end,
	on_deactivate = function(self)
		local ent = self.object
		local pos = vzxv.round_pos(ent:get_pos())
		container_entities[minetest.hash_node_position(pos)] = nil
	end,
})

local function get_container_entity(pos)
	return container_entities[minetest.hash_node_position(pos)]
end

local function add_container_entity(pos)
	pos = {x = pos.x, y = pos.y - 0.20, z = pos.z}
	minetest.add_entity(pos, "vzxv_itemstacks:itemstack")
end

local function remove_container_entity(pos)
	local h = minetest.hash_node_position(pos)
	if container_entities[h] then
		container_entities[h]:remove()
	end
	container_entities[h] = nil
end

function vzxv.is_container(pos)
	local item = minetest.get_node(pos).name
	return minetest.get_item_group(item, "container")
end

function vzxv.get_container_stack(pos)
	local meta = minetest.get_meta(pos)
	local stack = meta:get_string("stack")
	return ItemStack(stack)
end

function vzxv.set_container_stack(pos, stack)
	pos = vzxv.round_pos(pos)

	local entity = get_container_entity(pos)
	if stack and not entity then
		add_container_entity(pos)
		entity = get_container_entity(pos)
	elseif not stack and entity then
		remove_container_entity(pos)
	end

	local meta = minetest.get_meta(pos)
	meta:set_string("stack",stack:to_string())

	if entity then
		update_container_entity(entity, stack)
	end
end

minetest.register_lbm {
	name = "vzxv_itemstacks:load_itemstacks",
	nodenames = {"group:container"},
	run_at_every_load = true,
	action = function(pos)
		local stack = vzxv.get_container_stack(pos)
		local entity = get_container_entity(pos)
		if stack and not stack:is_empty() then
			if not entity then
				add_container_entity(pos)
				entity = get_container_entity(pos)
			end
			update_container_entity(entity, stack)
		end
	end,
}

-- containers must call this when removed
function vzxv.container_destruct(pos)
	remove_container_entity(pos)
end

function vzxv.add_container_items(pos, stack)
	local contents = vzxv.get_container_stack(pos)
	local free_space = contents:get_free_space()
	local amount = math.min(free_space, stack:get_count())
	contents:set_count(contents:get_count() + amount)
	vzxv.set_container_stack(pos, contents)

	stack:set_count(stack:get_count() - amount)
	return stack
end

function vzxv.take_container_items(pos, n)
	local contents = vzxv.get_container_stack(pos)
	local removed = contents:take_item(n)
	vzxv.set_container_stack(pos, contents)
	return removed
end

function vzxv.player_take_container_items(pos, _, player)
	local items = vzxv.take_container_items(pos, 99)
	local leftover = vzxv.collect_items(player, items)
	vzxv.add_container_items(pos, leftover)

	return true
end

function vzxv.player_add_container_items(pos, _, player, stack)
	local items = vzxv.remove_items(player, stack)
	local leftover = vzxv.add_container_items(pos, items)
	vzxv.give_items(player, leftover)

	return leftover
end