diff options
Diffstat (limited to 'ch_core/registrace.lua')
-rw-r--r-- | ch_core/registrace.lua | 274 |
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") |