forked from alterware/iw6-mod
		
	maint(bots): update logic
This commit is contained in:
		| @@ -75,8 +75,8 @@ namespace bots | ||||
| 				return; | ||||
| 			} | ||||
|  | ||||
| 			auto* bot_name = game::SV_BotGetRandomName(); | ||||
| 			auto* bot_ent = game::SV_AddBot(bot_name, 26, 62, 0); | ||||
| 			const auto* bot_name = game::SV_BotGetRandomName(); | ||||
| 			const auto* bot_ent = game::SV_AddBot(bot_name, 26, 62, 0); | ||||
| 			if (bot_ent) | ||||
| 			{ | ||||
| 				spawn_bot(bot_ent->s.number); | ||||
| @@ -87,34 +87,13 @@ namespace bots | ||||
| 		volatile bool bot_names_received = false; | ||||
| 		std::vector<std::string> bot_names; | ||||
|  | ||||
| 		const char* get_random_bot_name() | ||||
| 		{ | ||||
| 			if (bot_names.empty()) | ||||
| 			{ | ||||
| 				return get_bot_name_hook.invoke<const char*>(); | ||||
| 			} | ||||
|  | ||||
| 			const auto index = std::rand() % bot_names.size(); | ||||
| 			const auto& name = bot_names.at(index); | ||||
|  | ||||
| 			return utils::string::va("%.*s", static_cast<int>(name.size()), name.data()); | ||||
| 		} | ||||
|  | ||||
| 		bool should_update_bot_names() | ||||
| 		bool should_use_remote_bot_names() | ||||
| 		{ | ||||
| #ifdef ALLOW_CUSTOM_BOT_NAMES | ||||
| 			return !filesystem::exists("bots.txt"); | ||||
| 		} | ||||
|  | ||||
| 		void update_bot_names() | ||||
| 		{ | ||||
| 			bot_names_received = false; | ||||
|  | ||||
| 			game::netadr_s master{}; | ||||
| 			if (server_list::get_master_server(master)) | ||||
| 			{ | ||||
| 				console::info("Getting bots...\n"); | ||||
| 				network::send(master, "getbots"); | ||||
| 			} | ||||
| #else | ||||
| 			return true; | ||||
| #endif | ||||
| 		} | ||||
|  | ||||
| 		void parse_bot_names_from_file() | ||||
| @@ -141,6 +120,37 @@ namespace bots | ||||
| 				bot_names.emplace_back(entry); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		const char* get_random_bot_name() | ||||
| 		{ | ||||
| 			if (!bot_names_received && bot_names.empty()) | ||||
| 			{ | ||||
| 				// last attempt to use custom names if they can be found | ||||
| 				parse_bot_names_from_file(); | ||||
| 			} | ||||
|  | ||||
| 			if (bot_names.empty()) | ||||
| 			{ | ||||
| 				return get_bot_name_hook.invoke<const char*>(); | ||||
| 			} | ||||
|  | ||||
| 			const auto index = std::rand() % bot_names.size(); | ||||
| 			const auto& name = bot_names.at(index); | ||||
|  | ||||
| 			return utils::string::va("%.*s", static_cast<int>(name.size()), name.data()); | ||||
| 		} | ||||
|  | ||||
| 		void update_bot_names() | ||||
| 		{ | ||||
| 			bot_names_received = false; | ||||
|  | ||||
| 			game::netadr_s master{}; | ||||
| 			if (server_list::get_master_server(master)) | ||||
| 			{ | ||||
| 				console::info("Getting bots...\n"); | ||||
| 				network::send(master, "getbots"); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	class component final : public component_interface | ||||
| @@ -159,23 +169,23 @@ namespace bots | ||||
| 			{ | ||||
| 				if (!game::SV_Loaded()) return; | ||||
|  | ||||
| 				auto num_bots = 1; | ||||
| 				std::size_t num_bots = 1; | ||||
| 				if (params.size() == 2) | ||||
| 				{ | ||||
| 					num_bots = atoi(params.get(1)); | ||||
| 					num_bots = std::strtoul(params.get(1), nullptr, 10); | ||||
| 				} | ||||
|  | ||||
| 				num_bots = std::min(num_bots, *game::mp::svs_clientCount); | ||||
| 				num_bots = std::min(num_bots, static_cast<std::size_t>(*game::mp::svs_clientCount)); | ||||
|  | ||||
| 				console::info("Spawning %i %s\n", num_bots, (num_bots == 1 ? "bot" : "bots")); | ||||
| 				console::info("Spawning %zu %s\n", num_bots, (num_bots == 1 ? "bot" : "bots")); | ||||
|  | ||||
| 				for (auto i = 0; i < num_bots; i++) | ||||
| 				for (std::size_t i = 0; i < num_bots; ++i) | ||||
| 				{ | ||||
| 					scheduler::once(add_bot, scheduler::pipeline::server, 100ms * i); | ||||
| 				} | ||||
| 			}); | ||||
|  | ||||
| 			if (should_update_bot_names()) | ||||
| 			if (should_use_remote_bot_names()) | ||||
| 			{ | ||||
| 				scheduler::on_game_initialized([]() | ||||
| 				{ | ||||
|   | ||||
| @@ -142,21 +142,21 @@ namespace network | ||||
|  | ||||
| 	const char* net_adr_to_string(const game::netadr_s& a) | ||||
| 	{ | ||||
| 		if (a.type == game::netadrtype_t::NA_LOOPBACK) | ||||
| 		if (a.type == game::NA_LOOPBACK) | ||||
| 		{ | ||||
| 			return "loopback"; | ||||
| 		} | ||||
|  | ||||
| 		if (a.type == game::netadrtype_t::NA_BOT) | ||||
| 		if (a.type == game::NA_BOT) | ||||
| 		{ | ||||
| 			return "bot"; | ||||
| 		} | ||||
|  | ||||
| 		if (a.type == game::netadrtype_t::NA_IP || a.type == game::netadrtype_t::NA_BROADCAST) | ||||
| 		if (a.type == game::NA_IP || a.type == game::NA_BROADCAST) | ||||
| 		{ | ||||
| 			if (a.port) | ||||
| 			{ | ||||
| 				return utils::string::va("%u.%u.%u.%u:%u", a.ip[0], a.ip[1], a.ip[2], a.ip[3], htons(a.port)); | ||||
| 				return utils::string::va("%u.%u.%u.%u:%u", a.ip[0], a.ip[1], a.ip[2], a.ip[3], ::htons(a.port)); | ||||
| 			} | ||||
|  | ||||
| 			return utils::string::va("%u.%u.%u.%u", a.ip[0], a.ip[1], a.ip[2], a.ip[3]); | ||||
| @@ -193,10 +193,9 @@ namespace network | ||||
| 		a.jmp(0x14041DFBD); | ||||
| 	} | ||||
|  | ||||
| 	game::dvar_t* register_netport_stub(const char* dvarName, int value, int min, int max, unsigned int flags, | ||||
| 		const char* description) | ||||
| 	game::dvar_t* register_netport_stub(const char* dvarName, int value, int min, int max, unsigned int flags, const char* description) | ||||
| 	{ | ||||
| 		auto dvar = game::Dvar_RegisterInt("net_port", 27016, 0, 0xFFFFu, game::DVAR_FLAG_LATCHED, "Network port"); | ||||
| 		auto* dvar = game::Dvar_RegisterInt("net_port", 27016, 0, std::numeric_limits<uint16_t>::max(), game::DVAR_FLAG_LATCHED, "Network port"); | ||||
|  | ||||
| 		// read net_port from command line | ||||
| 		command::read_startup_variable("net_port"); | ||||
| @@ -231,7 +230,7 @@ namespace network | ||||
| 				utils::hook::set<uint8_t>(0x1402ECF1D, 0xEB); | ||||
| 				utils::hook::set<uint8_t>(0x1402ED02A, 0xEB); | ||||
| 				utils::hook::set<uint8_t>(0x1402ED34D, 0xEB); | ||||
| 				utils::hook::set<uint8_t>(0x1402C4A1F, 0xEB); // | ||||
| 				utils::hook::set<uint8_t>(0x1402C4A1F, 0xEB); | ||||
|  | ||||
| 				// ignore unregistered connection | ||||
| 				utils::hook::jump(0x140471AAC, reinterpret_cast<void*>(0x140471A50)); | ||||
| @@ -285,7 +284,7 @@ namespace network | ||||
| 				utils::hook::set<std::uint8_t>(0x1402C6AA4, 0xEB); | ||||
|  | ||||
| 				// patch buffer overflow | ||||
| 				utils::hook::call(0x14041D17E, memmove_stub); | ||||
| 				utils::hook::call(0x14041D17E, memmove_stub); // NET_DeferPacketToClient | ||||
| 				// this patches a crash found in a subroutine registered using atexit | ||||
| 				utils::hook::set<std::uint8_t>(0x140815D4E, 0xEB); | ||||
| 			} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user