예제 #1
0
static int ReadBytes(int offset, int n) {
	static WorstTime tm("LstnSrvrMsgs");
	tm.Start();
#ifdef WIN32
	int count = recv(sock_fd, (char *)&buff[offset], n, 0);
#else
	int count = read(sock_fd, &buff[offset], n);
#endif
	tm.Stop();

	if (count == 0 || (count<0 && errno == EEXIST)) { // EEXIST can happen on windows if connection is broken
		gMode.Set(GameMode::ESC);
		count = 0;
	}
	if (count < 0) {
		if (errno != EAGAIN) {
			auto &ss = View::gErrorManager.GetStream(true, false);
#ifdef WIN32
			ss << "ListenForServerMessages1: Error " << errno << " length " << count;
#else
			ss << "ListenForServerMessages1: Error " << errno << "(" << strerror(errno) << "), length" << count;
#endif
		}
		count = 0; // This is not a fatal error, need to try again
	}
	return count;
}
예제 #2
0
void SendMsg(unsigned char const *b, int n) {
	static WorstTime tm("SendMsg");
	tm.Start();
#ifdef WIN32
	int res = send(sock_fd, (char*)b, n, 0);
#else
	int res = write(sock_fd, b, n);
#endif
	tm.Stop();
	if (res == -1) {
		perror("write socket");
	}
}
예제 #3
0
int main(int argc, char** argv) {
	if (!glfwInit()) {
		ErrorDialog("Failed to initialize GLFW\n");
		exit(EXIT_FAILURE);
	}

	gCurrentFrameTime = 0.0;

	string optionsFilename = "ephenation.ini";
	string dataDir; // The directory where the client can save data
#ifdef unix
	const char *home = getenv("HOME");
	// Save Linux Path
	dataDir = string(home) + "/.ephenation";
	const char *ephenationPath = dataDir.c_str();
	struct stat st;
	if (stat(ephenationPath,&st) != 0) {
		mkdir(ephenationPath, 0777);
	}
	if (home)
		optionsFilename = dataDir + "/" + optionsFilename;
	else
		optionsFilename = ".ephenation/ephenation.ini"; // Fallback
#endif
#ifdef WIN32
	TCHAR home[MAX_PATH];
	HRESULT res = SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, 0, 0, home);
	if (res == S_OK) {
		dataDir = string(home) + "\\ephenation";
		const char *ephenationPath = dataDir.c_str();
		struct _stat st;
		if (_stat(ephenationPath,&st) != 0) {
			res = _mkdir(ephenationPath);
		}
		optionsFilename = dataDir + "\\" + optionsFilename; // Fallback
	}
#endif

	const char *host = "server1.ephenation.net";
	int port = 57862;
	/* getopt_long stores the option index here. */
	int option_index = 0;

	while(1) {
		int c = getopt_long (argc, argv, "", long_options, &option_index);

		/* Detect the end of the options. */
		if (c == -1)
			break;
	}
	if (optind < argc)
		host = argv[optind];
#ifdef WIN32
	if (!gDebugOpenGL && !gVerbose)
		FreeConsole();
	const char *cacheName = "\\cache";
#else
	const char *cacheName = "/cache";
#endif

	char *cachePath = new char[strlen(dataDir.c_str()) + strlen(cacheName) + strlen(host) + 2];
	strcpy(cachePath, dataDir.c_str());
#ifdef WIN32
	strcat(cachePath, "\\cache");
	strcat(cachePath, host);
	strcat(cachePath, "\\");
#else
	strcat(cachePath, "/cache");
	strcat(cachePath, host);
	strcat(cachePath, "/");
#endif

	ChunkCache::fgChunkCache.SetCacheDir(cachePath);

	//printf("Game Path: %s\n", dataDir);

	gOptions.Init(optionsFilename); // This one should come early, as it is used to initalize things.

	// If there was a saved position, use it for imnitialization.
	if (gOptions.fPlayerX != 0 || gOptions.fPlayerY != 0 || gOptions.fPlayerZ != 0)
		Model::gPlayer.SetPosition(gOptions.fPlayerX, gOptions.fPlayerY, gOptions.fPlayerZ);
	unsigned maxThreads = gOptions.fNumThreads;
	if (sSingleThread) {
		maxThreads = 1; // Override this number
		std::cout << "Limit to minimum number of threads" << std::endl;
	}
	glswInit();
	glswSetPath("shaders/", ".glsl");
	ConnectToServer(host, port);
	gSoundControl.Init();
	TSExec::gTSExec.Init(); // This must be called after initiating gSoundControl.

	if (gDebugOpenGL)
		printf("Number of threads: %d\n", maxThreads);
	int numChunkProc = maxThreads - 1;
	if (numChunkProc <= 0)
		numChunkProc = 1;
	gChunkProcess.Init(numChunkProc);

	//glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3);
	//glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 3);
	glfwOpenWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, gDebugOpenGL);
	// glfwOpenWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
	//glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // Need to specify at least version 3.3 for this to work.

	if (!glfwOpenWindow(gOptions.fWindowWidth, gOptions.fWindowHeight, 0, 0, 0, 0, 16, 1, gOptions.fFullScreen ? GLFW_FULLSCREEN : GLFW_WINDOW)) {
		glfwTerminate();

		ErrorDialog("Failed to open GLFW window");
	}
	glfwSetWindowTitle("Ephenation");
	checkError("glfwSetWindowTitle");
	GLFWvidmode desktopMode;
	glfwGetDesktopMode(&desktopMode);
	if (gDebugOpenGL)
		printf("Desktop mode %d blue bits, %d green bits, %d red bits, %dx%d\n", desktopMode.BlueBits, desktopMode.GreenBits, desktopMode.RedBits, desktopMode.Width, desktopMode.Height);
	gDesktopAspectRatio = float(desktopMode.Width)/float(desktopMode.Height);

	// Initialize glew
	GLenum err=glewInit();
	checkError("glewInit");
	if(err!=GLEW_OK) {
		//problem: glewInit failed, something is seriously wrong
		printf("Fail to init glew: Error: %s\n", glewGetErrorString(err));
		checkError("glewInit");
		return -1;
	}

	// Only continue, if OpenGL of the expected version is supported.
	int major, minor, revision;
	glfwGetGLVersion(&major, &minor, &revision);
	if ((major == 3 && minor < 3) || major < 3) {
		ErrorDialog("OpenGL context version parsed by GLFW: %u.%u.%u. Version 3.3 required\n", major, minor, revision);
	}

	if (gDebugOpenGL) {
		dumpInfo(major, minor, revision); // Enable this to show some version information about the OpenGL and the graphics card.
		// dumpGraphicsMemoryStats();
		// const GLubyte* sExtensions = glGetString(GL_EXTENSIONS);
		// printf("GL extensions: %s\n", sExtensions);
		// glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
		if (glDebugMessageCallbackARB != 0)
			glDebugMessageCallbackARB(DebugFunc, (void*)15);
		else if (glDebugMessageCallbackAMD != 0)
			glDebugMessageCallbackAMD(DebugFuncAMD, (void*)15);
	}

	glfwSwapInterval(gOptions.fVSYNC); // 0 means do not wait for VSYNC, which would delay the FPS sometimes.

	ComputeRelativeChunksSortedDistances();

	BlenderModel::InitModels();

	Model::gPlayer.loginOk = true;
	gUniformBuffer.Init();
	gDrawFont.Init("textures/georgia12"); // Must be done before gGameDialog.
	GameTexture::Init();
	Controller::gGameDialog.init();
	ChunkShader *shader = ChunkShader::Make();
	gChunkShaderPicking.Init();
	Tree::InitStatic();
	gLantern.Init(shader);
	gQuadStage1.Init();
	gBillboard.Init();

	gSoundControl.RequestMusicMode(SoundControl::SMusicModeMenu);
	glEnable(GL_DEPTH_TEST); // Always enabled by default

	// Immediately clear screen, to minimize chance that something undefined is shown.
	glClearColor(0.0f, 0.0f, 0.0f, 1.0f );
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
	glfwSwapBuffers();

	if (sTestUser)
		Model::gPlayer.fTestPlayer = true;

	// Last thing before starting the game, update the save copy of the options.
	Options::sfSave = gOptions;
	while(glfwGetWindowParam(GLFW_OPENED)) {
		while (ListenForServerMessages())
			continue;
		if (sTestUser && gMode.Get() == GameMode::LOGIN) {
			PerformLoginProcedure("", "", "", true);
			sTestUser = false; // Try this only once
		}
		static WorstTime tm(" Mainloop");
		tm.Start();
		gCurrentFrameTime = glfwGetTime();
		if (gShowPing && gCurrentFrameTime - gLastPing > 5.0) {
			// It was a request, so we need to send a response
			unsigned char msg[4];
			msg[0] = sizeof msg;
			msg[1] = 0;
			msg[2] = CMD_PING;
			msg[3] = 0; // 0 means request, 1 means response
			SendMsg(msg, sizeof msg);
			gLastPing = gCurrentFrameTime;
			gCurrentPing = 0.0;
			// Use a busy wait for the response, no time must be lost
			while (gCurrentPing == 0.0 && glfwGetTime() - gLastPing < 0.5)
				ListenForServerMessages();
		}

		Controller::gGameDialog.Update();
		Controller::gGameDialog.render(sHideGUI);

		glfwSwapBuffers();

		if (gMode.Get() == GameMode::ESC)
			glfwCloseWindow();
		tm.Stop();
	}

	// The window is closed, request quit (which will save the player on the server side)
	unsigned char b[] = { 0x03, 0x00, CMD_QUIT };
	SendMsg(b, sizeof b);

	// The logout acknowledge from the server may take sime time. Take the opportunity to
	// halt the process pool.ss
	gChunkProcess.RequestTerminate();
	glswShutdown();

	double timer = glfwGetTime();
	// Wait for ack from server, but not indefinitely
	while (gMode.Get() == GameMode::GAME && glfwGetTime() - timer < 2.0) {
		glfwSleep(0.1); // Avoid a busy wait
		ListenForServerMessages(); // Wait for acknowledge
	}

	if (gMode.Get() == GameMode::GAME) {
		printf("Failed to disconnect from server\n");
	}

	// The options will be saved by the destructor.
	Options::sfSave.fViewingDistance = maxRenderDistance;
	Options::sfSave.fPlayerX = Model::gPlayer.x;
	Options::sfSave.fPlayerY = Model::gPlayer.y;
	Options::sfSave.fPlayerZ = Model::gPlayer.z;
	gMode.Set(GameMode::EXIT);
	Options::sfSave.Save();
	return 0;
}