예제 #1
0
LoadPanel::LoadPanel(PlayerInfo &player, UI &gamePanels)
	: player(player), gamePanels(gamePanels), selectedPilot(player.Identifier())
{
	// If you have a player loaded, and the player is on a planet, makes sure
	// the player is saved so that any snapshot you create will be of the
	// player's current state, rather than one planet ago.
	if(player.GetPlanet() && !player.IsDead())
		player.Save();
	UpdateLists();
}
예제 #2
0
LoadPanel::LoadPanel(PlayerInfo &player, UI &gamePanels)
	: player(player), gamePanels(gamePanels), selectedPilot(player.Identifier())
{
	// If you have a player loaded, and the player is on a planet, makes sure
	// the player is saved so that any snapshot you create will be of the
	// player's current state, rather than one planet ago. Only do this if the
	// game is paused, i.e. the "main panel" is not on top:
	if(player.GetPlanet() && !player.IsDead() && !gamePanels.IsTop(&*gamePanels.Root()))
		player.Save();
	UpdateLists();
}
예제 #3
0
int main(int argc, char *argv[])
{
	Conversation conversation;
	bool debugMode = false;
	for(const char *const *it = argv + 1; *it; ++it)
	{
		string arg = *it;
		if(arg == "-h" || arg == "--help")
		{
			PrintHelp();
			return 0;
		}
		else if(arg == "-v" || arg == "--version")
		{
			PrintVersion();
			return 0;
		}
		else if(arg == "-t" || arg == "--talk")
			conversation = LoadConversation();
		else if(arg == "-d" || arg == "--debug")
			debugMode = true;
	}
	PlayerInfo player;
	
	try {
		SDL_Init(SDL_INIT_VIDEO);
		
		// Begin loading the game data.
		GameData::BeginLoad(argv);
		Audio::Init(GameData::Sources());
		
		// On Windows, make sure that the sleep timer has at least 1 ms resolution
		// to avoid irregular frame rates.
#ifdef _WIN32
		timeBeginPeriod(1);
#endif
		
		player.LoadRecent();
		player.ApplyChanges();
		
		// Check how big the window can be.
		SDL_DisplayMode mode;
		if(SDL_GetCurrentDisplayMode(0, &mode))
			return DoError("Unable to query monitor resolution!");
		
		Preferences::Load();
		Uint32 flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI;
		if(Preferences::Has("fullscreen"))
			flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
		
		// Make the window just slightly smaller than the monitor resolution.
		int maxWidth = mode.w;
		int maxHeight = mode.h;
		// Restore this after toggling fullscreen.
		int restoreWidth = 0;
		int restoreHeight = 0;
		if(maxWidth < 640 || maxHeight < 480)
			return DoError("Monitor resolution is too small!");
		
		if(Screen::RawWidth() && Screen::RawHeight())
		{
			// Never allow the saved screen width to be leaving less than 100
			// pixels free around the window. This avoids the problem where you
			// maximize without going full-screen, and next time the window pops
			// up you can't access the resize control because it is offscreen.
			Screen::SetRaw(
				min(Screen::RawWidth(), (maxWidth - 100)),
				min(Screen::RawHeight(), (maxHeight - 100)));
			if(flags & SDL_WINDOW_FULLSCREEN_DESKTOP)
			{
				restoreWidth = Screen::RawWidth();
				restoreHeight = Screen::RawHeight();
				Screen::SetRaw(maxWidth, maxHeight);
			}
		}
		else
			Screen::SetRaw(maxWidth - 100, maxHeight - 100);
		// Make sure the zoom factor is not set too high for the full UI to fit.
		if(Screen::Height() < 700)
			Screen::SetZoom(100);
		
		// Create the window.
		SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
#ifdef _WIN32
		SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
		SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
#endif
		SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
		
		SDL_Window *window = SDL_CreateWindow("Endless Sky",
			SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
			Screen::RawWidth(), Screen::RawHeight(), flags);
		if(!window)
			return DoError("Unable to create window!");
		
		SDL_GLContext context = SDL_GL_CreateContext(window);
		if(!context)
			return DoError("Unable to create OpenGL context! Check if your system supports OpenGL 3.0.", window);
		
		if(SDL_GL_MakeCurrent(window, context))
			return DoError("Unable to set the current OpenGL context!", window, context);
		
		SDL_GL_SetSwapInterval(1);
		
		// Initialize GLEW.
#ifndef __APPLE__
		glewExperimental = GL_TRUE;
		if(glewInit() != GLEW_OK)
			return DoError("Unable to initialize GLEW!", window, context);
#endif
		
		// Check that the OpenGL version is high enough.
		const char *glVersion = reinterpret_cast<const char *>(glGetString(GL_VERSION));
		if(!glVersion || !*glVersion)
			return DoError("Unable to query the OpenGL version!", window, context);
		
		const char *glslVersion = reinterpret_cast<const char *>(glGetString(GL_SHADING_LANGUAGE_VERSION));
		if(!glslVersion || !*glslVersion)
		{
			ostringstream out;
			out << "Unable to query the GLSL version. OpenGL version is " << glVersion << ".";
			return DoError(out.str(), window, context);
		}
		
		if(*glVersion < '3')
		{
			ostringstream out;
			out << "Endless Sky requires OpenGL version 3.0 or higher." << endl;
			out << "Your OpenGL version is " << glVersion << ", GLSL version " << glslVersion << "." << endl;
			out << "Please update your graphics drivers.";
			return DoError(out.str(), window, context);
		}
		
		glClearColor(0.f, 0.f, 0.0f, 1.f);
		glEnable(GL_BLEND);
		glDisable(GL_DEPTH_TEST);
		glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
		
		GameData::LoadShaders();
		
		{
			// Check whether this is a high-DPI window.
			int width = 0;
			int height = 0;
			SDL_GL_GetDrawableSize(window, &width, &height);
			Screen::SetHighDPI(width > Screen::RawWidth() && height > Screen::RawHeight());
			
			// Fix a possible race condition leading to the wrong window dimensions.
			glViewport(0, 0, width, height);
		}
		
		
		UI gamePanels;
		UI menuPanels;
		menuPanels.Push(new MenuPanel(player, gamePanels));
		if(!conversation.IsEmpty())
			menuPanels.Push(new ConversationPanel(player, conversation));
		
		string swizzleName = "_texture_swizzle";
#ifndef __APPLE__
		const char *extensions = reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS));
		if(!strstr(extensions, swizzleName.c_str()))
#else
		bool hasSwizzle = false;
		GLint extensionCount;
		glGetIntegerv(GL_NUM_EXTENSIONS, &extensionCount);
		for(GLint i = 0; i < extensionCount && !hasSwizzle; ++i)
		{
			const char *extension = reinterpret_cast<const char *>(glGetStringi(GL_EXTENSIONS, i));
			hasSwizzle = (extension && strstr(extension, swizzleName.c_str()));
		}
		if(!hasSwizzle)
#endif
			menuPanels.Push(new Dialog(
				"Note: your computer does not support the \"texture swizzling\" OpenGL feature, "
				"which Endless Sky uses to draw ships in different colors depending on which "
				"government they belong to. So, all human ships will be the same color, which "
				"may be confusing. Consider upgrading your graphics driver (or your OS)."));
		
		FrameTimer timer(60);
		bool isPaused = false;
		while(!menuPanels.IsDone())
		{
			// Handle any events that occurred in this frame.
			SDL_Event event;
			while(SDL_PollEvent(&event))
			{
				UI &activeUI = (menuPanels.IsEmpty() ? gamePanels : menuPanels);
				
				// The caps lock key slows the game down (to make it easier to
				// see and debug things that are happening quickly).
				if(debugMode && (event.type == SDL_KEYDOWN || event.type == SDL_KEYUP)
						&& event.key.keysym.sym == SDLK_CAPSLOCK)
				{
					timer.SetFrameRate((event.key.keysym.mod & KMOD_CAPS) ? 10 : 60);
				}
				else if(debugMode && event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_BACKQUOTE)
				{
					isPaused = !isPaused;
				}
				else if(event.type == SDL_KEYDOWN && menuPanels.IsEmpty()
						&& Command(event.key.keysym.sym).Has(Command::MENU)
						&& !gamePanels.IsEmpty() && gamePanels.Top()->IsInterruptible())
				{
					menuPanels.Push(shared_ptr<Panel>(
						new MenuPanel(player, gamePanels)));
				}
				else if(event.type == SDL_QUIT)
				{
					menuPanels.Quit();
				}
				else if(event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
				{
					int width = event.window.data1 & ~1;
					int height = event.window.data2 & ~1;
					if(width != Screen::RawWidth() || height != Screen::RawHeight())
					{
						Screen::SetRaw(width, height);
						if((event.window.data1 | event.window.data2) & 1)
							SDL_SetWindowSize(window, Screen::RawWidth(), Screen::RawHeight());
						SDL_GL_GetDrawableSize(window, &width, &height);
						glViewport(0, 0, width, height);
					}
				}
				else if(event.type == SDL_KEYDOWN
						&& (Command(event.key.keysym.sym).Has(Command::FULLSCREEN)
						|| (event.key.keysym.sym == SDLK_RETURN && event.key.keysym.mod & KMOD_ALT)))
				{
					if(restoreWidth)
					{
						SDL_SetWindowFullscreen(window, 0);
						Screen::SetRaw(restoreWidth, restoreHeight);
						SDL_SetWindowSize(window, Screen::RawWidth(), Screen::RawHeight());
						restoreWidth = 0;
						restoreHeight = 0;
					}
					else
					{
						restoreWidth = Screen::RawWidth();
						restoreHeight = Screen::RawHeight();
						Screen::SetRaw(maxWidth, maxHeight);
						SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
					}
					int width, height;
					SDL_GL_GetDrawableSize(window, &width, &height);
					glViewport(0, 0, width, height);
				}
				else if(activeUI.Handle(event))
				{
					// No need to do anything more!
				}
			}
			Font::ShowUnderlines(SDL_GetModState() & KMOD_ALT);
			
			// Tell all the panels to step forward, then draw them.
			((!isPaused && menuPanels.IsEmpty()) ? gamePanels : menuPanels).StepAll();
			Audio::Step();
			// That may have cleared out the menu, in which case we should draw
			// the game panels instead:
			(menuPanels.IsEmpty() ? gamePanels : menuPanels).DrawAll();
			
			SDL_GL_SwapWindow(window);
			timer.Wait();
		}
		
		// If you quit while landed on a planet, save the game.
		if(player.GetPlanet())
			player.Save();
		
		// The Preferences class reads the screen dimensions, so update them if
		// the window is full screen:
		bool isFullscreen = (restoreWidth != 0);
		Preferences::Set("fullscreen", isFullscreen);
		if(isFullscreen)
			Screen::SetRaw(restoreWidth, restoreHeight);
		Preferences::Save();
		
		Cleanup(window, context);
	}
	catch(const runtime_error &error)
	{
		DoError(error.what());
	}
	
	return 0;
}
예제 #4
0
void ReqLogin::OnSuccess()
{
  // Check for session ID or login failure
  TheVe1ReqManager::Instance()->SetLoggedIn(false);

  // Format of XML:
  // <session/>           <- Child(1)

  PXml p = m_xml.getChildNode(1);
  if (SafeStrCmp(p.getName(), "session"))
  {
#ifdef XML_DEBUG
std::cout << "found session element\n";
#endif

    std::string sessionId = p.getText();
    std::string playername;
    int objId = -1; // object ID for local player

    // Get player name and object ID for local player
    p = m_xml.getChildNode(2);
    if (SafeStrCmp(p.getName(), "playername"))
    {
      playername = p.getText();
std::cout << "**Got player name! \"" << playername << "\"\n";
    }
    else
    {
      // Got session ID but no player name, WTF ?
std::cout << "Got session ID but no player name, WTF??\n";
    }

    p = m_xml.getChildNode(3);
    if (SafeStrCmp(p.getName(), "objid"))
    {
      objId = ToInt(p.getText());
std::cout << "**Got local player object ID: " << objId << "\n";
    }
    else
    {
        // Got session ID but we don't know the object ID for the local player. WTF ?
std::cout << "Got session ID but we don't know the object ID for the local player. WTF?\n";
    }

    p = m_xml.getChildNode(4);
    if (SafeStrCmp(p.getName(), "loc"))
    {
      int loc = ToInt(p.getText());
      // TODO Use ResetLocalPlayer() to set start pos/loc ?????
      TheGSStartGame::Instance()->SetStartLoc(loc); 
std::cout << "Got start location: " << loc << "\n";
    }
    else
    {
      // Reset here to well known start location.
      ResetLocalPlayer();
std::cout << "No start location.\n";
    }

    std::cout << "Got session ID! " << sessionId << "\n"; 

    TheVe1ReqManager::Instance()->SetSessionId(sessionId);
    TheVe1ReqManager::Instance()->SetLoggedIn(true);

    // Check if we are set up
    std::string playerInfoFilename = playername + ".txt";
    // TODO Sanitise the filename

    ThePlayerInfoManager::Instance()->SetCurrentPlayer(playerInfoFilename);
    ThePlayerInfoManager::Instance()->Save();

    PlayerInfo* pi = ThePlayerInfoManager::Instance()->GetPI(); 

    pi->PISetInt(PI_KEY("player obj id"), objId);
    pi->PISetString(PI_KEY("playername"), playername);
    pi->PISetString(PI_KEY("email"), m_email);
    pi->Save();

    // Set options for this player
    TheGSOptions::Instance()->LoadSettingsFromPI(pi);

    // TODO Do we need to set this via ObjectUpdater too, so it gets sent to all clients ?

    // Set ID of this player object as the local player ID
    SetLocalPlayerId(objId);

    Assert(pi);

    // Play happy logged in sound
    TheSoundManager::Instance()->PlayWav("Sound/button112.wav");

    if (GetGameMode() == AMJU_MODE_EDIT)
    {
      TheGame::Instance()->SetCurrentState(TheGSStartGame::Instance());
    }
    else
    {
      // Handle research info: session, mode, etc.
      ChooseMode();
    }
  }
  else
  {
std::cout << "Didn't get sesssion ID from server :-(\n";
    TheGSLoginWaiting::Instance()->SetErrorString("Didn't get session ID from server");
  }
}