Пример #1
0
// called from ---NETPLAY--- thread
unsigned int NetPlayServer::OnDisconnect(sf::SocketTCP& socket)
{
	PlayerId pid = m_players[socket].pid;

	if (m_is_running)
	{
		for (PadMapping mapping : m_pad_map)
		{
			if (mapping == pid)
			{
				PanicAlertT("Client disconnect while game is running!! NetPlay is disabled. You must manually stop the game.");
				std::lock_guard<std::recursive_mutex> lkg(m_crit.game);
				m_is_running = false;

				sf::Packet spac;
				spac << (MessageId)NP_MSG_DISABLE_GAME;
				// this thread doesn't need players lock
				std::lock_guard<std::recursive_mutex> lks(m_crit.send);
				SendToClients(spac);
				break;
			}
		}
	}

	sf::Packet spac;
	spac << (MessageId)NP_MSG_PLAYER_LEAVE;
	spac << pid;

	m_selector.Remove(socket);

	std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
	m_players.erase(m_players.find(socket));

	// alert other players of disconnect
	std::lock_guard<std::recursive_mutex> lks(m_crit.send);
	SendToClients(spac);

	for (PadMapping& mapping : m_pad_map)
	{
		if (mapping == pid)
		{
			mapping = -1;
		}
	}
	UpdatePadMapping();

	for (PadMapping& mapping : m_wiimote_map)
	{
		if (mapping == pid)
		{
			mapping = -1;
		}
	}
	UpdateWiimoteMapping();

	return 0;
}
Пример #2
0
// called from ---NETPLAY--- thread
unsigned int NetPlayServer::OnDisconnect(const Client& player)
{
  const PlayerId pid = player.pid;

  if (m_is_running)
  {
    for (PadMapping mapping : m_pad_map)
    {
      if (mapping == pid && pid != 1)
      {
        std::lock_guard<std::recursive_mutex> lkg(m_crit.game);
        m_is_running = false;

        sf::Packet spac;
        spac << (MessageId)NP_MSG_DISABLE_GAME;
        // this thread doesn't need players lock
        SendToClients(spac, static_cast<PlayerId>(-1));
        break;
      }
    }
  }

  sf::Packet spac;
  spac << (MessageId)NP_MSG_PLAYER_LEAVE;
  spac << pid;

  enet_peer_disconnect(player.socket, 0);

  std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
  auto it = m_players.find(player.pid);
  if (it != m_players.end())
    m_players.erase(it);

  // alert other players of disconnect
  SendToClients(spac);

  for (PadMapping& mapping : m_pad_map)
  {
    if (mapping == pid)
    {
      mapping = -1;
      UpdatePadMapping();
    }
  }

  for (PadMapping& mapping : m_wiimote_map)
  {
    if (mapping == pid)
    {
      mapping = -1;
      UpdateWiimoteMapping();
    }
  }

  return 0;
}
Пример #3
0
// called from ---GUI--- thread
void NetPlayServer::SetWiimoteMapping(const PadMapping map[4])
{
	for (int i = 0; i < 4; i++)
		m_wiimote_map[i] = map[i];
	UpdateWiimoteMapping();
}
Пример #4
0
// called from ---NETPLAY--- thread
unsigned int NetPlayServer::OnConnect(sf::SocketTCP& socket)
{
	sf::Packet rpac;
	// TODO: make this not hang / check if good packet
	socket.Receive(rpac);

	std::string npver;
	rpac >> npver;
	// dolphin netplay version
	if (npver != NETPLAY_VERSION)
		return CON_ERR_VERSION_MISMATCH;

	// game is currently running
	if (m_is_running)
		return CON_ERR_GAME_RUNNING;

	// too many players
	if (m_players.size() >= 255)
		return CON_ERR_SERVER_FULL;

	// cause pings to be updated
	m_update_pings = true;

	Client player;
	player.socket = socket;
	rpac >> player.revision;
	rpac >> player.name;

	// give new client first available id
	player.pid = (PlayerId)(m_players.size() + 1);

	// try to automatically assign new user a pad
	for (PadMapping& mapping : m_pad_map)
	{
		if (mapping == -1)
		{
			mapping = player.pid;
			break;
		}
	}

	{
	std::lock_guard<std::recursive_mutex> lks(m_crit.send);

	// send join message to already connected clients
	sf::Packet spac;
	spac << (MessageId)NP_MSG_PLAYER_JOIN;
	spac << player.pid << player.name << player.revision;
	SendToClients(spac);

	// send new client success message with their id
	spac.Clear();
	spac << (MessageId)0;
	spac << player.pid;
	socket.Send(spac);

	// send new client the selected game
	if (m_selected_game != "")
	{
		spac.Clear();
		spac << (MessageId)NP_MSG_CHANGE_GAME;
		spac << m_selected_game;
		socket.Send(spac);
	}

	// send the pad buffer value
	spac.Clear();
	spac << (MessageId)NP_MSG_PAD_BUFFER;
	spac << (u32)m_target_buffer_size;
	socket.Send(spac);

	// sync values with new client
	for (const auto& p : m_players)
	{
		spac.Clear();
		spac << (MessageId)NP_MSG_PLAYER_JOIN;
		spac << p.second.pid << p.second.name << p.second.revision;
		socket.Send(spac);
	}

	} // unlock send

	// add client to the player list
	{
	std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
	m_players[socket] = player;
	std::lock_guard<std::recursive_mutex> lks(m_crit.send);
	UpdatePadMapping(); // sync pad mappings with everyone
	UpdateWiimoteMapping();
	}


	// add client to selector/ used for receiving
	m_selector.Add(socket);

	return 0;
}
Пример #5
0
// called from ---GUI--- thread
void NetPlayServer::SetWiimoteMapping(const PadMappingArray& mappings)
{
  m_wiimote_map = mappings;
  UpdateWiimoteMapping();
}
Пример #6
0
// called from ---NETPLAY--- thread
unsigned int NetPlayServer::OnConnect(ENetPeer* socket)
{
  sf::Packet rpac;
  ENetPacket* epack;
  do
  {
    epack = enet_peer_receive(socket, nullptr);
  } while (epack == nullptr);
  rpac.append(epack->data, epack->dataLength);

  // give new client first available id
  PlayerId pid = 1;
  for (auto i = m_players.begin(); i != m_players.end(); ++i)
  {
    if (i->second.pid == pid)
    {
      pid++;
      i = m_players.begin();
    }
  }
  socket->data = new PlayerId(pid);

  std::string npver;
  rpac >> npver;
  // Dolphin netplay version
  if (npver != Common::scm_rev_git_str)
    return CON_ERR_VERSION_MISMATCH;

  // game is currently running
  if (m_is_running)
    return CON_ERR_GAME_RUNNING;

  // too many players
  if (m_players.size() >= 255)
    return CON_ERR_SERVER_FULL;

  // cause pings to be updated
  m_update_pings = true;

  Client player;
  player.pid = pid;
  player.socket = socket;

  rpac >> player.revision;
  rpac >> player.name;

  enet_packet_destroy(epack);
  // try to automatically assign new user a pad
  for (PadMapping& mapping : m_pad_map)
  {
    if (mapping == -1)
    {
      mapping = player.pid;
      break;
    }
  }

  // send join message to already connected clients
  sf::Packet spac;
  spac << static_cast<MessageId>(NP_MSG_PLAYER_JOIN);
  spac << player.pid << player.name << player.revision;
  SendToClients(spac);

  // send new client success message with their id
  spac.clear();
  spac << static_cast<MessageId>(0);
  spac << player.pid;
  Send(player.socket, spac);

  // send new client the selected game
  if (m_selected_game != "")
  {
    spac.clear();
    spac << static_cast<MessageId>(NP_MSG_CHANGE_GAME);
    spac << m_selected_game;
    Send(player.socket, spac);
  }

  if (!m_host_input_authority)
  {
    // send the pad buffer value
    spac.clear();
    spac << static_cast<MessageId>(NP_MSG_PAD_BUFFER);
    spac << static_cast<u32>(m_target_buffer_size);
    Send(player.socket, spac);
  }

  // send input authority state
  spac.clear();
  spac << static_cast<MessageId>(NP_MSG_HOST_INPUT_AUTHORITY);
  spac << m_host_input_authority;
  Send(player.socket, spac);

  // sync GC SRAM with new client
  if (!g_SRAM_netplay_initialized)
  {
    SConfig::GetInstance().m_strSRAM = File::GetUserPath(F_GCSRAM_IDX);
    InitSRAM();
    g_SRAM_netplay_initialized = true;
  }
  spac.clear();
  spac << static_cast<MessageId>(NP_MSG_SYNC_GC_SRAM);
  for (size_t i = 0; i < sizeof(g_SRAM) - offsetof(Sram, settings); ++i)
  {
    spac << g_SRAM[offsetof(Sram, settings) + i];
  }
  Send(player.socket, spac);

  // sync values with new client
  for (const auto& p : m_players)
  {
    spac.clear();
    spac << static_cast<MessageId>(NP_MSG_PLAYER_JOIN);
    spac << p.second.pid << p.second.name << p.second.revision;
    Send(player.socket, spac);

    spac.clear();
    spac << static_cast<MessageId>(NP_MSG_GAME_STATUS);
    spac << p.second.pid << static_cast<u32>(p.second.game_status);
    Send(player.socket, spac);
  }

  if (Config::Get(Config::NETPLAY_ENABLE_QOS))
    player.qos_session = Common::QoSSession(player.socket);

  // add client to the player list
  {
    std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
    m_players.emplace(*(PlayerId*)player.socket->data, std::move(player));
    UpdatePadMapping();  // sync pad mappings with everyone
    UpdateWiimoteMapping();
  }

  return 0;
}