From e40766f8349edd7391cdbc005569d201c01da67d Mon Sep 17 00:00:00 2001 From: Unknown Date: Sun, 4 Mar 2018 21:50:44 +0300 Subject: [PATCH] network: refactoring, adding few debug options, 2 new events --- vmf_source/localization/vmf.lua | 10 + .../scripts/mods/vmf/modules/core/events.lua | 20 ++ .../scripts/mods/vmf/modules/core/network.lua | 217 +++++++++++------- .../scripts/mods/vmf/modules/vmf_options.lua | 14 ++ 4 files changed, 183 insertions(+), 78 deletions(-) diff --git a/vmf_source/localization/vmf.lua b/vmf_source/localization/vmf.lua index 0a3a81b..cbbbbe7 100644 --- a/vmf_source/localization/vmf.lua +++ b/vmf_source/localization/vmf.lua @@ -41,6 +41,16 @@ return { ru = "Открывает новое окно, в которое в реальном времени выводится игровой лог.\n\n" .. "Чтобы его закрыть, сначала выключите консоль из меню настроек, и потом закройте вручную.", }, + show_network_debug_info = { + en = "Log Network Calls", + ru = "Логгирование сетевых вызовов", + }, + show_network_debug_info_tooltip = { + en = "Log all the VMF network calls and all the data transfered with them.\n\n" .. + "The method 'info' is used for the logging.", + ru = "Логирование всех сетевых вызовов VMF и передаваемых с ними данных.\n\n" .. + "Для логирования используется метод 'info'.", + }, logging_mode = { en = "Logging Settings.", ru = "Настройки логирования", diff --git a/vmf_source/scripts/mods/vmf/modules/core/events.lua b/vmf_source/scripts/mods/vmf/modules/core/events.lua index 619a11a..22c1c7c 100644 --- a/vmf_source/scripts/mods/vmf/modules/core/events.lua +++ b/vmf_source/scripts/mods/vmf/modules/core/events.lua @@ -94,4 +94,24 @@ vmf.mod_disabled_event = function(mod, initial_call) else mod:warning("Attemt to call undefined event 'mod.%s'.", event_name) end +end + +vmf.mod_user_joined_the_game = function(mod, player) + + local event_name = "on_user_joined" + + local event = mod[event_name] + if event then + run_event(mod, event_name, event, player) + end +end + +vmf.mod_user_left_the_game = function(mod, player) + + local event_name = "on_user_left" + + local event = mod[event_name] + if event then + run_event(mod, event_name, event, player) + end end \ No newline at end of file diff --git a/vmf_source/scripts/mods/vmf/modules/core/network.lua b/vmf_source/scripts/mods/vmf/modules/core/network.lua index bbaff96..8390c3e 100644 --- a/vmf_source/scripts/mods/vmf/modules/core/network.lua +++ b/vmf_source/scripts/mods/vmf/modules/core/network.lua @@ -1,5 +1,3 @@ --- @TODO: when recieving maps of other users, check for consistency --- @TODO: don't call during suspension local vmf = get_mod("VMF") local _VMF_USERS = {} @@ -13,17 +11,31 @@ local _SHARED_RPCS_MAP = "" local _NETWORK_MODULE_IS_INITIALIZED = false --- converting +-- #################################################################################################################### +-- ##### Local functions ############################################################################################## +-- #################################################################################################################### -local function convert_names_to_numbers(user_rpcs_dictionary, mod_name, rpc_name) +local function is_rpc_registered(mod_name, rpc_name) - local mod_number = user_rpcs_dictionary[1][mod_name] - if mod_number then + local success = pcall(function() return _RPC_CALLBACKS[mod_name][rpc_name] end) + return success +end - local rpc_number = user_rpcs_dictionary[2][mod_number][rpc_name] - if rpc_number then +-- CONVERTING - return mod_number, rpc_number +local function convert_names_to_numbers(peer_id, mod_name, rpc_name) + + local user_rpcs_dictionary = _VMF_USERS[peer_id] + if user_rpcs_dictionary then + + local mod_number = user_rpcs_dictionary[1][mod_name] + if mod_number then + + local rpc_number = user_rpcs_dictionary[2][mod_number][rpc_name] + if rpc_number then + + return mod_number, rpc_number + end end end return nil @@ -44,7 +56,7 @@ local function convert_numbers_to_names(mod_number, rpc_number) return nil end --- serialization +-- SERIALIZATION local function serialize_data(...) @@ -66,52 +78,86 @@ local function deserialize_data(data) return unpack(data, 1, args_number) end --- rpcs +-- DEBUG + +local function network_debug(rpc_type, action_type, peer_id, mod_name, rpc_name, data) + + if vmf.network_debug then + + local debug_message = nil + + if action_type == "local" then + debug_message = "[NETWORK][LOCAL]" + else + debug_message = "[NETWORK][" .. peer_id .. " (" .. tostring(Managers.player:player_from_peer_id(peer_id)) .. ")]" .. (action_type == "sent" and "<-" or "->") + end + + if rpc_type == "ping" then + + debug_message = debug_message .. "[PING]" + + elseif rpc_type == "pong" then + + debug_message = debug_message .. "[PONG]" + + elseif rpc_type == "data" then + + debug_message = debug_message .. "[DATA][" .. mod_name .. "][" .. rpc_name .. "]: " + + if type(data) == "string" then + debug_message = debug_message .. data + else + local success, serialized_data = pcall(serialize_data, unpack(data)) + if success then + debug_message = debug_message .. serialized_data + end + end + end + + vmf:info(debug_message) + end +end + +-- NETWORK local function send_rpc_vmf_ping(peer_id) + network_debug("ping", "sent", peer_id) RPC.rpc_chat_message(peer_id, 3, Network.peer_id(), "", "", false, true, false) - - vmf:info("[NETWORK][SENT PING] %s", peer_id) -- @DEBUG: end local function send_rpc_vmf_pong(peer_id) + network_debug("pong", "sent", peer_id) RPC.rpc_chat_message(peer_id, 4, Network.peer_id(), _SHARED_MODS_MAP, _SHARED_RPCS_MAP, false, true, false) - - vmf:info("[NETWORK][SENT PONG] %s", peer_id) -- @DEBUG: end -local function send_rpc_vmf_data(peer_id, mod_number, rpc_number, ...) +local function send_rpc_vmf_data(peer_id, mod_name, rpc_name, ...) - local rpc_info = cjson.encode({mod_number, rpc_number}) - local success, data = pcall(serialize_data, ...) - if success then - RPC.rpc_chat_message(peer_id, 5, Network.peer_id(), rpc_info, data, false, true, false) - vmf:info("[NETWORK][SENT RPC] '%s' [%s]: %s", _VMF_USERS[peer_id][mod_number][rpc_number], peer_id, data) -- @DEBUG: + local mod_number, rpc_number = convert_names_to_numbers(peer_id, mod_name, rpc_name) + if mod_number then + + local rpc_info = cjson.encode({mod_number, rpc_number}) + local success, data = pcall(serialize_data, ...) + if success then + network_debug("data", "sent", peer_id, mod_name, rpc_name, data) + RPC.rpc_chat_message(peer_id, 5, Network.peer_id(), rpc_info, data, false, true, false) + end end end local function send_rpc_vmf_data_local(mod_name, rpc_name, ...) - local success, error_message = pcall(_RPC_CALLBACKS[mod_name][rpc_name], Network.peer_id(), ...) + if get_mod(mod_name):is_enabled() then + network_debug("data", "local", nil, mod_name, rpc_name, {...}) - if not success then - get_mod(mod_name):error("(local rpc) in rpc '%s': %s", rpc_name, error_message) - else - local success, data = pcall(serialize_data, ...) -- @DEBUG: - if success then -- @DEBUG: - vmf:info("[NETWORK][LOCAL RPC] '%s': %s", rpc_name, data) -- @DEBUG: - end -- @DEBUG: + local success, error_message = pcall(_RPC_CALLBACKS[mod_name][rpc_name], Network.peer_id(), ...) + if not success then + get_mod(mod_name):error("(local rpc) in rpc '%s': %s", tostring(rpc_name), tostring(error_message)) + end end end -local function is_rpc_registered(mod_name, rpc_name) - - local success = pcall(function() return _RPC_CALLBACKS[mod_name][rpc_name] end) - return success -end - -- #################################################################################################################### -- ##### VMFMod ####################################################################################################### -- #################################################################################################################### @@ -149,26 +195,16 @@ VMFMod.network_send = function (self, rpc_name, recipient, ...) if recipient == "all" then - for peer_id, user_rpcs_dictionary in pairs(_VMF_USERS) do - - local mod_number, rpc_number = convert_names_to_numbers(user_rpcs_dictionary, self:get_name(), rpc_name) - if mod_number then - - send_rpc_vmf_data(peer_id, mod_number, rpc_number, ...) - end + for peer_id, _ in pairs(_VMF_USERS) do + send_rpc_vmf_data(peer_id, self:get_name(), rpc_name, ...) end send_rpc_vmf_data_local(self:get_name(), rpc_name, ...) elseif recipient == "others" then - for peer_id, user_rpcs_dictionary in pairs(_VMF_USERS) do - - local mod_number, rpc_number = convert_names_to_numbers(user_rpcs_dictionary, self:get_name(), rpc_name) - if mod_number then - - send_rpc_vmf_data(peer_id, mod_number, rpc_number, ...) - end + for peer_id, _ in pairs(_VMF_USERS) do + send_rpc_vmf_data(peer_id, self:get_name(), rpc_name, ...) end elseif recipient == "local" or recipient == Network.peer_id() then @@ -177,15 +213,7 @@ VMFMod.network_send = function (self, rpc_name, recipient, ...) else -- recipient == peer_id - local user_rpcs_dictionary = _VMF_USERS[recipient] - if user_rpcs_dictionary then - - local mod_number, rpc_number = convert_names_to_numbers(user_rpcs_dictionary, self:get_name(), rpc_name) - if mod_number then - - send_rpc_vmf_data(recipient, mod_number, rpc_number, ...) - end - end + send_rpc_vmf_data(recipient, self:get_name(), rpc_name, ...) end end @@ -195,41 +223,61 @@ end vmf:hook("ChatManager.rpc_chat_message", function(func, self, sender, channel_id, message_sender, message, localization_param, ...) - if not _NETWORK_MODULE_IS_INITIALIZED then - return - end - if channel_id == 1 then func(self, sender, channel_id, message_sender, message, localization_param, ...) else + if not _NETWORK_MODULE_IS_INITIALIZED then + return + end + if channel_id == 3 then -- rpc_vmf_request + network_debug("ping", "received", sender) + send_rpc_vmf_pong(sender) - vmf:info("[NETWORK][RECIEVED PING] %s", sender) -- @DEBUG: + elseif channel_id == 4 then -- rpc_vmf_responce (@TODO: maybe I should protect it from sending by the player who's not in the game?) - elseif channel_id == 4 then -- rpc_vmf_responce + network_debug("pong", "received", sender) + if vmf.network_debug then + vmf:info("[RECEIVED MODS TABLE]: " .. message) + vmf:info("[RECEIVED RPCS TABLE]: " .. localization_param) + end - _VMF_USERS[sender] = {} + pcall(function() - _VMF_USERS[sender][1] = cjson.decode(message) -- mods - _VMF_USERS[sender][2] = cjson.decode(localization_param) -- rpcs + local user_rpcs_dictionary = {} - vmf:info("[NETWORK][RECIEVED PONG] %s", sender) -- @DEBUG: - vmf:info("[RECEIVED MODS TABLE]: " .. message) -- @DEBUG: - vmf:info("[RECEIVED RPCS TABLE]: " .. localization_param) -- @DEBUG: - vmf:info("Added %s to the VMF users list.", sender) + user_rpcs_dictionary[1] = cjson.decode(message) -- mods + user_rpcs_dictionary[2] = cjson.decode(localization_param) -- rpcs + + _VMF_USERS[sender] = user_rpcs_dictionary + + vmf:info("Added %s to the VMF users list.", sender) + + -- event + local player = Managers.player:player_from_peer_id(sender) + if player then + + for mod_name, _ in pairs(user_rpcs_dictionary[1]) do + local mod = get_mod(mod_name) + if mod then + vmf.mod_user_joined_the_game(mod, player) + end + end + end + end) elseif channel_id == 5 then local mod_number, rpc_number = unpack(cjson.decode(message)) local mod_name, rpc_name = convert_numbers_to_names(mod_number, rpc_number) - if mod_name then + if mod_name and get_mod(mod_name):is_enabled() then - vmf:info("[NETWORK][RECEIVED RPC] '%s.%s' [%s]: %s", mod_name, rpc_name, sender, message) -- @DEBUG: + network_debug("data", "received", sender, mod_name, rpc_name, localization_param) -- can be error in both callback_function() and deserialize_data() local success, error_message = pcall(function() _RPC_CALLBACKS[mod_name][rpc_name](sender, deserialize_data(localization_param)) end) @@ -258,8 +306,17 @@ vmf:hook("PlayerManager.remove_player", function (func, self, peer_id, local_pla for _, player in pairs(Managers.player:human_players()) do if player.peer_id == peer_id then - _VMF_USERS[peer_id] = nil vmf:info("Removed %s from the VMF users list.", peer_id) + + -- event + for mod_name, _ in pairs(_VMF_USERS[peer_id][1]) do + local mod = get_mod(mod_name) + if mod then + vmf.mod_user_left_the_game(mod, player) + end + end + + _VMF_USERS[peer_id] = nil break end end @@ -272,6 +329,8 @@ end) -- ##### VMF internal functions and variables ######################################################################### -- #################################################################################################################### +vmf.network_debug = vmf:get("developer_mode") and vmf:get("show_network_debug_info") + vmf.create_network_dictionary = function() _SHARED_MODS_MAP = {} @@ -306,11 +365,13 @@ end vmf.ping_vmf_users = function() - for _, player in pairs(Managers.player:human_players()) do - if player.peer_id ~= Network.peer_id() then + if Managers.player then + for _, player in pairs(Managers.player:human_players()) do + if player.peer_id ~= Network.peer_id() then - send_rpc_vmf_ping(player.peer_id) - send_rpc_vmf_pong(player.peer_id) + send_rpc_vmf_ping(player.peer_id) + send_rpc_vmf_pong(player.peer_id) + end end end end \ No newline at end of file diff --git a/vmf_source/scripts/mods/vmf/modules/vmf_options.lua b/vmf_source/scripts/mods/vmf/modules/vmf_options.lua index c8f86ff..5659777 100644 --- a/vmf_source/scripts/mods/vmf/modules/vmf_options.lua +++ b/vmf_source/scripts/mods/vmf/modules/vmf_options.lua @@ -42,6 +42,14 @@ local options_widgets = { vmf:localize("show_developer_console_tooltip"), ["default_value"] = false }, + { + ["setting_name"] = "show_network_debug_info", + ["widget_type"] = "checkbox", + ["text"] = vmf:localize("show_network_debug_info"), + ["tooltip"] = vmf:localize("show_network_debug_info") .. "\n" .. + vmf:localize("show_network_debug_info_tooltip"), + ["default_value"] = false + }, -- { -- ["setting_name"] = "toggle_developer_console", -- ["widget_type"] = "keybind", @@ -153,6 +161,8 @@ vmf.on_setting_changed = function (setting_name) Managers.mod._settings.developer_mode = vmf:get(setting_name) Application.set_user_setting("mod_settings", Managers.mod._settings) + vmf.network_debug = vmf:get(setting_name) and vmf:get("show_network_debug_info") + local show_developer_console = vmf:get(setting_name) and vmf:get("show_developer_console") vmf.toggle_developer_console(show_developer_console) @@ -160,6 +170,10 @@ vmf.on_setting_changed = function (setting_name) vmf.toggle_developer_console(vmf:get(setting_name)) + elseif setting_name == "show_network_debug_info" then + + vmf.network_debug = vmf:get(setting_name) + elseif setting_name == "logging_mode" then vmf.load_logging_settings()