From ca5526b2b70cad06aa21835bd64bafe2fa219ccf Mon Sep 17 00:00:00 2001 From: mdiluzio Date: Fri, 2 Jan 2015 13:55:23 +0000 Subject: [PATCH 01/43] Add base files for net code --- source/client/CMakeLists.txt | 7 ++++++- source/client/client.cpp | 1 + source/client/client.h | 4 ++++ source/client/net.cpp | 1 + source/client/net.h | 4 ++++ source/client/server.cpp | 1 + source/client/server.h | 4 ++++ 7 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 source/client/client.cpp create mode 100644 source/client/client.h create mode 100644 source/client/net.cpp create mode 100644 source/client/net.h create mode 100644 source/client/server.cpp create mode 100644 source/client/server.h diff --git a/source/client/CMakeLists.txt b/source/client/CMakeLists.txt index 6549943..53ae704 100644 --- a/source/client/CMakeLists.txt +++ b/source/client/CMakeLists.txt @@ -11,15 +11,20 @@ include_directories( # Add the sources set( SOURCES main.cpp + client.cpp + server.cpp + net.cpp ) -# Set defaults for ttrts maps and games +# Set defaults for ttrts variables set( TTRTS_MAPS "/usr/local/share/ttrts/maps/" ) set( TTRTS_GAMES "/tmp/" ) +set( TTRTS_PORT 11715 ) # define these defaults in code set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTTRTS_MAPS=${TTRTS_MAPS}" ) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTTRTS_GAMES=${TTRTS_GAMES}" ) +set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTTRTS_PORT=${TTRTS_PORT}" ) # Add the executable add_executable( ${PROJECT_NAME} ${SOURCES} ) diff --git a/source/client/client.cpp b/source/client/client.cpp new file mode 100644 index 0000000..a7f5447 --- /dev/null +++ b/source/client/client.cpp @@ -0,0 +1 @@ +#include "client.h" \ No newline at end of file diff --git a/source/client/client.h b/source/client/client.h new file mode 100644 index 0000000..cb8909f --- /dev/null +++ b/source/client/client.h @@ -0,0 +1,4 @@ +#ifndef _TTRTS_CLIENT_H_ +#define _TTRTS_CLIENT_H_ + +#endif \ No newline at end of file diff --git a/source/client/net.cpp b/source/client/net.cpp new file mode 100644 index 0000000..35b5308 --- /dev/null +++ b/source/client/net.cpp @@ -0,0 +1 @@ +#include "net.h" \ No newline at end of file diff --git a/source/client/net.h b/source/client/net.h new file mode 100644 index 0000000..26fdbf0 --- /dev/null +++ b/source/client/net.h @@ -0,0 +1,4 @@ +#ifndef _TTRTS_NET_H_ +#define _TTRTS_NET_H_ + +#endif \ No newline at end of file diff --git a/source/client/server.cpp b/source/client/server.cpp new file mode 100644 index 0000000..e9ea187 --- /dev/null +++ b/source/client/server.cpp @@ -0,0 +1 @@ +#include "server.h" \ No newline at end of file diff --git a/source/client/server.h b/source/client/server.h new file mode 100644 index 0000000..c13c320 --- /dev/null +++ b/source/client/server.h @@ -0,0 +1,4 @@ +#ifndef _TTRTS_SERVER_H_ +#define _TTRTS_SERVER_H_ + +#endif \ No newline at end of file From 3b5599ffad603b167a4bcfebd7885995ce5bcf97 Mon Sep 17 00:00:00 2001 From: mdiluzio Date: Fri, 2 Jan 2015 14:04:11 +0000 Subject: [PATCH 02/43] Remove references to non-existent maths --- source/client/CMakeLists.txt | 5 ++--- source/gen/CMakeLists.txt | 5 ++--- source/test/CMakeLists.txt | 3 +-- source/ttrts/CMakeLists.txt | 5 ++--- 4 files changed, 7 insertions(+), 11 deletions(-) diff --git a/source/client/CMakeLists.txt b/source/client/CMakeLists.txt index 53ae704..8fb0953 100644 --- a/source/client/CMakeLists.txt +++ b/source/client/CMakeLists.txt @@ -3,8 +3,7 @@ project( ttrts-client ) include_directories( - ${CMAKE_CURRENT_BINARY_DIR} - ../maths + ${CMAKE_CURRENT_BINARY_DIR} ../ttrts ) @@ -44,4 +43,4 @@ add_custom_target( cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_SOURCE_DIR}/scripts/gen_usage.sh "${CMAKE_CURRENT_BINARY_DIR}/usage.h" ) -add_dependencies(${PROJECT_NAME} ttrts-client-usage) \ No newline at end of file +add_dependencies(${PROJECT_NAME} ttrts-client-usage) diff --git a/source/gen/CMakeLists.txt b/source/gen/CMakeLists.txt index 466e233..67167f0 100644 --- a/source/gen/CMakeLists.txt +++ b/source/gen/CMakeLists.txt @@ -3,8 +3,7 @@ project( ttrts-gen ) include_directories( - ../ttrts - ../maths + ../ttrts ) set( SOURCES @@ -25,4 +24,4 @@ add_custom_target( add_dependencies(ttrts-gen-maps ${PROJECT_NAME}) # Installation target -install( DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/maps DESTINATION /usr/local/share/ttrts ) \ No newline at end of file +install( DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/maps DESTINATION /usr/local/share/ttrts ) diff --git a/source/test/CMakeLists.txt b/source/test/CMakeLists.txt index 179f7a8..3e6a60c 100644 --- a/source/test/CMakeLists.txt +++ b/source/test/CMakeLists.txt @@ -4,8 +4,7 @@ project( ttrts-test ) include_directories( - ../ttrts - ../maths + ../ttrts ) set( SOURCES diff --git a/source/ttrts/CMakeLists.txt b/source/ttrts/CMakeLists.txt index b528b3f..93a6d94 100644 --- a/source/ttrts/CMakeLists.txt +++ b/source/ttrts/CMakeLists.txt @@ -5,8 +5,7 @@ project( ttrts ) # Include the maths include_directories( - ${CMAKE_CURRENT_BINARY_DIR} - ../maths + ${CMAKE_CURRENT_BINARY_DIR} ) # Add our sources @@ -44,4 +43,4 @@ install( ) # Install the ttrts static lib -install( TARGETS ttrts DESTINATION lib ) \ No newline at end of file +install( TARGETS ttrts DESTINATION lib ) From 0962546a8226a80a8f435e67c6dca66c617af971 Mon Sep 17 00:00:00 2001 From: mdiluzio Date: Fri, 2 Jan 2015 14:04:37 +0000 Subject: [PATCH 03/43] Move current client code out to server file, still uses old file-system method --- source/client/main.cpp | 222 +-------------------------------------- source/client/server.cpp | 222 ++++++++++++++++++++++++++++++++++++++- source/client/server.h | 4 + 3 files changed, 230 insertions(+), 218 deletions(-) diff --git a/source/client/main.cpp b/source/client/main.cpp index 35bf5de..d5df140 100644 --- a/source/client/main.cpp +++ b/source/client/main.cpp @@ -1,16 +1,8 @@ -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - #include "game.h" +#include "server.h" + +#include +#include #define STRINGIFY(x) _STRINGIFY(x) #define _STRINGIFY(x) #x @@ -18,45 +10,6 @@ static const char* sk_usage = #include "usage.h" ; - -// Verbose mode -static const bool env_verbose = getenv("VERBOSE"); - -// time for waiting between file stats -static const std::chrono::milliseconds sk_waitTime = std::chrono::milliseconds(100); - -// Check if a file exists -inline bool FileExists( const std::string& name ) -{ - struct stat buffer; - return (stat (name.c_str(), &buffer) == 0); -} - -// Wait for a file to exist -inline void WaitForFile( const std::string& name, const std::chrono::milliseconds& time ) -{ - while( !FileExists(name) ) std::this_thread::sleep_for(time); -} - -bool OutputGameStateFile(CTTRTSGame &game, std::string &gameDir) -{ - char turnFileName[128]; - snprintf(turnFileName,128,"%s/Turn_%i.txt",gameDir.c_str(),game.GetTurn()); - std::ofstream turnFile(turnFileName, std::ios_base::trunc); // truncate to overwrite if a file exists - - if ( turnFile.bad() ) - { - return false; - } - - // Output the turn description - std::string turnDescriptor = GetStringFromGame(game); - - turnFile<(file)),std::istreambuf_iterator()); - - if( gameDescriptor.size() == 0 ) - { - std::cerr<<"Error: failed to read in any information from "<>input; - if( !input.size() || std::tolower(input[0]) != 'y' ) - { - std::cerr<<"Aborting..."<(turnFile)),std::istreambuf_iterator()); - - // Issue the orders to the game - if( game.IssueOrders(player, orders) ) - std::cerr<<"Warning: Orders for player "<<(int) player <<" failed to correctly parse"< +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +// time for waiting between file stats +static const std::chrono::milliseconds sk_waitTime = std::chrono::milliseconds(100); + +// Check if a file exists +inline bool FileExists( const std::string& name ) +{ + struct stat buffer; + return (stat (name.c_str(), &buffer) == 0); +} + +// Wait for a file to exist +inline void WaitForFile( const std::string& name, const std::chrono::milliseconds& time ) +{ + while( !FileExists(name) ) std::this_thread::sleep_for(time); +} + +bool OutputGameStateFile(CTTRTSGame &game, const std::string &gameDir) +{ + char turnFileName[128]; + snprintf(turnFileName,128,"%s/Turn_%i.txt",gameDir.c_str(),game.GetTurn()); + std::ofstream turnFile(turnFileName, std::ios_base::trunc); // truncate to overwrite if a file exists + + if ( turnFile.bad() ) + { + return false; + } + + // Output the turn description + std::string turnDescriptor = GetStringFromGame(game); + + turnFile<(file)),std::istreambuf_iterator()); + + if( gameDescriptor.size() == 0 ) + { + std::cerr<<"Error: failed to read in any information from "<>input; + if( !input.size() || std::tolower(input[0]) != 'y' ) + { + std::cerr<<"Aborting..."<(turnFile)),std::istreambuf_iterator()); + + // Issue the orders to the game + if( game.IssueOrders(player, orders) ) + std::cerr<<"Warning: Orders for player "<<(int) player <<" failed to correctly parse"< + +int runServer(const std::string& dir,const std::string& file); + #endif \ No newline at end of file From 8835bfb82aa4af52b7d1ac106b82adaa3450dd94 Mon Sep 17 00:00:00 2001 From: mdiluzio Date: Fri, 2 Jan 2015 14:09:29 +0000 Subject: [PATCH 04/43] On second thoughts move filesystem game code out to a filesystem cpp --- source/client/CMakeLists.txt | 1 + source/client/filesystem.cpp | 222 +++++++++++++++++++++++++++++++++++ source/client/filesystem.h | 8 ++ source/client/main.cpp | 4 +- source/client/server.cpp | 222 +---------------------------------- source/client/server.h | 4 - 6 files changed, 234 insertions(+), 227 deletions(-) create mode 100644 source/client/filesystem.cpp create mode 100644 source/client/filesystem.h diff --git a/source/client/CMakeLists.txt b/source/client/CMakeLists.txt index 8fb0953..e524304 100644 --- a/source/client/CMakeLists.txt +++ b/source/client/CMakeLists.txt @@ -13,6 +13,7 @@ set( SOURCES client.cpp server.cpp net.cpp + filesystem.cpp ) # Set defaults for ttrts variables diff --git a/source/client/filesystem.cpp b/source/client/filesystem.cpp new file mode 100644 index 0000000..59ac6b8 --- /dev/null +++ b/source/client/filesystem.cpp @@ -0,0 +1,222 @@ +#include "filesystem.h" + + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +// time for waiting between file stats +static const std::chrono::milliseconds sk_waitTime = std::chrono::milliseconds(100); + +// Check if a file exists +inline bool FileExists( const std::string& name ) +{ + struct stat buffer; + return (stat (name.c_str(), &buffer) == 0); +} + +// Wait for a file to exist +inline void WaitForFile( const std::string& name, const std::chrono::milliseconds& time ) +{ + while( !FileExists(name) ) std::this_thread::sleep_for(time); +} + +bool OutputGameStateFile(CTTRTSGame &game, const std::string &gameDir) +{ + char turnFileName[128]; + snprintf(turnFileName,128,"%s/Turn_%i.txt",gameDir.c_str(),game.GetTurn()); + std::ofstream turnFile(turnFileName, std::ios_base::trunc); // truncate to overwrite if a file exists + + if ( turnFile.bad() ) + { + return false; + } + + // Output the turn description + std::string turnDescriptor = GetStringFromGame(game); + + turnFile<(file)),std::istreambuf_iterator()); + + if( gameDescriptor.size() == 0 ) + { + std::cerr<<"Error: failed to read in any information from "<>input; + if( !input.size() || std::tolower(input[0]) != 'y' ) + { + std::cerr<<"Aborting..."<(turnFile)),std::istreambuf_iterator()); + + // Issue the orders to the game + if( game.IssueOrders(player, orders) ) + std::cerr<<"Warning: Orders for player "<<(int) player <<" failed to correctly parse"< + +int runFromFilesystem( const std::string& directory, const std::string gamefile ); + +#endif \ No newline at end of file diff --git a/source/client/main.cpp b/source/client/main.cpp index d5df140..8c31966 100644 --- a/source/client/main.cpp +++ b/source/client/main.cpp @@ -1,5 +1,5 @@ #include "game.h" -#include "server.h" +#include "filesystem.h" #include #include @@ -60,6 +60,6 @@ int main(int argc, char* argv[]) return -1; } - return runServer(ttrts_games_dir, gameFile); + return runFromFilesystem(ttrts_games_dir, gameFile); }; diff --git a/source/client/server.cpp b/source/client/server.cpp index 678d4f1..e9ea187 100644 --- a/source/client/server.cpp +++ b/source/client/server.cpp @@ -1,221 +1 @@ -#include "server.h" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -// time for waiting between file stats -static const std::chrono::milliseconds sk_waitTime = std::chrono::milliseconds(100); - -// Check if a file exists -inline bool FileExists( const std::string& name ) -{ - struct stat buffer; - return (stat (name.c_str(), &buffer) == 0); -} - -// Wait for a file to exist -inline void WaitForFile( const std::string& name, const std::chrono::milliseconds& time ) -{ - while( !FileExists(name) ) std::this_thread::sleep_for(time); -} - -bool OutputGameStateFile(CTTRTSGame &game, const std::string &gameDir) -{ - char turnFileName[128]; - snprintf(turnFileName,128,"%s/Turn_%i.txt",gameDir.c_str(),game.GetTurn()); - std::ofstream turnFile(turnFileName, std::ios_base::trunc); // truncate to overwrite if a file exists - - if ( turnFile.bad() ) - { - return false; - } - - // Output the turn description - std::string turnDescriptor = GetStringFromGame(game); - - turnFile<(file)),std::istreambuf_iterator()); - - if( gameDescriptor.size() == 0 ) - { - std::cerr<<"Error: failed to read in any information from "<>input; - if( !input.size() || std::tolower(input[0]) != 'y' ) - { - std::cerr<<"Aborting..."<(turnFile)),std::istreambuf_iterator()); - - // Issue the orders to the game - if( game.IssueOrders(player, orders) ) - std::cerr<<"Warning: Orders for player "<<(int) player <<" failed to correctly parse"< - -int runServer(const std::string& dir,const std::string& file); - #endif \ No newline at end of file From 2281bcb6cd7affcc6d0d8a6c2b74147c6bfbe928 Mon Sep 17 00:00:00 2001 From: mdiluzio Date: Fri, 2 Jan 2015 15:03:29 +0000 Subject: [PATCH 05/43] More refactoring of functionality into seperate files, with stubs for server and client --- source/client/client.cpp | 8 ++++- source/client/client.h | 4 +++ source/client/filesystem.cpp | 60 +++++++++++++++++++++++++++++++++--- source/client/filesystem.h | 17 +++++++++- source/client/main.cpp | 48 ++++++----------------------- source/client/server.cpp | 7 ++++- source/client/server.h | 2 ++ 7 files changed, 101 insertions(+), 45 deletions(-) diff --git a/source/client/client.cpp b/source/client/client.cpp index a7f5447..8a59232 100644 --- a/source/client/client.cpp +++ b/source/client/client.cpp @@ -1 +1,7 @@ -#include "client.h" \ No newline at end of file +#include "client.h" + + +int runClient( const std::string& host_address ) +{ + return 0; +} \ No newline at end of file diff --git a/source/client/client.h b/source/client/client.h index cb8909f..bd30a06 100644 --- a/source/client/client.h +++ b/source/client/client.h @@ -1,4 +1,8 @@ #ifndef _TTRTS_CLIENT_H_ #define _TTRTS_CLIENT_H_ +#include + +int runClient( const std::string& host_address ); + #endif \ No newline at end of file diff --git a/source/client/filesystem.cpp b/source/client/filesystem.cpp index 59ac6b8..a2abd1f 100644 --- a/source/client/filesystem.cpp +++ b/source/client/filesystem.cpp @@ -13,18 +13,19 @@ #include #include +// ===================================================================================================================== // time for waiting between file stats static const std::chrono::milliseconds sk_waitTime = std::chrono::milliseconds(100); // Check if a file exists -inline bool FileExists( const std::string& name ) +bool FileExists( const std::string& name ) { struct stat buffer; return (stat (name.c_str(), &buffer) == 0); } // Wait for a file to exist -inline void WaitForFile( const std::string& name, const std::chrono::milliseconds& time ) +void WaitForFile( const std::string& name, const std::chrono::milliseconds& time ) { while( !FileExists(name) ) std::this_thread::sleep_for(time); } @@ -49,8 +50,59 @@ bool OutputGameStateFile(CTTRTSGame &game, const std::string &gameDir) return true; } -int runFromFilesystem( const std::string& directory, const std::string gamefile ) +std::string getMapsDir() { + std::string maps = STRINGIFY(TTRTS_MAPS); + if( getenv("TTRTS_MAPS") ) + { + maps = getenv("TTRTS_MAPS"); + + // Additional trailing slash + if( maps.back() != '/' ) + maps += "/"; + } + + return maps; +} + +std::string getGamesDir() +{ + std::string dir = STRINGIFY(TTRTS_GAMES); + if( getenv("TTRTS_GAMES") ) + { + dir = getenv("TTRTS_GAMES"); + + // Additional trailing slash + if( dir.back() != '/' ) + dir += "/"; + } + return dir; +} + +// ===================================================================================================================== +int runFromFilesystem( const std::string& gamestring ) +{ + std::string gamefile = gamestring; + + // Default for maps + std::string ttrts_maps_dir = getMapsDir(); + + // Default for games + std::string ttrts_games_dir = getGamesDir(); + + // If file path is not local path and file doesn't exist + if( gamefile.find("/") == std::string::npos + && access( gamefile.c_str(), F_OK ) == -1 ) + { + gamefile = ttrts_maps_dir + gamefile; + } + + // If still not good + if( access( gamefile.c_str(), F_OK ) == -1 ) + { + std::cerr<<"Error: "<< gamefile <<" file not found"< +#include -int runFromFilesystem( const std::string& directory, const std::string gamefile ); +#include "game.h" + +#define STRINGIFY(x) _STRINGIFY(x) +#define _STRINGIFY(x) #x + +bool FileExists( const std::string& name ); + +void WaitForFile( const std::string& name, const std::chrono::milliseconds& time ); + +int runFromFilesystem( const std::string& gamefile ); + +bool OutputGameStateFile(CTTRTSGame &game, const std::string &gameDir); + +std::string getMapsDir(); +std::string getGamesDir(); #endif \ No newline at end of file diff --git a/source/client/main.cpp b/source/client/main.cpp index 8c31966..0d78823 100644 --- a/source/client/main.cpp +++ b/source/client/main.cpp @@ -1,11 +1,9 @@ #include "game.h" #include "filesystem.h" +#include "server.h" +#include "client.h" #include -#include - -#define STRINGIFY(x) _STRINGIFY(x) -#define _STRINGIFY(x) #x static const char* sk_usage = #include "usage.h" @@ -22,44 +20,18 @@ int main(int argc, char* argv[]) } // Attempt to open the game file - std::string gameFile = argv[1]; + std::string arg1 = argv[1]; - // Default for maps - std::string ttrts_maps_dir = STRINGIFY(TTRTS_MAPS); - if( getenv("TTRTS_MAPS") ) + if( arg1 == "client" ) { - ttrts_maps_dir = getenv("TTRTS_MAPS"); - - // Additional trailing slash - if( ttrts_maps_dir.back() != '/' ) - ttrts_maps_dir += "/"; + if( argc == 3 ) + return runClient(argv[2]); } - - // Default for games - std::string ttrts_games_dir = STRINGIFY(TTRTS_GAMES); - if( getenv("TTRTS_GAMES") ) + else if ( arg1 == "server" ) { - ttrts_games_dir = getenv("TTRTS_GAMES"); - - // Additional trailing slash - if( ttrts_games_dir.back() != '/' ) - ttrts_games_dir += "/"; + return runServer(); } - - // If file path is not local path and file doesn't exist - if( gameFile.find("/") == std::string::npos - && access( gameFile.c_str(), F_OK ) == -1 ) - { - gameFile = ttrts_maps_dir + gameFile; - } - - // If still not good - if( access( gameFile.c_str(), F_OK ) == -1 ) - { - std::cerr<<"Error: "< Date: Fri, 2 Jan 2015 15:06:04 +0000 Subject: [PATCH 06/43] Use argc and argv passed down --- source/client/client.cpp | 2 +- source/client/client.h | 2 +- source/client/filesystem.cpp | 4 ++-- source/client/filesystem.h | 4 ++-- source/client/main.cpp | 12 ++++-------- source/client/server.cpp | 4 ++-- source/client/server.h | 2 +- 7 files changed, 13 insertions(+), 17 deletions(-) diff --git a/source/client/client.cpp b/source/client/client.cpp index 8a59232..fdfeeb1 100644 --- a/source/client/client.cpp +++ b/source/client/client.cpp @@ -1,7 +1,7 @@ #include "client.h" -int runClient( const std::string& host_address ) +int runClient(int argc, char* argv[]) { return 0; } \ No newline at end of file diff --git a/source/client/client.h b/source/client/client.h index bd30a06..ab1e336 100644 --- a/source/client/client.h +++ b/source/client/client.h @@ -3,6 +3,6 @@ #include -int runClient( const std::string& host_address ); +int runClient(int argc, char* argv[]); #endif \ No newline at end of file diff --git a/source/client/filesystem.cpp b/source/client/filesystem.cpp index a2abd1f..6bd7111 100644 --- a/source/client/filesystem.cpp +++ b/source/client/filesystem.cpp @@ -80,9 +80,9 @@ std::string getGamesDir() } // ===================================================================================================================== -int runFromFilesystem( const std::string& gamestring ) +int runFromFilesystem(int argc, char* argv[]) { - std::string gamefile = gamestring; + std::string gamefile = argv[1]; // Default for maps std::string ttrts_maps_dir = getMapsDir(); diff --git a/source/client/filesystem.h b/source/client/filesystem.h index 4204ef9..d6a2ff9 100644 --- a/source/client/filesystem.h +++ b/source/client/filesystem.h @@ -13,11 +13,11 @@ bool FileExists( const std::string& name ); void WaitForFile( const std::string& name, const std::chrono::milliseconds& time ); -int runFromFilesystem( const std::string& gamefile ); - bool OutputGameStateFile(CTTRTSGame &game, const std::string &gameDir); std::string getMapsDir(); std::string getGamesDir(); +int runFromFilesystem(int argc, char* argv[]); + #endif \ No newline at end of file diff --git a/source/client/main.cpp b/source/client/main.cpp index 0d78823..218cab5 100644 --- a/source/client/main.cpp +++ b/source/client/main.cpp @@ -22,16 +22,12 @@ int main(int argc, char* argv[]) // Attempt to open the game file std::string arg1 = argv[1]; + // Either run the client, the server, or from local filesystem if( arg1 == "client" ) - { - if( argc == 3 ) - return runClient(argv[2]); - } + return runClient(argc,argv+1); else if ( arg1 == "server" ) - { - return runServer(); - } + return runServer(argc,argv+1); else - return runFromFilesystem(arg1); + return runFromFilesystem(argc,argv); }; diff --git a/source/client/server.cpp b/source/client/server.cpp index 1e62b61..be07929 100644 --- a/source/client/server.cpp +++ b/source/client/server.cpp @@ -1,6 +1,6 @@ #include "server.h" -int runServer() +int runServer(int argc, char* argv[]) { - + return 0; } \ No newline at end of file diff --git a/source/client/server.h b/source/client/server.h index 4f3af0e..54452c7 100644 --- a/source/client/server.h +++ b/source/client/server.h @@ -1,6 +1,6 @@ #ifndef _TTRTS_SERVER_H_ #define _TTRTS_SERVER_H_ -int runServer(); +int runServer(int argc, char* argv[]); #endif \ No newline at end of file From b4240cf1c80caf5e64dd444baf0f31429bb923d5 Mon Sep 17 00:00:00 2001 From: mdiluzio Date: Fri, 2 Jan 2015 15:13:05 +0000 Subject: [PATCH 07/43] pull in very simple client/server demo code inspired by http://www.linuxhowtos.org/C_C++/socket.htm --- source/client/client.cpp | 78 +++++++++++++++++++++++++++++++++++ source/client/client.h | 2 - source/client/main.cpp | 4 +- source/client/net.h | 9 +++++ source/client/server.cpp | 87 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 176 insertions(+), 4 deletions(-) diff --git a/source/client/client.cpp b/source/client/client.cpp index fdfeeb1..3e846de 100644 --- a/source/client/client.cpp +++ b/source/client/client.cpp @@ -1,7 +1,85 @@ #include "client.h" +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "net.h" int runClient(int argc, char* argv[]) { + int sockfd; // socket File descriptor + int portno; // Port number + int n = 0; // return value for read and write calls + + struct sockaddr_in serv_addr; // Server address + + struct hostent *server; // pointer to host information + + char buffer[1028]; // buffer for socked read + memset(buffer,0,sizeof(buffer)); + + // must provide information + if (argc < 2) + { + fprintf(stderr,"usage %s hostname\n", argv[0]); + exit(0); + } + + // Get port number + portno = 11715; + + // Create a new socket + // AF_INET is general internetsocked domain + // SOCK_STREAM as messages will be read in on this socket, SOCK_DGRAM would be for packets + // 0 is for default protocol + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd < 0) + error("ERROR opening socket"); + + // Get the hostent information for the host by name + server = gethostbyname(argv[1]); + if (server == NULL) + error("ERROR, no such host"); + + // Empty the server address struct + memset(&serv_addr,0, sizeof(serv_addr)); + + // Set the server to AF_INET + serv_addr.sin_family = AF_INET; + + // copy the server address into our server_addr struct + memcpy(&serv_addr.sin_addr.s_addr, server->h_addr, server->h_length); + + // Set our server address port to the port number provided + serv_addr.sin_port = htons(portno); + + // Attempt to connect to the server using the socket and server address info + if (connect(sockfd, (const sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) + error("ERROR connecting"); + + while ( n >= 0 ) + { + // Get the message to send + printf("Please enter the message: "); + memset(buffer,0,sizeof(buffer)); + fgets(buffer,sizeof(buffer)-1,stdin); + + // Place a test message into the buffer + strncpy(buffer,buffer,sizeof(buffer)); + + // Write to the socket with the buffer + n = write(sockfd,buffer,strlen(buffer)); + if (n < 0) + error("ERROR writing to socket"); + } + return 0; } \ No newline at end of file diff --git a/source/client/client.h b/source/client/client.h index ab1e336..201c0d9 100644 --- a/source/client/client.h +++ b/source/client/client.h @@ -1,8 +1,6 @@ #ifndef _TTRTS_CLIENT_H_ #define _TTRTS_CLIENT_H_ -#include - int runClient(int argc, char* argv[]); #endif \ No newline at end of file diff --git a/source/client/main.cpp b/source/client/main.cpp index 218cab5..cfa69e3 100644 --- a/source/client/main.cpp +++ b/source/client/main.cpp @@ -24,9 +24,9 @@ int main(int argc, char* argv[]) // Either run the client, the server, or from local filesystem if( arg1 == "client" ) - return runClient(argc,argv+1); + return runClient(argc-1,argv+1); else if ( arg1 == "server" ) - return runServer(argc,argv+1); + return runServer(argc-1,argv+1); else return runFromFilesystem(argc,argv); diff --git a/source/client/net.h b/source/client/net.h index 26fdbf0..613486f 100644 --- a/source/client/net.h +++ b/source/client/net.h @@ -1,4 +1,13 @@ #ifndef _TTRTS_NET_H_ #define _TTRTS_NET_H_ +#include +#include + +inline void error(const char *msg) +{ + perror(msg); + exit(1); +} + #endif \ No newline at end of file diff --git a/source/client/server.cpp b/source/client/server.cpp index be07929..dfac689 100644 --- a/source/client/server.cpp +++ b/source/client/server.cpp @@ -1,6 +1,93 @@ #include "server.h" +#include +#include +#include +#include + +#include +#include + +#include + +#include "net.h" + int runServer(int argc, char* argv[]) { + int sockfd; // socket File descriptor + int newsockfd; // new socket File descriptor + + int portno; // Port number + socklen_t clilen; // length of client address + clilen = sizeof(sockaddr_in); + + int n = 0; // return value for read and write calls + + char buffer[1028]; // buffer for socked read + memset(buffer,0,sizeof(buffer)); + + struct sockaddr_in serv_addr; // Server address + struct sockaddr_in cli_addr; // Client address + + // Create a new socket + // AF_INET is general internetsocked domain + // SOCK_STREAM as messages will be read in on this socket, SOCK_DGRAM would be for packets + // 0 is for default protocol + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd < 0) + error("ERROR opening socket"); + + // empty the server address + memset(&serv_addr,0, sizeof(serv_addr)); + + // Grab the port number + portno = 11715; + + // Set the server address family to AF_INET + serv_addr.sin_family = AF_INET; + + // Set the port number + // htons swaps from host byte order to network byte order + serv_addr.sin_port = htons(portno); + + // The host for this address is this current machines's IP + // INADDR_ANY fetches this + serv_addr.sin_addr.s_addr = INADDR_ANY; + + // bind out socket to this server address + if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) + error("ERROR on binding"); + + // Listen on the socket for messages + // Second param is length of backlog queue, the maximum number of connections + // that can be waiting while the process is handling a single connection + // max is usually set to 5 + listen(sockfd,5); + + // accept waits for a connection from a client + // it returns a new socket file descriptor for this connection + // client information will be stored in cli_addr + newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen); + if (newsockfd < 0) + error("ERROR on accept"); + + // loop + while( n >= 0 ) + { + // empty the buffer + memset(buffer,0,sizeof(buffer)); + + // Read in the new socket + // read will block until the client has called write + // up to the full size of the buffer + n = read(newsockfd,buffer,sizeof(buffer)-1); + if (n < 0) + error("ERROR reading from socket"); + + // print the message recieved + printf("%s",buffer); + } + + // Return return 0; } \ No newline at end of file From 83b9990bcc27960fc42ac3c32fe9db8e4a2d3054 Mon Sep 17 00:00:00 2001 From: mdiluzio Date: Fri, 2 Jan 2015 15:25:30 +0000 Subject: [PATCH 08/43] some more cleanup and using TTRTS_PORT --- source/client/client.cpp | 2 +- source/client/server.cpp | 24 +++++++++++++----------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/source/client/client.cpp b/source/client/client.cpp index 3e846de..dccaeff 100644 --- a/source/client/client.cpp +++ b/source/client/client.cpp @@ -34,7 +34,7 @@ int runClient(int argc, char* argv[]) } // Get port number - portno = 11715; + portno = TTRTS_PORT; // Create a new socket // AF_INET is general internetsocked domain diff --git a/source/client/server.cpp b/source/client/server.cpp index dfac689..f9ed4b5 100644 --- a/source/client/server.cpp +++ b/source/client/server.cpp @@ -14,23 +14,25 @@ int runServer(int argc, char* argv[]) { - int sockfd; // socket File descriptor - int newsockfd; // new socket File descriptor + // Server side information + int sockfd; // socket File descriptor + sockaddr_in serv_addr; // Server address + int portno; // Port number - int portno; // Port number + // information for each client + sockaddr_in cli_addr; // Client address socklen_t clilen; // length of client address - clilen = sizeof(sockaddr_in); + int clientsockfd; // new socket File descriptor + int n = 0; // return value for read and write calls char buffer[1028]; // buffer for socked read memset(buffer,0,sizeof(buffer)); - struct sockaddr_in serv_addr; // Server address - struct sockaddr_in cli_addr; // Client address // Create a new socket - // AF_INET is general internetsocked domain + // AF_INET is general internet socket domain // SOCK_STREAM as messages will be read in on this socket, SOCK_DGRAM would be for packets // 0 is for default protocol sockfd = socket(AF_INET, SOCK_STREAM, 0); @@ -41,7 +43,7 @@ int runServer(int argc, char* argv[]) memset(&serv_addr,0, sizeof(serv_addr)); // Grab the port number - portno = 11715; + portno = TTRTS_PORT; // Set the server address family to AF_INET serv_addr.sin_family = AF_INET; @@ -67,8 +69,8 @@ int runServer(int argc, char* argv[]) // accept waits for a connection from a client // it returns a new socket file descriptor for this connection // client information will be stored in cli_addr - newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen); - if (newsockfd < 0) + clientsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen); + if (clientsockfd < 0) error("ERROR on accept"); // loop @@ -80,7 +82,7 @@ int runServer(int argc, char* argv[]) // Read in the new socket // read will block until the client has called write // up to the full size of the buffer - n = read(newsockfd,buffer,sizeof(buffer)-1); + n = read(clientsockfd,buffer,sizeof(buffer)-1); if (n < 0) error("ERROR reading from socket"); From dcb9d68fb48e7086f52859dcd3afd04daae74705 Mon Sep 17 00:00:00 2001 From: mdiluzio Date: Fri, 2 Jan 2015 16:09:24 +0000 Subject: [PATCH 09/43] Revert back to cleaner copy of server code --- source/client/CMakeLists.txt | 6 +++--- source/client/client.cpp | 4 ++++ source/client/server.cpp | 29 ++++++++++++++--------------- 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/source/client/CMakeLists.txt b/source/client/CMakeLists.txt index e524304..92360c6 100644 --- a/source/client/CMakeLists.txt +++ b/source/client/CMakeLists.txt @@ -17,9 +17,9 @@ set( SOURCES ) # Set defaults for ttrts variables -set( TTRTS_MAPS "/usr/local/share/ttrts/maps/" ) -set( TTRTS_GAMES "/tmp/" ) -set( TTRTS_PORT 11715 ) +set( TTRTS_MAPS "/usr/local/share/ttrts/maps/" ) +set( TTRTS_GAMES "/tmp/" ) +set( TTRTS_PORT 11715 ) # define these defaults in code set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTTRTS_MAPS=${TTRTS_MAPS}" ) diff --git a/source/client/client.cpp b/source/client/client.cpp index dccaeff..ab20334 100644 --- a/source/client/client.cpp +++ b/source/client/client.cpp @@ -1,5 +1,7 @@ #include "client.h" +#include + #include #include #include @@ -49,6 +51,8 @@ int runClient(int argc, char* argv[]) if (server == NULL) error("ERROR, no such host"); + std::cout<<"Connecting to "< + #include #include #include @@ -9,21 +11,21 @@ #include #include +#include #include "net.h" int runServer(int argc, char* argv[]) { - // Server side information - int sockfd; // socket File descriptor - sockaddr_in serv_addr; // Server address - int portno; // Port number + sockaddr_in serv_addr; // Server address + int sockfd; // socket File descriptor + int portno = TTRTS_PORT; // Port number - // information for each client - sockaddr_in cli_addr; // Client address + struct sockaddr_in cli_addr; // Client address + int newsockfd; // new socket File descriptor socklen_t clilen; // length of client address - int clientsockfd; // new socket File descriptor + clilen = sizeof(sockaddr_in); int n = 0; // return value for read and write calls @@ -32,7 +34,7 @@ int runServer(int argc, char* argv[]) // Create a new socket - // AF_INET is general internet socket domain + // AF_INET is general internetsocked domain // SOCK_STREAM as messages will be read in on this socket, SOCK_DGRAM would be for packets // 0 is for default protocol sockfd = socket(AF_INET, SOCK_STREAM, 0); @@ -41,10 +43,7 @@ int runServer(int argc, char* argv[]) // empty the server address memset(&serv_addr,0, sizeof(serv_addr)); - - // Grab the port number - portno = TTRTS_PORT; - + // Set the server address family to AF_INET serv_addr.sin_family = AF_INET; @@ -69,8 +68,8 @@ int runServer(int argc, char* argv[]) // accept waits for a connection from a client // it returns a new socket file descriptor for this connection // client information will be stored in cli_addr - clientsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen); - if (clientsockfd < 0) + newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen); + if (newsockfd < 0) error("ERROR on accept"); // loop @@ -82,7 +81,7 @@ int runServer(int argc, char* argv[]) // Read in the new socket // read will block until the client has called write // up to the full size of the buffer - n = read(clientsockfd,buffer,sizeof(buffer)-1); + n = read(newsockfd,buffer,sizeof(buffer)-1); if (n < 0) error("ERROR reading from socket"); From 4285770d529f2102fb55ecdc1ea3852d4ee2a6a2 Mon Sep 17 00:00:00 2001 From: mdiluzio Date: Fri, 2 Jan 2015 16:18:18 +0000 Subject: [PATCH 10/43] Allow multiple client connections on different threads --- source/client/CMakeLists.txt | 2 +- source/client/server.cpp | 143 ++++++++++++++++++++++------------- 2 files changed, 91 insertions(+), 54 deletions(-) diff --git a/source/client/CMakeLists.txt b/source/client/CMakeLists.txt index 92360c6..7f26ed1 100644 --- a/source/client/CMakeLists.txt +++ b/source/client/CMakeLists.txt @@ -33,7 +33,7 @@ add_executable( ${PROJECT_NAME} ${SOURCES} ) set_target_properties( ${PROJECT_NAME} PROPERTIES OUTPUT_NAME ttrts ) # dependent on main ttrts libary -target_link_libraries( ${PROJECT_NAME} ttrts ) +target_link_libraries( ${PROJECT_NAME} ttrts pthread ) # Installation target install( TARGETS ${PROJECT_NAME} DESTINATION bin ) diff --git a/source/client/server.cpp b/source/client/server.cpp index 2a4edf7..9dabe82 100644 --- a/source/client/server.cpp +++ b/source/client/server.cpp @@ -1,5 +1,7 @@ #include "server.h" +#include +#include #include #include @@ -15,64 +17,17 @@ #include "net.h" -int runServer(int argc, char* argv[]) +std::vector gClientThreads; + +int clientHandler( sockaddr_in cli_addr, socklen_t clilen, int clientsockfd) { - sockaddr_in serv_addr; // Server address - int sockfd; // socket File descriptor - int portno = TTRTS_PORT; // Port number - - struct sockaddr_in cli_addr; // Client address - int newsockfd; // new socket File descriptor - socklen_t clilen; // length of client address - - clilen = sizeof(sockaddr_in); - - int n = 0; // return value for read and write calls + std::cout<<"Client connected from "<= 0 ) { // empty the buffer @@ -81,7 +36,7 @@ int runServer(int argc, char* argv[]) // Read in the new socket // read will block until the client has called write // up to the full size of the buffer - n = read(newsockfd,buffer,sizeof(buffer)-1); + n = read(clientsockfd,buffer,sizeof(buffer)-1); if (n < 0) error("ERROR reading from socket"); @@ -89,6 +44,88 @@ int runServer(int argc, char* argv[]) printf("%s",buffer); } + return 0; +} + +int runServer(int argc, char* argv[]) +{ + std::cout<<"Setting up server on port "< 10) + { + error("Binding failed after retries"); + } + + if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) >= 0) + break; + + std::cout<<"Binding failed on try "< Date: Fri, 2 Jan 2015 17:14:16 +0000 Subject: [PATCH 11/43] Clients now connect and recieve gamestate information --- source/client/client.cpp | 13 ++++- source/client/filesystem.cpp | 28 +++++---- source/client/filesystem.h | 2 + source/client/server.cpp | 109 +++++++++++++++++++++++++---------- source/gen/gen.cpp | 2 +- 5 files changed, 109 insertions(+), 45 deletions(-) diff --git a/source/client/client.cpp b/source/client/client.cpp index ab20334..9401df2 100644 --- a/source/client/client.cpp +++ b/source/client/client.cpp @@ -71,10 +71,17 @@ int runClient(int argc, char* argv[]) while ( n >= 0 ) { - // Get the message to send - printf("Please enter the message: "); memset(buffer,0,sizeof(buffer)); - fgets(buffer,sizeof(buffer)-1,stdin); + + // Receive gamestate + if (read(sockfd,buffer,sizeof(buffer)-1) < 0) + error("ERROR reading from client"); + + std::cout< #include #include +#include #include #include @@ -14,35 +15,35 @@ #include #include +#include +#include #include "net.h" +#include "filesystem.h" -std::vector gClientThreads; - -int clientHandler( sockaddr_in cli_addr, socklen_t clilen, int clientsockfd) +// Struct for net client info +struct ClientInfo { - std::cout<<"Client connected from "<= 0 ) - { - // empty the buffer - memset(buffer,0,sizeof(buffer)); + // Read in the new socket + // read will block until the client has called write + // up to the full size of the buffer + if (read(info.clientsockfd,buffer,sizeof(buffer)-1) < 0) + error("ERROR reading from client"); - // Read in the new socket - // read will block until the client has called write - // up to the full size of the buffer - n = read(clientsockfd,buffer,sizeof(buffer)-1); - if (n < 0) - error("ERROR reading from socket"); + std::cout<<"Recieved orders from "< myClients; + std::cout<<"Waiting for clients"< clientThreads; + for(auto client : myClients) + { + std::thread clientThread(waitForOrdersFromClient,std::ref(client), std::ref(gameMutex), std::ref(game)); + clientThreads.push_back(std::move(clientThread)); + } + + // Join up all the threads + for ( std::thread& thread : clientThreads ) + { + thread.join(); + } + + // Step to the next turn + gameMutex.lock(); + game.SimulateToNextTurn(); + gameMutex.unlock(); + } + + + // end game and disconnect clients + // Return return 0; } \ No newline at end of file diff --git a/source/gen/gen.cpp b/source/gen/gen.cpp index 8265a53..0f782b8 100644 --- a/source/gen/gen.cpp +++ b/source/gen/gen.cpp @@ -33,7 +33,7 @@ int main() //------ { CTTRTSGame game(6, 6); - game.SetName("Tiny2player"); + game.SetName("Tiny2Player"); AddUnitToGame( player_t::Red, '<', uvector2(4, 2), game); AddUnitToGame( player_t::Red, '<', uvector2(4, 4), game); From e01a718ac6240e9e58a3e49012727b06052dd3ad Mon Sep 17 00:00:00 2001 From: mdiluzio Date: Fri, 2 Jan 2015 18:57:47 +0000 Subject: [PATCH 12/43] Fix bug where we passed client info to the thread by ref, like an ape --- source/client/client.cpp | 17 ++++++++++------- source/client/server.cpp | 10 +++++++--- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/source/client/client.cpp b/source/client/client.cpp index 9401df2..241c002 100644 --- a/source/client/client.cpp +++ b/source/client/client.cpp @@ -39,13 +39,15 @@ int runClient(int argc, char* argv[]) portno = TTRTS_PORT; // Create a new socket - // AF_INET is general internetsocked domain + // AF_INET is general internetsocket domain // SOCK_STREAM as messages will be read in on this socket, SOCK_DGRAM would be for packets // 0 is for default protocol sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) error("ERROR opening socket"); + std::cout<<"Opened socket on "< clientThreads; for(auto client : myClients) { - std::thread clientThread(waitForOrdersFromClient,std::ref(client), std::ref(gameMutex), std::ref(game)); + std::thread clientThread(waitForOrdersFromClient, client, std::ref(gameMutex), std::ref(game)); clientThreads.push_back(std::move(clientThread)); } @@ -166,6 +169,7 @@ int runServer(int argc, char* argv[]) thread.join(); } + std::cout<<"Orders recieved, simulating turn"< Date: Fri, 2 Jan 2015 19:00:28 +0000 Subject: [PATCH 13/43] Handle end game state properly --- source/client/server.cpp | 46 ++++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/source/client/server.cpp b/source/client/server.cpp index 7c291b1..89cef9e 100644 --- a/source/client/server.cpp +++ b/source/client/server.cpp @@ -28,6 +28,23 @@ struct ClientInfo int clientsockfd; }; +void SendGameInfoToClients(std::vector &myClients, const CTTRTSGame &game, std::mutex &gameMutex) +{ + // Spawn threads + std::vector clientThreads; + for(auto client : myClients) + { + std::thread clientThread(waitForOrdersFromClient, client, ref(gameMutex), std::ref(game)); + clientThreads.push_back(move(clientThread)); + } + + // Join up all the threads + for ( std::thread& thread : clientThreads ) + { + thread.join(); + } +} + int waitForOrdersFromClient(const ClientInfo info, std::mutex& mut, CTTRTSGame& game ) { char buffer[1028]; // buffer for orders @@ -156,28 +173,31 @@ int runServer(int argc, char* argv[]) // Wait for orders from clients std::cout<<"Waiting for client orders"< clientThreads; - for(auto client : myClients) - { - std::thread clientThread(waitForOrdersFromClient, client, std::ref(gameMutex), std::ref(game)); - clientThreads.push_back(std::move(clientThread)); - } - - // Join up all the threads - for ( std::thread& thread : clientThreads ) - { - thread.join(); - } + SendGameInfoToClients(myClients, game, gameMutex); std::cout<<"Orders recieved, simulating turn"< Date: Fri, 2 Jan 2015 19:05:58 +0000 Subject: [PATCH 14/43] Fix server functions being used wrongly --- source/client/server.cpp | 65 +++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 31 deletions(-) diff --git a/source/client/server.cpp b/source/client/server.cpp index 89cef9e..ecfef7f 100644 --- a/source/client/server.cpp +++ b/source/client/server.cpp @@ -28,24 +28,7 @@ struct ClientInfo int clientsockfd; }; -void SendGameInfoToClients(std::vector &myClients, const CTTRTSGame &game, std::mutex &gameMutex) -{ - // Spawn threads - std::vector clientThreads; - for(auto client : myClients) - { - std::thread clientThread(waitForOrdersFromClient, client, ref(gameMutex), std::ref(game)); - clientThreads.push_back(move(clientThread)); - } - - // Join up all the threads - for ( std::thread& thread : clientThreads ) - { - thread.join(); - } -} - -int waitForOrdersFromClient(const ClientInfo info, std::mutex& mut, CTTRTSGame& game ) +int WaitForOrdersFromClient(const ClientInfo info, std::mutex &mut, CTTRTSGame &game) { char buffer[1028]; // buffer for orders memset(buffer,0,sizeof(buffer)); @@ -68,6 +51,37 @@ int waitForOrdersFromClient(const ClientInfo info, std::mutex& mut, CTTRTSGame& return 0; } +void GetOrdersFromClients(std::vector &myClients, CTTRTSGame &game, std::mutex &gameMutex) +{ + // Spawn threads + std::vector clientThreads; + for(auto client : myClients) + { + std::thread clientThread(WaitForOrdersFromClient, client, ref(gameMutex), std::ref(game)); + clientThreads.push_back(move(clientThread)); + } + + // Join up all the threads + for ( std::thread& thread : clientThreads ) + { + thread.join(); + } +} + +void SendGameInfoToClients(std::vector &myClients, const CTTRTSGame &game, std::mutex &gameMutex) +{ + gameMutex.lock(); + std::string gamestate_string = GetStringFromGame(game); + gameMutex.unlock(); + + for (auto client : myClients) + { + // Write to the socket with the buffer + if ( write( client.clientsockfd, gamestate_string.c_str(), gamestate_string.length() ) < 0 ) + error("ERROR sending to client"); + } +} + int runServer(int argc, char* argv[]) { std::cout<<"Setting up server on port "< Date: Fri, 2 Jan 2015 19:31:14 +0000 Subject: [PATCH 15/43] Make client and server perform a handshake to agree on player IDs --- source/client/client.cpp | 27 ++++++++++++++++++++++++++ source/client/server.cpp | 41 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/source/client/client.cpp b/source/client/client.cpp index 241c002..8eda536 100644 --- a/source/client/client.cpp +++ b/source/client/client.cpp @@ -14,9 +14,12 @@ #include #include "net.h" +#include "game.h" int runClient(int argc, char* argv[]) { + player_t myPlayer; + int sockfd; // socket File descriptor int portno; // Port number int n = 0; // return value for read and write calls @@ -71,6 +74,30 @@ int runClient(int argc, char* argv[]) if (connect(sockfd, (const sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) error("ERROR connecting"); + std::cout<<"Waiting for handshake"<= 0 ) { memset(buffer,0,sizeof(buffer)); diff --git a/source/client/server.cpp b/source/client/server.cpp index ecfef7f..f66408d 100644 --- a/source/client/server.cpp +++ b/source/client/server.cpp @@ -26,6 +26,7 @@ struct ClientInfo { sockaddr_in cli_addr; int clientsockfd; + player_t player; }; int WaitForOrdersFromClient(const ClientInfo info, std::mutex &mut, CTTRTSGame &game) @@ -45,7 +46,7 @@ int WaitForOrdersFromClient(const ClientInfo info, std::mutex &mut, CTTRTSGame & std::cout< players = game.GetPlayers(); unsigned int numClients = game.GetPlayers().size(); + auto player_iterator = players.begin(); // game mutex std::mutex gameMutex; @@ -162,9 +166,44 @@ int runServer(int argc, char* argv[]) error("ERROR on accept"); std::cout<<"Client connected from "< Date: Fri, 2 Jan 2015 19:46:09 +0000 Subject: [PATCH 16/43] add user input for starting the game --- source/client/client.cpp | 1 + source/client/server.cpp | 3 +++ 2 files changed, 4 insertions(+) diff --git a/source/client/client.cpp b/source/client/client.cpp index 8eda536..a5fe5ba 100644 --- a/source/client/client.cpp +++ b/source/client/client.cpp @@ -15,6 +15,7 @@ #include "net.h" #include "game.h" +#include "filesystem.h" int runClient(int argc, char* argv[]) { diff --git a/source/client/server.cpp b/source/client/server.cpp index f66408d..b0b2c82 100644 --- a/source/client/server.cpp +++ b/source/client/server.cpp @@ -206,6 +206,9 @@ int runServer(int argc, char* argv[]) std::cout<<"All clients connected"< Date: Fri, 2 Jan 2015 19:51:14 +0000 Subject: [PATCH 17/43] Pull base netcode functions out into net files --- source/client/net.cpp | 64 +++++++++++++++++++++++++++++++++++- source/client/net.h | 25 ++++++++++++++ source/client/server.cpp | 70 ---------------------------------------- 3 files changed, 88 insertions(+), 71 deletions(-) diff --git a/source/client/net.cpp b/source/client/net.cpp index 35b5308..967aa73 100644 --- a/source/client/net.cpp +++ b/source/client/net.cpp @@ -1 +1,63 @@ -#include "net.h" \ No newline at end of file +#include "net.h" + +#include +#include + +#include +#include +#include +#include + +int WaitForOrdersFromClient(const ClientInfo info, std::mutex &mut, CTTRTSGame &game) +{ + char buffer[1028]; // buffer for orders + memset(buffer,0,sizeof(buffer)); + + std::cout<<"Waiting for "< &myClients, CTTRTSGame &game, std::mutex &gameMutex) +{ + // Spawn threads + std::vector clientThreads; + for(auto client : myClients) + { + std::thread clientThread(WaitForOrdersFromClient, client, ref(gameMutex), std::ref(game)); + clientThreads.push_back(move(clientThread)); + } + + // Join up all the threads + for ( std::thread& thread : clientThreads ) + { + thread.join(); + } +} + +void SendGameInfoToClients(std::vector &myClients, const CTTRTSGame &game, std::mutex &gameMutex) +{ + gameMutex.lock(); + std::string gamestate_string = GetStringFromGame(game); + gameMutex.unlock(); + + for (auto client : myClients) + { + // Write to the socket with the buffer + if ( write( client.clientsockfd, gamestate_string.c_str(), gamestate_string.length() ) < 0 ) + error("ERROR sending to client"); + } +} diff --git a/source/client/net.h b/source/client/net.h index 613486f..fdab7d1 100644 --- a/source/client/net.h +++ b/source/client/net.h @@ -1,9 +1,34 @@ #ifndef _TTRTS_NET_H_ #define _TTRTS_NET_H_ +#include +#include + +#include +#include + +#include +#include +#include +#include + #include #include +// Struct for net client info +struct ClientInfo +{ + sockaddr_in cli_addr; + int clientsockfd; + player_t player; +}; + +int WaitForOrdersFromClient(const ClientInfo info, std::mutex &mut, CTTRTSGame &game); + +void GetOrdersFromClients(std::vector &myClients, CTTRTSGame &game, std::mutex &gameMutex); + +void SendGameInfoToClients(std::vector &myClients, const CTTRTSGame &game, std::mutex &gameMutex); + inline void error(const char *msg) { perror(msg); diff --git a/source/client/server.cpp b/source/client/server.cpp index b0b2c82..f9238b8 100644 --- a/source/client/server.cpp +++ b/source/client/server.cpp @@ -10,79 +10,9 @@ #include #include -#include -#include - -#include -#include -#include -#include - #include "net.h" #include "filesystem.h" -// Struct for net client info -struct ClientInfo -{ - sockaddr_in cli_addr; - int clientsockfd; - player_t player; -}; - -int WaitForOrdersFromClient(const ClientInfo info, std::mutex &mut, CTTRTSGame &game) -{ - char buffer[1028]; // buffer for orders - memset(buffer,0,sizeof(buffer)); - - std::cout<<"Waiting for "< &myClients, CTTRTSGame &game, std::mutex &gameMutex) -{ - // Spawn threads - std::vector clientThreads; - for(auto client : myClients) - { - std::thread clientThread(WaitForOrdersFromClient, client, ref(gameMutex), std::ref(game)); - clientThreads.push_back(move(clientThread)); - } - - // Join up all the threads - for ( std::thread& thread : clientThreads ) - { - thread.join(); - } -} - -void SendGameInfoToClients(std::vector &myClients, const CTTRTSGame &game, std::mutex &gameMutex) -{ - gameMutex.lock(); - std::string gamestate_string = GetStringFromGame(game); - gameMutex.unlock(); - - for (auto client : myClients) - { - // Write to the socket with the buffer - if ( write( client.clientsockfd, gamestate_string.c_str(), gamestate_string.length() ) < 0 ) - error("ERROR sending to client"); - } -} - int runServer(int argc, char* argv[]) { std::cout<<"Setting up server on port "< Date: Sat, 3 Jan 2015 18:55:44 +0000 Subject: [PATCH 18/43] Improve both client and server code to account for END of messages, allowing for incomplete packets with TCP --- source/client/client.cpp | 20 +++++++++++++------- source/client/net.cpp | 24 ++++++++++++++++-------- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/source/client/client.cpp b/source/client/client.cpp index a5fe5ba..d781ce3 100644 --- a/source/client/client.cpp +++ b/source/client/client.cpp @@ -101,17 +101,23 @@ int runClient(int argc, char* argv[]) while ( n >= 0 ) { - memset(buffer,0,sizeof(buffer)); - std::cout<<"Waiting for gamestate"< Date: Sat, 3 Jan 2015 19:27:08 +0000 Subject: [PATCH 19/43] Make client output and read in game state and order files --- source/client/client.cpp | 8 +- source/client/filesystem.cpp | 142 +++++++++++++++++++---------------- source/client/filesystem.h | 2 + source/client/server.cpp | 7 +- 4 files changed, 88 insertions(+), 71 deletions(-) diff --git a/source/client/client.cpp b/source/client/client.cpp index d781ce3..668efcb 100644 --- a/source/client/client.cpp +++ b/source/client/client.cpp @@ -114,10 +114,12 @@ int runClient(int argc, char* argv[]) gamestate+=buffer; } - std::cout<(turnFile)), std::istreambuf_iterator()); + return orders; +} + +int CreateAndCleanGameDir(const std::string& gameDir) +{ struct stat info; int ret = stat( gameDir.c_str(), &info ); if( ret == 0 && info.st_mode & S_IFDIR ) @@ -178,6 +219,30 @@ int runFromFilesystem(int argc, char* argv[]) return -1; } + return 0; +} + +// ===================================================================================================================== +int runFromFilesystem(int argc, char* argv[]) +{ + std::string gamefile = argv[1]; + + std::cout<<"Launching TTRTS with "<(turnFile)),std::istreambuf_iterator()); + std::string orders = GetOrdersFromPlayerFile(game, player); // Issue the orders to the game if( game.IssueOrders(player, orders) ) diff --git a/source/client/filesystem.h b/source/client/filesystem.h index 851da73..aae2e14 100644 --- a/source/client/filesystem.h +++ b/source/client/filesystem.h @@ -15,6 +15,8 @@ void WaitForFile( const std::string& name, const std::chrono::milliseconds& time bool OutputGameStateFile(CTTRTSGame &game, const std::string &gameDir); +std::string GetOrdersFromPlayerFile(const CTTRTSGame &game, player_t &player); + CTTRTSGame GetGameFromFile( const std::string& file ); std::string getMapsDir(); diff --git a/source/client/server.cpp b/source/client/server.cpp index f9238b8..5c07804 100644 --- a/source/client/server.cpp +++ b/source/client/server.cpp @@ -68,7 +68,7 @@ int runServer(int argc, char* argv[]) CTTRTSGame game = GetGameFromFile("Tiny2Player.txt"); std::vector players = game.GetPlayers(); - unsigned int numClients = game.GetPlayers().size(); + unsigned int numClients = players.size(); auto player_iterator = players.begin(); // game mutex @@ -103,10 +103,7 @@ int runServer(int argc, char* argv[]) clientInfo.player = *player_iterator; player_iterator++; - - // Could verify if player is valid here - - myClients.push_back({cli_addr,clientsockfd}); + myClients.push_back(clientInfo); } // Perform the initial handshake with clients From 61c012370db08eb946dda466c709ef5d0ddb486d Mon Sep 17 00:00:00 2001 From: mdiluzio Date: Sat, 3 Jan 2015 19:31:42 +0000 Subject: [PATCH 20/43] Fix filesystem game method --- source/client/client.cpp | 2 +- source/client/filesystem.cpp | 10 +++++----- source/client/filesystem.h | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/source/client/client.cpp b/source/client/client.cpp index 668efcb..1fd192b 100644 --- a/source/client/client.cpp +++ b/source/client/client.cpp @@ -116,7 +116,7 @@ int runClient(int argc, char* argv[]) // Output the gamestate file for this game CTTRTSGame thisGame = GetGameFromString(gamestate); - OutputGameStateFile(thisGame, getGamesDir()); + OutputGameStateFile(thisGame); // Get the order file for this turn std::string orders = GetOrdersFromPlayerFile(thisGame,myPlayer); diff --git a/source/client/filesystem.cpp b/source/client/filesystem.cpp index a692324..061303d 100644 --- a/source/client/filesystem.cpp +++ b/source/client/filesystem.cpp @@ -30,10 +30,10 @@ void WaitForFile( const std::string& name, const std::chrono::milliseconds& time while( !FileExists(name) ) std::this_thread::sleep_for(time); } -bool OutputGameStateFile(CTTRTSGame &game, const std::string &gameDir) +bool OutputGameStateFile(CTTRTSGame &game) { char turnFileName[128]; - snprintf(turnFileName,128,"%s/%s/Turn_%i.txt",gameDir.c_str(),game.GetName().c_str(),game.GetTurn()); + snprintf(turnFileName,128,"%s%s/Turn_%i.txt", getGamesDir().c_str(),game.GetName().c_str(),game.GetTurn()); std::ofstream turnFile(turnFileName, std::ios_base::trunc); // truncate to overwrite if a file exists if ( turnFile.bad() ) @@ -127,7 +127,7 @@ std::string GetOrdersFromPlayerFile(const CTTRTSGame &game, player_t &player) std::string gameDir = getGamesDir(); char playerOrderFileName[128]; - snprintf(playerOrderFileName, 128, "%s/%s/Player_%i_Turn_%i.txt", gameDir.c_str(),game.GetName().c_str(),(int) player, game.GetTurn()); + snprintf(playerOrderFileName, 128, "%s%s/Player_%i_Turn_%i.txt", gameDir.c_str(),game.GetName().c_str(),(int) player, game.GetTurn()); // Wait for the player order file to be created std::cout<<"Waiting for "<< playerOrderFileName << std::endl; @@ -249,7 +249,7 @@ int runFromFilesystem(int argc, char* argv[]) std::cout<<"Starting turn "< Date: Sat, 3 Jan 2015 20:04:31 +0000 Subject: [PATCH 21/43] Add game name to handshake and formalise handshake format --- source/client/client.cpp | 22 +++++++++++----------- source/client/filesystem.cpp | 8 +++----- source/client/filesystem.h | 2 ++ source/client/net.h | 2 ++ source/client/server.cpp | 11 +++++++---- 5 files changed, 25 insertions(+), 20 deletions(-) diff --git a/source/client/client.cpp b/source/client/client.cpp index 1fd192b..2776971 100644 --- a/source/client/client.cpp +++ b/source/client/client.cpp @@ -82,22 +82,22 @@ int runClient(int argc, char* argv[]) error("ERROR recieving handshake from server"); std::string handshake(buffer); + std::cout<<"Handshake:"<= 0 ) { diff --git a/source/client/filesystem.cpp b/source/client/filesystem.cpp index 061303d..1ab70f5 100644 --- a/source/client/filesystem.cpp +++ b/source/client/filesystem.cpp @@ -179,8 +179,9 @@ std::string GetOrdersFromPlayerFile(const CTTRTSGame &game, player_t &player) return orders; } -int CreateAndCleanGameDir(const std::string& gameDir) +int CreateAndCleanGameDir(const std::string& gameName) { + std::string gameDir = getGamesDir()+gameName; struct stat info; int ret = stat( gameDir.c_str(), &info ); if( ret == 0 && info.st_mode & S_IFDIR ) @@ -236,11 +237,8 @@ int runFromFilesystem(int argc, char* argv[]) // Default for games std::string ttrts_games_dir = getGamesDir(); - // Current game directory - std::string gameDir = ttrts_games_dir + game.GetName(); - // Empty the current game directory - if ( CreateAndCleanGameDir(gameDir) < 0) + if ( CreateAndCleanGameDir(game.GetName()) < 0) return -1; // While the game isn't finished diff --git a/source/client/filesystem.h b/source/client/filesystem.h index 8d63fc1..7b7c338 100644 --- a/source/client/filesystem.h +++ b/source/client/filesystem.h @@ -24,4 +24,6 @@ std::string getGamesDir(); int runFromFilesystem(int argc, char* argv[]); +int CreateAndCleanGameDir(const std::string& gameName); + #endif \ No newline at end of file diff --git a/source/client/net.h b/source/client/net.h index fdab7d1..af8b64e 100644 --- a/source/client/net.h +++ b/source/client/net.h @@ -15,6 +15,8 @@ #include #include +#define TTRTS_HANDSHAKE_FORMAT "player %u name %s" + // Struct for net client info struct ClientInfo { diff --git a/source/client/server.cpp b/source/client/server.cpp index 5c07804..17fb421 100644 --- a/source/client/server.cpp +++ b/source/client/server.cpp @@ -110,13 +110,14 @@ int runServer(int argc, char* argv[]) for( auto client : myClients ) { // Handshake currently just player - std::string handshake = std::string("player ")+std::to_string((int)client.player); + char handshake[64]; + snprintf(handshake, sizeof(handshake), TTRTS_HANDSHAKE_FORMAT,(unsigned int)client.player,game.GetName().c_str()); // Output the handshake - std::cout<<"Handshaking with "< Date: Sat, 3 Jan 2015 22:30:52 +0000 Subject: [PATCH 22/43] Use new fatal_error and fatal_perror functions for errors --- source/client/client.cpp | 18 +++++++++--------- source/client/net.cpp | 4 ++-- source/client/net.h | 9 ++++++++- source/client/server.cpp | 12 ++++++------ 4 files changed, 25 insertions(+), 18 deletions(-) diff --git a/source/client/client.cpp b/source/client/client.cpp index 2776971..1184678 100644 --- a/source/client/client.cpp +++ b/source/client/client.cpp @@ -48,14 +48,14 @@ int runClient(int argc, char* argv[]) // 0 is for default protocol sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) - error("ERROR opening socket"); + fatal_perror("ERROR opening socket"); std::cout<<"Opened socket on "< &myClients, const CTTRTSGame { // Write to the socket with the buffer if ( write( client.clientsockfd, gamestate_string.c_str(), gamestate_string.length() ) < 0 ) - error("ERROR sending to client"); + fatal_perror("ERROR sending to client"); } } diff --git a/source/client/net.h b/source/client/net.h index af8b64e..5ac3f55 100644 --- a/source/client/net.h +++ b/source/client/net.h @@ -14,6 +14,7 @@ #include #include +#include #define TTRTS_HANDSHAKE_FORMAT "player %u name %s" @@ -31,7 +32,13 @@ void GetOrdersFromClients(std::vector &myClients, CTTRTSGame &game, void SendGameInfoToClients(std::vector &myClients, const CTTRTSGame &game, std::mutex &gameMutex); -inline void error(const char *msg) +inline void fatal_error(const char *msg) +{ + std::cerr< 10) { - error("Binding failed after retries"); + fatal_error("Binding failed after retries"); } if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) >= 0) @@ -93,7 +93,7 @@ int runServer(int argc, char* argv[]) // client information will be stored in cli_addr clientsockfd = accept(sockfd, (sockaddr *) &cli_addr, &clilen); if (clientsockfd < 0) - error("ERROR on accept"); + fatal_perror("ERROR on accept"); std::cout<<"Client connected from "< Date: Sat, 3 Jan 2015 22:43:39 +0000 Subject: [PATCH 23/43] Refactor running game server into own function --- source/client/server.cpp | 51 ++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/source/client/server.cpp b/source/client/server.cpp index 4f8d16b..c11035c 100644 --- a/source/client/server.cpp +++ b/source/client/server.cpp @@ -9,16 +9,17 @@ #include #include #include +#include #include "net.h" #include "filesystem.h" -int runServer(int argc, char* argv[]) +CTTRTSGame &RunServerForGame(CTTRTSGame &game) { - std::cout<<"Setting up server on port "<= 0) break; - std::cout<<"Binding failed on try "< players = game.GetPlayers(); unsigned int numClients = players.size(); auto player_iterator = players.begin(); @@ -77,7 +75,7 @@ int runServer(int argc, char* argv[]) // Set of clients std::vector myClients; - std::cout<<"Waiting for clients"< Date: Sun, 4 Jan 2015 11:08:35 +0000 Subject: [PATCH 24/43] More refactoring by pulling code out of client and server files --- source/client/client.cpp | 24 ++++---------- source/client/net.cpp | 71 ++++++++++++++++++++++++++++++++++++++-- source/client/net.h | 8 ++++- source/client/server.cpp | 44 +++---------------------- 4 files changed, 86 insertions(+), 61 deletions(-) diff --git a/source/client/client.cpp b/source/client/client.cpp index 1184678..8619898 100644 --- a/source/client/client.cpp +++ b/source/client/client.cpp @@ -19,7 +19,7 @@ int runClient(int argc, char* argv[]) { - player_t myPlayer; + player_t myPlayer = player_t::NUM_INVALID; // My player int sockfd; // socket File descriptor int portno; // Port number @@ -29,7 +29,7 @@ int runClient(int argc, char* argv[]) struct hostent *server; // pointer to host information - char buffer[1028]; // buffer for socked read + char buffer[1028]; // buffer for socket read memset(buffer,0,sizeof(buffer)); // must provide information @@ -77,27 +77,17 @@ int runClient(int argc, char* argv[]) std::cout<<"Waiting for handshake"<= 0 ) { diff --git a/source/client/net.cpp b/source/client/net.cpp index 2de2e77..ed171f6 100644 --- a/source/client/net.cpp +++ b/source/client/net.cpp @@ -8,7 +8,7 @@ #include #include -int WaitForOrdersFromClient(const ClientInfo info, std::mutex &mut, CTTRTSGame &game) +void WaitForOrdersFromClient(const ClientInfo info, std::mutex &mut, CTTRTSGame &game) { char buffer[1028]; // buffer for orders @@ -35,8 +35,6 @@ int WaitForOrdersFromClient(const ClientInfo info, std::mutex &mut, CTTRTSGame & mut.lock(); game.IssueOrders(info.player , orders); mut.unlock(); - - return 0; } void GetOrdersFromClients(std::vector &myClients, CTTRTSGame &game, std::mutex &gameMutex) @@ -69,3 +67,70 @@ void SendGameInfoToClients(std::vector &myClients, const CTTRTSGame fatal_perror("ERROR sending to client"); } } + + +void PerformClientHandshake(int sockfd, unsigned int &player, std::string &gameNameString) +{ + char handshakeBuffer[128]; + memset(handshakeBuffer,0,sizeof(handshakeBuffer)); + + if (read(sockfd, handshakeBuffer,sizeof(handshakeBuffer)-1) < 0) + fatal_perror("ERROR recieving handshake from server"); + + std::string handshake(handshakeBuffer); + std::cout<<"Handshake:"< 10) + fatal_error("Binding failed"); + + // Attempt to bind our listening socket + if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) >= 0) + break; + + std::cout<<"Binding failed on try "< &myClients, CTTRTSGame &game, std::mutex &gameMutex); void SendGameInfoToClients(std::vector &myClients, const CTTRTSGame &game, std::mutex &gameMutex); +void TryBindSocket(int sockfd, sockaddr_in &serv_addr); + +void PerformServerHandshakeWithClient(const ClientInfo &client, const CTTRTSGame &game); + +void PerformClientHandshake(int sockfd, unsigned int &player, std::string &gameNameString); + inline void fatal_error(const char *msg) { std::cerr< 10) - { - fatal_error("Binding failed after retries"); - } - - if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) >= 0) - break; - - std::cout<<"Binding failed on try "< players = game.GetPlayers(); unsigned int numClients = players.size(); auto player_iterator = players.begin(); @@ -108,28 +94,7 @@ CTTRTSGame &RunServerForGame(CTTRTSGame &game) for( auto client : myClients ) { // Handshake currently just player - char handshake[64]; - snprintf(handshake, sizeof(handshake), TTRTS_HANDSHAKE_FORMAT,(unsigned int)client.player,game.GetName().c_str()); - - // Output the handshake - std::cout<<"Handshaking:"< Date: Sun, 4 Jan 2015 11:22:54 +0000 Subject: [PATCH 25/43] Some more refactoring with additional comments Server now performs handshake instantly --- source/client/net.cpp | 10 +++++----- source/client/net.h | 17 +++++++++++++---- source/client/server.cpp | 28 ++++++++++++++-------------- 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/source/client/net.cpp b/source/client/net.cpp index ed171f6..0fc85ba 100644 --- a/source/client/net.cpp +++ b/source/client/net.cpp @@ -8,7 +8,7 @@ #include #include -void WaitForOrdersFromClient(const ClientInfo info, std::mutex &mut, CTTRTSGame &game) +void WaitForOrdersFromClient(const ClientInfo info, CTTRTSGame &game, std::mutex &mut) { char buffer[1028]; // buffer for orders @@ -37,13 +37,13 @@ void WaitForOrdersFromClient(const ClientInfo info, std::mutex &mut, CTTRTSGame mut.unlock(); } -void GetOrdersFromClients(std::vector &myClients, CTTRTSGame &game, std::mutex &gameMutex) +void WaitForOrdersFromClients(std::vector &myClients, CTTRTSGame &game, std::mutex &gameMutex) { // Spawn threads std::vector clientThreads; for(auto client : myClients) { - std::thread clientThread(WaitForOrdersFromClient, client, ref(gameMutex), std::ref(game)); + std::thread clientThread(WaitForOrdersFromClient, client, std::ref(game), ref(gameMutex)); clientThreads.push_back(move(clientThread)); } @@ -54,7 +54,7 @@ void GetOrdersFromClients(std::vector &myClients, CTTRTSGame &game, } } -void SendGameInfoToClients(std::vector &myClients, const CTTRTSGame &game, std::mutex &gameMutex) +void SendGamestateToClients(std::vector &myClients, const CTTRTSGame &game, std::mutex &gameMutex) { gameMutex.lock(); std::string gamestate_string = GetStringFromGame(game); @@ -90,7 +90,7 @@ void PerformClientHandshake(int sockfd, unsigned int &player, std::string &gameN gameNameString = gameName; } -void PerformServerHandshakeWithClient(const ClientInfo &client, const CTTRTSGame &game) +void PerformServerHandshake(const ClientInfo &client, const CTTRTSGame &game) { char handshake[64]; snprintf(handshake, sizeof(handshake), TTRTS_HANDSHAKE_FORMAT,(unsigned int)client.player,game.GetName().c_str()); diff --git a/source/client/net.h b/source/client/net.h index eaa8737..e80c091 100644 --- a/source/client/net.h +++ b/source/client/net.h @@ -26,24 +26,33 @@ struct ClientInfo player_t player; }; -void WaitForOrdersFromClient(const ClientInfo info, std::mutex &mut, CTTRTSGame &game); +// Wait for orders from a client, will not return until client has send valid orders +// Will automatically add orders to the game +void WaitForOrdersFromClient(const ClientInfo info, CTTRTSGame &game, std::mutex &mut); -void GetOrdersFromClients(std::vector &myClients, CTTRTSGame &game, std::mutex &gameMutex); +// Iterates through a list of clients calling WaitForOrdersFromClient +void WaitForOrdersFromClients(std::vector &myClients, CTTRTSGame &game, std::mutex &gameMutex); -void SendGameInfoToClients(std::vector &myClients, const CTTRTSGame &game, std::mutex &gameMutex); +// Sends current gamestate to each client +void SendGamestateToClients(std::vector &myClients, const CTTRTSGame &game, std::mutex &gameMutex); +// Tries to bind to a socket, will attempt 10 times with longer waits between void TryBindSocket(int sockfd, sockaddr_in &serv_addr); -void PerformServerHandshakeWithClient(const ClientInfo &client, const CTTRTSGame &game); +// Perform the server side handshake with a client +void PerformServerHandshake(const ClientInfo &client, const CTTRTSGame &game); +// Perform the client side handshake with the server void PerformClientHandshake(int sockfd, unsigned int &player, std::string &gameNameString); +// For local fatal errors inline void fatal_error(const char *msg) { std::cerr< Date: Sun, 4 Jan 2015 11:59:58 +0000 Subject: [PATCH 26/43] Fix up all logging output Remove debug logging Use cerr or clog in the correct places refactor a few more functions --- bootstrap.sh | 2 +- source/client/client.cpp | 16 +++---- source/client/filesystem.cpp | 55 ++++++++---------------- source/client/main.cpp | 1 + source/client/net.cpp | 81 +++++++++++++++++++++++++++++------- source/client/net.h | 14 ++++++- source/client/server.cpp | 77 ++++++++-------------------------- 7 files changed, 121 insertions(+), 125 deletions(-) diff --git a/bootstrap.sh b/bootstrap.sh index 26e306d..701f47b 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -16,7 +16,7 @@ if [[ $? != 0 ]]; then exit fi -echo "Performing install" +echo "TTRTS: Performing install" sudo make install if [[ $? != 0 ]]; then echo "TTRTS: Install failed, check output" diff --git a/source/client/client.cpp b/source/client/client.cpp index 8619898..f052ad2 100644 --- a/source/client/client.cpp +++ b/source/client/client.cpp @@ -50,14 +50,12 @@ int runClient(int argc, char* argv[]) if (sockfd < 0) fatal_perror("ERROR opening socket"); - std::cout<<"Opened socket on "<= 0 ) { - std::cout<<"Waiting for gamestate"< @@ -95,10 +96,7 @@ CTTRTSGame GetGameFromFile( const std::string& filename ) // If still not good if( access( gamefile.c_str(), F_OK ) == -1 ) - { - std::cerr<<"Error: "<< gamefile <<" file not found"<(file)),std::istreambuf_iterator()); if( gameDescriptor.size() == 0 ) - { - std::cerr<<"Error: failed to read in any information from "<>input; if( !input.size() || std::tolower(input[0]) != 'y' ) - { - std::cerr<<"Aborting..."<= 0) break; - std::cout<<"Binding failed on try "< &myClients, CTTRTSGame &ga void SendGamestateToClients(std::vector &myClients, const CTTRTSGame &game, std::mutex &gameMutex); // Tries to bind to a socket, will attempt 10 times with longer waits between -void TryBindSocket(int sockfd, sockaddr_in &serv_addr); +void TryBindSocket(int sockfd, const sockaddr_in &serv_addr); // Perform the server side handshake with a client -void PerformServerHandshake(const ClientInfo &client, const CTTRTSGame &game); +void PerformServerHandshake(const ClientInfo &client, const std::string &game); // Perform the client side handshake with the server void PerformClientHandshake(int sockfd, unsigned int &player, std::string &gameNameString); diff --git a/source/client/server.cpp b/source/client/server.cpp index f5ff5e0..b54a541 100644 --- a/source/client/server.cpp +++ b/source/client/server.cpp @@ -16,39 +16,13 @@ void RunServerForGame(CTTRTSGame &game) { - std::cout<<"Setting up server on port "< players = game.GetPlayers(); @@ -61,59 +35,40 @@ void RunServerForGame(CTTRTSGame &game) // Set of clients std::vector myClients; - std::cout<<"Waiting for clients"<< std::endl; + std::cout<<"TTRTS: Waiting for "< Date: Sun, 4 Jan 2015 13:09:37 +0000 Subject: [PATCH 27/43] Major cleanup of client code, extracting various functionality --- source/client/client.cpp | 92 +++++++++--------------------------- source/client/filesystem.cpp | 55 ++++++++++++++------- source/client/net.cpp | 73 +++++++++++++++++++++++++++- source/client/net.h | 26 ++++++++++ source/client/server.cpp | 15 +----- 5 files changed, 161 insertions(+), 100 deletions(-) diff --git a/source/client/client.cpp b/source/client/client.cpp index f052ad2..d5de77f 100644 --- a/source/client/client.cpp +++ b/source/client/client.cpp @@ -2,117 +2,69 @@ #include -#include -#include -#include -#include - -#include -#include -#include - -#include - #include "net.h" + #include "game.h" #include "filesystem.h" int runClient(int argc, char* argv[]) { - player_t myPlayer = player_t::NUM_INVALID; // My player - - int sockfd; // socket File descriptor - int portno; // Port number - int n = 0; // return value for read and write calls - - struct sockaddr_in serv_addr; // Server address - - struct hostent *server; // pointer to host information - - char buffer[1028]; // buffer for socket read - memset(buffer,0,sizeof(buffer)); - // must provide information if (argc < 2) - { - fprintf(stderr,"usage %s hostname\n", argv[0]); - exit(0); - } + fatal_error("Usage: ttrts client HOST"); - // Get port number - portno = TTRTS_PORT; + std::string hostname = argv[1]; - // Create a new socket - // AF_INET is general internetsocket domain - // SOCK_STREAM as messages will be read in on this socket, SOCK_DGRAM would be for packets - // 0 is for default protocol - sockfd = socket(AF_INET, SOCK_STREAM, 0); - if (sockfd < 0) - fatal_perror("ERROR opening socket"); - - // Get the hostent information for the host by name - server = gethostbyname(argv[1]); - if (server == NULL) - fatal_error("ERROR, no such host"); - - std::cout<<"TTRTS: Connecting to "<h_addr, server->h_length); - // Set our server address port to the port number provided - serv_addr.sin_port = htons(portno); + serv_addr.sin_port = htons(TTRTS_PORT); - // Attempt to connect to the server using the socket and server address info - if (connect(sockfd, (const sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) - fatal_perror("ERROR connecting"); + std::cout<<"TTRTS: Connecting to "<= 0 ) { std::cout<<"TTRTS: Waiting for gamestate"< + #include #include @@ -186,4 +188,73 @@ sockaddr_in GetLocalServerAddress() // The host for this address is this current machine's IP, INADDR_ANY fetches this serv_addr.sin_addr.s_addr = INADDR_ANY; return serv_addr; -} \ No newline at end of file +} + + +int ConnectToHostServer(const std::string &hostname, sockaddr_in &serv_addr) +{ + // Create a new socket + int sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd < 0) + fatal_perror("ERROR opening socket"); + + // Get the hostent information for the host by name + hostent *server = gethostbyname(hostname.c_str()); + if (server == NULL) + fatal_error("ERROR, no such host"); + + // copy the server address into our server_addr struct + memcpy(&serv_addr.sin_addr.s_addr, server->h_addr, server->h_length); + + // Attempt to connect to the server using the socket and server address info + if (connect(sockfd, (const sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) + fatal_perror("ERROR connecting"); + + return sockfd; +} + +std::string WaitForGamestateMessage(int sockfd) +{ + std::string gamestate; + char gamestateBuffer[1028]; + while( gamestate.find("END") == std::string::npos ) + { + memset(gamestateBuffer,0,sizeof(gamestateBuffer)); + + // Receive gamestate + if (read(sockfd,gamestateBuffer,sizeof(gamestateBuffer)-1) < 0) + fatal_perror("ERROR reading from client"); + + gamestate+=gamestateBuffer; + } + return gamestate; +} + +int SendOrdersToServer(int sockfd, const std::string &orders) +{ + int n = write(sockfd,orders.c_str(),orders.length()); + if (0 < n) + fatal_perror("ERROR writing to socket"); + return n; +} + + +int OutputGameEnd( CTTRTSGame& game ) +{ + std::cout<<"TTRTS: Game Over!"< Date: Tue, 6 Jan 2015 12:39:56 +0000 Subject: [PATCH 28/43] Guard against missing file param for server --- source/client/server.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/client/server.cpp b/source/client/server.cpp index 7a552fa..e4b1d41 100644 --- a/source/client/server.cpp +++ b/source/client/server.cpp @@ -82,6 +82,10 @@ void RunServerForGame(CTTRTSGame &game) int runServer(int argc, char* argv[]) { + // argv[1] needs to be a valid game file + if( argc < 2 ) + fatal_error("must provide game file argument"); + // Set up game CTTRTSGame game = GetGameFromFile(argv[1]); if(game.GetNumUnits() == 0) From a0ff8680a3e5e4bd3845bfdd8e24f8559cbbc27b Mon Sep 17 00:00:00 2001 From: JackUnthank Date: Tue, 6 Jan 2015 17:01:15 +0000 Subject: [PATCH 29/43] Make the AI print out the walls not the map. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don’t worry I wasn’t doing this all afternoon I had a spare 5 minutes whilst waiting for some .DAT files to md5. =P --- api/perl/ttrts.pm | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/api/perl/ttrts.pm b/api/perl/ttrts.pm index 6dc279e..793269b 100644 --- a/api/perl/ttrts.pm +++ b/api/perl/ttrts.pm @@ -238,6 +238,13 @@ sub PrintGameFromGamestateString $map[$invalidPos[0]][$invalidPos[1]] = "~"; } + # Fill with walls + foreach my $wall ( $info[8] =~ /\[(\d+,\d+)\]/g ) + { + $wall =~ /(\d+),(\d+)/; + $map[$1][$2] = "|"; + } + # Fill with units for my $unit (@units) { From 3291bf126e1831645531689c23fd4022fb31ae0d Mon Sep 17 00:00:00 2001 From: Marc Di Luzio Date: Wed, 7 Jan 2015 12:39:27 +0000 Subject: [PATCH 30/43] Compare write result correctly with 0 Fixes client sending of orders --- source/client/net.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/client/net.cpp b/source/client/net.cpp index 956c688..1de5847 100644 --- a/source/client/net.cpp +++ b/source/client/net.cpp @@ -233,7 +233,7 @@ std::string WaitForGamestateMessage(int sockfd) int SendOrdersToServer(int sockfd, const std::string &orders) { int n = write(sockfd,orders.c_str(),orders.length()); - if (0 < n) + if (n < 0) fatal_perror("ERROR writing to socket"); return n; } From c51119c3e2c1772cd5385478d0bcf0ca51d341eb Mon Sep 17 00:00:00 2001 From: Marc Di Luzio Date: Wed, 7 Jan 2015 12:40:41 +0000 Subject: [PATCH 31/43] Add TTRTS: Prefix to output --- source/client/net.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/client/net.cpp b/source/client/net.cpp index 956c688..9ee7b45 100644 --- a/source/client/net.cpp +++ b/source/client/net.cpp @@ -32,7 +32,7 @@ void WaitForOrdersFromClient(const ClientInfo info, CTTRTSGame &game, std::mute orders+=buffer; } - std::clog<<"Recieved orders from "< Date: Wed, 7 Jan 2015 13:25:16 +0000 Subject: [PATCH 32/43] Fix walls in strings and move constructor --- source/ttrts/formatters.cpp | 2 +- source/ttrts/game.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/source/ttrts/formatters.cpp b/source/ttrts/formatters.cpp index 6d6d03a..332c5ac 100644 --- a/source/ttrts/formatters.cpp +++ b/source/ttrts/formatters.cpp @@ -92,7 +92,7 @@ CTTRTSGame GetGameFromString( const std::string& input ) size_t pos; while ( ( pos = walls_str.find(']') ) != std::string::npos ) { - std::string pos_string = walls_str.substr(0,pos); + std::string pos_string = walls_str.substr(0,pos+1); // Use scanf to extract positions diff --git a/source/ttrts/game.cpp b/source/ttrts/game.cpp index 96800d5..d649060 100644 --- a/source/ttrts/game.cpp +++ b/source/ttrts/game.cpp @@ -17,6 +17,7 @@ CTTRTSGame::CTTRTSGame(CTTRTSGame&& game) , dimensions(std::move(game.dimensions)) , turn(std::move(game.turn)) , name(std::move(game.name)) +, m_walls(std::move(game.m_walls)) { } From 1b2010faba984cf499ac98a08216720f9288cd39 Mon Sep 17 00:00:00 2001 From: mdiluzio Date: Sat, 10 Jan 2015 15:11:36 +0000 Subject: [PATCH 33/43] Use some version checking on generator scripts, preventing a full rebuild on every build --- scripts/gen_manpage.sh | 16 ++++++++++++---- scripts/gen_usage.sh | 10 +++++++++- scripts/gen_version_header.sh | 7 ++++++- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/scripts/gen_manpage.sh b/scripts/gen_manpage.sh index 57ad57c..aed24fc 100755 --- a/scripts/gen_manpage.sh +++ b/scripts/gen_manpage.sh @@ -1,10 +1,13 @@ #! /bin/bash # Used to a man page from markdown -echo ".\" Man page for the ttrts project" > $4 -echo ".\" this man page is auto-generated, do not edit directly" >> $4 +FILE="$4" +TEMP="$FILE.tmp" -echo ".TH TTRTS\ v$1.$2.$3 6 $(date +%Y-%m-%d) http://mdiluz.github.io/ttrts/" >> $4 +echo ".\" Man page for the ttrts project" > $TEMP +echo ".\" this man page is auto-generated, do not edit directly" >> $TEMP + +echo ".TH TTRTS\ v$1.$2.$3 6 $(date +%Y-%m-%d) http://mdiluz.github.io/ttrts/" >> $TEMP # NOTE: For the OSX version of sed we use -E, which on linux appears be an undocumented switch for -r # we also have to use [A-Za-z] instead of \w for some reason @@ -32,4 +35,9 @@ cat "$5" \ | sed -E 's/-----+//g' \ | sed -E 's/`(.*)`/\\fB\1\\fR/g' \ | sed -E 's/MAPFILE/\\fImapfile\\fR/g' \ - | sed -E 's/ ttrts -/ ttrts \\-/g' >> $4 + | sed -E 's/ ttrts -/ ttrts \\-/g' >> $TEMP + + +if [ ! -e $FILE ] || [ ! -z $( diff $FILE $TEMP ) ]; then + mv -f $TEMP $FILE +fi diff --git a/scripts/gen_usage.sh b/scripts/gen_usage.sh index efeab0a..5e33166 100755 --- a/scripts/gen_usage.sh +++ b/scripts/gen_usage.sh @@ -1,10 +1,18 @@ #! /bin/bash # Used to generate usage text from markdown +FILE="$1" +TEMP="${FILE}_tmp" + cat README.md \ | sed -E 's/^#+ //g' \ | sed -E 's/^ /\\t/g' \ | sed -E 's/^ /\\t/g' \ | sed -E 's/^/\"/' \ | sed -E 's/$/\\n\"/' \ - > $1 + > $TEMP + +# If no difference +if [ ! -e $FILE ] || [ ! -z "$( diff $TEMP $FILE )" ]; then + mv -f $TEMP $FILE +fi diff --git a/scripts/gen_version_header.sh b/scripts/gen_version_header.sh index 907c2be..69db452 100755 --- a/scripts/gen_version_header.sh +++ b/scripts/gen_version_header.sh @@ -10,4 +10,9 @@ HEADER="// Auto generated ttrts version header #endif //_TTRTS_VERSION_H_" -echo "$HEADER" > "version.h" \ No newline at end of file +echo "$HEADER" > "version.h.tmp" + +# If no difference +if [ ! -e version.h ] || [ ! -z $( diff version.h version.h.tmp ) ]; then + mv -f version.h.tmp version.h +fi From 0ead12c7dd68097ffbb0ab6fdc9e287f972f31a9 Mon Sep 17 00:00:00 2001 From: mdiluzio Date: Sat, 10 Jan 2015 16:55:30 +0000 Subject: [PATCH 34/43] Huge refactor, pulling server and local out into their own binaries --- source/client/CMakeLists.txt | 30 +------- source/client/README.md | 98 ------------------------ source/client/client.cpp | 8 +- source/client/client.h | 6 -- source/client/main.cpp | 34 -------- source/client/server.h | 6 -- source/local/CMakeLists.txt | 23 ++++++ source/local/local.cpp | 62 +++++++++++++++ source/server/CMakeLists.txt | 23 ++++++ source/{client => server}/server.cpp | 6 +- source/system/CMakeLists.txt | 21 +++++ source/system/error.h | 25 ++++++ source/{client => system}/filesystem.cpp | 52 +------------ source/{client => system}/filesystem.h | 0 source/{client => system}/net.cpp | 1 + source/{client => system}/net.h | 17 ---- 16 files changed, 165 insertions(+), 247 deletions(-) delete mode 100644 source/client/README.md delete mode 100644 source/client/client.h delete mode 100644 source/client/main.cpp delete mode 100644 source/client/server.h create mode 100644 source/local/CMakeLists.txt create mode 100644 source/local/local.cpp create mode 100644 source/server/CMakeLists.txt rename source/{client => server}/server.cpp (95%) create mode 100644 source/system/CMakeLists.txt create mode 100644 source/system/error.h rename source/{client => system}/filesystem.cpp (82%) rename source/{client => system}/filesystem.h (100%) rename source/{client => system}/net.cpp (99%) rename source/{client => system}/net.h (87%) diff --git a/source/client/CMakeLists.txt b/source/client/CMakeLists.txt index 7f26ed1..1ae8054 100644 --- a/source/client/CMakeLists.txt +++ b/source/client/CMakeLists.txt @@ -3,45 +3,21 @@ project( ttrts-client ) include_directories( - ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ../system ../ttrts ) # Add the sources set( SOURCES - main.cpp client.cpp - server.cpp - net.cpp - filesystem.cpp ) -# Set defaults for ttrts variables -set( TTRTS_MAPS "/usr/local/share/ttrts/maps/" ) -set( TTRTS_GAMES "/tmp/" ) -set( TTRTS_PORT 11715 ) - -# define these defaults in code -set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTTRTS_MAPS=${TTRTS_MAPS}" ) -set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTTRTS_GAMES=${TTRTS_GAMES}" ) -set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTTRTS_PORT=${TTRTS_PORT}" ) - # Add the executable add_executable( ${PROJECT_NAME} ${SOURCES} ) -# Set our output name to ttrts -set_target_properties( ${PROJECT_NAME} PROPERTIES OUTPUT_NAME ttrts ) - # dependent on main ttrts libary -target_link_libraries( ${PROJECT_NAME} ttrts pthread ) +target_link_libraries( ${PROJECT_NAME} ttrts ttrts-system ) # Installation target install( TARGETS ${PROJECT_NAME} DESTINATION bin ) - -# Run the gen_usage script to generate our usage header -add_custom_target( - ttrts-client-usage - cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_SOURCE_DIR}/scripts/gen_usage.sh "${CMAKE_CURRENT_BINARY_DIR}/usage.h" -) - -add_dependencies(${PROJECT_NAME} ttrts-client-usage) diff --git a/source/client/README.md b/source/client/README.md deleted file mode 100644 index 9e8cf27..0000000 --- a/source/client/README.md +++ /dev/null @@ -1,98 +0,0 @@ -# NAME - ttrts - Tiny Terminal RTS - -# SYNOPSIS - ttrts MAPFILE - -# DESCRIPTION - ttrts is a tiny terminal based RTS that uses text files as order lists to control the units - - This means that any user, program or cat that can read and write to text files can play the game - -# RETURN VALUE - ttrts will return -1 on error, or the winning player on completion - -# OPTIONS - MAPFILE - File to read in the initial game state. Local or in ${TTRTS_MAPS} - -# USAGE - When invoked, ttrts will set up the game in a directory within ${TTRTS_GAMES} by the name of the map - - The files in this directory can be read and interpreted by human, robot or cat - - ttrts will then await order files from each participant - - Once all order files have been received ttrts will calculate the turn and output a new gamestate file - - This process repeats until the game is over - -# ENVIRONMENT - ${TTRTS_MAPS} - Map file lookup location, defaults to `/usr/share/ttrts/maps/` - - ${TTRTS_GAMES} - Game directory for I/O, defaults to `/tmp/` - ------------------------------------------------------------ -# FILES - `/usr/share/ttrts/maps/` holds a sample set of maps - -## Gamestate File - Turn_{TURNNUMBER}.txt - -### Contents - ===== ttrts v{MAJOR}.{MINOR}.{PATCH} ===== - NAME:{GAMENAME} - SIZE:[{X},{Y}] - TURN:{TURNNUMBER} - WALL:[{X},{Y}][{X},{Y}][{X},{Y}]...{repeat for all walls} - ~~~~ - UNIT:{ID} pl:{PLAYER} vs:{VIS} dr:{DIR(NESW)} ps:[{X},{Y}] - ... {continue for all units} - END - -## Order File - Player_{PLAYER_ID}_Turn_{TURN_NUMBER}.txt - -### Contents - ORDER:{ORDER_CHAR} id:{UNIT_ID} - ... {continue for all orders} - END - ------------------------------------------------------------ -# GAMEPLAY - - The game takes place in a series of simultaneous turns on an arbitrarily sized 2D board - - Each turn, the client outputs a gamestate file and waits for an order file from each player - - All commands are evaluated simultaneously with friendly fire enabled by default - - The game is over when any of three conditions are met - - * All remaining units are controlled by a single player - * No units are left (draw) - * All units left are unable to move (draw) - -# UNITS - Each unit occupies a single tile on the board, facing in a compass direction (NESW) - - Units will only accept orders from their owner - - Units can receive only a single order each turn - - Units cannot occupy the same tile as other units/walls - -# ORDERS -### F - Move unit [F]orward one space, leaving a wall - - This wall will remain until the end of the game, blocking movement to that tile - - Movement orders have no effect if impossible, eg. - * Attempting to move outside of map - * Attempting to move on to tile occupied by unit/wall - -### L/R - Rotate unit [L]eft or [R]ight - - Unit will rotate clockwise or counter-clockwise, this order cannot fail - -### A - [A]ttack in straight line in front of unit - - Attack will continue forward until unit can't progress, all units within the path of the attack are destroyed. diff --git a/source/client/client.cpp b/source/client/client.cpp index d5de77f..116a5a0 100644 --- a/source/client/client.cpp +++ b/source/client/client.cpp @@ -1,17 +1,15 @@ -#include "client.h" - #include #include "net.h" - #include "game.h" +#include "error.h" #include "filesystem.h" -int runClient(int argc, char* argv[]) +int main(int argc, char* argv[]) { // must provide information if (argc < 2) - fatal_error("Usage: ttrts client HOST"); + fatal_error("Usage: ttrts-client HOST"); std::string hostname = argv[1]; diff --git a/source/client/client.h b/source/client/client.h deleted file mode 100644 index 201c0d9..0000000 --- a/source/client/client.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _TTRTS_CLIENT_H_ -#define _TTRTS_CLIENT_H_ - -int runClient(int argc, char* argv[]); - -#endif \ No newline at end of file diff --git a/source/client/main.cpp b/source/client/main.cpp deleted file mode 100644 index a436d6a..0000000 --- a/source/client/main.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include "game.h" -#include "filesystem.h" -#include "server.h" -#include "client.h" - -#include - -static const char* sk_usage = -#include "usage.h" -; - -// Main program entry point -int main(int argc, char* argv[]) -{ - // If no args, print usage - if ( argc == 1 ) - { - std::cout< + +// ===================================================================================================================== +int main(int argc, char* argv[]) +{ + // must provide information + if (argc < 2) + fatal_error("Usage: ttrts-local MAPFILE"); + + std::string gamefile = argv[1]; + + std::cout<<"TTRTS: Launching with "< #include @@ -80,11 +80,11 @@ void RunServerForGame(CTTRTSGame &game) SendGamestateToClients(myClients, game, gameMutex); } -int runServer(int argc, char* argv[]) +int main(int argc, char* argv[]) { // argv[1] needs to be a valid game file if( argc < 2 ) - fatal_error("must provide game file argument"); + fatal_error("Usage: ttrts-server MAPFILE"); // Set up game CTTRTSGame game = GetGameFromFile(argv[1]); diff --git a/source/system/CMakeLists.txt b/source/system/CMakeLists.txt new file mode 100644 index 0000000..c17548e --- /dev/null +++ b/source/system/CMakeLists.txt @@ -0,0 +1,21 @@ +cmake_minimum_required(VERSION 2.8.7) + +# Main ttrts library +project( ttrts-system ) + +# Include the maths +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ../ttrts +) + +# Add our sources +set( SOURCES + net.cpp + filesystem.cpp +) + +# Add this library +add_library( ${PROJECT_NAME} ${SOURCES} ) + +target_link_libraries( ${PROJECT_NAME} ttrts pthread ) diff --git a/source/system/error.h b/source/system/error.h new file mode 100644 index 0000000..2d9cde5 --- /dev/null +++ b/source/system/error.h @@ -0,0 +1,25 @@ +#ifndef _TTRTS_ERROR_H_ +#define _TTRTS_ERROR_H_ + +#include +#include +#include + +//====================================================================================================================== +// Error functions + +// For local fatal errors +inline void fatal_error(const char *msg) +{ + std::cerr< @@ -244,55 +245,4 @@ int OutputgameEnd(const CTTRTSGame &game) { } return (int)winningPlayer; -} - -// ===================================================================================================================== -int runFromFilesystem(int argc, char* argv[]) -{ - std::string gamefile = argv[1]; - - std::cout<<"TTRTS: Launching with "< diff --git a/source/client/net.h b/source/system/net.h similarity index 87% rename from source/client/net.h rename to source/system/net.h index 4d0cc33..bfcc97e 100644 --- a/source/client/net.h +++ b/source/system/net.h @@ -74,23 +74,6 @@ std::string WaitForGamestateMessage(int sockfd); // Send orders to the server int SendOrdersToServer(int sockfd, const std::string &orders); -//====================================================================================================================== -// Error functions - -// For local fatal errors -inline void fatal_error(const char *msg) -{ - std::cerr< Date: Sat, 10 Jan 2015 16:56:01 +0000 Subject: [PATCH 35/43] Update CMakelists to reflect refactor --- CMakeLists.txt | 23 ++++++++++++++--------- source/CMakeLists.txt | 13 +++++++++++++ 2 files changed, 27 insertions(+), 9 deletions(-) create mode 100644 source/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 01d8a13..97a47ba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,8 +2,18 @@ cmake_minimum_required( VERSION 2.8.7 ) # Set version information set( TTRTS_VERSION_MAJOR 0 ) -set( TTRTS_VERSION_MINOR 3 ) -set( TTRTS_VERSION_PATCH 2 ) +set( TTRTS_VERSION_MINOR 4 ) +set( TTRTS_VERSION_PATCH 0 ) + +# Set defaults for ttrts variables +set( TTRTS_MAPS "/usr/local/share/ttrts/maps/" ) +set( TTRTS_GAMES "/tmp/" ) +set( TTRTS_PORT 11715 ) + +# define these defaults in code +set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTTRTS_MAPS=${TTRTS_MAPS}" ) +set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTTRTS_GAMES=${TTRTS_GAMES}" ) +set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTTRTS_PORT=${TTRTS_PORT}" ) # Use c++1y (14) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++1y" ) @@ -26,7 +36,7 @@ install( FILES scripts/ttrts_complete DESTINATION /etc/bash_completion.d/ ) # Run the gen_usage script to generate our usage header add_custom_target( ttrts-gen-manpage ALL - ${CMAKE_SOURCE_DIR}/scripts/gen_manpage.sh "${TTRTS_VERSION_MAJOR}" "${TTRTS_VERSION_MINOR}" "${TTRTS_VERSION_PATCH}" "ttrts.6" "${CMAKE_SOURCE_DIR}/source/client/README.md" + ${CMAKE_SOURCE_DIR}/scripts/gen_manpage.sh "${TTRTS_VERSION_MAJOR}" "${TTRTS_VERSION_MINOR}" "${TTRTS_VERSION_PATCH}" "ttrts.6" "${CMAKE_SOURCE_DIR}/source/README.md" ) # Install the ttrts man page @@ -41,9 +51,4 @@ endif() install( FILES "${CMAKE_BINARY_DIR}/ttrts.6" DESTINATION ${MANPAGE_LOC} ) # Subprojects -add_subdirectory( source/ttrts ) -add_subdirectory( source/client ) - -# Auxhilary binaries -add_subdirectory( source/test ) -add_subdirectory( source/gen ) +add_subdirectory( source ) diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt new file mode 100644 index 0000000..d73e509 --- /dev/null +++ b/source/CMakeLists.txt @@ -0,0 +1,13 @@ +# Main libraries +add_subdirectory( ttrts ) +add_subdirectory( system ) + +# Main binaries +add_subdirectory( launcher ) +add_subdirectory( client ) +add_subdirectory( server ) +add_subdirectory( local ) + +# Auxhilary binaries +add_subdirectory( test ) +add_subdirectory( gen ) \ No newline at end of file From 06057e6e5222816959811cbe400704a3662fe940 Mon Sep 17 00:00:00 2001 From: mdiluzio Date: Sat, 10 Jan 2015 16:56:27 +0000 Subject: [PATCH 36/43] Add perl launcher script and new Readme --- source/README.md | 105 +++++++++++++++++++++++++++++---- source/launcher/CMakeLists.txt | 6 ++ source/launcher/ttrts.pl | 42 +++++++++++++ 3 files changed, 143 insertions(+), 10 deletions(-) create mode 100644 source/launcher/CMakeLists.txt create mode 100755 source/launcher/ttrts.pl diff --git a/source/README.md b/source/README.md index 5ca2d8e..fa89aec 100644 --- a/source/README.md +++ b/source/README.md @@ -1,13 +1,98 @@ -# Targets -### client -Main TTRTS binary, runs from the command line and acts as host for games +# NAME + ttrts - Tiny Terminal RTS -### test -Test binary, to be compiled and run to test various functionality +# SYNOPSIS + ttrts [--server] [--client] [--host=HOSTNAME] [MAPFILE] + +# DESCRIPTION + ttrts is a tiny terminal based RTS that uses text files as order lists to control the units -### gen -Binary to generate example map files + This means that any user, program or cat that can read and write to text files can play the game -# Libraries -### ttrts -Implementation of the RTS rules and simulation +# RETURN VALUE + ttrts will return -1 on error, or the winning player on completion + +# OPTIONS + MAPFILE - File to read in the initial game state. Local or in ${TTRTS_MAPS} + +# USAGE + When invoked, ttrts will set up the game in a directory within ${TTRTS_GAMES} by the name of the map + + The files in this directory can be read and interpreted by human, robot or cat + + ttrts will then await order files from each participant + + Once all order files have been received ttrts will calculate the turn and output a new gamestate file + + This process repeats until the game is over + +# ENVIRONMENT + ${TTRTS_MAPS} - Map file lookup location, defaults to `/usr/share/ttrts/maps/` + + ${TTRTS_GAMES} - Game directory for I/O, defaults to `/tmp/` + +----------------------------------------------------------- +# FILES + `/usr/share/ttrts/maps/` holds a sample set of maps + +## Gamestate File + Turn_{TURNNUMBER}.txt + +### Contents + ===== ttrts v{MAJOR}.{MINOR}.{PATCH} ===== + NAME:{GAMENAME} + SIZE:[{X},{Y}] + TURN:{TURNNUMBER} + WALL:[{X},{Y}][{X},{Y}][{X},{Y}]...{repeat for all walls} + ~~~~ + UNIT:{ID} pl:{PLAYER} vs:{VIS} dr:{DIR(NESW)} ps:[{X},{Y}] + ... {continue for all units} + END + +## Order File + Player_{PLAYER_ID}_Turn_{TURN_NUMBER}.txt + +### Contents + ORDER:{ORDER_CHAR} id:{UNIT_ID} + ... {continue for all orders} + END + +----------------------------------------------------------- +# GAMEPLAY + + The game takes place in a series of simultaneous turns on an arbitrarily sized 2D board + + Each turn, the client outputs a gamestate file and waits for an order file from each player + + All commands are evaluated simultaneously with friendly fire enabled by default + + The game is over when any of three conditions are met - + * All remaining units are controlled by a single player + * No units are left (draw) + * All units left are unable to move (draw) + +# UNITS + Each unit occupies a single tile on the board, facing in a compass direction (NESW) + + Units will only accept orders from their owner + + Units can receive only a single order each turn + + Units cannot occupy the same tile as other units/walls + +# ORDERS +### F - Move unit [F]orward one space, leaving a wall + + This wall will remain until the end of the game, blocking movement to that tile + + Movement orders have no effect if impossible, eg. + * Attempting to move outside of map + * Attempting to move on to tile occupied by unit/wall + +### L/R - Rotate unit [L]eft or [R]ight + + Unit will rotate clockwise or counter-clockwise, this order cannot fail + +### A - [A]ttack in straight line in front of unit + + Attack will continue forward until unit can't progress, all units within the path of the attack are destroyed. diff --git a/source/launcher/CMakeLists.txt b/source/launcher/CMakeLists.txt new file mode 100644 index 0000000..c6726c7 --- /dev/null +++ b/source/launcher/CMakeLists.txt @@ -0,0 +1,6 @@ +# ====================== ttrts ======================= +# Project name +project( ttrts-perl-launch ) + +# Add bash completion to install +install( PROGRAMS ttrts.pl DESTINATION bin RENAME ttrts ) diff --git a/source/launcher/ttrts.pl b/source/launcher/ttrts.pl new file mode 100755 index 0000000..b757ee9 --- /dev/null +++ b/source/launcher/ttrts.pl @@ -0,0 +1,42 @@ +#! /usr/bin/perl +# Main ttrts launcher script + +use strict; +use warnings; +use 5.0; + +use Getopt::Long qw(GetOptions); + +sub print_usage +{ + print "Unknown option: @_\n" if ( @_ ); + print "Usage: ttrts [--server] [--client] [--host=HOSTNAME] [--map=MAPFILE]\n"; + exit; +} + +our $VERBOSE = $ENV{"VERBOSE"}; + +our $server; +our $client; +our $host; +our $map; + +print_usage() if ( @ARGV < 1 or + !GetOptions( + 'client' => \$client, + 'server' => \$server, + 'host=s' => \$host, + 'map=s' => \$map, + ) ); + +print "Cannot run as both client and server\n" and exit if $client and $server; +print "Client requires hostname\n" and exit if $client and not $host; +print "Server requires mapfile\n" and exit if $server and not $map; +print "Running locally requires mapfile\n" and exit if not $server and not $client and not $map; + +# Run client, server or local +system("ttrts-client $host") if $client and $host; +system("ttrts-server $map") if $server and $map; +system("ttrts-local $map") if not $server and not $client and $map; + +print "Success!\n"; \ No newline at end of file From d65ef46634a6f112f424baf463fb2652e25d27d4 Mon Sep 17 00:00:00 2001 From: mdiluzio Date: Sat, 10 Jan 2015 16:56:42 +0000 Subject: [PATCH 37/43] Fix some bugs in generation scripts --- scripts/gen_manpage.sh | 2 +- scripts/gen_version_header.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/gen_manpage.sh b/scripts/gen_manpage.sh index aed24fc..0ce6110 100755 --- a/scripts/gen_manpage.sh +++ b/scripts/gen_manpage.sh @@ -38,6 +38,6 @@ cat "$5" \ | sed -E 's/ ttrts -/ ttrts \\-/g' >> $TEMP -if [ ! -e $FILE ] || [ ! -z $( diff $FILE $TEMP ) ]; then +if [ ! -e $FILE ] || [ ! -z "$( diff $FILE $TEMP )" ]; then mv -f $TEMP $FILE fi diff --git a/scripts/gen_version_header.sh b/scripts/gen_version_header.sh index 69db452..aec60e2 100755 --- a/scripts/gen_version_header.sh +++ b/scripts/gen_version_header.sh @@ -13,6 +13,6 @@ HEADER="// Auto generated ttrts version header echo "$HEADER" > "version.h.tmp" # If no difference -if [ ! -e version.h ] || [ ! -z $( diff version.h version.h.tmp ) ]; then +if [ ! -e version.h ] || [ ! -z "$( diff version.h version.h.tmp )" ]; then mv -f version.h.tmp version.h fi From 96f5c08c14071d19048bb7306696884e58a87296 Mon Sep 17 00:00:00 2001 From: mdiluzio Date: Sat, 10 Jan 2015 16:59:45 +0000 Subject: [PATCH 38/43] Update completion script with new parameters --- scripts/ttrts_complete | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/ttrts_complete b/scripts/ttrts_complete index 7b884b7..65759a9 100755 --- a/scripts/ttrts_complete +++ b/scripts/ttrts_complete @@ -5,10 +5,11 @@ test ! -z TTRTS_MAPS && TTRTS_MAPS=/usr/share/ttrts/maps/ have ttrts && function _ttrts { - commandnames="" + commandnames="--server --client --map --host localhost " for filename in ${TTRTS_MAPS}/* do map="${filename##*/}" + commandnames+="--map=$map " commandnames+="$map " done From 96153f8c609b4bd9f8b72931ba5300389ac6af9f Mon Sep 17 00:00:00 2001 From: mdiluzio Date: Sat, 10 Jan 2015 17:04:55 +0000 Subject: [PATCH 39/43] Update launcher script with handing of return value --- source/launcher/ttrts.pl | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/source/launcher/ttrts.pl b/source/launcher/ttrts.pl index b757ee9..886fed6 100755 --- a/source/launcher/ttrts.pl +++ b/source/launcher/ttrts.pl @@ -29,14 +29,16 @@ print_usage() if ( @ARGV < 1 or 'map=s' => \$map, ) ); +# Verify we have the right parameters print "Cannot run as both client and server\n" and exit if $client and $server; print "Client requires hostname\n" and exit if $client and not $host; print "Server requires mapfile\n" and exit if $server and not $map; print "Running locally requires mapfile\n" and exit if not $server and not $client and not $map; # Run client, server or local -system("ttrts-client $host") if $client and $host; -system("ttrts-server $map") if $server and $map; -system("ttrts-local $map") if not $server and not $client and $map; +my $res = -1; +$res = system("ttrts-client $host") if $client and $host; +$res = system("ttrts-server $map") if $server and $map; +$res = system("ttrts-local $map") if not $server and not $client and $map; -print "Success!\n"; \ No newline at end of file +return $res \ No newline at end of file From 3bb576606128e8323618788a493f13ccd70521e3 Mon Sep 17 00:00:00 2001 From: mdiluzio Date: Sat, 10 Jan 2015 17:06:23 +0000 Subject: [PATCH 40/43] Fix completion script to take into account non-positional arguments --- scripts/ttrts_complete | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/ttrts_complete b/scripts/ttrts_complete index 65759a9..d257ed4 100755 --- a/scripts/ttrts_complete +++ b/scripts/ttrts_complete @@ -5,12 +5,11 @@ test ! -z TTRTS_MAPS && TTRTS_MAPS=/usr/share/ttrts/maps/ have ttrts && function _ttrts { - commandnames="--server --client --map --host localhost " + commandnames="--server --client --host= --host=localhost " for filename in ${TTRTS_MAPS}/* do map="${filename##*/}" commandnames+="--map=$map " - commandnames+="$map " done local cur prev From 5e66596d30b3a42ab1ce0a49f16baec97e9b666d Mon Sep 17 00:00:00 2001 From: mdiluzio Date: Sat, 10 Jan 2015 17:22:34 +0000 Subject: [PATCH 41/43] Update the Readme with new server and client communication options --- source/README.md | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/source/README.md b/source/README.md index fa89aec..22b8dea 100644 --- a/source/README.md +++ b/source/README.md @@ -2,7 +2,7 @@ ttrts - Tiny Terminal RTS # SYNOPSIS - ttrts [--server] [--client] [--host=HOSTNAME] [MAPFILE] + ttrts [--server] [--client] [--host=HOSTNAME] [--map=MAPFILE] # DESCRIPTION ttrts is a tiny terminal based RTS that uses text files as order lists to control the units @@ -13,7 +13,13 @@ ttrts will return -1 on error, or the winning player on completion # OPTIONS - MAPFILE - File to read in the initial game state. Local or in ${TTRTS_MAPS} + --server - Run in server mode, must provide a map file + + --client - Run in client mode, must provide a hostname for a running server + + --map=MAPFILE - File to read in the initial game state. Local or in ${TTRTS_MAPS} + + --host=HOSTNAME - Name of host to connect to in client mode # USAGE When invoked, ttrts will set up the game in a directory within ${TTRTS_GAMES} by the name of the map @@ -24,6 +30,8 @@ Once all order files have been received ttrts will calculate the turn and output a new gamestate file + In server and client mode, the client will output and read in these files while the server simulates the game + This process repeats until the game is over # ENVIRONMENT @@ -57,6 +65,21 @@ ... {continue for all orders} END +----------------------------------------------------------- +# SERVER/CLIENT + When in server or client mode, the game can be played across a network. If desired, a player could design an AI to act as a client instead of using the client mode and intermediary filesystem. + +## Protocol + The server is accesible on port 11715 + + To perform the handshake the server will write to the socket with the format "player PLAYER_ID name GAME_NAME", it will expect this exact information to be written back to in reply. + + Once handshake is performed, the server will write to the socket in the form of the Gamestate file as above. + + The server will then wait for a new-line delimited and END terminated list of orders + + This will be repeated until the game is over + ----------------------------------------------------------- # GAMEPLAY From f13a8bd5c4a633d56336dc3cbd57740b7704302c Mon Sep 17 00:00:00 2001 From: mdiluzio Date: Sat, 10 Jan 2015 17:25:01 +0000 Subject: [PATCH 42/43] Ensure that hostname is also properly highlighted --- scripts/gen_manpage.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/gen_manpage.sh b/scripts/gen_manpage.sh index 0ce6110..e699063 100755 --- a/scripts/gen_manpage.sh +++ b/scripts/gen_manpage.sh @@ -35,6 +35,7 @@ cat "$5" \ | sed -E 's/-----+//g' \ | sed -E 's/`(.*)`/\\fB\1\\fR/g' \ | sed -E 's/MAPFILE/\\fImapfile\\fR/g' \ + | sed -E 's/HOSTNAME/\\fIhostname\\fR/g' \ | sed -E 's/ ttrts -/ ttrts \\-/g' >> $TEMP From ae8a3bf0c2d6ba944f37972980dbf8f5dc3c6b21 Mon Sep 17 00:00:00 2001 From: mdiluzio Date: Sat, 10 Jan 2015 17:29:22 +0000 Subject: [PATCH 43/43] Update changelog for v0.4.0 --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 1f18053..a6b299b 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,14 @@ TTRTS is from the ground up designed to be a fun way to practice programming. An ----------------------------------------------------------- ## Changelog +#### v0.4.0 +* Updated with network functionality + * Game can now be hosted with ttrts --server option + * Server can be connected to with ttrts --client +* Updated command line interface with new launcher script + * map file must now be specified with --map=FILE +* Slight refactor of libraries to account for new run targets + #### v0.3.2 * Fix bug when loading map files with walls * Fix ttrts on OSX