aboutsummaryrefslogtreecommitdiff
path: root/ch_core/kos.lua
diff options
context:
space:
mode:
Diffstat (limited to 'ch_core/kos.lua')
-rw-r--r--ch_core/kos.lua210
1 files changed, 210 insertions, 0 deletions
diff --git a/ch_core/kos.lua b/ch_core/kos.lua
new file mode 100644
index 0000000..ac9bb83
--- /dev/null
+++ b/ch_core/kos.lua
@@ -0,0 +1,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")