diff --git a/base/misc.cpp b/base/misc.cpp index 5f8fcff..ced873e 100644 --- a/base/misc.cpp +++ b/base/misc.cpp @@ -1,6 +1,7 @@ #include "base/misc.h" #include #include +#include namespace base { diff --git a/game/chooseserverform.cpp b/game/chooseserverform.cpp index 4ef78c2..feb1c87 100644 --- a/game/chooseserverform.cpp +++ b/game/chooseserverform.cpp @@ -297,21 +297,27 @@ bool ChooseServerForm::RequestInfos() { } // Don't show servers to disallowed client platforms - #if defined(__MACOSX__) +#if defined(__MACOSX__) if (info.disallow.find("mac") != std::string::npos) { continue; } - #endif - #if defined(__ANDROID__) +#elif defined(DARWIN) + if (info.disallow.find("darwin") != std::string::npos) { + continue; + } +#elif defined(__LINUX__) + if (info.disallow.find("linux") != std::string::npos) { + continue; + } +#elif defined(__ANDROID__) if (info.disallow.find("android") != std::string::npos) { continue; } - #endif - #if defined(IPHONE) || defined(__IPHONEOS__) +#elif defined(IPHONE) || defined(__IPHONEOS__) if (info.disallow.find("iphone") != std::string::npos) { continue; } - #endif +#endif // If there is an info with this name that matches the protocol, // keep it and discard the new info diff --git a/game/httppackinfomanager.cpp b/game/httppackinfomanager.cpp index ca6c710..42eb65f 100644 --- a/game/httppackinfomanager.cpp +++ b/game/httppackinfomanager.cpp @@ -3,6 +3,7 @@ #include "base/format.h" #include #include +#include namespace wi { @@ -173,7 +174,7 @@ void HttpPackInfoManager::OnError(HttpRequest *preq, const char *pszError) { } } -bool HttpPackInfoManager::FinishInstall() { +bool HttpPackInfoManager::FinishInstall() { if (tempfile_ == NULL) { return false; } diff --git a/game/sdl/host.cpp b/game/sdl/host.cpp index 5b3c99c..46dc7a4 100644 --- a/game/sdl/host.cpp +++ b/game/sdl/host.cpp @@ -218,6 +218,7 @@ bool ProcessSdlEvent(base::Message *pmsg, Event *pevt) SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH can be used to process mouse events separately from touch events (it's a shame a similar hint doesn't exist for other platforms). Thus, Android can process both input event types. + - Linux... We'll try only processing SDL_MOUSE events for now. */ #if defined(__IPHONEOS__) || defined(__ANDROID__) @@ -292,7 +293,7 @@ bool ProcessSdlEvent(base::Message *pmsg, Event *pevt) break; #endif -#if defined(__MACOSX__) || defined(__ANDROID__) +#if defined(__MACOSX__) || defined(__ANDROID__) || defined(__LINUX__) case SDL_MOUSEBUTTONDOWN: pevt->eType = penDownEvent; pevt->x = event.button.x; diff --git a/game/sdl/htplatform.h b/game/sdl/htplatform.h index bbb2fee..66a6d9e 100644 --- a/game/sdl/htplatform.h +++ b/game/sdl/htplatform.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/game/sdl/linux/hosthelpers.cpp b/game/sdl/linux/hosthelpers.cpp new file mode 100644 index 0000000..1cd7549 --- /dev/null +++ b/game/sdl/linux/hosthelpers.cpp @@ -0,0 +1,220 @@ +#include "game/sdl/linux/linuxchatcontroller.h" +#include "game/sdl/hosthelpers.h" +#include "game/sdl/sdlhttpservice.h" +#include "base/thread.h" +#include +#include +#include +#include +#include +#include +#include + +namespace wi { + +char gszLinuxGamesDir[PATH_MAX]; // /home/[user]/Games +char gszHomeDir[PATH_MAX]; // /home/[user]/Games/WarfareIncorporated + +char gszMainDataDir[PATH_MAX]; // data files directory +char gszTempDir[PATH_MAX]; // temp file directory +char gszMissionPacksDir[PATH_MAX]; // downloaded mission packs +char gszMissionPackInfosDir[PATH_MAX]; +char gszSaveGamesDir[PATH_MAX]; // saved games +char gszPrefsFilename[PATH_MAX]; // game prefs +char gszCompletesDir[PATH_MAX]; // for "mission completed" tracking +HttpService *gphttp; +IChatController *gpchat; + +bool HostHelpers::Init() { + // Get the user's home directory + struct passwd *pw = getpwuid(getuid()); + const char *linuxHomeDir = pw->pw_dir; + + // Add a Games folder to it + sprintf(gszLinuxGamesDir, "%s/Games", linuxHomeDir); + + // By HomeDir we are refering to the game's home dir and not the user's home dir + sprintf(gszHomeDir, "%s/HostileTakeover", gszLinuxGamesDir); + + // MainDataDir is where htdata.pdb and htsfx.pdb are stored + // Linux players should run install.sh to copy the database files this location + sprintf(gszMainDataDir, "%s", gszHomeDir); + + sprintf(gszTempDir, "%s/tmp", gszHomeDir); + sprintf(gszMissionPacksDir, "%s/MissionPacks", gszHomeDir); + sprintf(gszMissionPackInfosDir, "%s/MissionPackInfos", gszHomeDir); + sprintf(gszSaveGamesDir, "%s/SaveGames", gszHomeDir); + sprintf(gszCompletesDir, "%s/Completes/", gszHomeDir); + sprintf(gszPrefsFilename, "%s/prefs.bin", gszHomeDir); + + // Make the directories + mkdir(gszLinuxGamesDir, 0755); + mkdir(gszHomeDir, 0755); + mkdir(gszMissionPacksDir, 0755); + mkdir(gszMissionPackInfosDir, 0755); + mkdir(gszSaveGamesDir, 0755); + mkdir(gszCompletesDir, 0755); + mkdir(gszTempDir, 0755); + + extern HttpService *gphttp; + gphttp = (HttpService *)new SdlHttpService(); + + gpchat = NULL; + + return true; +} + +void HostHelpers::Cleanup() { + delete gphttp; +} + +const char *HostHelpers::GetMainDataDir() { + return gszMainDataDir; +} + +const char *HostHelpers::GetTempDir() { + return gszTempDir; +} + +const char *HostHelpers::GetMissionPacksDir() { + return gszMissionPacksDir; +} + +const char *HostHelpers::GetMissionPackInfosDir() { + return gszMissionPackInfosDir; +} + +const char *HostHelpers::GetSaveGamesDir() { + return gszSaveGamesDir; +} + +const char *HostHelpers::GetCompletesDir() { + return gszCompletesDir; +} + +const char *HostHelpers::GetPrefsFilename() { + return gszPrefsFilename; +} + +void HostHelpers::OpenUrl(const char *pszUrl) { + Log("HostHelpers::OpenUrl not implemented yet"); +} + +void HostHelpers::Log(const char *pszFormat, va_list va) +{ +#if 0 + LOGX() << base::Log::vFormat(pszFormat, va); +#endif + + char sz[512]; + vsnprintf(sz, sizeof(sz), pszFormat, va); + + printf("%s\n", sz); +} + +void HostHelpers::Log(const char *pszFormat, ...) +{ + va_list va; + va_start(va, pszFormat); + Log(pszFormat, va); + va_end(va); +} + +void HostHelpers::MessageBox(const char *pszFormat, va_list va) +{ + Log(pszFormat, va); +} + +void HostHelpers::Break() +{ + Log("BREAK!!"); +} + +void HostHelpers::GetSurfaceProperties(SurfaceProperties *pprops) +{ + int cxScreen, cyScreen; + + cxScreen = 800; + cyScreen = 600; + + pprops->cxWidth = cxScreen; + pprops->cyHeight = cyScreen; + pprops->cbxPitch = 1; + pprops->cbyPitch = pprops->cxWidth; + pprops->ffFormat = wi::kfDirect8; +} + +bool HostHelpers::IsExiting() +{ +#if 0 + return [g_appDelegate isExiting]; +#else + Log("HostHelpers::IsExitig not implemented yet"); + return false; +#endif +} + +const char *HostHelpers::GetUdid() +{ +// Use the Mac Address for the DID (doesn't work on Mac) +#ifndef DARWIN + + #define MAC_STRING_LENGTH 13 + char *ret = (char *)malloc(MAC_STRING_LENGTH); + struct ifreq s; + int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); + + strcpy(s.ifr_name, "eth0"); + if (fd >= 0 && ret && 0 == ioctl(fd, SIOCGIFHWADDR, &s)) { + int i; + for (i = 0; i < 6; ++i) + snprintf(ret+i*2,MAC_STRING_LENGTH-i*2,"%02x",(unsigned char) s.ifr_addr.sa_data[i]); + } else { + LOG() << "malloc/socket/ioctl failed"; + } + + return (const char *)ret; + +#else + static char gszUdid[20]; + + char *pch = gszUdid; + if (*pch == 0) { + for (int i = 0; i < 19; i++) + *pch++ = '0' + GetAsyncRandom() % 10; + *pch = 0; + } + return gszUdid; +#endif +} + +void HostHelpers::InitiateAsk(const char *title, int max, const char *def, + int keyboard, bool secure) +{ + Log("HostHelpers::InitiateAsk not implemented yet"); +} + +void HostHelpers::GetAskString(char *psz, int cb) +{ + Log("HostHelpers::GetAskString not implemented yet"); +} + +IChatController *HostHelpers::GetChatController() +{ + if (gpchat == NULL) { + gpchat = new wi::LinuxChatController(); + } + return gpchat; +} + +void HostHelpers::InitiateWebView(const char *title, const char *url) { + Log("HostHelpers::InitiateWebView not implemented yet"); +} + +const char *HostHelpers::GetPlatformString() { + static struct utsname systemInfo; + uname(&systemInfo); + return systemInfo.sysname; +} + +} // namespace wi diff --git a/game/sdl/linux/install.sh b/game/sdl/linux/install.sh new file mode 100755 index 0000000..1f934ea --- /dev/null +++ b/game/sdl/linux/install.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +HT_ROOT=$SCRIPT_DIR/../../.. + +echo "mkdir ~/Games" +mkdir ~/Games + +echo "mkdir ~/Games/HostileTakeover" +mkdir ~/Games/HostileTakeover + +# If release build, htdata832.pdb needs to be marked +cp $HT_ROOT/game/htdata832.pdb ~/Games/HostileTakeover +cp $HT_ROOT/game/htsfx.pdb ~/Games/HostileTakeover + +if [ "$(uname -s)" == "Darwin" ]; then + cp -r $HT_ROOT/game/sdl/SDL2/osx/SDL2.framework ~/Games/HostileTakeover +else +echo "sudo password may be required to download and install the SDL2 library..." +sudo apt-get updates +sudo apt-get install libsdl2-dev +fi diff --git a/game/sdl/linux/linuxchatcontroller.cpp b/game/sdl/linux/linuxchatcontroller.cpp new file mode 100644 index 0000000..0ff74c7 --- /dev/null +++ b/game/sdl/linux/linuxchatcontroller.cpp @@ -0,0 +1,58 @@ +#include "linuxchatcontroller.h" +#include "game/sdl/hosthelpers.h" + +namespace wi { + +IChatControllerCallback *pcccb_; +wi::LinuxChatController *chatc_; + +LinuxChatController::LinuxChatController() { +} + +void LinuxChatController::Clear() { +} + +void LinuxChatController::AddChat(const char *player, const char *chat) { +} + +void LinuxChatController::Show(bool fShow) { +} + +void LinuxChatController::SetTitle(const char *title) { +} + +const char *LinuxChatController::GetTitle() { +} + +IChatControllerCallback *LinuxChatController::SetCallback( + IChatControllerCallback *pcccb) { + IChatControllerCallback *old = pcccb_; + pcccb_ = pcccb; + return old; +} + +void LinuxChatController::OnMessage(base::Message *pmsg) { + switch (pmsg->id) { + case kidmOnDismissed: + if (pcccb_ != NULL) { + pcccb_->OnChatDismissed(); + } + break; + + case kidmOnSend: + if (pcccb_ != NULL) { + ChatParams *params = (ChatParams *)pmsg->data; + pcccb_->OnChatSend(params->chat.c_str()); + delete params; + } + break; + + case kidmOnPlayers: + if (pcccb_ != NULL) { + pcccb_->OnPlayers(); + } + break; + } +} + +} // namespace wi diff --git a/game/sdl/linux/linuxchatcontroller.h b/game/sdl/linux/linuxchatcontroller.h new file mode 100644 index 0000000..1731918 --- /dev/null +++ b/game/sdl/linux/linuxchatcontroller.h @@ -0,0 +1,39 @@ +#ifndef __LINUXCHATCONTROLLER_H__ +#define __LINUXCHATCONTROLLER_H__ + +#include +#include "game/sdl/hosthelpers.h" +#include "base/thread.h" +#include "game/chatcontroller.h" + +#define kidmOnSend 1 +#define kidmOnDismissed 2 +#define kidmOnPlayers 3 + +namespace wi { + +struct ChatParams : base::MessageData { + ChatParams(const std::string& chat) : chat(chat) {} + std::string chat; +}; + +// Game thread c++ interface to the ChatViewController +class LinuxChatController : public IChatController, public base::MessageHandler { +public: + LinuxChatController(); + + void Clear(); + void AddChat(const char *player, const char *chat); + void Show(bool fShow); + void SetTitle(const char *title); + const char *GetTitle(); + IChatControllerCallback *SetCallback(IChatControllerCallback *pcccb); + +private: + // MessageHandler + virtual void OnMessage(base::Message *pmsg); +}; + +} // namespace wi + +#endif // __LINUXCHATCONTROLLER_H__ diff --git a/game/sdl/linux/makefile b/game/sdl/linux/makefile new file mode 100644 index 0000000..79a891c --- /dev/null +++ b/game/sdl/linux/makefile @@ -0,0 +1,117 @@ +BINARY = HostileTakeover +HTROOT := ../../.. +CC = gcc +CXX = g++ +LD = g++ + +CPPFLAGS += -w -Wno-write-strings -fsigned-char \ +-I../../../base -I../../../mpshared -I../../../inc \ +-I../SDL2/include -I../curl/include -I../../../ -I../../ -I../ \ +-D__LINUX__ -DSDL -DMULTIPLAYER -DTRACKSTATE + +ifeq ($(REL),1) +OUTDIR = release +CPPFLAGS += -O2 +else +CPPFLAGS += -g -O0 -DDEV_BUILD -DDEBUG_LOGGING -DDEBUG +OUTDIR = debug +endif + +ifeq ($(shell uname), Darwin) +LDFLAGS += -F/System/Library/Frameworks -framework cocoa -framework foundation \ +-F../SDL2/osx -framework SDL2 -fobjc-link-runtime -framework SDL2 \ +-rpath ~/Games/HostileTakeover -lcurl -lpthread +CPPFLAGS += -DDARWIN +else +LDFLAGS += -lSDL2 -lcurl -lpthread +endif + +# For each source directory: +# wildcard to get all the .cpp or .c files +# notdir to remove the path from the file paths +# basename to remove the suffix from the file name +# filter-out to remove any unwanted source files + +GAME_FILES := $(wildcard $(HTROOT)/game/*.cpp) +GAME_FILES := $(notdir $(GAME_FILES)) +GAME_FILES := $(basename $(GAME_FILES)) +GAME_FILES := $(filter-out SocTransport miscgraphics \ +hashtablecode filepdbreader DebugHelpers, $(GAME_FILES)) + +BASE_FILES := $(wildcard $(HTROOT)/base/*.cpp) +BASE_FILES := $(notdir $(BASE_FILES)) +BASE_FILES := $(basename $(BASE_FILES)) +BASE_FILES := $(filter-out epollserver stdindispatcher, $(BASE_FILES)) + +MPSHARED_FILES := $(wildcard $(HTROOT)/mpshared/*.cpp) +MPSHARED_FILES := $(notdir $(MPSHARED_FILES)) +MPSHARED_FILES := $(basename $(MPSHARED_FILES)) + +INC_FILES := rip + +YAJL_C_FILES := $(wildcard $(HTROOT)/yajl/src/*.c) +YAJL_C_FILES := $(notdir $(YAJL_C_FILES)) +YAJL_C_FILES := $(basename $(YAJL_C_FILES)) + +YAJL_CPP_FILES := $(wildcard $(HTROOT)/yajl/wrapper/*.cpp) +YAJL_CPP_FILES := $(notdir $(YAJL_CPP_FILES)) +YAJL_CPP_FILES := $(basename $(YAJL_CPP_FILES)) +YAJL_CPP_FILES := $(filter-out jsonbuilder_test, $(YAJL_CPP_FILES)) + +SDL_FILES = $(wildcard $(HTROOT)/game/sdl/*.cpp) +SDL_FILES := $(notdir $(SDL_FILES)) +SDL_FILES := $(basename $(SDL_FILES)) + +LINUX_FILES = $(wildcard $(HTROOT)/game/sdl/linux/*.cpp) +LINUX_FILES := $(notdir $(LINUX_FILES)) +LINUX_FILES := $(basename $(LINUX_FILES)) + +all: before_make $(OUTDIR)/$(BINARY) + +before_make: + test -d $(OUTDIR) || mkdir -p $(OUTDIR) + test -d $(OUTDIR)/game || mkdir -p $(OUTDIR)/game + test -d $(OUTDIR)/base || mkdir -p $(OUTDIR)/base + test -d $(OUTDIR)/mpshared || mkdir -p $(OUTDIR)/mpshared + test -d $(OUTDIR)/inc || mkdir -p $(OUTDIR)/inc + test -d $(OUTDIR)/yajl || mkdir -p $(OUTDIR)/yajl + test -d $(OUTDIR)/sdl || mkdir -p $(OUTDIR)/sdl + test -d $(OUTDIR)/linux || mkdir -p $(OUTDIR)/linux + +clean: + rm -rf $(OUTDIR)/* + +$(OUTDIR)/$(BINARY): \ +$(GAME_FILES:%=$(OUTDIR)/game/%.o) \ +$(BASE_FILES:%=$(OUTDIR)/base/%.o) \ +$(MPSHARED_FILES:%=$(OUTDIR)/mpshared/%.o) \ +$(INC_FILES:%=$(OUTDIR)/inc/%.o) \ +$(YAJL_CPP_FILES:%=$(OUTDIR)/yajl/%.o) \ +$(YAJL_C_FILES:%=$(OUTDIR)/yajl/%.o) \ +$(SDL_FILES:%=$(OUTDIR)/sdl/%.o) \ +$(LINUX_FILES:%=$(OUTDIR)/linux/%.o) + $(LD) -o $@ $^ $(LDFLAGS) + +$(GAME_FILES:%=$(OUTDIR)/game/%.o): $(GAME_FILES:%=../../%.cpp) + $(CXX) $(CPPFLAGS) -c $( -#include +#include namespace wi {