mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	SDL: add multiplayer options (#3072)
* SDL: Add multiplayer options * SDL: Make the exit conditions LOG_ERROR * fixup! SDL: Make the exit conditions LOG_ERROR
This commit is contained in:
		
							parent
							
								
									fcf0d104c9
								
							
						
					
					
						commit
						0acc3ed62f
					
				
					 1 changed files with 114 additions and 12 deletions
				
			
		|  | @ -4,6 +4,7 @@ | |||
| 
 | ||||
| #include <iostream> | ||||
| #include <memory> | ||||
| #include <regex> | ||||
| #include <string> | ||||
| #include <thread> | ||||
| 
 | ||||
|  | @ -39,20 +40,69 @@ | |||
| #include "core/hle/service/am/am.h" | ||||
| #include "core/loader/loader.h" | ||||
| #include "core/settings.h" | ||||
| #include "network/network.h" | ||||
| 
 | ||||
| static void PrintHelp(const char* argv0) { | ||||
|     std::cout << "Usage: " << argv0 | ||||
|               << " [options] <filename>\n" | ||||
|                  "-g, --gdbport=NUMBER  Enable gdb stub on port NUMBER\n" | ||||
|                  "-i, --install=FILE    Installs a specified CIA file\n" | ||||
|                  "-h, --help            Display this help and exit\n" | ||||
|                  "-v, --version         Output version information and exit\n"; | ||||
|     std::cout << "Usage: " << argv0 << " [options] <filename>\n" | ||||
|                                        "-g, --gdbport=NUMBER Enable gdb stub on port NUMBER\n" | ||||
|                                        "-i, --install=FILE    Installs a specified CIA file\n" | ||||
|                                        "-m, --multiplayer=nick:password@address:port" | ||||
|                                        " Nickname, password, address and port for multiplayer\n" | ||||
|                                        "-h, --help           Display this help and exit\n" | ||||
|                                        "-v, --version        Output version information and exit\n"; | ||||
| } | ||||
| 
 | ||||
| static void PrintVersion() { | ||||
|     std::cout << "Citra " << Common::g_scm_branch << " " << Common::g_scm_desc << std::endl; | ||||
| } | ||||
| 
 | ||||
| static void OnStateChanged(const Network::RoomMember::State& state) { | ||||
|     switch (state) { | ||||
|     case Network::RoomMember::State::Idle: | ||||
|         LOG_DEBUG(Network, "Network is idle"); | ||||
|         break; | ||||
|     case Network::RoomMember::State::Joining: | ||||
|         LOG_DEBUG(Network, "Connection sequence to room started"); | ||||
|         break; | ||||
|     case Network::RoomMember::State::Joined: | ||||
|         LOG_DEBUG(Network, "Successfully joined to the room"); | ||||
|         break; | ||||
|     case Network::RoomMember::State::LostConnection: | ||||
|         LOG_DEBUG(Network, "Lost connection to the room"); | ||||
|         break; | ||||
|     case Network::RoomMember::State::CouldNotConnect: | ||||
|         LOG_ERROR(Network, "State: CouldNotConnect"); | ||||
|         exit(1); | ||||
|         break; | ||||
|     case Network::RoomMember::State::NameCollision: | ||||
|         LOG_ERROR( | ||||
|             Network, | ||||
|             "You tried to use the same nickname then another user that is connected to the Room"); | ||||
|         exit(1); | ||||
|         break; | ||||
|     case Network::RoomMember::State::MacCollision: | ||||
|         LOG_ERROR(Network, "You tried to use the same MAC-Address then another user that is " | ||||
|                            "connected to the Room"); | ||||
|         exit(1); | ||||
|         break; | ||||
|     case Network::RoomMember::State::WrongPassword: | ||||
|         LOG_ERROR(Network, "Room replied with: Wrong password"); | ||||
|         exit(1); | ||||
|         break; | ||||
|     case Network::RoomMember::State::WrongVersion: | ||||
|         LOG_ERROR(Network, | ||||
|                   "You are using a different version then the room you are trying to connect to"); | ||||
|         exit(1); | ||||
|         break; | ||||
|     default: | ||||
|         break; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void OnMessageReceived(const Network::ChatEntry& msg) { | ||||
|     std::cout << std::endl << msg.nickname << ": " << msg.message << std::endl << std::endl; | ||||
| } | ||||
| 
 | ||||
| /// Application entry point
 | ||||
| int main(int argc, char** argv) { | ||||
|     Config config; | ||||
|  | @ -71,16 +121,20 @@ int main(int argc, char** argv) { | |||
| #endif | ||||
|     std::string filepath; | ||||
| 
 | ||||
|     bool use_multiplayer = false; | ||||
|     std::string nickname{}; | ||||
|     std::string password{}; | ||||
|     std::string address{}; | ||||
|     u16 port = Network::DefaultRoomPort; | ||||
| 
 | ||||
|     static struct option long_options[] = { | ||||
|         {"gdbport", required_argument, 0, 'g'}, | ||||
|         {"install", required_argument, 0, 'i'}, | ||||
|         {"help", no_argument, 0, 'h'}, | ||||
|         {"version", no_argument, 0, 'v'}, | ||||
|         {0, 0, 0, 0}, | ||||
|         {"gdbport", required_argument, 0, 'g'},     {"install", required_argument, 0, 'i'}, | ||||
|         {"multiplayer", required_argument, 0, 'm'}, {"help", no_argument, 0, 'h'}, | ||||
|         {"version", no_argument, 0, 'v'},           {0, 0, 0, 0}, | ||||
|     }; | ||||
| 
 | ||||
|     while (optind < argc) { | ||||
|         char arg = getopt_long(argc, argv, "g:i:hv", long_options, &option_index); | ||||
|         char arg = getopt_long(argc, argv, "g:i:m:hv", long_options, &option_index); | ||||
|         if (arg != -1) { | ||||
|             switch (arg) { | ||||
|             case 'g': | ||||
|  | @ -103,6 +157,41 @@ int main(int argc, char** argv) { | |||
|                     errno = EINVAL; | ||||
|                 if (errno != 0) | ||||
|                     exit(1); | ||||
|             } | ||||
|             case 'm': { | ||||
|                 use_multiplayer = true; | ||||
|                 std::string str_arg(optarg); | ||||
|                 // regex to check if the format is nickname:password@ip:port
 | ||||
|                 // with optional :password
 | ||||
|                 std::regex re("^([^:]+)(?::(.+))?@([^:]+)(?::([0-9]+))?$"); | ||||
|                 if (!std::regex_match(str_arg, re)) { | ||||
|                     std::cout << "Wrong format for option --multiplayer\n"; | ||||
|                     PrintHelp(argv[0]); | ||||
|                     return 0; | ||||
|                 } | ||||
| 
 | ||||
|                 std::smatch match; | ||||
|                 std::regex_search(str_arg, match, re); | ||||
|                 ASSERT(match.size() == 5); | ||||
|                 nickname = match[1]; | ||||
|                 password = match[2]; | ||||
|                 address = match[3]; | ||||
|                 if (!match[4].str().empty()) | ||||
|                     port = std::stoi(match[4]); | ||||
|                 std::regex nickname_re("^[a-zA-Z0-9._- ]+$"); | ||||
|                 if (!std::regex_match(nickname, nickname_re)) { | ||||
|                     std::cout | ||||
|                         << "Nickname is not valid. Must be 4 to 20 alphanumeric characters.\n"; | ||||
|                     return 0; | ||||
|                 } | ||||
|                 if (address.empty()) { | ||||
|                     std::cout << "Address to room must not be empty.\n"; | ||||
|                     return 0; | ||||
|                 } | ||||
|                 if (port > 65535) { | ||||
|                     std::cout << "Port must be between 0 and 65535.\n"; | ||||
|                     return 0; | ||||
|                 } | ||||
|                 break; | ||||
|             } | ||||
|             case 'h': | ||||
|  | @ -183,6 +272,19 @@ int main(int argc, char** argv) { | |||
| 
 | ||||
|     Core::Telemetry().AddField(Telemetry::FieldType::App, "Frontend", "SDL"); | ||||
| 
 | ||||
|     if (use_multiplayer) { | ||||
|         if (auto member = Network::GetRoomMember().lock()) { | ||||
|             member->BindOnChatMessageRecieved(OnMessageReceived); | ||||
|             member->BindOnStateChanged(OnStateChanged); | ||||
|             LOG_DEBUG(Network, "Start connection to %s:%u with nickname %s", address.c_str(), port, | ||||
|                       nickname.c_str()); | ||||
|             member->Join(nickname, address.c_str(), port, 0, Network::NoPreferredMac, password); | ||||
|         } else { | ||||
|             LOG_ERROR(Network, "Could not access RoomMember"); | ||||
|             return 0; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     while (emu_window->IsOpen()) { | ||||
|         system.RunLoop(); | ||||
|     } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue