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
|
ch_core.open_submod("kos", {lib = true})
local player_name_to_trash_inv = {}
local trash_inv_width, trash_inv_height = 4, 2
local function return_zero()
return 0
end
local function on_take(inv, listname, index, stack, player)
local s = stack:to_string()
s = s:sub(1, 1024)
minetest.log("action", player:get_player_name().." retreived from the trash bin: "..s)
end
local inv_callbacks = {
allow_move = return_zero,
allow_put = return_zero,
-- allow_take = yes,
on_take = on_take,
}
local function on_joinplayer(player, _last_login)
local player_name = player:get_player_name()
local trash_inv = minetest.create_detached_inventory("ch_core_trash_"..player_name, inv_callbacks, player_name)
trash_inv:set_size("main", trash_inv_width * trash_inv_height)
player_name_to_trash_inv[player_name] = trash_inv
end
local function on_leaveplayer(player, _timeouted)
local player_name = player:get_player_name()
minetest.remove_detached_inventory("ch_core_trash_"..player_name)
player_name_to_trash_inv[player_name] = nil
end
minetest.register_on_joinplayer(on_joinplayer)
minetest.register_on_leaveplayer(on_leaveplayer)
--[[
Vrací nil, pokud pro danou postavu inventář koše neexistuje.
Jinak vrací:
{
inventory = InvRef,
location = string,
listname = string,
width = int,
height = int,
}
]]
function ch_core.get_trash_inventory(player_name)
local result = {
inventory = player_name_to_trash_inv[player_name],
location = "detached:ch_core_trash_"..player_name,
listname = "main",
width = trash_inv_width,
height = trash_inv_height,
}
if result.inventory ~= nil then
return result
end
end
--[[
Smaže obsah zadaného inventáře a zaznamená to jako příkaz daného
hráče/ky.
player_name -- přihlašovací jméno hráče/ky nebo nil
inv -- odkaz na inventář
listname -- listname ke smazání
description -- heslovitý popis kontextu mazání
]]
function ch_core.vyhodit_inventar(player_name, inv, listname, description)
if not player_name then
player_name = "???"
end
if not description then
description = "???"
end
local t = inv:get_list(listname)
if t == nil then
return false
end
local craftitems, tools, item_strings = {}, {}, {}
for _, stack in ipairs(t) do
if not stack:is_empty() then
if stack:get_stack_max() <= 1 then
table.insert(tools, stack)
else
table.insert(craftitems, stack)
end
table.insert(item_strings, stack:to_string():sub(1, 1024))
end
end
if #item_strings > 0 then
minetest.log("action", "Player "..player_name.." trashed "..#item_strings.." items ("..description.."): "..table.concat(item_strings, ", "))
local empty_list = {}
inv:set_list(listname, empty_list)
if player_name ~= "???" then
-- Trash inventory:
local trash_inv = player_name_to_trash_inv[player_name]
if trash_inv ~= nil then
local old_trash_list = trash_inv:get_list("main")
trash_inv:set_list("main", empty_list)
for i = #tools, 1, -1 do
trash_inv:add_item("main", tools[i])
end
for i = #craftitems, 1, -1 do
trash_inv:add_item("main", craftitems[i])
end
for i = #old_trash_list, 1, -1 do
local stack = old_trash_list[i]
if not stack:is_empty() then
trash_inv:add_item("main", stack)
end
end
if not trash_inv:is_empty("main") then
old_trash_list = trash_inv:get_list("main")
local n = 1
while n < #old_trash_list and not old_trash_list[n + 1]:is_empty() do
n = n + 1
end
-- reverse the list:
for i = 1, math.floor(n / 2) do
old_trash_list[i], old_trash_list[1 + n - i] = old_trash_list[1 + n - i], old_trash_list[i]
end
trash_inv:set_list("main", old_trash_list)
end
else
minetest.log("warning", "Player "..player_name.." has no trash inventory!")
end
local trash_sound
if #item_strings == 1 then
trash_sound = ch_core.overridable.trash_one_sound
else
trash_sound = ch_core.overridable.trash_all_sound
end
if trash_sound ~= nil and trash_sound ~= "" then
minetest.sound_play(trash_sound, { to_player = player_name, gain = 1.0 })
end
end
end
return true
end
function ch_core.vyhodit_predmet(player_name, stack, description)
if not player_name then
player_name = "???"
end
if not description then
description = "???"
end
if stack == nil or stack:is_empty() then
return false
end
minetest.log("action", "Player "..player_name.." trashed an item ("..description.."): "..stack:to_string():sub(1, 1024))
local trash_inv = player_name_to_trash_inv[player_name]
if trash_inv == nil then
minetest.log("warning", "Player "..player_name.." has no trash inventory!")
elseif trash_inv:room_for_item("main", stack) then
trash_inv:add_item("main", stack)
else
-- shift the inventory:
local list = trash_inv:get_list("main")
for i = 1, #list - 1 do
list[i] = list[i + 1]
end
list[#list] = stack
trash_inv:set_list("main", list)
end
local trash_sound = ch_core.overridable.trash_one_sound
if trash_sound ~= nil and trash_sound ~= "" then
minetest.sound_play(trash_sound, { to_player = player_name, gain = 1.0 })
end
return true
end
-- přepsat minetest.item_drop:
local old_minetest_item_drop = minetest.item_drop
function minetest.item_drop(itemstack, dropper, pos)
if minetest.is_player(dropper) then
local player_name = assert(dropper:get_player_name())
local offline_charinfo = ch_data.offline_charinfo[player_name]
if
offline_charinfo ~= nil and
offline_charinfo.discard_drops ~= nil and
offline_charinfo.discard_drops == 1 and
ch_core.get_trash_inventory(player_name) ~= nil
then
ch_core.vyhodit_predmet(player_name, itemstack, "item_drop")
return ItemStack()
end
end
local dropper_name = "???"
local dropper_pos = "(???)"
if dropper ~= nil and dropper.get_player_name ~= nil and dropper.get_pos ~= nil then
dropper_name = dropper:get_player_name()
dropper_pos = core.pos_to_string(vector.round(dropper:get_pos()))
elseif pos ~= nil then
dropper_pos = core.pos_to_string(vector.round(pos))
end
local item_name = itemstack:get_name()
if core.registered_items[item_name] ~= nil then
core.log("action", "Item drop: "..dropper_name.." dropped "..itemstack:get_count().." of '"..item_name.."' at "..dropper_pos)
end
return old_minetest_item_drop(itemstack, dropper, pos)
end
ch_core.close_submod("kos")
|