Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dedicated room #4

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .travis/linux/upload.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ COMPRESSION_FLAGS="-cJvf"
mkdir "$REV_NAME"

cp build/src/citra/citra "$REV_NAME"
cp build/src/dedicated_room/citra-room "$REV_NAME"
cp build/src/citra_qt/citra-qt "$REV_NAME"

# We need icons on Linux for .desktop entries
Expand Down
1 change: 1 addition & 0 deletions .travis/macos/upload.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ mkdir "$REV_NAME"

cp build/src/citra/citra "$REV_NAME"
cp -r build/src/citra_qt/citra-qt.app "$REV_NAME"
cp build/src/dedicated_room/citra-room "$REV_NAME"

# move qt libs into app bundle for deployment
$(brew --prefix)/opt/qt5/bin/macdeployqt "${REV_NAME}/citra-qt.app"
Expand Down
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ endif()
if (ENABLE_WEB_SERVICE)
add_subdirectory(web_service)
endif()
add_subdirectory(dedicated_room)
19 changes: 19 additions & 0 deletions src/dedicated_room/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/CMakeModules)

add_executable(citra-room
citra-room.cpp
citra-room.rc
)

create_target_directory_groups(citra-room)

target_link_libraries(citra-room PRIVATE common core network)
target_link_libraries(citra-room PRIVATE glad)
if (MSVC)
target_link_libraries(citra-room PRIVATE getopt)
endif()
target_link_libraries(citra-room PRIVATE ${PLATFORM_LIBRARIES} SDL2 Threads::Threads)

if(UNIX AND NOT APPLE)
install(TARGETS citra-room RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/bin")
endif()
210 changes: 210 additions & 0 deletions src/dedicated_room/citra-room.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
// Copyright 2017 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.

#include <chrono>
#include <iostream>
#include <memory>
#include <regex>
#include <string>
#include <thread>
#define SDL_MAIN_HANDLED
#include <SDL.h>
#include <glad/glad.h>

#ifdef _MSC_VER
#include <getopt.h>
#else
#include <getopt.h>
#include <unistd.h>
#endif

#ifdef _WIN32
// windows.h needs to be included before shellapi.h
#include <windows.h>

#include <shellapi.h>
#endif

#include "common/common_types.h"
#include "common/scm_rev.h"
#include "core/announce_multiplayer_session.h"
#include "core/core.h"
#include "core/settings.h"
#include "network/network.h"

static void PrintHelp(const char* argv0) {
std::cout << "Usage: " << argv0
<< " [options] <filename>\n"
"--room-name The name of the room\n"
"--port The port used for the room\n"
"--max_members The maximum number of players for this room\n"
"--password The password for the room\n"
"--preferred-game The preferred game for this room\n"
"--preferred-game-id The preferred game-id for this room\n"
"--username The username used for announce\n"
"--token The token used for announce\n"
"--announce-url The url to the announce server\n"
"-h, --help Display this help and exit\n"
"-v, --version Output version information and exit\n";
}

static void PrintVersion() {
std::cout << "Citra dedicated room " << Common::g_scm_branch << " " << Common::g_scm_desc
<< " Libnetwork: " << Network::network_version << std::endl;
}

/// Application entry point
int main(int argc, char** argv) {
int option_index = 0;
char* endarg;

// This is just to be able to link against core
gladLoadGLLoader(static_cast<GLADloadproc>(SDL_GL_GetProcAddress));

std::string room_name;
std::string password;
std::string preferred_game;
std::string username;
std::string token;
std::string announce_url;
u64 preferred_game_id = 0;
u16 port = Network::DefaultRoomPort;
u32 max_members = 16;

static struct option long_options[] = {
{"room-name", required_argument, 0, 'n'},
{"port", required_argument, 0, 'p'},
{"max_members", required_argument, 0, 'm'},
{"password", required_argument, 0, 'w'},
{"preferred-game", required_argument, 0, 'g'},
{"preferred-game-id", required_argument, 0, 'i'},
{"username", required_argument, 0, 'u'},
{"token", required_argument, 0, 't'},
{"announce-url", required_argument, 0, 'a'},
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'v'},
{0, 0, 0, 0},
};

while (optind < argc) {
char arg = getopt_long(argc, argv, "n:p:m:w:g:u:t:a:i:hv", long_options, &option_index);
if (arg != -1) {
switch (arg) {
case 'n':
room_name.assign(optarg);
break;
case 'p':
port = strtoul(optarg, &endarg, 0);
break;
case 'm':
max_members = strtoul(optarg, &endarg, 0);
break;
case 'w':
password.assign(optarg);
break;
case 'g':
preferred_game.assign(optarg);
break;
case 'i':
preferred_game_id = strtoull(optarg, &endarg, 16);
break;
case 'u':
username.assign(optarg);
break;
case 't':
token.assign(optarg);
break;
case 'a':
announce_url.assign(optarg);
break;
case 'h':
PrintHelp(argv[0]);
return 0;
case 'v':
PrintVersion();
return 0;
}
}
}

if (room_name.empty()) {
std::cout << "room name is empty!\n\n";
PrintHelp(argv[0]);
return -1;
}
if (preferred_game.empty()) {
std::cout << "prefered game is empty!\n\n";
PrintHelp(argv[0]);
return -1;
}
if (preferred_game_id == 0) {
std::cout << "prefered-game-id not set!\nThis should get set to allow users to find your "
"room.\nSet with --prefered-game-id id\n\n";
}
if (max_members >= Network::MaxConcurrentConnections || max_members < 2) {
std::cout << "max_members needs to be in the range 2 - "
<< Network::MaxConcurrentConnections << "!\n\n";
PrintHelp(argv[0]);
return -1;
}
if (port > 65535) {
std::cout << "port needs to be in the range 0 - 65535!\n\n";
PrintHelp(argv[0]);
return -1;
}
bool announce = true;
if (username.empty()) {
announce = false;
std::cout << "username is empty: Hosting a private room\n\n";
}
if (token.empty() && announce) {
announce = false;
std::cout << "token is empty: Hosting a private room\n\n";
}
if (announce_url.empty() && announce) {
announce = false;
std::cout << "announce url is empty: Hosting a private room\n\n";
}
if (announce) {
std::cout << "Hosting a public room\n\n";
Settings::values.announce_multiplayer_room_endpoint_url = announce_url;
Settings::values.citra_username = username;
Settings::values.citra_token = token;
}

Network::Init();
if (std::shared_ptr<Network::Room> room = Network::GetRoom().lock()) {
if (!room->Create(room_name, "", port, password, max_members, preferred_game,
preferred_game_id)) {
std::cout << "Failed to create room: \n\n";
return -1;
}
std::cout << "Room is open. Close with Q+Enter...\n\n";
auto announce_session = std::make_unique<Core::AnnounceMultiplayerSession>();
if (announce) {
announce_session->Start();
}
while (room->GetState() == Network::Room::State::Open) {
std::string in;
std::cin >> in;
if (in.size() > 0) {
if (announce) {
announce_session->Stop();
}
announce_session.reset();
room->Destroy();
Network::Shutdown();
return 0;
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
if (announce) {
announce_session->Stop();
}
announce_session.reset();
room->Destroy();
}
Network::Shutdown();
return 0;
}
17 changes: 17 additions & 0 deletions src/dedicated_room/citra-room.rc
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include "winresrc.h"
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//

// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
CITRA_ICON ICON "../../dist/citra.ico"


/////////////////////////////////////////////////////////////////////////////
//
// RT_MANIFEST
//

1 RT_MANIFEST "../../dist/citra.manifest"