Allow using AI in lan racing game
This commit is contained in:
parent
c801191d80
commit
a26f67bf16
21
src/main.cpp
21
src/main.cpp
@ -251,6 +251,7 @@
|
|||||||
#include "utils/log.hpp"
|
#include "utils/log.hpp"
|
||||||
#include "utils/mini_glm.hpp"
|
#include "utils/mini_glm.hpp"
|
||||||
#include "utils/profiler.hpp"
|
#include "utils/profiler.hpp"
|
||||||
|
#include "utils/separate_process.hpp"
|
||||||
#include "utils/string_utils.hpp"
|
#include "utils/string_utils.hpp"
|
||||||
#include "utils/translation.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 ipv4;
|
||||||
std::string ipv6;
|
std::string ipv6;
|
||||||
bool has_ipv4 = CommandLine::has("--connect-now", &ipv4);
|
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'.",
|
Log::info("main", "Creating a LAN server '%s'.",
|
||||||
server_name.c_str());
|
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"))
|
if (CommandLine::has("--auto-connect"))
|
||||||
|
@ -361,10 +361,12 @@ void ClientLobby::update(int ticks)
|
|||||||
case LINKED:
|
case LINKED:
|
||||||
{
|
{
|
||||||
NetworkConfig::get()->clearServerCapabilities();
|
NetworkConfig::get()->clearServerCapabilities();
|
||||||
|
std::string ua = StringUtils::getUserAgentString();
|
||||||
|
if (NetworkConfig::get()->isNetworkAITester())
|
||||||
|
ua = "AI";
|
||||||
NetworkString* ns = getNetworkString();
|
NetworkString* ns = getNetworkString();
|
||||||
ns->addUInt8(LE_CONNECTION_REQUESTED)
|
ns->addUInt8(LE_CONNECTION_REQUESTED)
|
||||||
.addUInt32(ServerConfig::m_server_version)
|
.addUInt32(ServerConfig::m_server_version).encodeString(ua)
|
||||||
.encodeString(StringUtils::getUserAgentString())
|
|
||||||
.addUInt16((uint16_t)stk_config->m_network_capabilities.size());
|
.addUInt16((uint16_t)stk_config->m_network_capabilities.size());
|
||||||
for (const std::string& cap : stk_config->m_network_capabilities)
|
for (const std::string& cap : stk_config->m_network_capabilities)
|
||||||
ns->encodeString(cap);
|
ns->encodeString(cap);
|
||||||
@ -391,7 +393,10 @@ void ClientLobby::update(int ticks)
|
|||||||
|
|
||||||
bool encryption = false;
|
bool encryption = false;
|
||||||
uint32_t id = PlayerManager::getCurrentOnlineId();
|
uint32_t id = PlayerManager::getCurrentOnlineId();
|
||||||
|
bool lan_ai = !m_server->supportsEncryption() &&
|
||||||
|
NetworkConfig::get()->isNetworkAITester();
|
||||||
|
if (lan_ai)
|
||||||
|
id = 0;
|
||||||
BareNetworkString* rest = new BareNetworkString();
|
BareNetworkString* rest = new BareNetworkString();
|
||||||
if (m_server->supportsEncryption() && id != 0)
|
if (m_server->supportsEncryption() && id != 0)
|
||||||
{
|
{
|
||||||
@ -410,11 +415,22 @@ void ClientLobby::update(int ticks)
|
|||||||
|
|
||||||
rest->encodeString(ServerConfig::m_private_server_password)
|
rest->encodeString(ServerConfig::m_private_server_password)
|
||||||
.addUInt8(player_count);
|
.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);
|
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());
|
addFloat(player->getDefaultKartColor());
|
||||||
// Per-player handicap
|
// Per-player handicap
|
||||||
rest->addUInt8(std::get<2>(p));
|
rest->addUInt8(std::get<2>(p));
|
||||||
|
@ -3201,7 +3201,7 @@ void ServerLobby::updateServerOwner()
|
|||||||
for (auto peer: peers)
|
for (auto peer: peers)
|
||||||
{
|
{
|
||||||
// Only 127.0.0.1 can be server owner in case of graphics-client-server
|
// 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() ||
|
(NetworkConfig::get()->getServerIdFile().empty() ||
|
||||||
peer->getAddress().getIP() == 0x7f000001))
|
peer->getAddress().getIP() == 0x7f000001))
|
||||||
{
|
{
|
||||||
|
@ -1639,3 +1639,17 @@ void STKHost::updatePlayers(unsigned* ingame, unsigned* waiting,
|
|||||||
if (total)
|
if (total)
|
||||||
*total = total_players;
|
*total = total_players;
|
||||||
} // updatePlayers
|
} // 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
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include <enet/enet.h>
|
#include <enet/enet.h>
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <cassert>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <map>
|
#include <map>
|
||||||
@ -340,9 +341,15 @@ public:
|
|||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
void sendToServer(NetworkString *data, bool reliable = true);
|
void sendToServer(NetworkString *data, bool reliable = true);
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** True if this is a client and server in graphics mode made by server
|
bool isClientServer() const;
|
||||||
* creation screen. */
|
// ------------------------------------------------------------------------
|
||||||
bool isClientServer() const { return m_separate_process != NULL; }
|
bool hasServerAI() const;
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
void setSeparateProcess(SeparateProcess* p)
|
||||||
|
{
|
||||||
|
assert(m_separate_process == NULL);
|
||||||
|
m_separate_process = p;
|
||||||
|
}
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
void initClientNetwork(ENetEvent& event, Network* new_network);
|
void initClientNetwork(ENetEvent& event, Network* new_network);
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
@ -86,6 +86,7 @@ void CreateServerScreen::loadedFromFile()
|
|||||||
void CreateServerScreen::init()
|
void CreateServerScreen::init()
|
||||||
{
|
{
|
||||||
Screen::init();
|
Screen::init();
|
||||||
|
m_supports_ai = NetworkConfig::get()->isLAN();
|
||||||
m_info_widget->setText("", false);
|
m_info_widget->setText("", false);
|
||||||
LabelWidget *title = getWidget<LabelWidget>("title");
|
LabelWidget *title = getWidget<LabelWidget>("title");
|
||||||
|
|
||||||
@ -142,7 +143,14 @@ void CreateServerScreen::eventCallback(Widget* widget, const std::string& name,
|
|||||||
updateMoreOption(selection);
|
updateMoreOption(selection);
|
||||||
m_prev_mode = 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
|
} // eventCallback
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -154,17 +162,39 @@ void CreateServerScreen::updateMoreOption(int game_mode)
|
|||||||
case 1:
|
case 1:
|
||||||
{
|
{
|
||||||
m_more_options_text->setVisible(true);
|
m_more_options_text->setVisible(true);
|
||||||
|
m_more_options_spinner->setVisible(true);
|
||||||
|
m_more_options_spinner->clearLabels();
|
||||||
|
if (m_supports_ai)
|
||||||
|
{
|
||||||
|
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
|
//I18N: In the create server screen
|
||||||
m_more_options_text->setText(_("No. of grand prix track(s)"),
|
m_more_options_text->setText(_("No. of grand prix track(s)"),
|
||||||
false);
|
false);
|
||||||
m_more_options_spinner->setVisible(true);
|
|
||||||
m_more_options_spinner->clearLabels();
|
|
||||||
m_more_options_spinner->addLabel(_("Disabled"));
|
m_more_options_spinner->addLabel(_("Disabled"));
|
||||||
for (int i = 1; i <= 20; i++)
|
for (int i = 1; i <= 20; i++)
|
||||||
{
|
{
|
||||||
m_more_options_spinner->addLabel(StringUtils::toWString(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;
|
break;
|
||||||
}
|
}
|
||||||
case 2:
|
case 2:
|
||||||
@ -359,11 +389,19 @@ void CreateServerScreen::createServer()
|
|||||||
server_cfg << " --battle-mode=" << esi;
|
server_cfg << " --battle-mode=" << esi;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (m_supports_ai)
|
||||||
|
{
|
||||||
|
if (esi > 0)
|
||||||
|
server_cfg << " --server-ai=" << esi;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// Grand prix track count
|
// Grand prix track count
|
||||||
if (esi > 0)
|
if (esi > 0)
|
||||||
server_cfg << " --network-gp=" << esi;
|
server_cfg << " --network-gp=" << esi;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
m_prev_mode = gamemode_widget->getSelection(PLAYER_ID_GAME_MASTER);
|
m_prev_mode = gamemode_widget->getSelection(PLAYER_ID_GAME_MASTER);
|
||||||
m_prev_value = esi;
|
m_prev_value = esi;
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,8 @@ class CreateServerScreen : public GUIEngine::Screen,
|
|||||||
private:
|
private:
|
||||||
int m_prev_mode, m_prev_value;
|
int m_prev_mode, m_prev_value;
|
||||||
|
|
||||||
|
bool m_supports_ai;
|
||||||
|
|
||||||
friend class GUIEngine::ScreenSingleton<CreateServerScreen>;
|
friend class GUIEngine::ScreenSingleton<CreateServerScreen>;
|
||||||
|
|
||||||
CreateServerScreen();
|
CreateServerScreen();
|
||||||
|
@ -79,14 +79,15 @@ std::string SeparateProcess::getCurrentExecutableLocation()
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
SeparateProcess::SeparateProcess(const std::string& exe,
|
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
|
#ifdef ANDROID
|
||||||
m_child_handle = NULL;
|
m_child_handle = NULL;
|
||||||
m_child_abort_proc = NULL;
|
m_child_abort_proc = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!createChildProcess(exe, argument, create_pipe))
|
if (!createChildProcess(exe, argument, create_pipe, childprocess_name))
|
||||||
{
|
{
|
||||||
Log::error("SeparateProcess", "Failed to run %s %s",
|
Log::error("SeparateProcess", "Failed to run %s %s",
|
||||||
exe.c_str(), argument.c_str());
|
exe.c_str(), argument.c_str());
|
||||||
@ -184,7 +185,8 @@ SeparateProcess::~SeparateProcess()
|
|||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
bool SeparateProcess::createChildProcess(const std::string& exe,
|
bool SeparateProcess::createChildProcess(const std::string& exe,
|
||||||
const std::string& argument,
|
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
|
// Based on: https://msdn.microsoft.com/en-us/library/windows/desktop/ms682499(v=vs.85).aspx
|
||||||
SECURITY_ATTRIBUTES sec_attr;
|
SECURITY_ATTRIBUTES sec_attr;
|
||||||
@ -281,7 +283,8 @@ bool SeparateProcess::createChildProcess(const std::string& exe,
|
|||||||
|
|
||||||
bool SeparateProcess::createChildProcess(const std::string& exe,
|
bool SeparateProcess::createChildProcess(const std::string& exe,
|
||||||
const std::string& argument,
|
const std::string& argument,
|
||||||
bool create_pipe)
|
bool create_pipe,
|
||||||
|
const std::string& childprocess_name)
|
||||||
{
|
{
|
||||||
if (create_pipe)
|
if (create_pipe)
|
||||||
{
|
{
|
||||||
@ -324,7 +327,8 @@ bool SeparateProcess::createChildProcess(const std::string& exe,
|
|||||||
|
|
||||||
Log::info("SeparateProcess", "Data dir found in: %s", data_path.c_str());
|
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)
|
if (access(child_path.c_str(), R_OK) != 0)
|
||||||
{
|
{
|
||||||
@ -408,7 +412,8 @@ bool SeparateProcess::createChildProcess(const std::string& exe,
|
|||||||
|
|
||||||
bool SeparateProcess::createChildProcess(const std::string& exe,
|
bool SeparateProcess::createChildProcess(const std::string& exe,
|
||||||
const std::string& argument,
|
const std::string& argument,
|
||||||
bool create_pipe)
|
bool create_pipe,
|
||||||
|
const std::string& childprocess_name)
|
||||||
{
|
{
|
||||||
const int PIPE_READ=0;
|
const int PIPE_READ=0;
|
||||||
const int PIPE_WRITE=1;
|
const int PIPE_WRITE=1;
|
||||||
|
@ -51,7 +51,8 @@ private:
|
|||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
bool createChildProcess(const std::string& exe,
|
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();
|
std::string getLine();
|
||||||
|
|
||||||
@ -60,7 +61,8 @@ public:
|
|||||||
static std::string getCurrentExecutableLocation();
|
static std::string getCurrentExecutableLocation();
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
SeparateProcess(const std::string& exe, const std::string& argument,
|
SeparateProcess(const std::string& exe, const std::string& argument,
|
||||||
bool create_pipe = false);
|
bool create_pipe = false,
|
||||||
|
const std::string& childprocess_name = "childprocess");
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
~SeparateProcess();
|
~SeparateProcess();
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
Loading…
x
Reference in New Issue
Block a user