diff options
Diffstat (limited to 'ch_core/init.lua')
-rw-r--r-- | ch_core/init.lua | 518 |
1 files changed, 518 insertions, 0 deletions
diff --git a/ch_core/init.lua b/ch_core/init.lua new file mode 100644 index 0000000..50e94d6 --- /dev/null +++ b/ch_core/init.lua @@ -0,0 +1,518 @@ +ch_base.open_mod(core.get_current_modname()) + +local modpath = core.get_modpath("ch_core") +ch_core = { + storage = minetest.get_mod_storage(), + submods_loaded = {}, -- submod => true + + ap_interval = 15, -- interval pro podmód „ap“ + cas = 0, + gs_tasks = {}, + inventory_size = { + normal = 32, + extended = 64, + }, + supported_lang_codes = {cs = true, sk = true}, + verze_ap = 1, -- aktuální verze podmódu „ap“ + vezeni_data = { + min = vector.new(-1000, -1000, -1000), + max = vector.new(1000, 1000, 1000), + -- dvere = nil, + stred = vector.new(0, 0, 0), + }, + colors = { + black = minetest.get_color_escape_sequence("#000000"), + blue = minetest.get_color_escape_sequence("#0000AA"), + green = minetest.get_color_escape_sequence("#00AA00"), + cyan = minetest.get_color_escape_sequence("#00AAAA"), + red = minetest.get_color_escape_sequence("#AA0000"), + magenta = minetest.get_color_escape_sequence("#AA00AA"), + brown = minetest.get_color_escape_sequence("#AA5500"), + yellow = minetest.get_color_escape_sequence("#AAAA00"), + light_gray = minetest.get_color_escape_sequence("#CCCCCC"), + dark_gray = minetest.get_color_escape_sequence("#555555"), + light_blue = minetest.get_color_escape_sequence("#5555FF"), + light_green = minetest.get_color_escape_sequence("#55FF55"), + light_cyan = minetest.get_color_escape_sequence("#55FFFF"), + light_red = minetest.get_color_escape_sequence("#FF5555"), + light_magenta = minetest.get_color_escape_sequence("#FF55FF"), + light_yellow = minetest.get_color_escape_sequence("#FFFF55"), + white = minetest.get_color_escape_sequence("#FFFFFF"), + }, + overridable = { + -- funkce a proměnné, které mohou být přepsány z ostatních módů + reset_bank_account = function(player_name) return end, + trash_all_sound = "", -- zvuk k přehrání při mazání více předmětů + trash_one_sound = "", -- zvuk k přehrání při mazání jednoho předmětu + chyba_handler = function(player, text) return end, + }, +} + +ch_time.set_time_speed_during_day(26) -- was 24 +ch_time.set_time_speed_during_night(132) -- was 48 + +local current_submod + +function ch_core.open_submod(submod, required_submods) + if current_submod ~= nil then + error("[ch_core/"..current_submod.."] modul nebyl uzavřen!") + end + for s, c in pairs(required_submods or {}) do + if c and not ch_core.submods_loaded[s] then + error("ch_core submodule '"..s.."' is required to be loaded before '"..submod.."'!") + end + end + current_submod = submod + return true +end +function ch_core.close_submod(submod) + if current_submod == nil then + error("Vícenásobné volání ch_core.close_submod()!") + elseif current_submod ~= submod then + error("[ch_core/"..current_submod.."] modul chybně uzavřen jako "..submod.."!") + end + current_submod = nil + ch_core.submods_loaded[submod] = true + return true +end + +dofile(modpath .. "/active_objects.lua") +dofile(modpath .. "/markers.lua") +dofile(modpath .. "/barvy_linek.lua") +dofile(modpath .. "/nodes.lua") +dofile(modpath .. "/plaster.lua") +dofile(modpath .. "/hotbar.lua") +dofile(modpath .. "/vgroups.lua") +dofile(modpath .. "/data.lua") +dofile(modpath .. "/lib.lua") -- : data +dofile(modpath .. "/entity_register.lua") -- : lib +dofile(modpath .. "/interiors.lua") -- : lib +dofile(modpath .. "/shapes_db.lua") -- : lib +dofile(modpath .. "/penize.lua") -- : lib +dofile(modpath .. "/nodedir.lua") -- : lib +dofile(modpath .. "/formspecs.lua") -- : data, lib +dofile(modpath .. "/areas.lua") -- : data, lib +dofile(modpath .. "/nametag.lua") -- : data, lib +dofile(modpath .. "/privs.lua") +dofile(modpath .. "/clean_players.lua") -- : data, lib, privs +dofile(modpath .. "/localize_chatcommands.lua") -- : data, lib, privs +dofile(modpath .. "/udm.lua") -- : areas, data, lib +dofile(modpath .. "/chat.lua") -- : areas, data, lib, privs, nametag, udm +dofile(modpath .. "/shape_selector.lua") -- : chat, formspecs, lib +dofile(modpath .. "/events.lua") -- : chat, data, lib, privs +dofile(modpath .. "/stavby.lua") -- : chat, events, lib +-- dofile(modpath .. "/inv_inspector.lua") -- : data, formspecs, lib, chat +dofile(modpath .. "/podnebi.lua") -- : privs, chat +dofile(modpath .. "/dennoc.lua") -- : privs, chat +dofile(modpath .. "/hud.lua") -- : data, lib, chat +dofile(modpath .. "/ap.lua") -- : chat, data, events, hud, lib +dofile(modpath .. "/registrace.lua") -- : chat, data, events, lib, nametag +dofile(modpath .. "/pryc.lua") -- : data, lib, events, privs +dofile(modpath .. "/joinplayer.lua") -- : chat, data, formspecs, lib, nametag, pryc, events +dofile(modpath .. "/padlock.lua") -- : data, lib +dofile(modpath .. "/vezeni.lua") -- : privs, data, lib, chat, hud +dofile(modpath .. "/timers.lua") -- : data, chat, hud +dofile(modpath .. "/wielded_light.lua") -- : data, lib, nodes +dofile(modpath .. "/teleportace.lua") -- : data, lib, chat, privs, stavby, timers +dofile(modpath .. "/creative_inventory.lua") -- : lib +dofile(modpath .. "/kos.lua") -- : lib + + +local ifthenelse = assert(ch_core.ifthenelse) +local last_timeofday = 0 -- pravděpodobně se pokusí něco přehrát v prvním globalstepu, +-- ale to nevadí, protöže v tu chvíli stejně nemůže být ještě nikdo online. +local abs = math.abs +local get_timeofday = core.get_timeofday +local gain_1 = {gain = 1.0} +local head_bone_name = "Head" +local head_bone_override = { + position = {vec = vector.new(0, 6.35, 0), absolute = true}, + rotation = {vec = vector.zero(), absolute = true}, +} +local emoting = (core.get_modpath("emote") and emote.emoting) or {} +local globstep_dtime_accumulated = 0.0 +local hud_dtime_accumulated = 0.0 +local get_us_time = assert(core.get_us_time) +local has_wielded_light = core.get_modpath("wielded_light") +local custom_globalsteps = {} +local last_ap_timestamp = 0 +local use_forbidden_height = ifthenelse(core.settings:get_bool("ch_forbidden_height", false), true, false) +local gs_task +local gs_task_next_step +local gs_handler = { + cancel = "on_cancelled", + finished = "on_finished", + failed = "on_failed", +} + +local stepheight_low = {stepheight = 0.3} +local stepheight_high = {stepheight = 1.1} + +local function get_root(o) + local r = o:get_attach() + while r do + o = r + r = o:get_attach() + end + return o +end + +function ch_core.register_player_globalstep(func, index) + if not index then + index = #custom_globalsteps + 1 + end + if not func then + error("Invalid call to ch_core.register_player_globalstep()!") + end + custom_globalsteps[index] = func + return index +end + +local function globalstep(dtime) + if globstep_dtime_accumulated == 0 then + -- první globalstep: + ch_core.update_creative_inventory(true) + globstep_dtime_accumulated = globstep_dtime_accumulated + dtime + return + end + + globstep_dtime_accumulated = globstep_dtime_accumulated + dtime + ch_core.cas = globstep_dtime_accumulated + local ch_core_cas = globstep_dtime_accumulated + local us_time = get_us_time() + + -- DEN: 5:30 .. 19:00 + local tod = get_timeofday() + local byla_noc = last_timeofday < 0.2292 or last_timeofday > 0.791666 + local je_noc = tod < 0.2292 or tod > 0.791666 + if byla_noc and not je_noc then + -- Ráno + minetest.sound_play("birds", gain_1) + local new_speed = ch_time.get_time_speed_during_day() + if new_speed ~= nil then + core.settings:set("time_speed", tostring(new_speed)) + end + elseif not byla_noc and je_noc then + -- Noc + core.sound_play("owl", gain_1) + local new_speed = ch_time.get_time_speed_during_night() + if new_speed ~= nil then + core.settings:set("time_speed", tostring(new_speed)) + end + end + last_timeofday = tod + + local process_ap = us_time - last_ap_timestamp >= ch_core.ap_interval * 1000000 + if process_ap then + last_ap_timestamp = us_time + end + + hud_dtime_accumulated = hud_dtime_accumulated + dtime + if hud_dtime_accumulated > 1 then + hud_dtime_accumulated = 0 + ch_core.update_gametime_hudbar(nil, tod) + end + + -- PRO KAŽDÉHO HRÁČE/KU: + local connected_players = core.get_connected_players() + for _, player in pairs(connected_players) do + local player_name = player:get_player_name() + local player_pos = player:get_pos() + local online_charinfo = ch_data.online_charinfo[player_name] + local offline_charinfo = ch_data.get_or_add_offline_charinfo(player_name) + local disrupt_teleport_flag = false + local disrupt_pryc_flag = false + local player_wielded_item_name = player:get_wielded_item():get_name() or "" + local player_root = get_root(player) + + if online_charinfo then + local previous_wield_item_name = online_charinfo.wielded_item_name or "" + online_charinfo.wielded_item_name = player_wielded_item_name + + -- ÚHEL HLAVY: + local emote = emoting[player] + if not emote or emote ~= "lehni" then + local puvodni_uhel_hlavy = online_charinfo.uhel_hlavy or 0 + local novy_uhel_hlavy = player:get_look_vertical() - 0.01745329251994329577 * (online_charinfo.head_offset or 0) + local rozdil = novy_uhel_hlavy - puvodni_uhel_hlavy + if rozdil > 0.001 or rozdil < -0.001 then + if rozdil > 0.3 then + -- omezit pohyb hlavy + novy_uhel_hlavy = puvodni_uhel_hlavy + 0.3 + elseif rozdil < -0.3 then + novy_uhel_hlavy = puvodni_uhel_hlavy - 0.3 + end + head_bone_override.rotation.vec.x = -0.5 * (puvodni_uhel_hlavy + novy_uhel_hlavy) + player:set_bone_override(head_bone_name, head_bone_override) + online_charinfo.uhel_hlavy = novy_uhel_hlavy + end + else + head_bone_override.rotation.vec.x = 0 + player:set_bone_override(head_bone_name, head_bone_override) + end + + -- REAGOVAT NA KLÁVESY: + local old_control_bits = online_charinfo.klavesy_b or 0 + local new_control_bits = player:get_player_control_bits() + if new_control_bits ~= old_control_bits then + local new_controls = player:get_player_control() + local old_controls = online_charinfo.klavesy or new_controls + online_charinfo.klavesy = new_controls + online_charinfo.klavesy_b = new_control_bits + if new_controls.aux1 and not old_controls.aux1 then + ch_core.show_player_list(player, online_charinfo) + player:set_properties(stepheight_high) + elseif not new_controls.aux1 and old_controls.aux1 then + ch_core.hide_player_list(player, online_charinfo) + player:set_properties(stepheight_low) + end + + disrupt_pryc_flag = true + if not disrupt_teleport_flag and (new_controls.up or new_controls.down or new_controls.left or new_controls.right or new_controls.jump or new_controls.dig or new_controls.place) then + disrupt_teleport_flag = true + end + end + + -- VĚZENÍ, zakázaná výška: + if --[[ ch_core.submods_loaded["vezeni"] and ]] offline_charinfo.player.trest > 0 then + ch_core.vykon_trestu(player, player_pos, us_time, online_charinfo) + elseif use_forbidden_height and player_pos.y >= 1024 and player_pos.y <= 1256 then + -- zakázaná výška + minetest.log("warning", "Player "..player_name.." reached forbidden area at "..minetest.pos_to_string(player_pos).."!") + minetest.after(0.1, function() + ch_core.teleport_player({ + type = "admin", + player = player, + target_pos = ch_core.positions["zacatek_1"] or vector.zero(), + sound_after = "chat3_bell", + }) + ch_core.systemovy_kanal(player_name, "Dostali jste se do zakázaného výškového pásma! Pozice y >= 1024 jsou nepřístupné.") + end) + end + + -- pokud se změnil držený předmět, možná bude potřeba zobrazit jeho nápovědu + if player_wielded_item_name ~= previous_wield_item_name then + disrupt_pryc_flag = true + local help_def = ch_data.should_show_help(player, online_charinfo, player_wielded_item_name) + if help_def then + local zluta = minetest.get_color_escape_sequence("#ffff00") + local zelena = minetest.get_color_escape_sequence("#00ff00") + local s = zluta.."Nápověda k předmětu „"..zelena..(help_def.description or ""):gsub("\n", "\n "..zelena)..zluta.."“:\n "..zluta..(help_def._ch_help or ""):gsub("\n", "\n "..zluta) + ch_core.systemovy_kanal(player_name, s) + end + + -- periskop: + if online_charinfo.periskop ~= nil and player_wielded_item_name ~= "ch_extras:periskop" then + online_charinfo.periskop.cancel() + end + end + + -- ZRUŠIT /pryč: + if disrupt_pryc_flag and online_charinfo.pryc then + online_charinfo.pryc(player, online_charinfo) + end + + -- ČASOVAČE + local timers = online_charinfo.ch_timers + if timers then + for timer_id, timer_def in pairs(table.copy(timers)) do + local remains = timer_def.run_at - ch_core_cas + if remains <= 0.1 then + local func_to_run = timer_def.func + ch_core.cancel_ch_timer(online_charinfo, timer_id) + if func_to_run then + minetest.after(0.1, function() + return func_to_run() + end) + end + elseif timer_def.hudbar then + remains = math.ceil(remains) + if remains ~= timer_def.last_hud_value then + hb.change_hudbar(player, timer_def.hudbar, remains) + timer_def.last_hud_value = remains + end + end + end + end + + -- ZRUŠIT teleport + local teleport_def = ch_core.get_ch_timer_info(online_charinfo, "teleportace") + if teleport_def then + if not disrupt_teleport_flag then + local ts_pos = teleport_def.start_pos + if ts_pos then + disrupt_teleport_flag = abs(ts_pos.x - player_pos.x) > 0.5 or abs(ts_pos.z - player_pos.z) > 0.5 + end + end + if disrupt_teleport_flag then + ch_core.cancel_teleport(player_name, true) + end + end + + -- ZRUŠIT horkou zprávu + local horka_zprava = online_charinfo.horka_zprava + if horka_zprava and ch_core_cas >= horka_zprava.timeout then + online_charinfo.horka_zprava = nil + player:set_nametag_attributes(ch_core.compute_player_nametag(online_charinfo, offline_charinfo)) + end + + -- nesmrtelnost (stačilo by spouštět občas) + if minetest.is_creative_enabled(player_name) then + if not online_charinfo.is_creative then + online_charinfo.is_creative = true + ch_core.set_immortal(player, online_charinfo.is_creative) + end + else + if online_charinfo.is_creative then + online_charinfo.is_creative = false + ch_core.set_immortal(player, online_charinfo.is_creative) + end + end + + -- SPUSTIT registrované obslužné funkce + local i = 1 + while custom_globalsteps[i] do + custom_globalsteps[i](player, player_name, online_charinfo, offline_charinfo, us_time) + i = i + 1 + end + + -- SLEDOVÁNÍ AKTIVITY + local ap = online_charinfo.ap + if ap then + if player_pos.x ~= ap.pos.x then + ap.pos_x_gen = ap.pos_x_gen + 1 + end + if player_pos.y ~= ap.pos.y then + ap.pos_y_gen = ap.pos_y_gen + 1 + end + if player_pos.z ~= ap.pos.z then + ap.pos_z_gen = ap.pos_z_gen + 1 + end + ap.pos = player_pos + + local player_velocity = player_root:get_velocity() + if player_velocity.x ~= ap.velocity.x then + ap.velocity_x_gen = ap.velocity_x_gen + 1 + end + if player_velocity.y ~= ap.velocity.y then + ap.velocity_y_gen = ap.velocity_y_gen + 1 + end + if player_velocity.z ~= ap.velocity.z then + ap.velocity_z_gen = ap.velocity_z_gen + 1 + end + ap.velocity = player_velocity + + local player_control_bits = player:get_player_control_bits() + if player_control_bits ~= ap.control then + ap.control = player_control_bits + ap.control_gen = ap.control_gen + 1 + end + + local look_horizontal = player:get_look_horizontal() + if look_horizontal ~= ap.look_h then + ap.look_h = look_horizontal + ap.look_h_gen = ap.look_h_gen + 1 + end + local look_vertical = player:get_look_vertical() + if look_vertical ~= ap.look_v then + ap.look_v = look_vertical + ap.look_v_gen = ap.look_v_gen + 1 + end + + local last + last = ch_core.last_mistni + if last.char == player_name then + ap.chat_mistni_gen = last.char_gen + end + last = ch_core.last_celoserverovy + if last.char == player_name then + ap.chat_celoserverovy_gen = last.char_gen + end + last = ch_core.last_sepot + if last.char == player_name then + ap.chat_sepot_gen = last.char_gen + end + last = ch_core.last_soukromy + if last.char == player_name then + ap.chat_soukromy_gen = last.char_gen + end + + if process_ap then + ch_core.ap_update(player, online_charinfo, offline_charinfo) + end + elseif process_ap then + ch_core.ap_init(player, online_charinfo, offline_charinfo) + end + + -- NASTAVIT OSVĚTLENÍ [data, nodes, wielded_light] + -- - provést po proběhnutí registrovaných obslužných funkcí, + -- protože ty mohly osvětlení změnit + local light_slots = has_wielded_light and online_charinfo.wielded_lights + if light_slots then + local new_light_level = 0 + for _, light_level in pairs(light_slots) do + if light_level > new_light_level then + new_light_level = light_level + end + end + if new_light_level ~= online_charinfo.light_level then + minetest.log("info", "Light level of player "..player_name.." changed: "..online_charinfo.light_level.." to "..new_light_level) + if new_light_level > 0 then + wielded_light.track_user_entity(player, "ch_core", string.format("ch_core:light_%02d", new_light_level)) + else + wielded_light.track_user_entity(player, "ch_core", "default:cobble") + end + online_charinfo.light_level = new_light_level + online_charinfo.light_level_timestamp = us_time + elseif new_light_level > 0 and us_time - online_charinfo.light_level_timestamp > 5000000 then + -- refresh non-zero light level each 5 seconds + wielded_light.track_user_entity(player, "ch_core", string.format("ch_core:light_%02d", new_light_level)) + online_charinfo.light_level_timestamp = us_time + end + end + end + end + + -- globalstep tasks: + if gs_task ~= nil then + -- run the step + local context = gs_task.context + local step = gs_task.steps[gs_task_next_step] + local n_steps = #gs_task.steps + local result = gs_task.on_step(context, step, gs_task_next_step, n_steps) + local handler = gs_handler[result] -- if this crashes on nil, add 'or ""' + if handler == nil then + if gs_task_next_step < n_steps then + -- příště pokračovat dalším krokem stejného úkolu + gs_task_next_step = gs_task_next_step + 1 + else + -- úkol dokončen + handler = "on_finished" + end + end + if handler ~= nil then + -- zavolat obsluhu a skončit + handler = gs_task[handler] + if handler ~= nil then + handler(context, gs_task_next_step, n_steps) + end + gs_task = nil + end + + elseif ch_core.gs_tasks[1] ~= nil then + -- vyzvednout další úkol a zavolat jeho on_start() + gs_task = ch_core.gs_tasks[1] + gs_task_next_step = 1 + table.remove(ch_core.gs_tasks, 1) + if gs_task.on_start ~= nil then + local result = gs_task.on_start(gs_task.context) + local handler = gs_handler[result] -- if this crashes on nil, add 'or ""' + if handler ~= nil then + gs_task = nil + end + end + end +end +core.register_globalstep(globalstep) + +ch_base.close_mod(minetest.get_current_modname()) |