aboutsummaryrefslogtreecommitdiff
path: root/ch_core/registrace.lua
diff options
context:
space:
mode:
Diffstat (limited to 'ch_core/registrace.lua')
-rw-r--r--ch_core/registrace.lua274
1 files changed, 274 insertions, 0 deletions
diff --git a/ch_core/registrace.lua b/ch_core/registrace.lua
new file mode 100644
index 0000000..d267d43
--- /dev/null
+++ b/ch_core/registrace.lua
@@ -0,0 +1,274 @@
+ch_core.open_submod("registrace", {chat = true, data = true, events = true, lib = true, nametag = true})
+
+ch_core.register_event_type("reg_new", {
+ access = "admin",
+ description = "registrace (turistická postava)",
+ default_text = "nová postava {PLAYER} vstoupila do hry",
+ chat_access = "admin",
+})
+
+ch_core.register_event_type("reg_na_server", {
+ access = "public",
+ description = "přijetí na server",
+ chat_access = "public",
+ color = "#00ff00",
+})
+
+local survival_creative = {survival = true, creative = true}
+local default_privs_to_reg_type = {
+ ch_registered_player = survival_creative,
+ creative = {new = true},
+ fast = true,
+ give = {creative = true},
+ hiking = survival_creative,
+ home = true,
+ interact = true,
+ peaceful_player = true,
+ railway_operator = survival_creative,
+ shout = true,
+ track_builder = survival_creative,
+ train_operator = survival_creative,
+}
+local reg_types = {
+ new = "turistická postava",
+ survival = "dělnický styl hry",
+ creative = "kouzelnický styl hry",
+}
+local function get_flashlight()
+ local stack = ItemStack("technic:flashlight")
+ stack:set_wear(1)
+ local meta = stack:get_meta()
+ meta:set_string("", "return {charge=30000}")
+ return stack
+end
+local function get_replacer()
+ local stack = ItemStack("replacer:replacer")
+ stack:set_wear(1)
+ local meta = stack:get_meta()
+ meta:set_string("", "return {charge=50000}")
+ return stack
+end
+local default_items = {
+ {stack = ItemStack("ch_extras:magic_wand"), creative = true},
+ {stack = ItemStack("ch_extras:jumptool"), new = true, survival = true, creative = true},
+ {stack = ItemStack("rotate:wrench_copper_cw"), survival = true, creative = true},
+ {stack = get_replacer(), survival = true, creative = true},
+ {stack = ItemStack("ch_extras:periskop"), new = true, survival = true, creative = true},
+ {stack = ItemStack("ch_extras:sickle_steel"), survival = true},
+ -- {stack = ItemStack("ch_extras:teleporter_unsellable"), new = true, survival = true},
+ {stack = ItemStack("ch_extras:runa_navratu"), new = true, creative = true},
+ {stack = ItemStack("advtrains_line_automation:jrad"), new = true},
+ {stack = ItemStack("unified_inventory:bag_large"), survival = true, creative = true},
+ {stack = ItemStack("bridger:scaffolding 100"), survival = true, creative = true},
+ {stack = ItemStack("towercrane:base"), survival = true, creative = true},
+ {stack = ItemStack("bike:bike"), new = true, survival = true, creative = false},
+ {stack = ItemStack("anvil:hammer"), survival = true},
+ --{stack = ItemStack("airtanks:bronze_tank"), survival = true, creative = true},
+ {stack = ItemStack("ch_core:kcs_kcs 1000"), survival = true},
+ {stack = ItemStack("ch_extras:lupa"), new = true, survival = true},
+ {stack = ItemStack("orienteering:builder_compass_1"), survival = true, creative = true},
+ {stack = ItemStack("basic_signs:vevystavbe"), survival = true, creative = true},
+ {stack = ItemStack("ch_extras:teleporter_unsellable 100"), creative = true},
+ {stack = ItemStack("binoculars:binoculars"), new = true},
+ {stack = ItemStack("ch_core:chisel"), survival = true, creative = true},
+
+ {stack = get_flashlight(), min_index = 17, new = true, survival = true, creative = true},
+ -- {stack = ItemStack("orienteering:map"), min_index = 18, new = true, survival = true, creative = true},
+ {stack = ItemStack("orienteering:triangulator"), min_index = 18, survival = true, creative = true},
+}
+
+for i, item in ipairs(default_items) do
+ item.i = i
+ if item.min_index == nil then
+ item.min_index = 2
+ end
+end
+table.sort(default_items, function(a, b) return a.min_index < b.min_index or (a.min_index == b.min_index and a.i < b.i) end)
+
+local function compute_initial_inventory(reg_type)
+ local empty_stack = ItemStack()
+ local initial_inventory = {}
+ local i_in = 1
+ local item = default_items[1]
+
+ for i_out = 1, 32 do
+ while item ~= nil and not item[reg_type] do
+ -- skip items not for the current reg_type
+ i_in = i_in + 1
+ item = default_items[i_in]
+ end
+ if item == nil then
+ -- all items were assigned
+ break
+ end
+ if item.min_index > i_out then
+ initial_inventory[i_out] = empty_stack
+ else
+ initial_inventory[i_out] = item.stack
+ i_in = i_in + 1
+ item = default_items[i_in]
+ end
+ end
+ return initial_inventory
+end
+
+function ch_core.registrovat(player_name, reg_type, extra_privs)
+ if extra_privs == nil then
+ extra_privs = {}
+ elseif type(extra_privs) == "string" then
+ extra_privs = minetest.string_to_privs(extra_privs)
+ end
+ if type(extra_privs) ~= "table" then
+ error("Invalid extra_privs type: "..type(extra_privs))
+ else
+ extra_privs = table.copy(extra_privs)
+ end
+ local offline_charinfo = ch_data.offline_charinfo[player_name]
+ if not offline_charinfo then
+ return false, "offline_charinfo not found!"
+ end
+ local reg_type_desc = reg_types[reg_type]
+ if not reg_type_desc then
+ return false, "unknown registration type "..reg_type
+ end
+
+ -- compute privs
+ for priv, priv_setting in pairs(default_privs_to_reg_type) do
+ if priv_setting == true or (type(priv_setting) == "table" and priv_setting[reg_type]) then
+ extra_privs[priv] = true
+ end
+ end
+
+ -- reset the bank account
+ if reg_type == "new" and ch_core.get_player_role(player_name) ~= "new" then
+ ch_core.overridable.reset_bank_account(player_name)
+ end
+
+ print("Will compute initial inventory for reg_type \""..(reg_type or "nil").."\"")
+ local initial_inventory = compute_initial_inventory(reg_type)
+ print("Computed initial inventory for reg_type \""..(reg_type or "nil").."\": "..dump2({initial_inventory = initial_inventory, reg_type = reg_type}))
+ local player = minetest.get_player_by_name(player_name)
+ if not player then
+ return false, "the player is offline"
+ end
+ local inv = player:get_inventory()
+ local bags_inv = minetest.get_inventory({type = "detached", name = player_name.."_bags"})
+ local empty_stack = ItemStack()
+ local old_lists = inv:get_lists()
+ minetest.log("action", "Will clear inventories of "..player_name..", old inventories: "..dump2(old_lists))
+ old_lists.hand = nil
+ old_lists.main = nil
+ for inv_name, _ in pairs(old_lists) do
+ inv:set_list(inv_name, {})
+ end
+ inv:set_list("main", initial_inventory)
+ local new_lists = inv:get_lists()
+ local bags_count = 0
+ if bags_inv ~= nil then
+ for i = 1, 8 do
+ local bag = bags_inv:get_stack("bag"..i, 1)
+ if bag ~= nil and not bag:is_empty() then
+ bags_inv:set_stack("bag"..i, 1, empty_stack)
+ bags_count = bags_count + 1
+ end
+ end
+ end
+ minetest.log("action", "Cleared inventories of "..player_name.." ("..bags_count.." bags), new inventories: "..dump2(new_lists))
+ minetest.set_player_privs(player_name, extra_privs)
+ local new_privs = minetest.privs_to_string(minetest.get_player_privs(player_name))
+ minetest.log("action", "Player "..player_name.." privs set to: "..new_privs)
+ local message = "Vaše registrace byla nastavena do režimu „"..reg_type_desc.."“."
+ if reg_type ~= "new" then
+ message = message.." Zkontrolujte si, prosím, svoje nová práva příkazem /práva."
+ end
+ ch_core.systemovy_kanal(player_name, message)
+ player:set_nametag_attributes(ch_core.compute_player_nametag(ch_data.online_charinfo[player_name], offline_charinfo))
+ offline_charinfo.past_playtime = 0
+ offline_charinfo.past_ap_playtime = 0
+ offline_charinfo.ap_level = 1
+ offline_charinfo.ap_xp = 0
+ ch_data.save_offline_charinfo(player_name)
+ ch_core.ap_add(player_name, offline_charinfo)
+ if reg_type == "new" then
+ ch_core.add_event("reg_new", nil, player_name)
+ else
+ if reg_type == "survival" then
+ message = "dělnická postava {PLAYER} byla nově přijata na server"
+ elseif reg_type == "creative" then
+ message = "kouzelnická postava {PLAYER} byla nově přijata na server"
+ else
+ message = "postava {PLAYER} byla nově přijata na server ("..reg_type_desc..")"
+ end
+ ch_core.add_event("reg_na_server", message, player_name)
+ end
+ return true
+end
+
+local function on_joinplayer(player_name)
+ local player = minetest.get_player_by_name(player_name)
+ if not player then
+ minetest.log("warning", "on_joinplayer: failed to fetch player object for registration of "..(player_name or "nil"))
+ end
+ ch_data.get_joining_online_charinfo(player)
+ local offline_charinfo = ch_data.get_offline_charinfo(player_name)
+ if offline_charinfo.pending_registration_type == "" then
+ return
+ end
+ local result, error_message = ch_core.registrovat(player_name, offline_charinfo.pending_registration_type, offline_charinfo.pending_registration_privs)
+ if result then
+ offline_charinfo.pending_registration_privs = ""
+ offline_charinfo.pending_registration_type = ""
+ ch_data.save_offline_charinfo(player_name)
+ return
+ else
+ minetest.log("warning", "Registration of "..player_name.." failed: "..(error_message or "nil"))
+ end
+end
+
+minetest.register_on_joinplayer(function(player, last_login)
+ local player_name = player:get_player_name()
+ local online_charinfo = ch_data.get_joining_online_charinfo(player) or {}
+ local offline_charinfo = ch_data.get_offline_charinfo(player_name)
+ if offline_charinfo.pending_registration_type ~= "" and online_charinfo.news_role ~= "disconnect" and online_charinfo.news_role ~= "invalid_name" then
+ minetest.after(0.5, on_joinplayer, player_name)
+ end
+end)
+
+local def = {
+ params = "<new|survival|creative> <jméno_postavy> [extra_privs]",
+ description = "registrovat",
+ privs = {server = true},
+ func = function(player_name, param)
+ local reg_type, player_to_register, extra_privs = string.match(param, "^(%S+) (%S+) (%S+)$")
+ if not reg_type then
+ reg_type, player_to_register = string.match(param, "^(%S+) (%S+)$")
+ end
+ if not reg_type then
+ return false, "Neplatné zadání!"
+ end
+ player_to_register = ch_core.jmeno_na_prihlasovaci(player_to_register)
+ local offline_charinfo = ch_data.offline_charinfo[player_to_register]
+ if not offline_charinfo then
+ return false, "Postava "..player_to_register.." neexistuje!"
+ end
+ local online_charinfo = ch_data.online_charinfo[player_to_register]
+ if online_charinfo then
+ -- register immediately
+ local result, err_text = ch_core.registrovat(player_to_register, reg_type, extra_privs or "")
+ if result then
+ return true, "Postava registrována."
+ else
+ return false, "Registrace selhala; "..err_text
+ end
+ else
+ offline_charinfo.pending_registration_type = reg_type
+ offline_charinfo.pending_registration_privs = extra_privs or ""
+ ch_data.save_offline_charinfo(player_to_register)
+ return true, "Registrace naplánována."
+ end
+ end,
+}
+
+minetest.register_chatcommand("registrovat", def)
+
+ch_core.close_submod("registrace")