File main.c
File List > engine > src > main.c
Go to the documentation of this file
#include "main.h"
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <stdio.h>
#include "DynArray.h"
#include "GameFramework.h"
#include "XMLUIGameLayer.h"
#include "ImageFileRegstry.h"
#include "Atlas.h"
#include "Widget.h"
#include "Scripting.h"
#include <string.h>
#include "PlatformDefs.h"
#include <libxml/parser.h>
#include "Log.h"
#include "Network.h"
#include "AssertLib.h"
#include "Audio.h"
#include "cwalk.h"
#define SCR_WIDTH 640
#define SCR_HEIGHT 480
#define TARGET_FPS 60
InputContext gInputContext;
DrawContext gDrawContext;
struct CommandLineArgs gCmdArgs;
DrawContext* GetDrawContext()
{
return &gDrawContext;
}
InputContext* GetInputContext()
{
return &gInputContext;
}
int Mn_GetScreenWidth()
{
return gDrawContext.screenWidth;
}
int Mn_GetScreenHeight()
{
return gDrawContext.screenHeight;
}
void FramebufferSizeCallback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
Dr_OnScreenDimsChange(&gDrawContext, width, height);
In_FramebufferResize(&gInputContext, width, height);
GF_OnWindowDimsChanged(width, height);
}
void MouseCallback(GLFWwindow* window, double xposIn, double yposIn)
{
In_RecieveMouseMove(&gInputContext, xposIn, yposIn);
}
void ScrollCallback(GLFWwindow* window, double xoffset, double yoffset)
{
In_RecieveScroll(&gInputContext, xoffset, yoffset);
}
void MouseBtnCallback(GLFWwindow* window, int button, int action, int mods)
{
In_RecieveMouseButton(&gInputContext, button, action, mods);
}
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
In_RecieveKeyboardKey(&gInputContext, key, scancode, action, mods);
}
void joystick_callback(int jid, int event)
{
if (event == GLFW_CONNECTED)
{
In_SetControllerPresent(jid);
}
else if (event == GLFW_DISCONNECTED)
{
In_SetControllerPresent(-1);
}
}
static void GLAPIENTRY MessageCallback(GLenum source,
GLenum type,
GLuint id,
GLenum severity,
GLsizei length,
const GLchar* message,
const void* userParam)
{
//if (severity >= minimumLogSeverityIncluding)
{
Log_Warning("GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n\n",
(type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""),
type, severity, message);
}
}
typedef void(*GameInitFn)(InputContext*,DrawContext*);
void Engine_ParseCmdArgs(int argc, char** argv, ArgHandlerFn handlerFn)
{
gCmdArgs.role = GR_Singleplayer;
gCmdArgs.serverAddress = "127.0.0.1:40000";
gCmdArgs.clientAddress = "0.0.0.0";
gCmdArgs.matchmakingServerAddress = NULL;
gCmdArgs.playerName = "Jim";
gCmdArgs.bLogTextColoured = true;
gCmdArgs.bIncludeLogTimeStamps = true;
gCmdArgs.bLogTIDs = true;
gCmdArgs.logfilePath = NULL;
gCmdArgs.networkSimulatorConfigPath = NULL;
gCmdArgs.bLogToConsole = true;
gCmdArgs.assetsDir = "./WfAssets";
gCmdArgs.configDir = "./WfAssets";
if(argc > 1)
{
for(int i=1; i <argc; i++)
{
Log_Info("Cmd arg %i: %s", i, argv[i]);
if(strcmp(argv[i], "--name") == 0 || strcmp(argv[i], "-n") == 0)
{
EASSERT(i + 1 < argc);
i++;
Log_Info("Cmd arg %i: %s", i, argv[i]);
gCmdArgs.playerName = argv[i];
}
if(strcmp(argv[i], "--role") == 0 || strcmp(argv[i], "-r") == 0)
{
EASSERT(i + 1 < argc);
i++;
Log_Info("Cmd arg %i: %s", i, argv[i]);
if(strcmp(argv[i], "server") == 0 || strcmp(argv[i], "s") == 0)
{
gCmdArgs.role = GR_ClientServer;
}
else if(strcmp(argv[i], "client") == 0 || strcmp(argv[i], "c") == 0)
{
gCmdArgs.role = GR_Client;
}
}
else if(strcmp(argv[i], "--server_address") == 0 || strcmp(argv[i], "-s") == 0)
{
EASSERT(i + 1 < argc);
i++;
Log_Info("Cmd arg %i: %s", i, argv[i]);
gCmdArgs.serverAddress = argv[i];
}
else if(strcmp(argv[i], "--client_address") == 0 || strcmp(argv[i], "-c") == 0)
{
EASSERT(i + 1 < argc);
i++;
Log_Info("Cmd arg %i: %s", i, argv[i]);
gCmdArgs.clientAddress = argv[i];
}
else if(strcmp(argv[i], "--matchmaking_address") == 0 || strcmp(argv[i], "-m") == 0)
{
EASSERT(i + 1 < argc);
i++;
Log_Info("Cmd arg %i: %s", i, argv[i]);
gCmdArgs.matchmakingServerAddress = argv[i];
}
else if(strcmp(argv[i], "--log_level") == 0 || strcmp(argv[i], "-l") == 0)
{
EASSERT(i + 1 < argc);
i++;
Log_Info("Cmd arg %i: %s", i, argv[i]);
if(strcmp(argv[i], "verbose") == 0 || strcmp(argv[i], "v") == 0)
{
Log_SetLevel(LogLvl_Verbose);
}
else if(strcmp(argv[i], "info") == 0 || strcmp(argv[i], "i") == 0)
{
Log_SetLevel(LogLvl_Info);
}
else if(strcmp(argv[i], "warning") == 0 || strcmp(argv[i], "w") == 0)
{
Log_SetLevel(LogLvl_Warning);
}
else if(strcmp(argv[i], "error") == 0 || strcmp(argv[i], "e") == 0)
{
Log_SetLevel(LogLvl_Error);
}
}
else if(strcmp(argv[i], "--disable_log_colour") == 0)
{
gCmdArgs.bLogTextColoured = false;
}
else if(strcmp(argv[i], "--disable_log_timestamp") == 0)
{
gCmdArgs.bIncludeLogTimeStamps = false;
}
else if(strcmp(argv[i], "--logfile") == 0 || strcmp(argv[i], "--lf") == 0)
{
EASSERT(i + 1 < argc);
i++;
Log_Info("Cmd arg %i: %s", i, argv[i]);
gCmdArgs.logfilePath = argv[i];
}
else if(strcmp(argv[i], "--disable_log_tid") == 0)
{
gCmdArgs.bLogTIDs = false;
}
else if(strcmp(argv[i], "--disable_console_log") == 0)
{
gCmdArgs.bLogToConsole = false;
}
else if(strcmp(argv[i], "--network_sim_config") == 0)
{
EASSERT(i + 1 < argc);
i++;
Log_Info("Cmd arg %i: %s", i, argv[i]);
gCmdArgs.networkSimulatorConfigPath = argv[i];
}
else if(strcmp(argv[i], "--assetsDir") == 0)
{
EASSERT(i + 1 < argc);
i++;
Log_Info("Cmd arg %i: %s", i, argv[i]);
gCmdArgs.assetsDir = argv[i];
}
else if(strcmp(argv[i], "--configDir") == 0)
{
EASSERT(i + 1 < argc);
i++;
Log_Info("Cmd arg %i: %s", i, argv[i]);
gCmdArgs.configDir = argv[i];
}
else if(handlerFn)
{
handlerFn(argc, argv, &i);
}
}
}
}
static void DoNetworkQueues()
{
/* placeholder */
struct NetworkConnectionEvent event;
while(NW_DequeueConnectionEvent(&event))
{
Log_Info("NETWORK EVENT: %s CLIENT: %i", event.type == NCE_ClientConnected ? "NCE_ClientConnected" : "NCE_ClientDisconnected", event.client);
}
}
int EngineStart(int argc, char** argv, GameInitFn init, ArgHandlerFn argHandler)
{
Engine_ParseCmdArgs(argc, argv, argHandler);
Log_Init();
NW_Init();
int audioSystemInitCode = Au_Init();
Log_Info("Initialized audio, return code: %i", audioSystemInitCode);
Log_Verbose("testing libxml version...");
LIBXML_TEST_VERSION
Log_Verbose("hello world");
// glfw: initialize and configure
// ------------------------------
glfwInit();
Log_Verbose("glfwInit");
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
// glfw window creation
// --------------------
const char* windowTitle = "Stardew Engine";
switch(NW_GetRole())
{
case GR_Client:
windowTitle = "Stardew Engine (Client)";
break;
case GR_ClientServer:
windowTitle = "Stardew Engine (Server)";
break;
}
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, windowTitle, NULL, NULL);
if (window == NULL)
{
/*std::cout << "Failed to create GLFW window" << std::endl;*/
Log_Error("Failed to create GLFW window");
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSwapInterval(0); // Enable vsync
glfwJoystickPresent(GLFW_JOYSTICK_1);
glfwSetFramebufferSizeCallback(window, FramebufferSizeCallback);
glfwSetCursorPosCallback(window, MouseCallback);
glfwSetScrollCallback(window, ScrollCallback);
glfwSetMouseButtonCallback(window, MouseBtnCallback);
glfwSetKeyCallback(window, key_callback);
// tell GLFW to capture our mouse
//glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
// glad: load all OpenGL function pointers
// ---------------------------------------
#if GAME_GL_API_TYPE == GAME_GL_API_TYPE_CORE
Log_Verbose("loading Opengl procs\n");
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
Log_Verbose("Failed to initialize GLAD");
return -1;
}
#elif GAME_GL_API_TYPE == GAME_GL_API_TYPE_ES
Log_Verbose("loading Opengl ES procs");
if (!gladLoadGLES2Loader((GLADloadproc)glfwGetProcAddress))
{
Log_Verbose("Failed to initialize GLAD");
return -1;
}
#endif
// configure global opengl state
// -----------------------------
Log_Verbose("configuring global opengl state");
//glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// During init, enable debug output
glEnable(GL_DEBUG_OUTPUT);
#if GAME_GL_API_TYPE == GAME_GL_API_TYPE_CORE
glDebugMessageCallback(MessageCallback, 0);
#endif
Log_Verbose("done");
double accumulator = 0;
double lastUpdate = 0;
double slice = 1.0 / TARGET_FPS;
Log_Verbose("initialising draw context");
gDrawContext = Dr_InitDrawContext();
Log_Verbose("done");
Log_Verbose("initial screen dims change");
Dr_OnScreenDimsChange(&gDrawContext, SCR_WIDTH, SCR_HEIGHT);
Log_Verbose("done");
Log_Verbose("initialising input context");
gInputContext = In_InitInputContext();
Log_Verbose("done");
Log_Verbose("Initialising game framework");
GF_InitGameFramework();
Log_Verbose("done");
Log_Verbose("initialising image registry");
char pathBuf[256];
cwk_path_join(gCmdArgs.assetsDir, "ImageFiles.json", pathBuf, 256);
IR_InitImageRegistry(pathBuf);
Log_Verbose("done");
Log_Verbose("initialising atlas");
At_Init();
Log_Verbose("done");
Log_Verbose("initialising UI");
UI_Init();
Log_Verbose("done");
Log_Verbose("initialising scripting");
Sc_InitScripting();
Log_Verbose("done");
init(&gInputContext, &gDrawContext);
double frameTimeTotal = 0.0;
int onCount = 0;
int numCounts = 60;
while (!glfwWindowShouldClose(window))
{
double time = glfwGetTime();
double delta = time - lastUpdate;
lastUpdate = time;
accumulator += delta;
while (accumulator > slice)
{
glfwPollEvents();
//DoNetworkQueues();
GF_InputGameFramework(&gInputContext);
GF_UpdateGameFramework((float)slice);
In_EndFrame(&gInputContext);
GF_EndFrame(&gDrawContext, &gInputContext);
accumulator -= slice;
}
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
GF_DrawGameFramework(&gDrawContext);
glfwSwapBuffers(window);
frameTimeTotal += delta;
onCount++;
if(onCount == numCounts)
{
onCount = 0;
//printf("frame time: %f\n", 1.0 / (frameTimeTotal / (double)numCounts));
frameTimeTotal = 0.0f;
}
}
Sc_DeInitScripting();
IR_DestroyImageRegistry();
GF_DestroyGameFramework();
glfwTerminate();
Log_DeInit();
if(audioSystemInitCode == 0)
{
Au_DeInit();
}
}
void GameInit(InputContext* pIC, DrawContext* pDC)
{
struct GameFrameworkLayer testLayer;
memset(&testLayer, 0, sizeof(struct GameFrameworkLayer));
struct XMLUIGameLayerOptions options;
options.bLoadImmediately = true;
char buf[256];
cwk_path_join(buf, "test.xml", buf, 256);
options.xmlPath = buf;
options.pDc = pDC;
Log_Verbose("making xml ui layer");
XMLUIGameLayer_Get(&testLayer, &options);
Log_Verbose("done");
Log_Verbose("pushing framework layer");
GF_PushGameFrameworkLayer(&testLayer);
Log_Verbose("done");
}