Allow using AI in lan racing game

This commit is contained in:
Benau 2019-10-09 14:08:22 +08:00
parent c801191d80
commit a26f67bf16
9 changed files with 136 additions and 31 deletions

View File

@ -251,6 +251,7 @@
#include "utils/log.hpp"
#include "utils/mini_glm.hpp"
#include "utils/profiler.hpp"
#include "utils/separate_process.hpp"
#include "utils/string_utils.hpp"
#include "utils/translation.hpp"
@ -1326,6 +1327,14 @@ int handleCmdLine(bool has_server_config, bool has_parent_process)
}
}
int ai_num = 0;
if (CommandLine::has("--server-ai", &ai_num))
{
Log::info("main", "Add %d server ai(s) server configurable will be "
"disabled.", ai_num);
ServerConfig::m_server_configurable = false;
}
std::string ipv4;
std::string ipv6;
bool has_ipv4 = CommandLine::has("--connect-now", &ipv4);
@ -1407,6 +1416,18 @@ int handleCmdLine(bool has_server_config, bool has_parent_process)
Log::info("main", "Creating a LAN server '%s'.",
server_name.c_str());
}
if (ai_num > 0)
{
STKHost::get()->setSeparateProcess(
new SeparateProcess(
SeparateProcess::getCurrentExecutableLocation(),
std::string("--stdout=server_ai.log --no-graphics"
" --auto-connect --connect-now=127.0.0.1:") +
StringUtils::toString(STKHost::get()->getPrivatePort()) +
" --no-console-log --network-ai="
+ StringUtils::toString(ai_num), false/*create_pipe*/,
"childprocess_ai"/*childprocess_name*/));
}
}
if (CommandLine::has("--auto-connect"))

View File

@ -361,10 +361,12 @@ void ClientLobby::update(int ticks)
case LINKED:
{
NetworkConfig::get()->clearServerCapabilities();
std::string ua = StringUtils::getUserAgentString();
if (NetworkConfig::get()->isNetworkAITester())
ua = "AI";
NetworkString* ns = getNetworkString();
ns->addUInt8(LE_CONNECTION_REQUESTED)
.addUInt32(ServerConfig::m_server_version)
.encodeString(StringUtils::getUserAgentString())
.addUInt32(ServerConfig::m_server_version).encodeString(ua)
.addUInt16((uint16_t)stk_config->m_network_capabilities.size());
for (const std::string& cap : stk_config->m_network_capabilities)
ns->encodeString(cap);
@ -391,7 +393,10 @@ void ClientLobby::update(int ticks)
bool encryption = false;
uint32_t id = PlayerManager::getCurrentOnlineId();
bool lan_ai = !m_server->supportsEncryption() &&
NetworkConfig::get()->isNetworkAITester();
if (lan_ai)
id = 0;
BareNetworkString* rest = new BareNetworkString();
if (m_server->supportsEncryption() && id != 0)
{
@ -410,11 +415,22 @@ void ClientLobby::update(int ticks)
rest->encodeString(ServerConfig::m_private_server_password)
.addUInt8(player_count);
for (auto& p : NetworkConfig::get()->getNetworkPlayers())
for (unsigned i = 0;
i < NetworkConfig::get()->getNetworkPlayers().size(); i++)
{
core::stringw name;
auto& p = NetworkConfig::get()->getNetworkPlayers()[i];
PlayerProfile* player = std::get<1>(p);
rest->encodeString(player->getName()).
core::stringw name = player->getName();
if (lan_ai)
{
// I18N: Shown in lobby to indicate it's a bot in LAN game
name = _("Bot");
if (i > 0)
{
name += core::stringw(" ") + StringUtils::toWString(i);
}
}
rest->encodeString(name).
addFloat(player->getDefaultKartColor());
// Per-player handicap
rest->addUInt8(std::get<2>(p));

View File

@ -3201,7 +3201,7 @@ void ServerLobby::updateServerOwner()
for (auto peer: peers)
{
// Only 127.0.0.1 can be server owner in case of graphics-client-server
if (peer->isValidated() &&
if (peer->isValidated() && peer->getUserVersion() != "AI" &&
(NetworkConfig::get()->getServerIdFile().empty() ||
peer->getAddress().getIP() == 0x7f000001))
{

View File

@ -1639,3 +1639,17 @@ void STKHost::updatePlayers(unsigned* ingame, unsigned* waiting,
if (total)
*total = total_players;
} // updatePlayers
// ----------------------------------------------------------------------------
/** True if this is a client and server in graphics mode made by server
* creation screen. */
bool STKHost::isClientServer() const
{
return NetworkConfig::get()->isClient() && m_separate_process != NULL;
} // isClientServer
// ----------------------------------------------------------------------------
bool STKHost::hasServerAI() const
{
return NetworkConfig::get()->isServer() && m_separate_process != NULL;
} // hasServerAI

View File

@ -37,6 +37,7 @@
#include <enet/enet.h>
#include <atomic>
#include <cassert>
#include <list>
#include <functional>
#include <map>
@ -340,9 +341,15 @@ public:
// ------------------------------------------------------------------------
void sendToServer(NetworkString *data, bool reliable = true);
// ------------------------------------------------------------------------
/** True if this is a client and server in graphics mode made by server
* creation screen. */
bool isClientServer() const { return m_separate_process != NULL; }
bool isClientServer() const;
// ------------------------------------------------------------------------
bool hasServerAI() const;
// ------------------------------------------------------------------------
void setSeparateProcess(SeparateProcess* p)
{
assert(m_separate_process == NULL);
m_separate_process = p;
}
// ------------------------------------------------------------------------
void initClientNetwork(ENetEvent& event, Network* new_network);
// ------------------------------------------------------------------------

View File

@ -86,6 +86,7 @@ void CreateServerScreen::loadedFromFile()
void CreateServerScreen::init()
{
Screen::init();
m_supports_ai = NetworkConfig::get()->isLAN();
m_info_widget->setText("", false);
LabelWidget *title = getWidget<LabelWidget>("title");
@ -142,7 +143,14 @@ void CreateServerScreen::eventCallback(Widget* widget, const std::string& name,
updateMoreOption(selection);
m_prev_mode = selection;
}
else if (name == m_max_players_widget->m_properties[PROP_ID] &&
m_supports_ai)
{
m_prev_value = m_more_options_spinner->getValue();
const int selection =
m_game_mode_widget->getSelection(PLAYER_ID_GAME_MASTER);
updateMoreOption(selection);
}
} // eventCallback
// ----------------------------------------------------------------------------
@ -154,17 +162,39 @@ void CreateServerScreen::updateMoreOption(int game_mode)
case 1:
{
m_more_options_text->setVisible(true);
//I18N: In the create server screen
m_more_options_text->setText(_("No. of grand prix track(s)"),
false);
m_more_options_spinner->setVisible(true);
m_more_options_spinner->clearLabels();
m_more_options_spinner->addLabel(_("Disabled"));
for (int i = 1; i <= 20; i++)
if (m_supports_ai)
{
m_more_options_spinner->addLabel(StringUtils::toWString(i));
m_more_options_text->setText(_("Number of AI karts"),
false);
for (int i = 0; i <= m_max_players_widget->getValue() - 2; i++)
{
m_more_options_spinner->addLabel(
StringUtils::toWString(i));
}
if (m_prev_value > m_max_players_widget->getValue() - 2)
{
m_more_options_spinner->setValue(
m_max_players_widget->getValue() - 2);
}
else
m_more_options_spinner->setValue(m_prev_value);
}
else
{
//I18N: In the create server screen
m_more_options_text->setText(_("No. of grand prix track(s)"),
false);
m_more_options_spinner->addLabel(_("Disabled"));
for (int i = 1; i <= 20; i++)
{
m_more_options_spinner->addLabel(
StringUtils::toWString(i));
}
m_more_options_spinner->setValue(m_prev_value);
}
m_more_options_spinner->setValue(m_prev_value);
break;
}
case 2:
@ -360,9 +390,17 @@ void CreateServerScreen::createServer()
}
else
{
// Grand prix track count
if (esi > 0)
server_cfg << " --network-gp=" << esi;
if (m_supports_ai)
{
if (esi > 0)
server_cfg << " --server-ai=" << esi;
}
else
{
// Grand prix track count
if (esi > 0)
server_cfg << " --network-gp=" << esi;
}
}
m_prev_mode = gamemode_widget->getSelection(PLAYER_ID_GAME_MASTER);
m_prev_value = esi;

View File

@ -34,6 +34,8 @@ class CreateServerScreen : public GUIEngine::Screen,
private:
int m_prev_mode, m_prev_value;
bool m_supports_ai;
friend class GUIEngine::ScreenSingleton<CreateServerScreen>;
CreateServerScreen();

View File

@ -79,14 +79,15 @@ std::string SeparateProcess::getCurrentExecutableLocation()
// ----------------------------------------------------------------------------
SeparateProcess::SeparateProcess(const std::string& exe,
const std::string& argument, bool create_pipe)
const std::string& argument, bool create_pipe,
const std::string& childprocess_name)
{
#ifdef ANDROID
m_child_handle = NULL;
m_child_abort_proc = NULL;
#endif
if (!createChildProcess(exe, argument, create_pipe))
if (!createChildProcess(exe, argument, create_pipe, childprocess_name))
{
Log::error("SeparateProcess", "Failed to run %s %s",
exe.c_str(), argument.c_str());
@ -184,7 +185,8 @@ SeparateProcess::~SeparateProcess()
#if defined(WIN32)
bool SeparateProcess::createChildProcess(const std::string& exe,
const std::string& argument,
bool create_pipe)
bool create_pipe,
const std::string& childprocess_name)
{
// Based on: https://msdn.microsoft.com/en-us/library/windows/desktop/ms682499(v=vs.85).aspx
SECURITY_ATTRIBUTES sec_attr;
@ -281,7 +283,8 @@ bool SeparateProcess::createChildProcess(const std::string& exe,
bool SeparateProcess::createChildProcess(const std::string& exe,
const std::string& argument,
bool create_pipe)
bool create_pipe,
const std::string& childprocess_name)
{
if (create_pipe)
{
@ -323,9 +326,10 @@ bool SeparateProcess::createChildProcess(const std::string& exe,
}
Log::info("SeparateProcess", "Data dir found in: %s", data_path.c_str());
std::string child_path = data_path + "/files/libchildprocess.so";
std::string child_path = data_path + "/files/lib" +
childprocess_name + ".so";
if (access(child_path.c_str(), R_OK) != 0)
{
Log::info("SeparateProcess", "Creating libchildprocess.so");
@ -408,7 +412,8 @@ bool SeparateProcess::createChildProcess(const std::string& exe,
bool SeparateProcess::createChildProcess(const std::string& exe,
const std::string& argument,
bool create_pipe)
bool create_pipe,
const std::string& childprocess_name)
{
const int PIPE_READ=0;
const int PIPE_WRITE=1;

View File

@ -51,7 +51,8 @@ private:
// ------------------------------------------------------------------------
bool createChildProcess(const std::string& exe,
const std::string& argument, bool create_pipe);
const std::string& argument, bool create_pipe,
const std::string& childprocess_name);
// ------------------------------------------------------------------------
std::string getLine();
@ -60,7 +61,8 @@ public:
static std::string getCurrentExecutableLocation();
// ------------------------------------------------------------------------
SeparateProcess(const std::string& exe, const std::string& argument,
bool create_pipe = false);
bool create_pipe = false,
const std::string& childprocess_name = "childprocess");
// ------------------------------------------------------------------------
~SeparateProcess();
// ------------------------------------------------------------------------