<commit_before>/***************************************************************************
 *   Copyright (C) 2007 by <NAME>                                      *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include <net/socket_helper.h>
#include <net/clientthread.h>
#include <net/clientstate.h>
#include <net/clientcontext.h>
#include <net/senderthread.h>
#include <net/receiverhelper.h>
#include <net/clientexception.h>
#include <net/socket_msg.h>
#include <core/avatarmanager.h>
#include <core/loghelper.h>
#include <clientenginefactory.h>
#include <game.h>
#include <qttoolsinterface.h>

#include <boost/lambda/lambda.hpp>
#include <sstream>
#include <memory>
#include <cassert>

using namespace std;


class ClientSenderCallback : public SenderCallback
{
public:
	ClientSenderCallback(ClientThread &client) : m_client(client) {}
	virtual ~ClientSenderCallback() {}

	virtual void SignalNetError(SessionId /*session*/, int errorID, int osErrorID)
	{
		// Just signal the error.
		// We assume that the client thread will be terminated.
		m_client.GetCallback().SignalNetClientError(errorID, osErrorID);
	}

private:
	ClientThread &m_client;
};


ClientThread::ClientThread(GuiInterface &gui, AvatarManager &avatarManager)
: m_curState(NULL), m_gui(gui), m_avatarManager(avatarManager),
  m_curGameId(0), m_curGameNum(1), m_guiPlayerId(0), m_sessionEstablished(false)
{
	m_context.reset(new ClientContext);
	m_senderCallback.reset(new ClientSenderCallback(*this));
	m_sender.reset(new SenderThread(GetSenderCallback()));
	m_receiver.reset(new ReceiverHelper);
	myQtToolsInterface.reset(CreateQtToolsWrapper());
}

ClientThread::~ClientThread()
{
}

void
ClientThread::Init(
	const string &serverAddress, const string &serverListUrl,
	bool useServerList, unsigned serverPort, bool ipv6, bool sctp,
	const string &pwd, const string &playerName, const string &avatarFile,
	const string &cacheDir)
{
	if (IsRunning())
	{
		assert(false);
		return;
	}

	ClientContext &context = GetContext();

	context.SetProtocol(sctp ? SOCKET_IPPROTO_SCTP : 0);
	context.SetAddrFamily(ipv6 ? AF_INET6 : AF_INET);
	context.SetServerAddr(serverAddress);
	context.SetServerListUrl(serverListUrl);
	context.SetUseServerList(useServerList);
	context.SetServerPort(serverPort);
	context.SetPassword(<PASSWORD>);
	context.SetPlayerName(playerName);
	context.SetAvatarFile(avatarFile);
	context.SetCacheDir(cacheDir);
}

void
ClientThread::SendKickPlayer(unsigned playerId)
{
	boost::shared_ptr<NetPacket> request(new NetPacketKickPlayer);
	NetPacketKickPlayer::Data requestData;
	requestData.playerId = playerId;
	static_cast<NetPacketKickPlayer *>(request.get())->SetData(requestData);
	boost::mutex::scoped_lock lock(m_outPacketListMutex);
	m_outPacketList.push_back(request);
}

void
ClientThread::SendLeaveCurrentGame()
{
	boost::shared_ptr<NetPacket> request(new NetPacketLeaveCurrentGame);
	boost::mutex::scoped_lock lock(m_outPacketListMutex);
	m_outPacketList.push_back(request);
}

void
ClientThread::SendStartEvent(bool fillUpWithCpuPlayers)
{
	// Warning: This function is called in the context of the GUI thread.
	// Create a network packet for the server start event.
	boost::shared_ptr<NetPacket> start(new NetPacketStartEvent);
	NetPacketStartEvent::Data startData;
	startData.fillUpWithCpuPlayers = fillUpWithCpuPlayers;
	try
	{
		static_cast<NetPacketStartEvent *>(start.get())->SetData(startData);
		boost::mutex::scoped_lock lock(m_outPacketListMutex);
		m_outPacketList.push_back(start);
	} catch (const NetException &e)
	{
		LOG_ERROR("ClientThread::SendStartEvent: " << e.what());
	}
}

void
ClientThread::SendPlayerAction()
{
	// Warning: This function is called in the context of the GUI thread.
	// Create a network packet containing the current player action.
	boost::shared_ptr<NetPacket> action(new NetPacketPlayersAction);
	NetPacketPlayersAction::Data actionData;
	boost::shared_ptr<PlayerInterface> myPlayer = GetGame()->getSeatsList()->front();
	actionData.gameState = static_cast<GameState>(GetGame()->getCurrentHand()->getCurrentRound());
	actionData.playerAction = static_cast<PlayerAction>(myPlayer->getMyAction());
	// Only send last bet if not fold/checked.
	if (actionData.playerAction != PLAYER_ACTION_FOLD && actionData.playerAction != PLAYER_ACTION_CHECK)
		actionData.playerBet = myPlayer->getMyLastRelativeSet();
	else
		actionData.playerBet = 0;
	try
	{
		static_cast<NetPacketPlayersAction *>(action.get())->SetData(actionData);
		// Just dump the packet.
		boost::mutex::scoped_lock lock(m_outPacketListMutex);
		m_outPacketList.push_back(action);
	} catch (const NetException &e)
	{
		LOG_ERROR("ClientThread::SendPlayerAction: " << e.what());
	}
}

void
ClientThread::SendChatMessage(const std::string &msg)
{
	// Warning: This function is called in the context of the GUI thread.
	// Create a network packet containing the chat message.
	boost::shared_ptr<NetPacket> chat(new NetPacketSendChatText);
	NetPacketSendChatText::Data chatData;
	chatData.text = msg;
	try
	{
		static_cast<NetPacketSendChatText *>(chat.get())->SetData(chatData);
		// Just dump the packet.
		boost::mutex::scoped_lock lock(m_outPacketListMutex);
		m_outPacketList.push_back(chat);
	} catch (const NetException &e)
	{
		LOG_ERROR("ClientThread::SendChatMessage: " << e.what());
	}
}

void
ClientThread::SendJoinFirstGame(const std::string &password)
{
	// Warning: This function is called in the context of the GUI thread.
	// Create a network packet to request joining a game.
	boost::shared_ptr<NetPacket> join(new NetPacketJoinGame);
	NetPacketJoinGame::Data joinData;
	joinData.gameId = 0;
	joinData.password = password;
	try
	{
		static_cast<NetPacketJoinGame *>(join.get())->SetData(joinData);
		boost::mutex::scoped_lock lock(m_outPacketListMutex);
		m_outPacketList.push_back(join);
	} catch (const NetException &e)
	{
		LOG_ERROR("ClientThread::SendJoinFirstGame: " << e.what());
	}
}

void
ClientThread::SendJoinGame(unsigned gameId, const std::string &password)
{
	// Warning: This function is called in the context of the GUI thread.<commit_msg>Fixed network game bug which was introduced in the bugfix release by changing the id of the first game to 1.<commit_after>/***************************************************************************
 *   Copyright (C) 2007 by <NAME>                                      *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include <net/socket_helper.h>
#include <net/clientthread.h>
#include <net/clientstate.h>
#include <net/clientcontext.h>
#include <net/senderthread.h>
#include <net/receiverhelper.h>
#include <net/clientexception.h>
#include <net/socket_msg.h>
#include <core/avatarmanager.h>
#include <core/loghelper.h>
#include <clientenginefactory.h>
#include <game.h>
#include <qttoolsinterface.h>

#include <boost/lambda/lambda.hpp>
#include <sstream>
#include <memory>
#include <cassert>

using namespace std;


class ClientSenderCallback : public SenderCallback
{
public:
	ClientSenderCallback(ClientThread &client) : m_client(client) {}
	virtual ~ClientSenderCallback() {}

	virtual void SignalNetError(SessionId /*session*/, int errorID, int osErrorID)
	{
		// Just signal the error.
		// We assume that the client thread will be terminated.
		m_client.GetCallback().SignalNetClientError(errorID, osErrorID);
	}

private:
	ClientThread &m_client;
};


ClientThread::ClientThread(GuiInterface &gui, AvatarManager &avatarManager)
: m_curState(NULL), m_gui(gui), m_avatarManager(avatarManager),
  m_curGameId(0), m_curGameNum(1), m_guiPlayerId(0), m_sessionEstablished(false)
{
	m_context.reset(new ClientContext);
	m_senderCallback.reset(new ClientSenderCallback(*this));
	m_sender.reset(new SenderThread(GetSenderCallback()));
	m_receiver.reset(new ReceiverHelper);
	myQtToolsInterface.reset(CreateQtToolsWrapper());
}

ClientThread::~ClientThread()
{
}

void
ClientThread::Init(
	const string &serverAddress, const string &serverListUrl,
	bool useServerList, unsigned serverPort, bool ipv6, bool sctp,
	const string &pwd, const string &playerName, const string &avatarFile,
	const string &cacheDir)
{
	if (IsRunning())
	{
		assert(false);
		return;
	}

	ClientContext &context = GetContext();

	context.SetProtocol(sctp ? SOCKET_IPPROTO_SCTP : 0);
	context.SetAddrFamily(ipv6 ? AF_INET6 : AF_INET);
	context.SetServerAddr(serverAddress);
	context.SetServerListUrl(serverListUrl);
	context.SetUseServerList(useServerList);
	context.SetServerPort(serverPort);
	context.SetPassword(<PASSWORD>);
	context.SetPlayerName(playerName);
	context.SetAvatarFile(avatarFile);
	context.SetCacheDir(cacheDir);
}

void
ClientThread::SendKickPlayer(unsigned playerId)
{
	boost::shared_ptr<NetPacket> request(new NetPacketKickPlayer);
	NetPacketKickPlayer::Data requestData;
	requestData.playerId = playerId;
	static_cast<NetPacketKickPlayer *>(request.get())->SetData(requestData);
	boost::mutex::scoped_lock lock(m_outPacketListMutex);
	m_outPacketList.push_back(request);
}

void
ClientThread::SendLeaveCurrentGame()
{
	boost::shared_ptr<NetPacket> request(new NetPacketLeaveCurrentGame);
	boost::mutex::scoped_lock lock(m_outPacketListMutex);
	m_outPacketList.push_back(request);
}

void
ClientThread::SendStartEvent(bool fillUpWithCpuPlayers)
{
	// Warning: This function is called in the context of the GUI thread.
	// Create a network packet for the server start event.
	boost::shared_ptr<NetPacket> start(new NetPacketStartEvent);
	NetPacketStartEvent::Data startData;
	startData.fillUpWithCpuPlayers = fillUpWithCpuPlayers;
	try
	{
		static_cast<NetPacketStartEvent *>(start.get())->SetData(startData);
		boost::mutex::scoped_lock lock(m_outPacketListMutex);
		m_outPacketList.push_back(start);
	} catch (const NetException &e)
	{
		LOG_ERROR("ClientThread::SendStartEvent: " << e.what());
	}
}

void
ClientThread::SendPlayerAction()
{
	// Warning: This function is called in the context of the GUI thread.
	// Create a network packet containing the current player action.
	boost::shared_ptr<NetPacket> action(new NetPacketPlayersAction);
	NetPacketPlayersAction::Data actionData;
	boost::shared_ptr<PlayerInterface> myPlayer = GetGame()->getSeatsList()->front();
	actionData.gameState = static_cast<GameState>(GetGame()->getCurrentHand()->getCurrentRound());
	actionData.playerAction = static_cast<PlayerAction>(myPlayer->getMyAction());
	// Only send last bet if not fold/checked.
	if (actionData.playerAction != PLAYER_ACTION_FOLD && actionData.playerAction != PLAYER_ACTION_CHECK)
		actionData.playerBet = myPlayer->getMyLastRelativeSet();
	else
		actionData.playerBet = 0;
	try
	{
		static_cast<NetPacketPlayersAction *>(action.get())->SetData(actionData);
		// Just dump the packet.
		boost::mutex::scoped_lock lock(m_outPacketListMutex);
		m_outPacketList.push_back(action);
	} catch (const NetException &e)
	{
		LOG_ERROR("ClientThread::SendPlayerAction: " << e.what());
	}
}

void
ClientThread::SendChatMessage(const std::string &msg)
{
	// Warning: This function is called in the context of the GUI thread.
	// Create a network packet containing the chat message.
	boost::shared_ptr<NetPacket> chat(new NetPacketSendChatText);
	NetPacketSendChatText::Data chatData;
	chatData.text = msg;
	try
	{
		static_cast<NetPacketSendChatText *>(chat.get())->SetData(chatData);
		// Just dump the packet.
		boost::mutex::scoped_lock lock(m_outPacketListMutex);
		m_outPacketList.push_back(chat);
	} catch (const NetException &e)
	{
		LOG_ERROR("ClientThread::SendChatMessage: " << e.what());
	}
}

void
ClientThread::SendJoinFirstGame(const std::string &password)
{
	// Warning: This function is called in the context of the GUI thread.
	// Create a network packet to request joining a game.
	boost::shared_ptr<NetPacket> join(new NetPacketJoinGame);
	NetPacketJoinGame::Data joinData;
	joinData.gameId = 1;
	joinData.password = password;
	try
	{
		static_cast<NetPacketJoinGame *>(join.get())->SetData(joinData);
		boost::mutex::scoped_lock lock(m_outPacketListMutex);
		m_outPacketList.push_back(join);
	} catch (const NetException &e)
	{
		LOG_ERROR("ClientThread::SendJoinFirstGame: " << e.what());
	}
}

void
ClientThread::SendJoinGame(unsigned gameId, const std::string &password)
{
	// Warning: This function is called in the context of the GUI thread.
{'fraction_non_alphanumeric': 0.1266351619752072, 'fraction_numerical': 0.003903842202588864, 'mean_word_length': 4.2487419122933145, 'pattern_counts': {'":': 0, '<': 85, '<?xml version=': 0, '>': 91, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 24, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5808644', 'n_tokens_mistral': 4440, 'n_tokens_neox': 4300, 'n_words': 1033}