/*
    Name:           PlayGate Framework
    Version:        1.0.0.0
    Copyright:      Copyright © 2008-2009 PlayGate by PsichiX. All rights reserved.
    Author:         PsichiX
    Description:    PlayGate - GML Security System Framework
    
    Uses:
    GMThreads.dll by Snake [http://gamebaseteam.eu]
    CodeCaroline.dll by PsichiX

    License:
    Allows modification and expansion of the source code stated in basic functions 
    (PlayGateStartUp, PlayGateProgress, PlayGateClosure) and adding new features.
    It's necessary to add information on the use of the PlayGate system (and GMThreads.dll) in 
    GameMaker application. It's forbidden to call self as an author PlayGate system,
    or not provide information about that we use PlayGate system.

    Built-in functions:
    
    void Wait(bool statement,int time)                                          | Wait while given statement is true
    double C2D(char* value)                                                     | Convert Char* to double
    char* D2C(char* buff,double value,int length)                               | Convert double to char*
    char* MergeChar(char* buff,int count,...)                                   | Merge strings

    PlayGate object functions:

    double PlayGate.Initiation(double handle);                                  | Initiation
    double PlayGate.Execute(int priority,bool suspended,string code);           | Execute GML code
    double PlayGate.ExecuteResult(int priority,string code);                    | Execute GML code and wait for results
    double PlayGate.ExecuteSuspend(double thread)                               | Suspend executed code
    double PlayGate.ExecuteResume(double thread)                                | Resume suspended code
    double PlayGate.GetResultDouble(void);                                      | Get double value from results list
    string PlayGate.GetResultString(void);                                      | Get string value from results list
    double PlayGate.ResultCount(bool type);                                     | Return results list size
    double PlayGate.ResultClear(bool type);                                     | Clear results list
*/

#include "PlayGate.h"

#define exportdll extern "C" __declspec(dllexport)

using namespace std;

/* Here you put declaration code */
/* Begin */
   class PLAYER // player class
   {
      public:
      double id;
      double x;
      double y;
      char nick[32];
      PLAYER(void)
      {
         id=-1;
         x=0;
         y=0;
         nick[0]=0;
      }
      void Move(double xrel,double yrel)
      {
         x+=xrel;
         y+=yrel;
      }
   };

   class IOSTATE // IO interface state
   {
      public:
      bool keyW;
      bool keyS;
      bool keyA;
      bool keyD;
      IOSTATE(void)
      {
         keyW=0;
         keyS=0;
         keyA=0;
         keyD=0;
      }
   }io;

   PLAYER player;
   char* str0=new char[32];
   char* str1=new char[32];
   char* str2=new char[32];
   char* cmd=new char[1024];
/* End */


exportdll double PlayGateStartUp(double hwnd) // PlayGate startup function
{
/*        DO NOT CHANGE!  BEGIN          */
GMLThreadLoadLibrary("GMThreads.dll");
PlayGate.Initiation(hwnd);
/*        DO NOT CHANGE!  END            */

/* Here you put the code (GML/C++) executed at startup of application */
/* Begin */
   PlayGate.ExecuteResult(3,0,"global.player=PlayGateReturnDouble(instance_create(0,0,logo));");
   player.id=PlayGate.GetResultDouble();
   MessageBox(GMappHandle,"PlayGate Framework: system test.\nPlayGate system start!","PlayGate",MB_OK);
   PlayGate.ExecuteResult(3,0,"PlayGateReturnChar('PlayGate User');");
   strcpy(player.nick,PlayGate.GetResultChar());
   player.x=320;
   player.y=240;
   MessageBox(GMappHandle,player.nick,"PlayGate: Welcome!",MB_OK);
   MessageBox(GMappHandle,"Move:\nW\t- up\nS\t- down\nA\t- left\nD\t- right","PlayGate",MB_OK);
/* End */
}

exportdll double PlayGateProgress(void) // PlayGate main function
{
/* Here you put the code (GML/C++) implemented in each call this function */
/* Begin */
   PlayGate.ResultClear(1);
   PlayGate.ExecuteResult(3,0,"PlayGateReturnDouble(keyboard_check(ord('W'))); PlayGateReturnDouble(keyboard_check(ord('S'))); PlayGateReturnDouble(keyboard_check(ord('A'))); PlayGateReturnDouble(keyboard_check(ord('D')));");
   io.keyW=(bool)PlayGate.GetResultDouble();
   io.keyS=(bool)PlayGate.GetResultDouble();
   io.keyA=(bool)PlayGate.GetResultDouble();
   io.keyD=(bool)PlayGate.GetResultDouble();
   Wait((bool)PlayGate.CheckAllThreads(),0);

   if(io.keyW==1)player.Move(0,-6);
   if(io.keyS==1)player.Move(0,6);
   if(io.keyA==1)player.Move(-6,0);
   if(io.keyD==1)player.Move(6,0);

   D2C(str0,player.id,6);
   D2C(str1,player.x,6);
   D2C(str2,player.y,6);
   MergeChar(cmd,7,"with(",str0,"){x=",str1,"; y=",str2,";}; room_caption=string(fps)+'/'+string(room_speed);");
   PlayGate.ExecuteResult(3,0,cmd);
/* End */
}

exportdll double PlayGateClosure(void) // PlayGate closure function
{
/* Here you put the code (GML/C++) executed at the close of application */
/* Begin */
   MessageBox(GMappHandle,player.nick,"PlayGate: Good bye!",MB_OK);
   delete[] str0;
   delete[] str1;
   delete[] str2;
   delete[] cmd;
/* End */

/*        DO NOT CHANGE!  BEGIN          */
Wait((bool)PlayGate.CheckAllThreads(),1);
GMLThreadFreeLibrary();
/*        DO NOT CHANGE!  END            */
}
