From 2be9c925088c16beb144dd9932202416d00ff581 Mon Sep 17 00:00:00 2001 From: Simon Robertshaw Date: Wed, 20 Jun 2012 13:40:18 +0100 Subject: [PATCH] OpenGL canvas for Windows, Notifications for main Game, Update checker in Client (+ other client triggered events) --- src/PowderToySDL.cpp | 8 ++ src/client/Client.cpp | 86 +++++++++++- src/client/Client.h | 12 ++ src/client/ClientListener.h | 22 +++ src/game/EllipseBrush.h | 2 +- src/game/GameController.cpp | 25 ++++ src/game/GameController.h | 8 +- src/game/GameModel.cpp | 33 +++++ src/game/GameModel.h | 7 + src/game/GameView.cpp | 52 ++++++++ src/game/GameView.h | 2 + src/game/Notification.h | 23 ++++ src/interface/Engine.cpp | 5 +- src/interface/Engine.h | 2 + src/powdertoyjava/OpenGLCanvasWin32.cpp | 169 ++++++++++++++++++++++++ src/powdertoyjava/OpenGLCanvasWin32.h | 35 +++++ src/powdertoyjava/PowderToyJava.cpp | 7 +- src/powdertoyjava/PowderToyJava.h | 5 +- 18 files changed, 490 insertions(+), 13 deletions(-) create mode 100644 src/client/ClientListener.h create mode 100644 src/game/Notification.h create mode 100644 src/powdertoyjava/OpenGLCanvasWin32.cpp create mode 100644 src/powdertoyjava/OpenGLCanvasWin32.h diff --git a/src/PowderToySDL.cpp b/src/PowderToySDL.cpp index 0229103f9..d268f578c 100644 --- a/src/PowderToySDL.cpp +++ b/src/PowderToySDL.cpp @@ -129,6 +129,7 @@ return surface; int main(int argc, char * argv[]) { int elapsedTime = 0, currentTime = 0, lastTime = 0, currentFrame = 0; + unsigned int lastTick = 0; float fps = 0, delta = 1.0f; sdl_scrn = SDLOpen(); @@ -192,6 +193,13 @@ int main(int argc, char * argv[]) engine->Tick(); engine->Draw(); + if(SDL_GetTicks()-lastTick>1000) + { + //Run client tick every second + lastTick = SDL_GetTicks(); + Client::Ref().Tick(); + } + #ifdef OGLR blit(); #else diff --git a/src/client/Client.cpp b/src/client/Client.cpp index f31ad0864..285a9ad64 100644 --- a/src/client/Client.cpp +++ b/src/client/Client.cpp @@ -24,8 +24,11 @@ #include "client/SaveInfo.h" +#include "ClientListener.h" + Client::Client(): - authUser(0, "") + authUser(0, ""), + updateAvailable(false) { int i = 0; std::string proxyString(""); @@ -108,6 +111,87 @@ Client::Client(): stampIDs.push_back(data); } stampsLib.close(); + + //Begin version check + versionCheckRequest = http_async_req_start(NULL, SERVER "/Version.json", NULL, 0, 1); +} + +void Client::Tick() +{ + //Check status on version check request + if(versionCheckRequest && http_async_req_status(versionCheckRequest)) + { + int status; + int dataLength; + char * data = http_async_req_stop(versionCheckRequest, &status, &dataLength); + versionCheckRequest = NULL; + + notifyUpdateAvailable(); + if(status != 200) + { + if(data) + free(data); + } + else + { + std::istringstream dataStream(data); + + try + { + json::Object objDocument; + json::Reader::Read(objDocument, dataStream); + + json::Object stableVersion = objDocument["Stable"]; + json::Object betaVersion = objDocument["Beta"]; + + json::Number stableMajor = stableVersion["Major"]; + json::Number stableMinor = stableVersion["Minor"]; + json::Number stableBuild = stableVersion["Build"]; + + json::Number betaMajor = betaVersion["Major"]; + json::Number betaMinor = betaVersion["Minor"]; + json::Number betaBuild = betaVersion["Build"]; + +#ifdef BETA + if( (betaMajor.Value()>SAVE_VERSION || (betaMinor.Value()>MINOR_VERSION && betaMajor.Value()==SAVE_VERSION) || betaBuild.Value()>BUILD_NUM) || + (stableMajor.Value()>SAVE_VERSION || (stableMinor.Value()>MINOR_VERSION && stableMajor.Value()==SAVE_VERSION) || stableBuild.Value()>BUILD_NUM)) + { + updateAvailable = true; + } +#else + if(stableMajor.Value()>SAVE_VERSION || (stableMinor.Value()>MINOR_VERSION && stableMajor.Value()==SAVE_VERSION) || stableBuild.Value()>BUILD_NUM) + { + updateAvailable = true; + } +#endif + + if(updateAvailable) + { + notifyUpdateAvailable(); + } + } + catch (json::Exception &e) + { + //Do nothing + } + + if(data) + free(data); + } + } +} + +void Client::notifyUpdateAvailable() +{ + for (std::vector::iterator iterator = listeners.begin(), end = listeners.end(); iterator != end; ++iterator) + { + (*iterator)->NotifyUpdateAvailable(this); + } +} + +void Client::AddListener(ClientListener * listener) +{ + listeners.push_back(listener); } Client::~Client() diff --git a/src/client/Client.h b/src/client/Client.h index 6c1baa584..6cdedd4aa 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -27,8 +27,13 @@ enum RequestStatus { RequestOkay, RequestFailure }; +class ClientListener; class Client: public Singleton { private: + void * versionCheckRequest; + bool updateAvailable; + + std::string lastError; list stampIDs; @@ -46,13 +51,19 @@ private: int activeThumbRequestCompleteTimes[IMGCONNS]; std::string activeThumbRequestIDs[IMGCONNS]; void updateStamps(); + + void notifyUpdateAvailable(); public: + vector listeners; + //Config file handle json::Object configDocument; Client(); ~Client(); + void AddListener(ClientListener * listener); + RequestStatus ExecVote(int saveID, int direction); RequestStatus UploadSave(SaveInfo * save); @@ -82,6 +93,7 @@ public: std::string GetLastError() { return lastError; } + void Tick(); }; #endif // CLIENT_H diff --git a/src/client/ClientListener.h b/src/client/ClientListener.h new file mode 100644 index 000000000..308721c2e --- /dev/null +++ b/src/client/ClientListener.h @@ -0,0 +1,22 @@ +/* + * ClientListener.h + * + * Created on: Jun 19, 2012 + * Author: Simon + */ + +#ifndef CLIENTLISTENER_H_ +#define CLIENTLISTENER_H_ + +class Client; +class ClientListener +{ +public: + ClientListener() {} + virtual ~ClientListener() {} + + virtual void NotifyUpdateAvailable(Client * sender) {} +}; + + +#endif /* CLIENTLISTENER_H_ */ diff --git a/src/game/EllipseBrush.h b/src/game/EllipseBrush.h index 8a1dc9aaa..a02516e16 100644 --- a/src/game/EllipseBrush.h +++ b/src/game/EllipseBrush.h @@ -17,7 +17,7 @@ public: EllipseBrush(ui::Point size_): Brush(size_) { - + SetRadius(size_); }; virtual void GenerateBitmap() { diff --git a/src/game/GameController.cpp b/src/game/GameController.cpp index 3031fb622..dfbd9354a 100644 --- a/src/game/GameController.cpp +++ b/src/game/GameController.cpp @@ -12,6 +12,7 @@ #include "dialogues/ErrorMessage.h" #include "GameModelException.h" #include "simulation/Air.h" +#include "Notification.h" using namespace std; @@ -132,6 +133,7 @@ GameController::GameController(): //commandInterface->AttachGameModel(gameModel); //sim = new Simulation(); + Client::Ref().AddListener(this); } GameController::~GameController() @@ -624,3 +626,26 @@ std::string GameController::ElementResolve(int type) return ""; } +void GameController::NotifyUpdateAvailable(Client * sender) +{ + class UpdateNotification : public Notification + { + GameController * c; + public: + UpdateNotification(GameController * c, std::string message) : c(c), Notification(message) {} + virtual ~UpdateNotification() {} + + virtual void Action() + { + c->RemoveNotification(this); + } + }; + + gameModel->AddNotification(new UpdateNotification(this, "An Update is available")); +} + +void GameController::RemoveNotification(Notification * notification) +{ + gameModel->RemoveNotification(notification); +} + diff --git a/src/game/GameController.h b/src/game/GameController.h index ecbe9b312..269cdf541 100644 --- a/src/game/GameController.h +++ b/src/game/GameController.h @@ -16,15 +16,17 @@ //#include "cat/TPTScriptInterface.h" #include "cat/LuaScriptInterface.h" #include "options/OptionsController.h" +#include "client/ClientListener.h" #include "Menu.h" using namespace std; +class Notification; class GameModel; class GameView; class CommandInterface; class ConsoleController; -class GameController +class GameController: public ClientListener { private: //Simulation * sim; @@ -101,6 +103,10 @@ public: void LoadClipboard(); void LoadStamp(); + + void RemoveNotification(Notification * notification); + + virtual void NotifyUpdateAvailable(Client * sender); }; #endif // GAMECONTROLLER_H diff --git a/src/game/GameModel.cpp b/src/game/GameModel.cpp index 5c9344d8d..054a4157d 100644 --- a/src/game/GameModel.cpp +++ b/src/game/GameModel.cpp @@ -513,6 +513,39 @@ deque GameModel::GetLog() return consoleLog; } +std::vector GameModel::GetNotifications() +{ + return notifications; +} + +void GameModel::AddNotification(Notification * notification) +{ + notifications.push_back(notification); + notifyNotificationsChanged(); +} + +void GameModel::RemoveNotification(Notification * notification) +{ + for(std::vector::iterator iter = notifications.begin(); iter != notifications.end(); ++iter) + { + if(*iter == notification) + { + notifications.erase(iter); + delete *iter; + break; + } + } + notifyNotificationsChanged(); +} + +void GameModel::notifyNotificationsChanged() +{ + for(std::vector::iterator iter = observers.begin(); iter != observers.end(); ++iter) + { + (*iter)->NotifyNotificationsChanged(this); + } +} + void GameModel::notifyColourSelectorColourChanged() { for(int i = 0; i < observers.size(); i++) diff --git a/src/game/GameModel.h b/src/game/GameModel.h index 9faf5fc2c..48364a749 100644 --- a/src/game/GameModel.h +++ b/src/game/GameModel.h @@ -10,6 +10,7 @@ #include "GameView.h" #include "Brush.h" #include "client/User.h" +#include "Notification.h" #include "Tool.h" #include "Menu.h" @@ -32,6 +33,7 @@ public: class GameModel { private: + vector notifications; //int clipboardSize; //unsigned char * clipboardData; GameSave * stamp; @@ -67,6 +69,7 @@ private: void notifyPlaceSaveChanged(); void notifyColourSelectorColourChanged(); void notifyColourSelectorVisibilityChanged(); + void notifyNotificationsChanged(); void notifyLogChanged(string entry); public: GameModel(); @@ -120,6 +123,10 @@ public: GameSave * GetClipboard(); GameSave * GetStamp(); GameSave * GetPlaceSave(); + + std::vector GetNotifications(); + void AddNotification(Notification * notification); + void RemoveNotification(Notification * notification); }; #endif // GAMEMODEL_H diff --git a/src/game/GameView.cpp b/src/game/GameView.cpp index 8abcca652..49006038d 100644 --- a/src/game/GameView.cpp +++ b/src/game/GameView.cpp @@ -846,6 +846,58 @@ void GameView::DoDraw() c->Tick(); } +void GameView::NotifyNotificationsChanged(GameModel * sender) +{ + class NotificationButtonAction : public ui::ButtonAction + { + GameView * v; + Notification * notification; + public: + NotificationButtonAction(GameView * v, Notification * notification) : v(v), notification(notification) { } + void ActionCallback(ui::Button * sender) + { + notification->Action(); + //v->c->RemoveNotification(notification); + } + }; + class CloseNotificationButtonAction : public ui::ButtonAction + { + GameView * v; + Notification * notification; + public: + CloseNotificationButtonAction(GameView * v, Notification * notification) : v(v), notification(notification) { } + void ActionCallback(ui::Button * sender) + { + v->c->RemoveNotification(notification); + } + }; + + for(std::vector::iterator iter = notificationComponents.begin(); iter != notificationComponents.end(); ++iter) { + RemoveComponent(*iter); + delete *iter; + } + notificationComponents.clear(); + + std::vector notifications = sender->GetNotifications(); + + int currentY = YRES-17; + for(std::vector::iterator iter = notifications.begin(); iter != notifications.end(); ++iter) + { + int width = (Graphics::textwidth((*iter)->Message.c_str()))+8; + ui::Button * tempButton = new ui::Button(ui::Point(XRES-width-22, currentY), ui::Point(width, 15), (*iter)->Message); + tempButton->SetActionCallback(new NotificationButtonAction(this, *iter)); + AddComponent(tempButton); + notificationComponents.push_back(tempButton); + + tempButton = new ui::Button(ui::Point(XRES-20, currentY), ui::Point(15, 15)); + tempButton->SetIcon(IconDelete); + tempButton->SetActionCallback(new CloseNotificationButtonAction(this, *iter)); + AddComponent(tempButton); + notificationComponents.push_back(tempButton); + + currentY -= 17; + } +} void GameView::NotifyZoomChanged(GameModel * sender) { diff --git a/src/game/GameView.h b/src/game/GameView.h index b7c69898f..55b9dc38d 100644 --- a/src/game/GameView.h +++ b/src/game/GameView.h @@ -43,6 +43,7 @@ private: //UI Elements vector menuButtons; vector toolButtons; + vector notificationComponents; deque logEntries; float lastLogEntry; ui::Button * searchButton; @@ -99,6 +100,7 @@ public: void NotifyColourSelectorVisibilityChanged(GameModel * sender); void NotifyColourSelectorColourChanged(GameModel * sender); void NotifyPlaceSaveChanged(GameModel * sender); + void NotifyNotificationsChanged(GameModel * sender); void NotifyLogChanged(GameModel * sender, string entry); virtual void OnMouseMove(int x, int y, int dx, int dy); virtual void OnMouseDown(int x, int y, unsigned button); diff --git a/src/game/Notification.h b/src/game/Notification.h new file mode 100644 index 000000000..4c64dea08 --- /dev/null +++ b/src/game/Notification.h @@ -0,0 +1,23 @@ +/* + * Notification.h + * + * Created on: Jun 20, 2012 + * Author: Simon + */ + +#ifndef NOTIFICATION_H_ +#define NOTIFICATION_H_ + +#include + +class Notification +{ +public: + Notification(std::string message) : Message(message) {} + virtual ~Notification() {}; + std::string Message; + + virtual void Action() { } +}; + +#endif /* NOTIFICATION_H_ */ diff --git a/src/interface/Engine.cpp b/src/interface/Engine.cpp index 05e53e79a..76832b67c 100644 --- a/src/interface/Engine.cpp +++ b/src/interface/Engine.cpp @@ -21,7 +21,8 @@ Engine::Engine(): windows(stack()), lastBuffer(NULL), prevBuffers(stack()), - windowTargetPosition(0, 0) + windowTargetPosition(0, 0), + FrameIndex(0) { } @@ -185,6 +186,8 @@ void Engine::Draw() sprintf(fpsText, "FPS: %.2f, Delta: %.3f", fps, dt); ui::Engine::Ref().g->drawtext(10, 10, fpsText, 255, 255, 255, 255); g->Finalise(); + FrameIndex++; + FrameIndex %= 7200; } void Engine::SetFps(float fps) diff --git a/src/interface/Engine.h b/src/interface/Engine.h index d27826584..ceabeb515 100644 --- a/src/interface/Engine.h +++ b/src/interface/Engine.h @@ -54,6 +54,8 @@ namespace ui inline Window* GetWindow() { return state_; } float FpsLimit; Graphics * g; + + unsigned int FrameIndex; private: float dt; float fps; diff --git a/src/powdertoyjava/OpenGLCanvasWin32.cpp b/src/powdertoyjava/OpenGLCanvasWin32.cpp new file mode 100644 index 000000000..9df0a0bd3 --- /dev/null +++ b/src/powdertoyjava/OpenGLCanvasWin32.cpp @@ -0,0 +1,169 @@ +#if defined(USE_JNI) && defined(WIN32) +#include "OpenGLCanvasWin32.h" + +static jfieldID ctxID = NULL; + +int defaultPixelFormat(PIXELFORMATDESCRIPTOR* pfd) +{ + ::ZeroMemory( pfd, sizeof( PIXELFORMATDESCRIPTOR ) ); + pfd->nSize = sizeof( PIXELFORMATDESCRIPTOR ); + pfd->nVersion = 1; + pfd->dwFlags = PFD_DRAW_TO_WINDOW | + PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; + pfd->iPixelType = PFD_TYPE_RGBA; + pfd->cColorBits = 24; + pfd->cDepthBits = 16; + pfd->iLayerType = PFD_MAIN_PLANE; + return 0; +} + +HGLRC ensureContext(JAWT_Win32DrawingSurfaceInfo* dsi_win, HGLRC hRC) { + + if (!hRC) { + int iFormat; + PIXELFORMATDESCRIPTOR pfd; + defaultPixelFormat(&pfd); + + iFormat = ChoosePixelFormat( dsi_win->hdc, &pfd ); + SetPixelFormat( dsi_win->hdc, iFormat, &pfd ); + + hRC = wglCreateContext( dsi_win->hdc ); + } + if (1 && wglGetCurrentDC() != dsi_win->hdc) { + wglMakeCurrent( dsi_win->hdc, hRC ); + } + + return hRC; +} + +ContextInfo* getContext(JNIEnv *env, jobject canvas) +{ + ContextInfo *ci; + if (!ctxID) { + jclass cls = env->GetObjectClass(canvas); + ctxID = env->GetFieldID(cls, "openGLContext", "J"); + } + + ci = (ContextInfo *)(long)(env->GetLongField(canvas, ctxID)); + + if (!ci) { + ci = (ContextInfo *)calloc(sizeof(ContextInfo), 1); + ci->awt = (JAWT *)calloc(sizeof(JAWT), 1); + env->SetLongField(canvas, ctxID, (jlong)(long)ci); + } + + return ci; +} + +void freeContext(JNIEnv *env, jobject canvas, ContextInfo* ci) +{ + if (ci) { + free(ci->awt); + free(ci); + env->SetLongField(canvas, ctxID, 0L); + } +} + +JNIEXPORT jboolean JNICALL Java_OpenGLCanvas_beginOpenGL(JNIEnv *env, jobject canvas) +{ + jint lock; + ContextInfo *ci = getContext(env, canvas); + + // Get the drawing surface. This can be safely cached -- not in win32 + // Anything below the DS (DSI, contexts, etc) + // can possibly change/go away and should not be cached. + ci->ds = ci->awt->GetDrawingSurface(env, canvas); + if (env->ExceptionOccurred()) { + env->ExceptionDescribe(); + } + assert(ci->ds != NULL); + + // Lock the drawing surface + // You must lock EACH TIME before drawing + lock = ci->ds->Lock(ci->ds); + if (env->ExceptionOccurred()) { + env->ExceptionDescribe(); + } + assert((lock & JAWT_LOCK_ERROR) == 0); + + // Get the drawing surface info + ci->dsi = ci->ds->GetDrawingSurfaceInfo(ci->ds); + + // Check DrawingSurfaceInfo. This can be NULL on Mac OS X + // if the windowing system is not ready + if (ci->dsi != NULL) { + // Get the platform-specific drawing info + // We will use this to get at Cocoa and CoreGraphics + // See + ci->dsi_win = (JAWT_Win32DrawingSurfaceInfo*)ci->dsi->platformInfo; + if (env->ExceptionOccurred()) { + env->ExceptionDescribe(); + } + + // Get the corresponding peer from the caller canvas + ci->hRC = ensureContext(ci->dsi_win, ci->hRC); + + return JNI_TRUE; + } + + return JNI_FALSE; +} + +JNIEXPORT void JNICALL Java_OpenGLCanvas_endOpenGL(JNIEnv *env, jobject canvas) +{ + ContextInfo *ci = getContext(env, canvas); + + SwapBuffers( ci->dsi_win->hdc ); + + // Free the DrawingSurfaceInfo + ci->ds->FreeDrawingSurfaceInfo(ci->dsi); + if (env->ExceptionOccurred()){ + env->ExceptionDescribe(); + } + + // Unlock the drawing surface + // You must unlock EACH TIME when done drawing + ci->ds->Unlock(ci->ds); + if (env->ExceptionOccurred()) { + env->ExceptionDescribe(); + } + + // Free the drawing surface (if not caching it) + ci->awt->FreeDrawingSurface(ci->ds); + if (env->ExceptionOccurred()) { + env->ExceptionDescribe(); + } +} + +JNIEXPORT void JNICALL Java_OpenGLCanvas_updateOpenGL(JNIEnv *env, jobject canvas) +{ + ContextInfo *ci = getContext(env, canvas); + + wglMakeCurrent( ci->dsi_win->hdc, ci->hRC ); +} + +JNIEXPORT void JNICALL Java_OpenGLCanvas_allocOpenGL(JNIEnv *env, jobject canvas) +{ + ContextInfo *ci = getContext(env, canvas); + + jboolean result = JNI_FALSE; + + // get the AWT + ci->awt->version = JAWT_VERSION_1_4; + result = JAWT_GetAWT(env, ci->awt); + if (env->ExceptionOccurred()) { + env->ExceptionDescribe(); + } + assert(result != JNI_FALSE); +} + +JNIEXPORT void JNICALL Java_OpenGLCanvas_releaseOpenGL(JNIEnv *env, jobject canvas) +{ + ContextInfo *ci = getContext(env, canvas); + if (ci->hRC) { + wglDeleteContext(ci->hRC); + } + + freeContext(env, canvas, ci); +} +#endif diff --git a/src/powdertoyjava/OpenGLCanvasWin32.h b/src/powdertoyjava/OpenGLCanvasWin32.h new file mode 100644 index 000000000..bff6b208e --- /dev/null +++ b/src/powdertoyjava/OpenGLCanvasWin32.h @@ -0,0 +1,35 @@ +#ifdef USE_JNI +#import + +#include +#include +#include + +int defaultPixelFormat(PIXELFORMATDESCRIPTOR* pfd); + +HGLRC ensureContext(JAWT_Win32DrawingSurfaceInfo* dsi_win, HGLRC hRC); + +typedef struct { + JAWT* awt; + JAWT_DrawingSurface* ds; + JAWT_DrawingSurfaceInfo* dsi; + JAWT_Win32DrawingSurfaceInfo* dsi_win; + HGLRC hRC; +} ContextInfo; + +ContextInfo* getContext(JNIEnv *env, jobject canvas); + +void freeContext(JNIEnv *env, jobject canvas, ContextInfo* ci); + +#ifdef __cplusplus +extern "C" { +#endif + JNIEXPORT jboolean JNICALL Java_OpenGLCanvas_beginOpenGL(JNIEnv *env, jobject canvas); + JNIEXPORT void JNICALL Java_OpenGLCanvas_endOpenGL(JNIEnv *env, jobject canvas); + JNIEXPORT void JNICALL Java_OpenGLCanvas_updateOpenGL(JNIEnv *env, jobject canvas); + JNIEXPORT void JNICALL Java_OpenGLCanvas_allocOpenGL(JNIEnv *env, jobject canvas); + JNIEXPORT void JNICALL Java_OpenGLCanvas_releaseOpenGL(JNIEnv *env, jobject canvas); +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/powdertoyjava/PowderToyJava.cpp b/src/powdertoyjava/PowderToyJava.cpp index 969d9b233..bcc9344e6 100644 --- a/src/powdertoyjava/PowderToyJava.cpp +++ b/src/powdertoyjava/PowderToyJava.cpp @@ -1,4 +1,4 @@ -#if defined(USE_JNI) && defined(MACOSX) +#if defined(USE_JNI) #include #include @@ -8,9 +8,6 @@ #include "Config.h" #include "PowderToyJava.h" #include "Graphics.h" -#if defined(LIN32) || defined(LIN64) -#include "icon.h" -#endif #include "game/GameController.h" @@ -24,8 +21,6 @@ float fps = 0, delta = 1.0f; JNIEXPORT void JNICALL Java_PowderToy_initialise(JNIEnv * env, jobject canvas) { - //InitWindowMac(env, canvas); - ui::Engine::Ref().g = new Graphics(); engine = &ui::Engine::Ref(); diff --git a/src/powdertoyjava/PowderToyJava.h b/src/powdertoyjava/PowderToyJava.h index be0b8b1cc..d39a8a9dc 100644 --- a/src/powdertoyjava/PowderToyJava.h +++ b/src/powdertoyjava/PowderToyJava.h @@ -1,5 +1,4 @@ -//#include -#include +#include #ifndef POWDERTOYJAVA #define POWDERTOYJAVA @@ -19,4 +18,4 @@ extern "C" { #ifdef __cplusplus } #endif -#endif \ No newline at end of file +#endif