mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-09 10:19:38 +00:00
WIP: port alien swarm and extend engine for asw
This commit is contained in:
@@ -0,0 +1,473 @@
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h> // multimedia timer (may need winmm.lib)
|
||||
#include "App.h"
|
||||
#include "ScriptSys.h"
|
||||
#include "GameObj.h"
|
||||
#include "ScriptObj.h"
|
||||
#include "gmCall.h"
|
||||
#include "InputKBWin32.h"
|
||||
|
||||
App* App::s_instancePtr = NULL;
|
||||
|
||||
|
||||
App::App()
|
||||
{
|
||||
s_instancePtr = this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
App::~App()
|
||||
{
|
||||
s_instancePtr = NULL;
|
||||
}
|
||||
|
||||
|
||||
bool App::Init()
|
||||
{
|
||||
InputKBWin32::Get().Init();
|
||||
|
||||
// Init console
|
||||
InitConsole();
|
||||
|
||||
// Init script system for game objects
|
||||
ScriptSys::Init();
|
||||
|
||||
// Register app bindings
|
||||
RegisterScriptBindings();
|
||||
|
||||
// Init timer
|
||||
m_deltaTime = 0;
|
||||
m_lastTime = timeGetTime();
|
||||
|
||||
// Compile and run script
|
||||
ScriptSys::Get()->ExecuteFile("TestGameObj.gm");
|
||||
|
||||
//TEST REMOVE
|
||||
// ClearScreen();
|
||||
// SetColor(COLOR_YELLOW, COLOR_RED);
|
||||
// SetCursor(10,10);
|
||||
// Print("Hello");
|
||||
// PrintAt(10,10,"Hello");
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void App::Destroy()
|
||||
{
|
||||
ScriptSys::Destroy();
|
||||
}
|
||||
|
||||
|
||||
bool App::Update()
|
||||
{
|
||||
int curTime = timeGetTime();
|
||||
m_deltaTime = curTime - m_lastTime;
|
||||
m_lastTime = curTime;
|
||||
|
||||
// Update input
|
||||
InputKBWin32::Get().Update();
|
||||
|
||||
// Execute some script
|
||||
ScriptSys::Get()->Execute(m_deltaTime);
|
||||
|
||||
if(InputKBWin32::Get().IsKeyPressed('A'))
|
||||
{
|
||||
TestA();
|
||||
}
|
||||
else if(InputKBWin32::Get().IsKeyPressed('B'))
|
||||
{
|
||||
TestB();
|
||||
}
|
||||
else if(InputKBWin32::Get().IsKeyPressed('C'))
|
||||
{
|
||||
TestC();
|
||||
}
|
||||
|
||||
if(InputKBWin32::Get().IsKeyPressed(VK_ESCAPE))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void App::InitConsole()
|
||||
{
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||
|
||||
m_console = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
|
||||
GetConsoleScreenBufferInfo(m_console, &csbi);
|
||||
|
||||
DWORD dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
|
||||
|
||||
m_screenSizeX = csbi.dwSize.X;
|
||||
m_screenSizeY = csbi.dwSize.Y;
|
||||
}
|
||||
|
||||
|
||||
void App::TestA()
|
||||
{
|
||||
// Test create a game object and set member in script
|
||||
GameObj* newObj = new GameObj;
|
||||
|
||||
printf("new GameObj = %x\n", newObj);
|
||||
printf("GameObj.m_scriptObj = %x\n", newObj->GetScriptObj());
|
||||
|
||||
newObj->GetScriptObj()->SetMemberString("m_name", "MangoBoy");
|
||||
newObj->GetScriptObj()->ExecuteGlobalFunctionOnThis("WhatsMyName");
|
||||
|
||||
delete newObj;
|
||||
|
||||
gmCall call;
|
||||
if(call.BeginGlobalFunction(ScriptSys::Get()->GetMachine(), "RunGlobalObject"))
|
||||
{
|
||||
call.End();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void App::TestB()
|
||||
{
|
||||
// Test call script function that keeps running for a bit
|
||||
gmCall call;
|
||||
if(call.BeginGlobalFunction(ScriptSys::Get()->GetMachine(), "ThreadYieldTest"))
|
||||
{
|
||||
call.End();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void App::TestC()
|
||||
{
|
||||
// Quick test of collect garbage and cpp owned objects
|
||||
|
||||
GameObj* newObj = new GameObj;
|
||||
|
||||
printf("new GameObj = %x\n", newObj);
|
||||
printf("GameObj.m_scriptObj = %x\n", newObj->GetScriptObj());
|
||||
|
||||
newObj->GetScriptObj()->SetMemberString("m_name", "PotatoHead");
|
||||
//newObj->GetScriptObj()->ExecuteGlobalFunctionOnThis("WhatsMyName");
|
||||
|
||||
ScriptSys::Get()->GetMachine()->CollectGarbage(true);
|
||||
|
||||
delete newObj;
|
||||
}
|
||||
|
||||
|
||||
void App::SetCursor(int a_x, int a_y)
|
||||
{
|
||||
ClipScreenCoordsi(a_x, a_y);
|
||||
|
||||
COORD point;
|
||||
|
||||
point.X = (short) a_x;
|
||||
point.Y = (short) a_y;
|
||||
|
||||
SetConsoleCursorPosition(m_console, point);
|
||||
}
|
||||
|
||||
|
||||
void App::ClearScreen()
|
||||
{
|
||||
COORD coordScreen = { 0, 0 };
|
||||
DWORD cCharsWritten;
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||
DWORD dwConSize;
|
||||
GetConsoleScreenBufferInfo(m_console, &csbi);
|
||||
dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
|
||||
FillConsoleOutputCharacter(m_console, TEXT(' '), dwConSize, coordScreen, &cCharsWritten);
|
||||
GetConsoleScreenBufferInfo(m_console, &csbi);
|
||||
FillConsoleOutputAttribute(m_console, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten);
|
||||
SetConsoleCursorPosition(m_console, coordScreen);
|
||||
}
|
||||
|
||||
|
||||
void App::Print(const char* a_string)
|
||||
{
|
||||
printf("%s", a_string);
|
||||
}
|
||||
|
||||
|
||||
void App::PrintAt(int a_x, int a_y, const char* a_string)
|
||||
{
|
||||
SetCursor(a_x, a_y);
|
||||
Print(a_string);
|
||||
}
|
||||
|
||||
|
||||
int App::GetAttribFromColIndex(int a_colorIndex, bool a_isForeground)
|
||||
{
|
||||
// WARNING These struct must match the color enums
|
||||
static int foreColors[COLOR_MAX]=
|
||||
{
|
||||
0, //COLOR_BLACK
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, //COLOR_WHITE,
|
||||
FOREGROUND_RED, //COLOR_RED
|
||||
FOREGROUND_GREEN, //COLOR_GREEN,
|
||||
FOREGROUND_BLUE, //COLOR_BLUE,
|
||||
FOREGROUND_RED | FOREGROUND_BLUE, //COLOR_MAGENTA,
|
||||
FOREGROUND_GREEN | FOREGROUND_BLUE, //COLOR_CYAN,
|
||||
FOREGROUND_RED | FOREGROUND_GREEN, //COLOR_YELLOW,
|
||||
};
|
||||
|
||||
static int backColors[COLOR_MAX]=
|
||||
{
|
||||
0, //COLOR_BLACK
|
||||
BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE, //COLOR_WHITE,
|
||||
BACKGROUND_RED, //COLOR_RED
|
||||
BACKGROUND_GREEN, //COLOR_GREEN,
|
||||
BACKGROUND_BLUE, //COLOR_BLUE,
|
||||
BACKGROUND_RED | BACKGROUND_BLUE, //COLOR_MAGENTA,
|
||||
BACKGROUND_GREEN | BACKGROUND_BLUE, //COLOR_CYAN,
|
||||
BACKGROUND_RED | BACKGROUND_GREEN, //COLOR_YELLOW,
|
||||
};
|
||||
|
||||
|
||||
if( (a_colorIndex < COLOR_MIN) && (a_colorIndex >= COLOR_MAX) )
|
||||
{
|
||||
if(a_isForeground)
|
||||
{
|
||||
return foreColors[COLOR_WHITE];
|
||||
}
|
||||
else
|
||||
{
|
||||
return backColors[COLOR_WHITE];
|
||||
}
|
||||
}
|
||||
|
||||
if(a_isForeground)
|
||||
{
|
||||
return foreColors[a_colorIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
return backColors[a_colorIndex];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void App::SetColor(int a_foreColorIndex, int a_backColorIndex)
|
||||
{
|
||||
int foreCol = GetAttribFromColIndex(a_foreColorIndex, true);
|
||||
int backCol = GetAttribFromColIndex(a_backColorIndex, false);
|
||||
|
||||
int param = foreCol | backCol;
|
||||
|
||||
SetConsoleTextAttribute(m_console, (short) param);
|
||||
}
|
||||
|
||||
|
||||
bool App::ClipScreenCoordsf(float& a_posX, float& a_posY)
|
||||
{
|
||||
bool wasClipped = false;
|
||||
|
||||
if(a_posX < 0.0f)
|
||||
{
|
||||
a_posX = 0.0f;
|
||||
wasClipped = true;
|
||||
}
|
||||
else if(a_posX >= (float)App::Get()->GetScreenSizeX())
|
||||
{
|
||||
a_posX = (float)(App::Get()->GetScreenSizeX() - 1);
|
||||
wasClipped = true;
|
||||
}
|
||||
|
||||
if(a_posY < 0.0f)
|
||||
{
|
||||
a_posY = 0.0f;
|
||||
wasClipped = true;
|
||||
}
|
||||
else if(a_posY >= (float)App::Get()->GetScreenSizeY())
|
||||
{
|
||||
a_posY = (float)(App::Get()->GetScreenSizeY() - 1);
|
||||
wasClipped = true;
|
||||
}
|
||||
|
||||
return wasClipped;
|
||||
}
|
||||
|
||||
|
||||
bool App::ClipScreenCoordsi(int& a_posX, int& a_posY)
|
||||
{
|
||||
bool wasClipped = false;
|
||||
|
||||
if(a_posX < 0)
|
||||
{
|
||||
a_posX = 0;
|
||||
wasClipped = true;
|
||||
}
|
||||
else if(a_posX >= App::Get()->GetScreenSizeX())
|
||||
{
|
||||
a_posX = App::Get()->GetScreenSizeX() - 1;
|
||||
wasClipped = true;
|
||||
}
|
||||
|
||||
if(a_posY < 0)
|
||||
{
|
||||
a_posY = 0;
|
||||
wasClipped = true;
|
||||
}
|
||||
else if(a_posY >= App::Get()->GetScreenSizeY())
|
||||
{
|
||||
a_posY = App::Get()->GetScreenSizeY() - 1;
|
||||
wasClipped = true;
|
||||
}
|
||||
|
||||
return wasClipped;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// Script bindings
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
|
||||
int GM_CDECL App::Console_Print(gmThread* a_thread)
|
||||
{
|
||||
GM_CHECK_NUM_PARAMS(1);
|
||||
GM_CHECK_STRING_PARAM(a_string, 0);
|
||||
|
||||
App::Get()->Print(a_string);
|
||||
|
||||
return GM_OK;
|
||||
}
|
||||
|
||||
|
||||
int GM_CDECL App::Console_SetCursor(gmThread* a_thread)
|
||||
{
|
||||
GM_CHECK_NUM_PARAMS(2);
|
||||
GM_CHECK_INT_PARAM(a_curX, 0);
|
||||
GM_CHECK_INT_PARAM(a_curY, 1);
|
||||
|
||||
App::Get()->ClipScreenCoordsi(a_curX, a_curY);
|
||||
App::Get()->SetCursor(a_curX, a_curY);
|
||||
|
||||
return GM_OK;
|
||||
}
|
||||
|
||||
|
||||
int GM_CDECL App::Console_SetColor(gmThread* a_thread)
|
||||
{
|
||||
GM_CHECK_NUM_PARAMS(2);
|
||||
GM_CHECK_INT_PARAM(a_foreCol, 0);
|
||||
GM_CHECK_INT_PARAM(a_backCol, 1);
|
||||
|
||||
App::Get()->SetColor(a_foreCol, a_backCol);
|
||||
|
||||
return GM_OK;
|
||||
}
|
||||
|
||||
|
||||
int GM_CDECL App::Input_KeyPressed(gmThread* a_thread)
|
||||
{
|
||||
GM_CHECK_NUM_PARAMS(1);
|
||||
GM_CHECK_INT_PARAM(a_vKey, 0);
|
||||
|
||||
if(InputKBWin32::Get().IsKeyPressed(a_vKey))
|
||||
{
|
||||
a_thread->PushInt(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
a_thread->PushInt(0);
|
||||
}
|
||||
|
||||
return GM_OK;
|
||||
}
|
||||
|
||||
|
||||
int GM_CDECL App::Input_KeyDown(gmThread* a_thread)
|
||||
{
|
||||
GM_CHECK_NUM_PARAMS(1);
|
||||
GM_CHECK_INT_PARAM(a_vKey, 0);
|
||||
|
||||
if(InputKBWin32::Get().IsKeyDown(a_vKey))
|
||||
{
|
||||
a_thread->PushInt(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
a_thread->PushInt(0);
|
||||
}
|
||||
|
||||
return GM_OK;
|
||||
}
|
||||
|
||||
|
||||
void App::RegisterScriptBindings()
|
||||
{
|
||||
static gmFunctionEntry ConsoleLib[] =
|
||||
{
|
||||
/*gm
|
||||
\lib Console
|
||||
\brief Console Library
|
||||
*/
|
||||
/*gm
|
||||
\function Print
|
||||
\brief Print string at current cursor position
|
||||
\param string a_string
|
||||
*/
|
||||
{"Print", Console_Print},
|
||||
/*gm
|
||||
\function SetCursor
|
||||
\brief Set cursor position
|
||||
\param int a_curX Cursor x position
|
||||
\param int a_curY Cursor y position
|
||||
*/
|
||||
{"SetCursor", Console_SetCursor},
|
||||
|
||||
/*gm
|
||||
\function SetColor
|
||||
\brief Set text color
|
||||
\param int a_foreCol Foreground color
|
||||
\param int a_backCol Background color
|
||||
*/
|
||||
{"SetColor", Console_SetColor},
|
||||
};
|
||||
|
||||
|
||||
static gmFunctionEntry InputLib[] =
|
||||
{
|
||||
/*gm
|
||||
\lib Console
|
||||
\brief Console Library
|
||||
*/
|
||||
/*gm
|
||||
\function KeyPressed
|
||||
\brief Was this key pressed
|
||||
\param int a_vKey windows virtual key code (Most match ascii uppercase)
|
||||
\return true if key was pressed this frame
|
||||
*/
|
||||
{"KeyPressed", Input_KeyPressed},
|
||||
|
||||
/*gm
|
||||
\function KeyDown
|
||||
\brief Is this key down
|
||||
\param int a_vKey windows virtual key code (Most match ascii uppercase)
|
||||
\return true if is down
|
||||
*/
|
||||
{"KeyDown", Input_KeyDown},
|
||||
|
||||
};
|
||||
|
||||
gmMachine* machine = ScriptSys::Get()->GetMachine();
|
||||
|
||||
machine->RegisterLibrary(ConsoleLib, sizeof(ConsoleLib) / sizeof(ConsoleLib[0]), "Console");
|
||||
machine->RegisterLibrary(InputLib, sizeof(InputLib) / sizeof(InputLib[0]), "Input");
|
||||
|
||||
// Make some global constants
|
||||
machine->GetGlobals()->Set(machine, "COLOR_BLACK", gmVariable(GM_INT, COLOR_BLACK));
|
||||
machine->GetGlobals()->Set(machine, "COLOR_WHITE", gmVariable(GM_INT, COLOR_WHITE));
|
||||
machine->GetGlobals()->Set(machine, "COLOR_RED", gmVariable(GM_INT, COLOR_RED));
|
||||
machine->GetGlobals()->Set(machine, "COLOR_GREEN", gmVariable(GM_INT, COLOR_GREEN));
|
||||
machine->GetGlobals()->Set(machine, "COLOR_BLUE", gmVariable(GM_INT, COLOR_BLUE));
|
||||
machine->GetGlobals()->Set(machine, "COLOR_MAGENTA", gmVariable(GM_INT, COLOR_MAGENTA));
|
||||
machine->GetGlobals()->Set(machine, "COLOR_CYAN", gmVariable(GM_INT, COLOR_CYAN));
|
||||
machine->GetGlobals()->Set(machine, "COLOR_YELLOW", gmVariable(GM_INT, COLOR_YELLOW));
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
//
|
||||
// Example application
|
||||
//
|
||||
#include <Windows.h>
|
||||
#include "gmThread.h"
|
||||
|
||||
class App
|
||||
{
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
COLOR_MIN = 0,
|
||||
|
||||
COLOR_BLACK = COLOR_MIN,
|
||||
COLOR_WHITE,
|
||||
COLOR_RED,
|
||||
COLOR_GREEN,
|
||||
COLOR_BLUE,
|
||||
COLOR_MAGENTA,
|
||||
COLOR_CYAN,
|
||||
COLOR_YELLOW,
|
||||
|
||||
|
||||
COLOR_MAX
|
||||
};
|
||||
|
||||
static App* Get() { return s_instancePtr; }
|
||||
|
||||
App();
|
||||
~App();
|
||||
bool Init();
|
||||
void Destroy();
|
||||
bool Update();
|
||||
|
||||
void SetCursor(int a_x, int a_y);
|
||||
void ClearScreen();
|
||||
void Print(const char* a_string);
|
||||
void PrintAt(int a_x, int a_y, const char* a_string);
|
||||
void SetColor(int a_foreColorIndex, int a_backColorIndex);
|
||||
int GetScreenSizeX() { return m_screenSizeX; }
|
||||
int GetScreenSizeY() { return m_screenSizeY; }
|
||||
|
||||
bool ClipScreenCoordsf(float& a_posX, float& a_posY);
|
||||
bool ClipScreenCoordsi(int& a_posX, int& a_posY);
|
||||
|
||||
protected:
|
||||
|
||||
int GetAttribFromColIndex(int a_colorIndex, bool a_isForeground);
|
||||
void InitConsole();
|
||||
void RegisterScriptBindings();
|
||||
|
||||
static int GM_CDECL Console_Print(gmThread* a_thread);
|
||||
static int GM_CDECL Console_SetCursor(gmThread* a_thread);
|
||||
static int GM_CDECL Console_SetColor(gmThread* a_thread);
|
||||
|
||||
static int GM_CDECL Input_KeyPressed(gmThread* a_thread);
|
||||
static int GM_CDECL Input_KeyDown(gmThread* a_thread);
|
||||
|
||||
void TestA();
|
||||
void TestB();
|
||||
void TestC();
|
||||
|
||||
int m_deltaTime;
|
||||
int m_lastTime;
|
||||
|
||||
int m_screenSizeX;
|
||||
int m_screenSizeY;
|
||||
HANDLE m_console;
|
||||
|
||||
static App* s_instancePtr; ///< Ptr to instance of this class when created
|
||||
};
|
||||
@@ -0,0 +1,317 @@
|
||||
//
|
||||
// GameObj.cpp
|
||||
//
|
||||
|
||||
#include <math.h>
|
||||
#include "GameObj.h"
|
||||
#include "App.h"
|
||||
#include "ScriptObj.h"
|
||||
#include "ScriptSys.h"
|
||||
|
||||
GameObj::GameObj()
|
||||
{
|
||||
m_scriptObj = NULL;
|
||||
m_posX = -1;
|
||||
m_posY = -1;
|
||||
m_destX = m_posX;
|
||||
m_destY = m_posY;
|
||||
m_speed = 1.0f;
|
||||
m_colorIndex = App::COLOR_WHITE;
|
||||
|
||||
m_scriptObj = new ScriptObj(this);
|
||||
}
|
||||
|
||||
|
||||
GameObj::~GameObj()
|
||||
{
|
||||
if(m_scriptObj)
|
||||
{
|
||||
delete m_scriptObj;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float GameObj::GetPosX() const
|
||||
{
|
||||
return m_posX;
|
||||
}
|
||||
|
||||
|
||||
float GameObj::GetPosY() const
|
||||
{
|
||||
return m_posY;
|
||||
}
|
||||
|
||||
|
||||
void GameObj::SetPos(const float a_x, const float a_y)
|
||||
{
|
||||
m_posX = a_x;
|
||||
m_posY = a_y;
|
||||
|
||||
App::Get()->ClipScreenCoordsf(m_posX, m_posY);
|
||||
|
||||
m_destX = m_posX;
|
||||
m_destY = m_posY;
|
||||
}
|
||||
|
||||
|
||||
void GameObj::MoveTo(const float a_x, const float a_y)
|
||||
{
|
||||
m_destX = a_x;
|
||||
m_destY = a_y;
|
||||
|
||||
App::Get()->ClipScreenCoordsf(m_destX, m_destY);
|
||||
}
|
||||
|
||||
|
||||
void GameObj::SetSpeed(const float a_speed)
|
||||
{
|
||||
m_speed = a_speed;
|
||||
}
|
||||
|
||||
|
||||
float GameObj::GetSpeed()
|
||||
{
|
||||
return m_speed;
|
||||
}
|
||||
|
||||
|
||||
void GameObj::SetColor(int a_colorIndex)
|
||||
{
|
||||
if(a_colorIndex >= App::COLOR_MIN && a_colorIndex < App::COLOR_MAX)
|
||||
{
|
||||
m_colorIndex = a_colorIndex;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GameObj::Update(float a_deltaTime)
|
||||
{
|
||||
// NOTE: A real game would probably not update each object each frame
|
||||
// but instead only update an object in a particular way when required.
|
||||
// This example will do all updating in one place, and do so each frame.
|
||||
|
||||
// Update movement
|
||||
{
|
||||
float dx = m_destX - m_posX;
|
||||
float dy = m_destY - m_posY;
|
||||
|
||||
float len2 = dx*dx + dy*dy;
|
||||
|
||||
if(len2 > 0.0f)
|
||||
{
|
||||
float moveThisFrame = a_deltaTime * m_speed;
|
||||
float distToGo = sqrtf(len2);
|
||||
|
||||
// We can reach dest this frame
|
||||
if(moveThisFrame > distToGo)
|
||||
{
|
||||
m_posX = m_destX;
|
||||
m_posY = m_destY;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_posX += dx * moveThisFrame;
|
||||
m_posY += dy * moveThisFrame;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GameObj::Render()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// Script
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
|
||||
int GM_CDECL GameObj::GameObj_MoveTo(gmThread* a_thread)
|
||||
{
|
||||
GM_CHECK_NUM_PARAMS(2);
|
||||
GM_CHECK_FLOAT_PARAM(destX, 0);
|
||||
GM_CHECK_FLOAT_PARAM(destY, 1);
|
||||
GameObj* thisPtr = GetThisGameObj(a_thread);
|
||||
if(!thisPtr)
|
||||
{
|
||||
return GM_EXCEPTION;
|
||||
}
|
||||
|
||||
thisPtr->MoveTo(destX, destY);
|
||||
|
||||
return GM_OK;
|
||||
}
|
||||
|
||||
|
||||
int GM_CDECL GameObj::GameObj_SetPos(gmThread* a_thread)
|
||||
{
|
||||
GM_CHECK_NUM_PARAMS(2);
|
||||
GM_CHECK_FLOAT_PARAM(posX, 0);
|
||||
GM_CHECK_FLOAT_PARAM(posY, 1);
|
||||
GameObj* thisPtr = GetThisGameObj(a_thread);
|
||||
if(!thisPtr)
|
||||
{
|
||||
return GM_EXCEPTION;
|
||||
}
|
||||
|
||||
thisPtr->SetPos(posX, posY);
|
||||
|
||||
return GM_OK;
|
||||
}
|
||||
|
||||
|
||||
int GM_CDECL GameObj::GameObj_GetPosX(gmThread* a_thread)
|
||||
{
|
||||
GM_CHECK_NUM_PARAMS(0);
|
||||
GameObj* thisPtr = GetThisGameObj(a_thread);
|
||||
if(!thisPtr)
|
||||
{
|
||||
return GM_EXCEPTION;
|
||||
}
|
||||
|
||||
a_thread->PushFloat(thisPtr->GetPosX());
|
||||
|
||||
return GM_OK;
|
||||
}
|
||||
|
||||
|
||||
int GM_CDECL GameObj::GameObj_GetPosY(gmThread* a_thread)
|
||||
{
|
||||
GM_CHECK_NUM_PARAMS(0);
|
||||
GameObj* thisPtr = GetThisGameObj(a_thread);
|
||||
if(!thisPtr)
|
||||
{
|
||||
return GM_EXCEPTION;
|
||||
}
|
||||
|
||||
a_thread->PushFloat(thisPtr->GetPosY());
|
||||
|
||||
return GM_OK;
|
||||
}
|
||||
|
||||
|
||||
int GM_CDECL GameObj::GameObj_IsValid(gmThread* a_thread)
|
||||
{
|
||||
GM_CHECK_NUM_PARAMS(0);
|
||||
GameObj* thisPtr = GetThisGameObj(a_thread);
|
||||
if(!thisPtr)
|
||||
{
|
||||
a_thread->PushInt(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
a_thread->PushInt(true);
|
||||
}
|
||||
|
||||
return GM_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int GM_CDECL GameObj::GameObj_SetSpeed(gmThread* a_thread)
|
||||
{
|
||||
GM_CHECK_NUM_PARAMS(1);
|
||||
GM_CHECK_FLOAT_PARAM(speed, 0);
|
||||
GameObj* thisPtr = GetThisGameObj(a_thread);
|
||||
if(!thisPtr)
|
||||
{
|
||||
return GM_EXCEPTION;
|
||||
}
|
||||
|
||||
thisPtr->SetSpeed(speed);
|
||||
|
||||
return GM_OK;
|
||||
}
|
||||
|
||||
|
||||
int GM_CDECL GameObj::GameObj_GetSpeed(gmThread* a_thread)
|
||||
{
|
||||
GM_CHECK_NUM_PARAMS(0);
|
||||
GameObj* thisPtr = GetThisGameObj(a_thread);
|
||||
if(!thisPtr)
|
||||
{
|
||||
return GM_EXCEPTION;
|
||||
}
|
||||
|
||||
a_thread->PushFloat(thisPtr->GetSpeed());
|
||||
|
||||
return GM_OK;
|
||||
}
|
||||
|
||||
|
||||
int GM_CDECL GameObj::GameObj_SetColor(gmThread* a_thread)
|
||||
{
|
||||
GM_CHECK_NUM_PARAMS(1);
|
||||
GM_CHECK_INT_PARAM(colorIndex, 0);
|
||||
GameObj* thisPtr = GetThisGameObj(a_thread);
|
||||
if(!thisPtr)
|
||||
{
|
||||
return GM_EXCEPTION;
|
||||
}
|
||||
|
||||
thisPtr->SetColor(colorIndex);
|
||||
|
||||
return GM_OK;
|
||||
}
|
||||
|
||||
|
||||
void GameObj::RegisterScriptBindings()
|
||||
{
|
||||
static gmFunctionEntry gameObjTypeLib[] =
|
||||
{
|
||||
/*gm
|
||||
\lib GameObj
|
||||
\brief Game Object class
|
||||
*/
|
||||
/*gm
|
||||
\function SetPos
|
||||
\brief Set position
|
||||
\param float a_posX New position X component
|
||||
\param float a_posY New position Y component
|
||||
*/
|
||||
{"SetPos", GameObj_SetPos},
|
||||
/*gm
|
||||
\function GetPosX
|
||||
\brief Get position X
|
||||
\return float Get position X component.
|
||||
*/
|
||||
{"GetPosX", GameObj_GetPosX},
|
||||
/*gm
|
||||
\function GetPosY
|
||||
\brief Get position Y
|
||||
\return float Get position Y component.
|
||||
*/
|
||||
{"GetPosY", GameObj_GetPosY},
|
||||
/*gm
|
||||
\function IsValid
|
||||
\brief Is this a valid object, or has it been deleted or such
|
||||
\return int true if valid
|
||||
*/
|
||||
{"IsValid", GameObj_IsValid},
|
||||
/*gm
|
||||
\function SetSpeed
|
||||
\brief Set speed
|
||||
\param a_speed New speed
|
||||
*/
|
||||
{"SetSpeed", GameObj_SetSpeed},
|
||||
/*gm
|
||||
\function GetSpeed
|
||||
\brief Get speed
|
||||
\return float Current speed
|
||||
*/
|
||||
{"GetSpeed", GameObj_GetSpeed},
|
||||
/*gm
|
||||
\function SetColor
|
||||
\brief Set color
|
||||
\param a_color New color
|
||||
*/
|
||||
{"SetColor", GameObj_SetColor},
|
||||
|
||||
};
|
||||
|
||||
ScriptSys::Get()->GetMachine()->RegisterTypeLibrary(ScriptObj::GMTYPE_GAMEOBJ, gameObjTypeLib, sizeof(gameObjTypeLib) / sizeof(gameObjTypeLib[0]));
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
#ifndef GAMEOBJ_H
|
||||
#define GAMEOBJ_H
|
||||
|
||||
#include "gmThread.h"
|
||||
|
||||
//
|
||||
// GameObj.h
|
||||
//
|
||||
// Example game object that uses the script interface component
|
||||
//
|
||||
|
||||
// Fwd decls
|
||||
class ScriptObj;
|
||||
|
||||
|
||||
|
||||
class GameObj
|
||||
{
|
||||
public:
|
||||
|
||||
GameObj();
|
||||
virtual ~GameObj();
|
||||
|
||||
ScriptObj* GetScriptObj() { return m_scriptObj; }
|
||||
|
||||
float GetPosX() const;
|
||||
float GetPosY() const;
|
||||
void SetPos(const float a_x, const float a_y);
|
||||
void MoveTo(const float a_x, const float a_y);
|
||||
void SetSpeed(const float a_speed);
|
||||
float GetSpeed();
|
||||
void SetColor(int a_colorIndex);
|
||||
|
||||
void Update(float a_deltaTime);
|
||||
void Render();
|
||||
|
||||
static void RegisterScriptBindings();
|
||||
|
||||
private:
|
||||
|
||||
static int GM_CDECL GameObj_SetPos(gmThread* a_thread);
|
||||
static int GM_CDECL GameObj_GetPosX(gmThread* a_thread);
|
||||
static int GM_CDECL GameObj_GetPosY(gmThread* a_thread);
|
||||
static int GM_CDECL GameObj_IsValid(gmThread* a_thread);
|
||||
static int GM_CDECL GameObj_MoveTo(gmThread* a_thread);
|
||||
static int GM_CDECL GameObj_SetSpeed(gmThread* a_thread);
|
||||
static int GM_CDECL GameObj_GetSpeed(gmThread* a_thread);
|
||||
static int GM_CDECL GameObj_SetColor(gmThread* a_thread);
|
||||
|
||||
ScriptObj* m_scriptObj;
|
||||
float m_posX;
|
||||
float m_posY;
|
||||
float m_destX;
|
||||
float m_destY;
|
||||
float m_speed;
|
||||
int m_colorIndex;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif //GAMEOBJ_H
|
||||
@@ -0,0 +1,470 @@
|
||||
# Microsoft Developer Studio Project File - Name="GameObject" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=GameObject - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "GameObject.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "GameObject.mak" CFG="GameObject - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "GameObject - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "GameObject - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName "Perforce Project"
|
||||
# PROP Scc_LocalPath "..\.."
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "GameObject - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\gm" /I "..\..\platform\win32msvc" /I "..\..\binds" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0xc09 /d "NDEBUG"
|
||||
# ADD RSC /l 0xc09 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 winmm.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Ws2_32.lib /nologo /subsystem:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "GameObject - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\gm" /I "..\..\platform\win32msvc" /I "..\..\binds" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD BASE RSC /l 0xc09 /d "_DEBUG"
|
||||
# ADD RSC /l 0xc09 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 winmm.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "GameObject - Win32 Release"
|
||||
# Name "GameObject - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\App.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\App.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\GameObj.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\GameObj.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\InputKBWin32.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\InputKBWin32.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\main.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\NetClient.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\NetClient.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ReadMe.txt
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ScriptObj.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ScriptObj.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ScriptSys.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ScriptSys.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\StdStuff.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\StdStuff.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\TestGameObj.gm
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "gm"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmArraySimple.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmArraySimple.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmByteCode.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmByteCode.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmByteCodeGen.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmByteCodeGen.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmCodeGen.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmCodeGen.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmCodeGenHooks.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmCodeGenHooks.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmCodeTree.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmCodeTree.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmConfig.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmCrc.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmCrc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmDebug.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmDebug.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmFunctionObject.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmFunctionObject.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmHash.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmHash.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmIncGC.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmIncGC.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmIterator.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmLibHooks.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmLibHooks.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmListDouble.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmListDouble.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmLog.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmLog.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmMachine.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmMachine.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmMachineLib.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmMachineLib.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmMem.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmMem.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmMemChain.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmMemChain.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmMemFixed.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmMemFixed.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmMemFixedSet.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmMemFixedSet.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmOperators.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmOperators.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmParser.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmParser.cpp.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmScanner.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmScanner.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmStream.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmStream.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmStreamBuffer.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmStreamBuffer.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmStringObject.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmStringObject.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmTableObject.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmTableObject.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmThread.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmThread.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmUserObject.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmUserObject.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmUtil.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmUtil.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmVariable.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmVariable.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "gmBinds"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\binds\gmCall.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\binds\gmCall.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\binds\gmHelpers.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\binds\gmHelpers.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\binds\gmMathLib.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\binds\gmMathLib.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\binds\gmStringLib.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\binds\gmStringLib.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\binds\gmSystemLib.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\binds\gmSystemLib.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "gmConfig"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\platform\win32msvc\gmConfig_p.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
@@ -0,0 +1,33 @@
|
||||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "GameObject"=.\GameObject.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
begin source code control
|
||||
Perforce Project
|
||||
..\..
|
||||
end source code control
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,102 @@
|
||||
//
|
||||
// InputKBWin32.cpp
|
||||
//
|
||||
|
||||
#include <windows.h>
|
||||
#include "InputKBWin32.h"
|
||||
|
||||
// Init statics and constants
|
||||
InputKBWin32 InputKBWin32::s_staticInstance;
|
||||
|
||||
|
||||
|
||||
InputKBWin32::InputKBWin32()
|
||||
{
|
||||
m_keyDownBufferIndex = 0;
|
||||
|
||||
Init();
|
||||
}
|
||||
|
||||
|
||||
|
||||
InputKBWin32::~InputKBWin32()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void InputKBWin32::Init()
|
||||
{
|
||||
for(int kIndex=0; kIndex<MAX_KEYS; ++kIndex)
|
||||
{
|
||||
m_keyDownBuffer[0][kIndex] = 0;
|
||||
m_keyDownBuffer[1][kIndex] = 0;
|
||||
m_keyStatus[kIndex] = KEY_STATUS_UP;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void InputKBWin32::Update()
|
||||
{
|
||||
//#define HAS_WINDOW_UPDATE // Define this if we have a window and a message pump
|
||||
|
||||
int lastBuffIndex = !m_keyDownBufferIndex;
|
||||
int curBuffIndex = m_keyDownBufferIndex;
|
||||
|
||||
m_keyDownBufferIndex = lastBuffIndex; // Flip buffers
|
||||
|
||||
char* bufferCurrent = &m_keyDownBuffer[curBuffIndex][0];
|
||||
char* bufferLast = &m_keyDownBuffer[lastBuffIndex][0];
|
||||
|
||||
// Get the button states from Win32
|
||||
#ifdef HAS_WINDOW_UPDATE
|
||||
// We have a window and message pump
|
||||
BYTE win32KeyBuffer[256];
|
||||
GetKeyboardState(win32KeyBuffer);
|
||||
#else // HAS_WINDOW_UPDATE
|
||||
short win32KeyBuffer[256];
|
||||
for(int vkIndex=0; vkIndex < 256; ++vkIndex)
|
||||
{
|
||||
win32KeyBuffer[vkIndex] = GetAsyncKeyState(vkIndex);
|
||||
}
|
||||
#endif //HAS_WINDOW_UPDATE
|
||||
|
||||
// Find state changes
|
||||
for(int kIndex=0; kIndex < MAX_KEYS; ++kIndex)
|
||||
{
|
||||
int status;
|
||||
|
||||
// Convert win32 keystate to true / false
|
||||
#ifdef HAS_WINDOW_UPDATE
|
||||
if(win32KeyBuffer[kIndex] & (1<<7))
|
||||
#else // HAS_WINDOW_UPDATE
|
||||
if(win32KeyBuffer[kIndex] & (1<<15))
|
||||
#endif // HAS_WINDOW_UPDATE
|
||||
{
|
||||
bufferCurrent[kIndex] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
bufferCurrent[kIndex] = false;
|
||||
}
|
||||
|
||||
status = 0;
|
||||
if(bufferCurrent[kIndex])
|
||||
{
|
||||
status |= KEY_STATUS_DOWN;
|
||||
if(!bufferLast[kIndex])
|
||||
{
|
||||
status |= KEY_STATUS_PRESSED;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status |= KEY_STATUS_UP;
|
||||
if(bufferLast[kIndex])
|
||||
{
|
||||
status |= KEY_STATUS_RELEASED;
|
||||
}
|
||||
}
|
||||
|
||||
m_keyStatus[kIndex] = status;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
#ifndef INPUTKBWIN32_H
|
||||
#define INPUTKBWIN32_H
|
||||
|
||||
//
|
||||
// InputKBWin32.h
|
||||
//
|
||||
|
||||
#include "gmThread.h" // For some basic types
|
||||
|
||||
/// A simple keyboard input class for Win32.
|
||||
class InputKBWin32
|
||||
{
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
MAX_KEYS = 256, ///< Max keys on keyboard (for buffer size etc.)
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
KEY_STATUS_UNKNOWN = 0, ///< Invalid status
|
||||
KEY_STATUS_UP = (1<<0), ///< Button is up
|
||||
KEY_STATUS_RELEASED = (1<<1), ///< Button released this frame
|
||||
KEY_STATUS_DOWN = (1<<2), ///< Button is down
|
||||
KEY_STATUS_PRESSED = (1<<3), ///< Button pressed this frame
|
||||
};
|
||||
|
||||
/// Access single instance of this class
|
||||
static InputKBWin32& Get() { return s_staticInstance; }
|
||||
|
||||
/// Destructor
|
||||
virtual ~InputKBWin32();
|
||||
|
||||
/// Initialize. Call before use.
|
||||
void Init();
|
||||
|
||||
/// Call each frame.
|
||||
void Update();
|
||||
|
||||
/// What is the status of a key. Returns one of the KEY_STATUS_* enums.
|
||||
inline int GetKeyStatus(int a_keyIndex)
|
||||
{
|
||||
GM_ASSERT((a_keyIndex >=0) && (a_keyIndex < MAX_KEYS));
|
||||
return m_keyStatus[a_keyIndex];
|
||||
}
|
||||
|
||||
/// Was key pressed this frame? (Non-zero if true)
|
||||
inline int IsKeyPressed(int a_keyIndex)
|
||||
{
|
||||
GM_ASSERT((a_keyIndex >= 0) && (a_keyIndex < MAX_KEYS));
|
||||
return (m_keyStatus[a_keyIndex] & KEY_STATUS_PRESSED);
|
||||
}
|
||||
|
||||
/// Is key down this frame? (Non-zero if true)
|
||||
inline int IsKeyDown(int a_keyIndex)
|
||||
{
|
||||
GM_ASSERT((a_keyIndex >= 0) && (a_keyIndex < MAX_KEYS));
|
||||
return (m_keyStatus[a_keyIndex] & KEY_STATUS_DOWN);
|
||||
}
|
||||
|
||||
/// Was key released this frame? (Non-zero if true)
|
||||
inline int IsKeyRelesed(int a_keyIndex)
|
||||
{
|
||||
GM_ASSERT((a_keyIndex >= 0) && (a_keyIndex < MAX_KEYS));
|
||||
return (m_keyStatus[a_keyIndex] & KEY_STATUS_RELEASED);
|
||||
}
|
||||
|
||||
/// Is key up this frame? (Non-zero if true)
|
||||
inline int IsKeyUp(int a_keyIndex)
|
||||
{
|
||||
GM_ASSERT((a_keyIndex >= 0) && (a_keyIndex < MAX_KEYS));
|
||||
return (m_keyStatus[a_keyIndex] & KEY_STATUS_UP);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/// Constructor, non-public to prevent multiple instances
|
||||
InputKBWin32();
|
||||
|
||||
char m_keyDownBuffer[2][MAX_KEYS]; ///< Store current and last frame snapshot
|
||||
int m_keyDownBufferIndex; ///< Index to swap buffers for current and last frame
|
||||
int m_keyStatus[MAX_KEYS]; ///< Status of keys for this frame, persists until updated.
|
||||
|
||||
static InputKBWin32 s_staticInstance; ///< Single instance of this class
|
||||
};
|
||||
|
||||
|
||||
#endif //INPUTKBWIN32_H
|
||||
@@ -0,0 +1,356 @@
|
||||
// See Copyright Notice in gmMachine.h
|
||||
|
||||
#include "NetClient.h"
|
||||
#include <windows.h>
|
||||
#include <process.h> // Requires Multi threaded library for _beginthread and _endthread
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <conio.h>
|
||||
#include <winsock.h> // Requires Ws2_32.lib
|
||||
#include <math.h>
|
||||
|
||||
#undef SendMessage // stupid windows
|
||||
|
||||
// These two are for MSVS 2005 security consciousness until safe std lib funcs are available
|
||||
#pragma warning(disable : 4996) // Deprecated functions
|
||||
#define _CRT_SECURE_NO_DEPRECATE // Allow old unsecure standard library functions, Disable some 'warning C4996 - function was deprecated'
|
||||
|
||||
|
||||
struct nPacket
|
||||
{
|
||||
int id; // id == 0x4fe27d9a
|
||||
int len;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// QUEUE
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct nQueueNode
|
||||
{
|
||||
char * m_buffer;
|
||||
int m_len;
|
||||
nQueueNode * m_next;
|
||||
};
|
||||
|
||||
class nQueue
|
||||
{
|
||||
public:
|
||||
nQueue()
|
||||
{
|
||||
m_queue = NULL;
|
||||
m_lastDeQueue = NULL;
|
||||
m_mutex = CreateMutex(NULL, FALSE, NULL);
|
||||
}
|
||||
|
||||
~nQueue()
|
||||
{
|
||||
WaitForSingleObject(m_mutex, INFINITE);
|
||||
|
||||
int a;
|
||||
while(DeQueue(a));
|
||||
DeQueue(a);
|
||||
|
||||
ReleaseMutex(m_mutex);
|
||||
|
||||
// destroy mutex... todo
|
||||
}
|
||||
|
||||
bool EnQueue(const char * a_buffer, int a_len)
|
||||
{
|
||||
WaitForSingleObject(m_mutex, INFINITE);
|
||||
|
||||
nQueueNode * node = new nQueueNode;
|
||||
node->m_len = a_len;
|
||||
node->m_buffer = new char[a_len];
|
||||
memcpy(node->m_buffer, a_buffer, a_len);
|
||||
node->m_next = NULL;
|
||||
|
||||
// add to end of list
|
||||
nQueueNode ** n = &m_queue;
|
||||
while(*n) n = &(*n)->m_next;
|
||||
*n = node;
|
||||
|
||||
ReleaseMutex(m_mutex);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const char * DeQueue(int &a_len)
|
||||
{
|
||||
const char * ret = NULL;
|
||||
|
||||
WaitForSingleObject(m_mutex, INFINITE);
|
||||
|
||||
if(m_lastDeQueue)
|
||||
{
|
||||
delete[] m_lastDeQueue->m_buffer;
|
||||
delete m_lastDeQueue;
|
||||
m_lastDeQueue = NULL;
|
||||
}
|
||||
|
||||
if(m_queue)
|
||||
{
|
||||
m_lastDeQueue = m_queue;
|
||||
m_queue = m_queue->m_next;
|
||||
a_len = m_lastDeQueue->m_len;
|
||||
ret = m_lastDeQueue->m_buffer;
|
||||
}
|
||||
|
||||
ReleaseMutex(m_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool IsEmpty() { return (m_queue == NULL); }
|
||||
|
||||
private:
|
||||
|
||||
HANDLE m_mutex;
|
||||
|
||||
nQueueNode * m_lastDeQueue;
|
||||
nQueueNode * m_queue;
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CLIENT
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
struct nClientData
|
||||
{
|
||||
SOCKET client;
|
||||
nQueue messages;
|
||||
CRITICAL_SECTION criticalSection;
|
||||
bool threadAlive;
|
||||
};
|
||||
|
||||
|
||||
|
||||
nClient::nClient()
|
||||
{
|
||||
nClientData * cd = new nClientData;
|
||||
cd->threadAlive = false;
|
||||
cd->client = INVALID_SOCKET;
|
||||
InitializeCriticalSection(&cd->criticalSection);
|
||||
m_data = cd;
|
||||
}
|
||||
|
||||
|
||||
|
||||
nClient::~nClient()
|
||||
{
|
||||
Close();
|
||||
nClientData * cd = (nClientData *) m_data;
|
||||
DeleteCriticalSection(&cd->criticalSection);
|
||||
delete cd;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void nClient::Close()
|
||||
{
|
||||
nClientData * cd = (nClientData *) m_data;
|
||||
EnterCriticalSection(&cd->criticalSection);
|
||||
|
||||
if(cd->client != INVALID_SOCKET)
|
||||
{
|
||||
closesocket(cd->client);
|
||||
cd->client = INVALID_SOCKET;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&cd->criticalSection);
|
||||
|
||||
// wait for the thread to die.
|
||||
while(cd->threadAlive)
|
||||
{
|
||||
_sleep(0);
|
||||
}
|
||||
|
||||
WSACleanup();
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool nClient::IsConnected()
|
||||
{
|
||||
bool result = false;
|
||||
nClientData * cd = (nClientData *) m_data;
|
||||
EnterCriticalSection(&cd->criticalSection);
|
||||
if(cd->client != INVALID_SOCKET)
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
LeaveCriticalSection(&cd->criticalSection);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool nClient::SendMessage(const char * a_buffer, int a_len)
|
||||
{
|
||||
bool res = false;
|
||||
nClientData * cd = (nClientData *) m_data;
|
||||
nPacket packet;
|
||||
packet.id = 0x4fe27d9a;
|
||||
packet.len = a_len;
|
||||
|
||||
EnterCriticalSection(&cd->criticalSection);
|
||||
if(cd->client != INVALID_SOCKET)
|
||||
{
|
||||
send(cd->client, (const char *) &packet, sizeof(nPacket), 0);
|
||||
send(cd->client, (const char *) a_buffer, a_len, 0);
|
||||
res = true;
|
||||
}
|
||||
LeaveCriticalSection(&cd->criticalSection);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char * nClient::PumpMessage(int &a_len)
|
||||
{
|
||||
nClientData * cd = (nClientData *) m_data;
|
||||
const char * buffer = cd->messages.DeQueue(a_len);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void nClientThread(void * param)
|
||||
{
|
||||
nClientData * cd = (nClientData *) param;
|
||||
EnterCriticalSection(&cd->criticalSection);
|
||||
cd->threadAlive = true;
|
||||
SOCKET client = cd->client;
|
||||
LeaveCriticalSection(&cd->criticalSection);
|
||||
|
||||
char * dbuffer = NULL;
|
||||
char buffer[4096];
|
||||
char * sbp;
|
||||
int state = 0; // 0 searching for packet, 1 getting message
|
||||
int need = sizeof(nPacket);
|
||||
|
||||
// packet header
|
||||
nPacket packet;
|
||||
char * dbp = (char *) &packet;
|
||||
|
||||
// packet data
|
||||
int dbufferSize = 0, n;
|
||||
|
||||
// read loop
|
||||
for(;;)
|
||||
{
|
||||
// read
|
||||
n = recv(client, buffer, 4096, 0);
|
||||
if(n == SOCKET_ERROR || n == 0) break;
|
||||
sbp = buffer;
|
||||
|
||||
// consume
|
||||
while(n > 0)
|
||||
{
|
||||
int have = (n > need) ? need : n;
|
||||
need -= have;
|
||||
n -= have;
|
||||
memcpy(dbp, sbp, have);
|
||||
sbp += have;
|
||||
dbp += have;
|
||||
|
||||
// can we change state?
|
||||
if(need == 0)
|
||||
{
|
||||
if(state == 0)
|
||||
{
|
||||
if(packet.id != 0x4fe27d9a) goto terror;
|
||||
state = 1;
|
||||
need = packet.len;
|
||||
|
||||
// allocate the dbuffer
|
||||
if(need > dbufferSize)
|
||||
{
|
||||
if(dbuffer) { delete[] dbuffer; }
|
||||
dbufferSize = need + 512;
|
||||
dbuffer = new char[dbufferSize];
|
||||
}
|
||||
dbp = dbuffer;
|
||||
}
|
||||
else if(state == 1)
|
||||
{
|
||||
cd->messages.EnQueue(dbuffer, packet.len);
|
||||
dbp = (char *) &packet;
|
||||
need = sizeof(nPacket);
|
||||
state = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
terror:
|
||||
|
||||
if(dbuffer) { delete[] dbuffer; }
|
||||
|
||||
EnterCriticalSection(&cd->criticalSection);
|
||||
cd->threadAlive = false;
|
||||
LeaveCriticalSection(&cd->criticalSection);
|
||||
|
||||
_endthread();
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool nClient::Connect(const char * a_server, short a_port)
|
||||
{
|
||||
WSADATA wsaData;
|
||||
struct hostent *hp;
|
||||
unsigned int addr;
|
||||
struct sockaddr_in server;
|
||||
|
||||
int wsaret=WSAStartup(0x101,&wsaData);
|
||||
if(wsaret)
|
||||
return false;
|
||||
|
||||
SOCKET conn;
|
||||
|
||||
conn = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
|
||||
if(conn==INVALID_SOCKET)
|
||||
return false;
|
||||
|
||||
addr=inet_addr(a_server);
|
||||
hp=gethostbyaddr((char*)&addr,sizeof(addr),AF_INET);
|
||||
|
||||
if(hp==NULL)
|
||||
{
|
||||
closesocket(conn);
|
||||
return false;
|
||||
}
|
||||
|
||||
server.sin_addr.s_addr=*((unsigned long*)hp->h_addr);
|
||||
server.sin_family=AF_INET;
|
||||
server.sin_port=htons((u_short) a_port);
|
||||
|
||||
if(connect(conn,(struct sockaddr*)&server,sizeof(server)))
|
||||
{
|
||||
closesocket(conn);
|
||||
return false;
|
||||
}
|
||||
|
||||
nClientData * cd = (nClientData *) m_data;
|
||||
EnterCriticalSection(&cd->criticalSection);
|
||||
cd->client = conn;
|
||||
LeaveCriticalSection(&cd->criticalSection);
|
||||
|
||||
_beginthread(nClientThread, 0, cd);
|
||||
_sleep(0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef _NETCLIENT_H_
|
||||
#define _NETCLIENT_H_
|
||||
|
||||
// See Copyright Notice in gmMachine.h
|
||||
|
||||
#undef SendMessage // windows clash
|
||||
|
||||
//
|
||||
// nClient
|
||||
//
|
||||
class nClient
|
||||
{
|
||||
public:
|
||||
nClient();
|
||||
~nClient();
|
||||
|
||||
bool Connect(const char * a_server, short a_port);
|
||||
void Close();
|
||||
bool IsConnected();
|
||||
|
||||
bool SendMessage(const char * a_buffer, int a_len);
|
||||
const char * PumpMessage(int &a_len);
|
||||
|
||||
private:
|
||||
|
||||
void * m_data;
|
||||
};
|
||||
|
||||
|
||||
#endif //_NETCLIENT_H_
|
||||
@@ -0,0 +1,10 @@
|
||||
This example is simply one way to implement 'Game Objects'. The example is a work in
|
||||
progress, and is included because some of the code may provide useful to look at.
|
||||
|
||||
|
||||
TODO
|
||||
o make 'triggers' and 'units'
|
||||
o make IsUnitInSquare function to clip movement
|
||||
o use states for units to be 'player' 'following' 'mental'
|
||||
o make triggers that change unit color and triggers that create mental state if not player
|
||||
o highlight player by color and allow player to cycle through units to control
|
||||
@@ -0,0 +1,326 @@
|
||||
//
|
||||
// ScriptObj.cpp
|
||||
//
|
||||
|
||||
#include "gmCall.h"
|
||||
#include "ScriptObj.h"
|
||||
#include "ScriptSys.h"
|
||||
#include "GameObj.h"
|
||||
|
||||
|
||||
// Init statics and constants
|
||||
gmType ScriptObj::GMTYPE_GAMEOBJ = -1;
|
||||
|
||||
|
||||
ScriptObj::ScriptObj(GameObj* a_gameObj)
|
||||
{
|
||||
GM_ASSERT(ScriptSys::Get());
|
||||
|
||||
m_userObject = NULL; // A user object will be created when it is first used, and shared by all script variables.
|
||||
m_gameObj = a_gameObj;
|
||||
m_tableObject = ScriptSys::Get()->GetMachine()->AllocTableObject();
|
||||
|
||||
ScriptSys::Get()->GetMachine()->AddCPPOwnedGMObject(m_tableObject);
|
||||
}
|
||||
|
||||
|
||||
ScriptObj::~ScriptObj()
|
||||
{
|
||||
// Stop related threads
|
||||
KillThreads();
|
||||
|
||||
if(m_userObject)
|
||||
{
|
||||
// Nullify script link to C object
|
||||
m_userObject->m_user = NULL;
|
||||
}
|
||||
|
||||
// Destruct the gmObjects
|
||||
#if GM_USE_INCGC
|
||||
// Do nothing, it will be collected later, just nullify all reference to it
|
||||
#else
|
||||
if(m_userObject)
|
||||
{
|
||||
m_userObject->Destruct(ScriptSys::Get()->GetMachine());
|
||||
}
|
||||
m_tableObject->Destruct(ScriptSys::Get()->GetMachine());
|
||||
#endif
|
||||
|
||||
// Remove object from the list of all objects
|
||||
ScriptSys::Get()->GetMachine()->RemoveCPPOwnedGMObject(m_tableObject);
|
||||
if( m_userObject )
|
||||
{
|
||||
ScriptSys::Get()->GetMachine()->RemoveCPPOwnedGMObject(m_userObject);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
gmUserObject* ScriptObj::GetUserObject()
|
||||
{
|
||||
if(!m_userObject)
|
||||
{
|
||||
m_userObject = ScriptSys::Get()->GetMachine()->AllocUserObject(this, GMTYPE_GAMEOBJ);
|
||||
ScriptSys::Get()->GetMachine()->AddCPPOwnedGMObject(m_userObject);
|
||||
}
|
||||
|
||||
return m_userObject;
|
||||
}
|
||||
|
||||
|
||||
void ScriptObj::KillThreads()
|
||||
{
|
||||
for(unsigned int tIndex=0; tIndex<m_threads.GetSize(); ++tIndex)
|
||||
{
|
||||
ScriptSys::Get()->RemoveThreadIdButDontTouchGameObj(m_threads[tIndex]);
|
||||
ScriptSys::Get()->GetMachine()->KillThread(m_threads[tIndex]);
|
||||
}
|
||||
m_threads.Reset();
|
||||
}
|
||||
|
||||
|
||||
void ScriptObj::ExecuteStringOnThis(const char* a_string)
|
||||
{
|
||||
gmMachine* machine = ScriptSys::Get()->GetMachine();
|
||||
gmVariable thisVar;
|
||||
thisVar.SetUser(GetUserObject());
|
||||
int threadId = GM_INVALID_THREAD;
|
||||
|
||||
int errors = machine->ExecuteString(a_string, &threadId, true, NULL, &thisVar);
|
||||
if(errors)
|
||||
{
|
||||
bool first = true;
|
||||
const char * message;
|
||||
while((message = machine->GetLog().GetEntry(first)))
|
||||
{
|
||||
ScriptSys::Get()->LogError("%s\n", message);
|
||||
}
|
||||
machine->GetLog().Reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
ScriptSys::Get()->AssociateThreadIdWithGameObj(threadId, *GetGameObj());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool ScriptObj::ExecuteGlobalFunctionOnThis(const char* a_functionName)
|
||||
{
|
||||
gmVariable thisVar;
|
||||
thisVar.SetUser(GetUserObject());
|
||||
|
||||
gmCall call;
|
||||
if(call.BeginGlobalFunction(ScriptSys::Get()->GetMachine(), a_functionName, thisVar, false))
|
||||
{
|
||||
call.End();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void ScriptObj::SetMemberInt(const char* a_memberName, int a_int)
|
||||
{
|
||||
ScriptSys::Get()->SetTableInt(a_memberName, a_int, m_tableObject);
|
||||
}
|
||||
|
||||
|
||||
void ScriptObj::SetMemberFloat(const char* a_memberName, float a_float)
|
||||
{
|
||||
ScriptSys::Get()->SetTableFloat(a_memberName, a_float, m_tableObject);
|
||||
}
|
||||
|
||||
|
||||
void ScriptObj::SetMemberString(const char* a_memberName, const char* a_string, int a_strLength)
|
||||
{
|
||||
ScriptSys::Get()->SetTableString(a_memberName, a_string, a_strLength, m_tableObject);
|
||||
}
|
||||
|
||||
|
||||
void ScriptObj::SetMemberGameObj(const char* a_memberName, GameObj* a_gameObj)
|
||||
{
|
||||
ScriptSys::Get()->SetTableGameObj(a_memberName, a_gameObj, m_tableObject);
|
||||
}
|
||||
|
||||
|
||||
gmTableObject* ScriptObj::SetMemberTable(const char* a_memberName)
|
||||
{
|
||||
return ScriptSys::Get()->SetTableTable(a_memberName, m_tableObject);
|
||||
}
|
||||
|
||||
|
||||
bool ScriptObj::GetMemberInt(const char* a_memberName, int& a_int)
|
||||
{
|
||||
return ScriptSys::Get()->GetTableInt(a_memberName, a_int, m_tableObject);
|
||||
}
|
||||
|
||||
|
||||
bool ScriptObj::GetMemberFloat(const char* a_memberName, float& a_float)
|
||||
{
|
||||
return ScriptSys::Get()->GetTableFloat(a_memberName, a_float, m_tableObject);
|
||||
}
|
||||
|
||||
|
||||
bool ScriptObj::GetMemberString(const char* a_memberName, String& a_string)
|
||||
{
|
||||
return ScriptSys::Get()->GetTableString(a_memberName, a_string, m_tableObject);
|
||||
}
|
||||
|
||||
|
||||
bool ScriptObj::GetMemberGameObj(const char* a_memberName, GameObj*& a_gameObj)
|
||||
{
|
||||
return ScriptSys::Get()->GetTableGameObj(a_memberName, a_gameObj, m_tableObject);
|
||||
}
|
||||
|
||||
|
||||
bool ScriptObj::GetMemberTable(const char* a_memberName, gmTableObject*& a_retTable)
|
||||
{
|
||||
return ScriptSys::Get()->GetTableTable(a_memberName, a_retTable, m_tableObject);
|
||||
}
|
||||
|
||||
|
||||
void GM_CDECL ScriptObj::GameObjCallback_AsString(gmUserObject * a_object, char* a_buffer, int a_bufferLen)
|
||||
{
|
||||
char mixBuffer[128];
|
||||
|
||||
ScriptObj* scriptObj = (ScriptObj*)a_object->m_user;
|
||||
GameObj* gameObjPtr = NULL;
|
||||
|
||||
if(scriptObj)
|
||||
{
|
||||
gameObjPtr = scriptObj->GetGameObj();
|
||||
}
|
||||
|
||||
sprintf(mixBuffer,"CPtr: %x", gameObjPtr);
|
||||
|
||||
int mixLength = strlen(mixBuffer);
|
||||
int useLength = gmMin(mixLength, a_bufferLen-1);
|
||||
GM_ASSERT(useLength > 0);
|
||||
strncpy(a_buffer, mixBuffer, useLength);
|
||||
a_buffer[useLength] = 0;
|
||||
}
|
||||
|
||||
|
||||
#if GM_USE_INCGC
|
||||
|
||||
bool GM_CDECL ScriptObj::GameObjCallback_GCTrace(gmMachine * a_machine, gmUserObject* a_object, gmGarbageCollector* a_gc, const int a_workRemaining, int& a_workDone)
|
||||
{
|
||||
GM_ASSERT(a_object->m_userType == GMTYPE_GAMEOBJ);
|
||||
ScriptObj* scriptObj = (ScriptObj*)a_object->m_user;
|
||||
|
||||
if(scriptObj)
|
||||
{
|
||||
a_gc->GetNextObject(scriptObj->GetTableObject());
|
||||
}
|
||||
a_workDone +=2;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void GM_CDECL ScriptObj::GameObjCallback_GCDestruct(gmMachine * a_machine, gmUserObject * a_object)
|
||||
{
|
||||
GM_ASSERT(a_object->m_userType == GMTYPE_GAMEOBJ);
|
||||
ScriptObj* scriptObj = (ScriptObj*)a_object->m_user;
|
||||
|
||||
if(scriptObj)
|
||||
{
|
||||
scriptObj->m_userObject = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#else //GM_USE_INCGC
|
||||
|
||||
void GM_CDECL ScriptObj::GameObjCallback_GCMark(gmMachine * a_machine, gmUserObject * a_object, gmuint32 a_mark)
|
||||
{
|
||||
GM_ASSERT(a_object->m_userType == GMTYPE_GAMEOBJ);
|
||||
ScriptObj* scriptObj = (ScriptObj*)a_object->m_user;
|
||||
|
||||
if(scriptObj)
|
||||
{
|
||||
if(scriptObj->GetTableObject()->NeedsMark(a_mark))
|
||||
{
|
||||
scriptObj->GetTableObject()->Mark(a_machine, a_mark);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GM_CDECL ScriptObj::GameObjCallback_GCCollect(gmMachine * a_machine, gmUserObject * a_object, gmuint32 a_mark)
|
||||
{
|
||||
GM_ASSERT(a_object->m_userType == GMTYPE_GAMEOBJ);
|
||||
ScriptObj* scriptObj = (ScriptObj*)a_object->m_user;
|
||||
|
||||
if(scriptObj)
|
||||
{
|
||||
scriptObj->m_userObject = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif //GM_USE_INCGC
|
||||
|
||||
|
||||
// NOTE: If you wanted to enable other dot operator behavior
|
||||
// here is the place to do it, in the GetDot and SetDot operators.
|
||||
// This example merely uses the gmTable embedded in the GameObj
|
||||
// to allow script functions and data to be members of this object type.
|
||||
// GameObj also registers 'type' functions that are accessed via the
|
||||
// dot operator.
|
||||
|
||||
|
||||
void GM_CDECL ScriptObj::GameObj_GetDot(gmThread * a_thread, gmVariable * a_operands)
|
||||
{
|
||||
//O_GETDOT = 0, // object, "member" (tos is a_operands + 2)
|
||||
GM_ASSERT(a_operands[0].m_type == GMTYPE_GAMEOBJ);
|
||||
|
||||
gmUserObject* userObj = (gmUserObject*) GM_OBJECT(a_operands[0].m_value.m_ref);
|
||||
ScriptObj* scriptObj = (ScriptObj*)userObj->m_user;
|
||||
|
||||
if(!scriptObj)
|
||||
{
|
||||
a_operands[0].Nullify();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
a_operands[0] = scriptObj->GetTableObject()->Get(a_operands[1]);
|
||||
}
|
||||
|
||||
|
||||
void GM_CDECL ScriptObj::GameObj_SetDot(gmThread * a_thread, gmVariable * a_operands)
|
||||
{
|
||||
//O_SETDOT, // object, value, "member" (tos is a_operands + 3)
|
||||
GM_ASSERT(a_operands[0].m_type == GMTYPE_GAMEOBJ);
|
||||
|
||||
gmUserObject* userObj = (gmUserObject*) GM_OBJECT(a_operands[0].m_value.m_ref);
|
||||
ScriptObj* scriptObj = (ScriptObj*)userObj->m_user;
|
||||
|
||||
if(scriptObj)
|
||||
{
|
||||
scriptObj->GetTableObject()->Set(a_thread->GetMachine(), a_operands[2], a_operands[1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ScriptObj::RegisterScriptBindings()
|
||||
{
|
||||
gmMachine* machine = ScriptSys::Get()->GetMachine();
|
||||
|
||||
GM_ASSERT(machine);
|
||||
|
||||
// Register new user type
|
||||
GMTYPE_GAMEOBJ = machine->CreateUserType("GameObj");
|
||||
// Register garbage collection for our new type
|
||||
#if GM_USE_INCGC
|
||||
machine->RegisterUserCallbacks(GMTYPE_GAMEOBJ, GameObjCallback_GCTrace, GameObjCallback_GCDestruct, GameObjCallback_AsString);
|
||||
#else //GM_USE_INCGC
|
||||
machine->RegisterUserCallbacks(GMTYPE_GAMEOBJ, GameObjCallback_GCMark, GameObjCallback_GCCollect, GameObjCallback_AsString);
|
||||
#endif //GM_USE_INCGC
|
||||
// Bind Get dot operator for our type
|
||||
machine->RegisterTypeOperator(GMTYPE_GAMEOBJ, O_GETDOT, NULL, GameObj_GetDot);
|
||||
// Bind Set dot operator for our type
|
||||
machine->RegisterTypeOperator(GMTYPE_GAMEOBJ, O_SETDOT, NULL, GameObj_SetDot);
|
||||
// Bind functions
|
||||
// machine->RegisterLibrary(regFuncList, sizeof(regFuncList) / sizeof(regFuncList[0]));
|
||||
// Bind type functions
|
||||
// machine->RegisterTypeLibrary(GM_GOB, regTypeFuncList, sizeof(regTypeFuncList) / sizeof(regTypeFuncList[0]));
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
#ifndef SCRIPTOBJ_H
|
||||
#define SCRIPTOBJ_H
|
||||
|
||||
//
|
||||
// ScriptObj.h
|
||||
//
|
||||
// Example script interface component for game object
|
||||
//
|
||||
|
||||
#include "gmThread.h"
|
||||
#include "StdStuff.h"
|
||||
|
||||
// Fwd decls
|
||||
class GameObj;
|
||||
|
||||
|
||||
// NOTE: In this implementation, the 'gmUserObject' only exists when the cpp object is used or needed by script.
|
||||
// This implementation also shares that single user object amongst all referencing variables in script.
|
||||
// Because of this, the cpp code does not need to handle the user object as if it were owned by cpp.
|
||||
// The cpp object does however always contain a gmTableObject, and this is owned by cpp as it may not
|
||||
// exist (be referenced) within the script. For this reason, the gmTableObject must be handled as a
|
||||
// cpp owned object to allow correct GC handling.
|
||||
//
|
||||
// An alternate method, would be to always have a gmUserObject and let cpp code own this. This
|
||||
// user object would be the root of its own child objects like the gmTableObject. This method may
|
||||
// be simpler.
|
||||
//
|
||||
|
||||
// Script interface for game objects
|
||||
class ScriptObj
|
||||
{
|
||||
public:
|
||||
|
||||
static gmType GMTYPE_GAMEOBJ; ///< The user type of a game object
|
||||
|
||||
static void RegisterScriptBindings(); ///< Register game object script bindings
|
||||
|
||||
ScriptObj(GameObj* a_gameObj);
|
||||
virtual ~ScriptObj();
|
||||
|
||||
GameObj* GetGameObj() { return m_gameObj; }
|
||||
|
||||
gmTableObject* GetTableObject() { return m_tableObject; }
|
||||
gmUserObject* GetUserObject();
|
||||
|
||||
void AddThreadId(int a_threadId)
|
||||
{
|
||||
m_threads.InsertLast(a_threadId);
|
||||
}
|
||||
|
||||
void RemoveThreadId(int a_threadId)
|
||||
{
|
||||
for(unsigned int tIndex=0; tIndex < m_threads.GetSize(); ++tIndex)
|
||||
{
|
||||
if(m_threads[tIndex] == a_threadId)
|
||||
{
|
||||
m_threads.RemoveSwapLast(tIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Kill all threads running on this object
|
||||
void KillThreads();
|
||||
|
||||
void ExecuteStringOnThis(const char* a_string);
|
||||
|
||||
bool ExecuteGlobalFunctionOnThis(const char* a_functionName);
|
||||
|
||||
void SetMemberInt(const char* a_memberName, int a_int);
|
||||
void SetMemberFloat(const char* a_memberName, float a_float);
|
||||
void SetMemberString(const char* a_memberName, const char* a_string, int a_strLength = -1);
|
||||
void SetMemberGameObj(const char* a_memberName, GameObj* a_gameObj);
|
||||
gmTableObject* SetMemberTable(const char* a_memberName);
|
||||
|
||||
bool GetMemberInt(const char* a_memberName, int& a_int);
|
||||
bool GetMemberFloat(const char* a_memberName, float& a_float);
|
||||
bool GetMemberString(const char* a_memberName, String& a_string);
|
||||
bool GetMemberGameObj(const char* a_memberName, GameObj*& a_gameObj);
|
||||
bool GetMemberTable(const char* a_memberName, gmTableObject*& a_retTable);
|
||||
|
||||
protected:
|
||||
|
||||
static void GM_CDECL GameObjCallback_AsString(gmUserObject * a_object, char* a_buffer, int a_bufferLen);
|
||||
#if GM_USE_INCGC
|
||||
static bool GM_CDECL GameObjCallback_GCTrace(gmMachine * a_machine, gmUserObject* a_object, gmGarbageCollector* a_gc, const int a_workRemaining, int& a_workDone);
|
||||
static void GM_CDECL GameObjCallback_GCDestruct(gmMachine * a_machine, gmUserObject * a_object);
|
||||
#else //GM_USE_INCGC
|
||||
static void GM_CDECL GameObjCallback_GCMark(gmMachine * a_machine, gmUserObject * a_object, gmuint32 a_mark);
|
||||
static void GM_CDECL GameObjCallback_GCCollect(gmMachine * a_machine, gmUserObject * a_object, gmuint32 a_mark);
|
||||
#endif //GM_USE_INCGC
|
||||
static void GM_CDECL GameObj_GetDot(gmThread * a_thread, gmVariable * a_operands);
|
||||
static void GM_CDECL GameObj_SetDot(gmThread * a_thread, gmVariable * a_operands);
|
||||
|
||||
GameObj* m_gameObj; ///< The game object owner of this interface
|
||||
gmUserObject* m_userObject; ///< The script object
|
||||
gmTableObject* m_tableObject; ///< Table functionality for script object members
|
||||
gmArraySimple<int> m_threads; ///< Threads associated with this game object
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
/// \brief Get 'this' as GameObj of TYPE
|
||||
/// Eg. Soldier* obj = GetThisGameObj<Soldier>(a_thread);
|
||||
template<class TYPE>
|
||||
TYPE* GetThisGameObj(gmThread* a_thread)
|
||||
{
|
||||
GM_ASSERT(a_thread->GetThis()->m_type == ScriptObj::GMTYPE_GAMEOBJ); //Paranoid check for type function
|
||||
|
||||
ScriptObj* scriptObj = (ScriptObj*)a_thread->ThisUser();
|
||||
|
||||
CHECK(scriptObj); //Check for null GameObj ptr
|
||||
|
||||
// You can check for valid derived type here
|
||||
|
||||
return static_cast<TYPE*>(scriptObj->GetGameObj());
|
||||
}
|
||||
|
||||
|
||||
/// \brief Get param as GameObj of TYPE
|
||||
/// Eg. Soldier* obj = GetGameObjParam<Soldier>(a_thread, 0);
|
||||
template<class TYPE>
|
||||
TYPE* GetGameObjParam(gmThread* a_thread, int a_paramIndex)
|
||||
{
|
||||
ScriptObj* scriptObj = (ScriptObj*)a_thread->ParamUserCheckType(a_paramIndex, ScriptObj::GMTYPE_GAMEOBJ);
|
||||
|
||||
CHECK(scriptObj); //Check for null GameObj ptr
|
||||
|
||||
// You can check for valid derived type here
|
||||
|
||||
return static_cast<TYPE*>(scriptObj->GetGameObj());
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/// \brief Get 'this' as GameObj of TYPE
|
||||
inline GameObj* GetThisGameObj(gmThread* a_thread)
|
||||
{
|
||||
GM_ASSERT(a_thread->GetThis()->m_type == ScriptObj::GMTYPE_GAMEOBJ); //Paranoid check for type function
|
||||
|
||||
ScriptObj* scriptObj = (ScriptObj*)a_thread->ThisUser();
|
||||
|
||||
if(!scriptObj)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return scriptObj->GetGameObj();
|
||||
}
|
||||
|
||||
|
||||
/// \brief Get param as GameObj of TYPE
|
||||
inline GameObj* GetGameObjParam(gmThread* a_thread, int a_paramIndex)
|
||||
{
|
||||
ScriptObj* scriptObj = (ScriptObj*)a_thread->ParamUserCheckType(a_paramIndex, ScriptObj::GMTYPE_GAMEOBJ);
|
||||
|
||||
if(!scriptObj)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return scriptObj->GetGameObj();
|
||||
}
|
||||
|
||||
|
||||
#endif //SCRIPTOBJ_H
|
||||
@@ -0,0 +1,432 @@
|
||||
//
|
||||
// ScriptSys.cpp
|
||||
//
|
||||
|
||||
#include "gmCall.h"
|
||||
#include "ScriptSys.h"
|
||||
#include "ScriptObj.h"
|
||||
#include "GameObj.h"
|
||||
|
||||
|
||||
// Init statics and constants
|
||||
ScriptSys* ScriptSys::s_instance = NULL;
|
||||
const int ScriptSys::DEBUGGER_DEFAULT_PORT = 49001;
|
||||
const char* ScriptSys::DEBUGGER_DEFAULT_IP = "127.0.0.1"; // localhost
|
||||
|
||||
|
||||
void ScriptSys::Init()
|
||||
{
|
||||
GM_ASSERT( !s_instance ); // Just have one instance for this example
|
||||
|
||||
s_instance = new ScriptSys;
|
||||
|
||||
// Register Game Object type and bindings
|
||||
ScriptObj::RegisterScriptBindings();
|
||||
GameObj::RegisterScriptBindings();
|
||||
}
|
||||
|
||||
|
||||
void ScriptSys::Destroy()
|
||||
{
|
||||
delete s_instance;
|
||||
s_instance = NULL;
|
||||
}
|
||||
|
||||
|
||||
void ScriptSys::DebuggerSendMessage(gmDebugSession * a_session, const void * a_command, int a_len)
|
||||
{
|
||||
nClient * client = (nClient *) a_session->m_user;
|
||||
client->SendMessage((const char *) a_command, a_len);
|
||||
}
|
||||
|
||||
|
||||
const void* ScriptSys::DebuggerPumpMessage(gmDebugSession * a_session, int &a_len)
|
||||
{
|
||||
nClient * client = (nClient *) a_session->m_user;
|
||||
return client->PumpMessage(a_len);
|
||||
}
|
||||
|
||||
|
||||
ScriptSys::ScriptSys()
|
||||
{
|
||||
m_machine = new gmMachine;
|
||||
|
||||
//Set machine callbacks
|
||||
gmMachine::s_machineCallback = ScriptSysCallback_Machine;
|
||||
gmMachine::s_printCallback = ScriptSysCallback_Print;
|
||||
|
||||
// Init debugger
|
||||
gmBindDebugLib(m_machine); // Register debugging library
|
||||
|
||||
m_debuggerIP = DEBUGGER_DEFAULT_IP;
|
||||
m_debuggerPort = DEBUGGER_DEFAULT_PORT;
|
||||
m_debugSession.m_sendMessage = DebuggerSendMessage;
|
||||
m_debugSession.m_pumpMessage = DebuggerPumpMessage;
|
||||
m_debugSession.m_user = &m_debugClient;
|
||||
|
||||
if(m_debugClient.Connect(m_debuggerIP, ((short) m_debuggerPort)))
|
||||
{
|
||||
m_debugSession.Open(m_machine);
|
||||
fprintf(stderr, "Debug session opened"GM_NL);
|
||||
}
|
||||
m_machine->SetDebugMode(true);
|
||||
}
|
||||
|
||||
|
||||
ScriptSys::~ScriptSys()
|
||||
{
|
||||
// End debugger session if any
|
||||
m_debugSession.Close();
|
||||
m_debugClient.Close();
|
||||
|
||||
// For debugging
|
||||
_gmDumpLeaks();
|
||||
|
||||
delete m_machine;
|
||||
}
|
||||
|
||||
|
||||
void __cdecl ScriptSys::LogError(const char *a_str, ...)
|
||||
{
|
||||
// WARNING This is not safe for longer strings, should use non-ansi vsprintnf, string type, or similar.
|
||||
const int MAX_CHARS = 512;
|
||||
char buffer[MAX_CHARS];
|
||||
|
||||
va_list args;
|
||||
va_start(args, a_str);
|
||||
|
||||
vsprintf(buffer, a_str, args);
|
||||
|
||||
va_end(args);
|
||||
|
||||
fprintf(stderr, "ERROR: %s", a_str);
|
||||
}
|
||||
|
||||
|
||||
GameObj* ScriptSys::GetGameObjFromThreadId(int a_threadId)
|
||||
{
|
||||
ScriptObj* scriptObj;
|
||||
|
||||
if(m_mapThreadGameObjs.GetAt(a_threadId, scriptObj))
|
||||
{
|
||||
return scriptObj->GetGameObj();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void ScriptSys::AssociateThreadIdWithGameObj(int a_threadId, GameObj& a_gameObj)
|
||||
{
|
||||
ScriptObj* scriptObj = a_gameObj.GetScriptObj();
|
||||
|
||||
scriptObj->AddThreadId(a_threadId);
|
||||
m_mapThreadGameObjs.SetAt(a_threadId, scriptObj);
|
||||
}
|
||||
|
||||
|
||||
void ScriptSys::DisassociateThreadIdWithGameObj(int a_threadId)
|
||||
{
|
||||
ScriptObj* scriptObj;
|
||||
|
||||
if(m_mapThreadGameObjs.RemoveAt(a_threadId, scriptObj))
|
||||
{
|
||||
scriptObj->RemoveThreadId(a_threadId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ScriptSys::RemoveThreadIdButDontTouchGameObj(int a_threadId)
|
||||
{
|
||||
m_mapThreadGameObjs.RemoveAt(a_threadId);
|
||||
}
|
||||
|
||||
|
||||
void ScriptSys::SetTableNull(const char* a_memberName, gmTableObject* a_table)
|
||||
{
|
||||
GM_ASSERT(a_table);
|
||||
gmTableObject* table = a_table;
|
||||
gmVariable newVar;
|
||||
newVar.Nullify();
|
||||
table->Set(m_machine, a_memberName, newVar);
|
||||
}
|
||||
|
||||
|
||||
void ScriptSys::SetTableInt(const char* a_memberName, int a_int, gmTableObject* a_table)
|
||||
{
|
||||
GM_ASSERT(a_table);
|
||||
gmTableObject* table = a_table;
|
||||
gmVariable newVar;
|
||||
newVar.SetInt(a_int);
|
||||
table->Set(m_machine, a_memberName, newVar);
|
||||
}
|
||||
|
||||
|
||||
void ScriptSys::SetTableFloat(const char* a_memberName, float a_float, gmTableObject* a_table)
|
||||
{
|
||||
GM_ASSERT(a_table);
|
||||
gmTableObject* table = a_table;
|
||||
gmVariable newVar;
|
||||
newVar.SetFloat(a_float);
|
||||
table->Set(m_machine, a_memberName, newVar);
|
||||
}
|
||||
|
||||
|
||||
void ScriptSys::SetTableString(const char* a_memberName, const char* a_string, int a_strLength, gmTableObject* a_table)
|
||||
{
|
||||
GM_ASSERT(a_table);
|
||||
gmTableObject* table = a_table;
|
||||
gmVariable newVar;
|
||||
newVar.SetString(m_machine->AllocStringObject(a_string, a_strLength));
|
||||
table->Set(m_machine, a_memberName, newVar);
|
||||
}
|
||||
|
||||
void ScriptSys::SetTableGameObj(const char* a_memberName, GameObj* a_gameObj, gmTableObject* a_table)
|
||||
{
|
||||
GM_ASSERT(a_table);
|
||||
GM_ASSERT(a_gameObj);
|
||||
gmTableObject* table = a_table;
|
||||
gmVariable newVar;
|
||||
newVar.SetUser(a_gameObj->GetScriptObj()->GetUserObject());
|
||||
table->Set(m_machine, a_memberName, newVar);
|
||||
}
|
||||
|
||||
|
||||
gmTableObject* ScriptSys::SetTableTable(const char* a_memberName, gmTableObject* a_table)
|
||||
{
|
||||
GM_ASSERT(a_table);
|
||||
gmTableObject* table = a_table;
|
||||
gmMachine* machine = m_machine;
|
||||
gmVariable newVar;
|
||||
gmTableObject* newTable = machine->AllocTableObject();
|
||||
newVar.SetTable(newTable);
|
||||
table->Set(machine, a_memberName, newVar);
|
||||
return newTable; //Return the table so we can potentially put things in it
|
||||
}
|
||||
|
||||
|
||||
bool ScriptSys::GetTableInt(const char* a_memberName, int& a_int, gmTableObject* a_table)
|
||||
{
|
||||
GM_ASSERT(a_table);
|
||||
gmTableObject* table = a_table;
|
||||
gmVariable stringName;
|
||||
gmVariable retVar;
|
||||
|
||||
stringName.SetString(m_machine->AllocStringObject(a_memberName));
|
||||
retVar = table->Get(stringName);
|
||||
if(retVar.m_type == GM_INT)
|
||||
{
|
||||
a_int = retVar.m_value.m_int;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool ScriptSys::GetTableFloat(const char* a_memberName, float& a_float, gmTableObject* a_table)
|
||||
{
|
||||
GM_ASSERT(a_table);
|
||||
gmTableObject* table = a_table;
|
||||
gmVariable stringName;
|
||||
gmVariable retVar;
|
||||
|
||||
stringName.SetString(m_machine->AllocStringObject(a_memberName));
|
||||
retVar = table->Get(stringName);
|
||||
if(retVar.m_type == GM_FLOAT)
|
||||
{
|
||||
a_float = retVar.m_value.m_float;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool ScriptSys::GetTableString(const char* a_memberName, String& a_string, gmTableObject* a_table)
|
||||
{
|
||||
GM_ASSERT(a_table);
|
||||
gmTableObject* table = a_table;
|
||||
gmVariable stringName;
|
||||
gmVariable retVar;
|
||||
|
||||
stringName.SetString(m_machine->AllocStringObject(a_memberName));
|
||||
retVar = table->Get(stringName);
|
||||
if(retVar.m_type == GM_STRING)
|
||||
{
|
||||
gmStringObject* stringObj = (gmStringObject*)GM_MOBJECT(m_machine, retVar.m_value.m_ref);
|
||||
a_string = stringObj->GetString();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool ScriptSys::GetTableGameObj(const char* a_memberName, GameObj*& a_gameObj, gmTableObject* a_table)
|
||||
{
|
||||
GM_ASSERT(a_table);
|
||||
gmTableObject* table = a_table;
|
||||
gmVariable stringName;
|
||||
gmVariable retVar;
|
||||
|
||||
stringName.SetString(m_machine->AllocStringObject(a_memberName));
|
||||
retVar = table->Get(stringName);
|
||||
if(retVar.m_type == ScriptObj::GMTYPE_GAMEOBJ)
|
||||
{
|
||||
gmUserObject* userObj = (gmUserObject*)GM_MOBJECT(m_machine, retVar.m_value.m_ref);
|
||||
a_gameObj = ((ScriptObj*)userObj->m_user)->GetGameObj();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool ScriptSys::GetTableTable(const char* a_memberName, gmTableObject*& a_retTable, gmTableObject* a_table)
|
||||
{
|
||||
GM_ASSERT(a_table);
|
||||
gmTableObject* table = a_table;
|
||||
gmVariable stringName;
|
||||
gmVariable retVar;
|
||||
|
||||
stringName.SetString(m_machine->AllocStringObject(a_memberName));
|
||||
retVar = table->Get(stringName);
|
||||
if(retVar.m_type == GM_TABLE)
|
||||
{
|
||||
a_retTable = (gmTableObject*)GM_MOBJECT(m_machine, retVar.m_value.m_ref);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void GM_CDECL ScriptSys::ScriptSysCallback_Print(gmMachine* a_machine, const char* a_string)
|
||||
{
|
||||
printf("%s\n", a_string);
|
||||
}
|
||||
|
||||
|
||||
bool GM_CDECL ScriptSys::ScriptSysCallback_Machine(gmMachine* a_machine, gmMachineCommand a_command, const void* a_context)
|
||||
{
|
||||
switch(a_command)
|
||||
{
|
||||
case MC_THREAD_EXCEPTION:
|
||||
{
|
||||
ScriptSys::Get()->LogAnyMachineErrorMessages();
|
||||
break;
|
||||
}
|
||||
case MC_COLLECT_GARBAGE:
|
||||
{
|
||||
/* // Old code
|
||||
#if GM_USE_INCGC
|
||||
gmGarbageCollector* gc = a_machine->GetGC();
|
||||
|
||||
for(unsigned int objIndex = 0; objIndex<ScriptSys::Get()->m_allScriptObjs.Count(); ++objIndex)
|
||||
{
|
||||
ScriptObj* scriptObj = ScriptSys::Get()->m_allScriptObjs[objIndex];
|
||||
gc->GetNextObject(scriptObj->GetTableObject());
|
||||
}
|
||||
#else //GM_USE_INCGC
|
||||
gmuint32 mark = *(gmuint32*)a_context;
|
||||
|
||||
for(unsigned int objIndex = 0; objIndex<ScriptSys::Get()->m_allScriptObjs.Count(); ++objIndex)
|
||||
{
|
||||
ScriptObj* scriptObj = ScriptSys::Get()->m_allScriptObjs[objIndex];
|
||||
|
||||
if(scriptObj->GetTableObject()->NeedsMark(mark))
|
||||
{
|
||||
scriptObj->GetTableObject()->Mark(a_machine, mark);
|
||||
}
|
||||
}
|
||||
#endif //GM_USE_INCGC
|
||||
*/
|
||||
break;
|
||||
}
|
||||
case MC_THREAD_CREATE: // Called when a thread is created. a_context is the thread.
|
||||
{
|
||||
break;
|
||||
}
|
||||
case MC_THREAD_DESTROY: // Called when a thread is destroyed. a_context is the thread that is about to die
|
||||
{
|
||||
gmThread* thread = (gmThread*)a_context;
|
||||
ScriptSys::Get()->DisassociateThreadIdWithGameObj(thread->GetId());
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool ScriptSys::ExecuteFile(const char* a_fileName)
|
||||
{
|
||||
FILE* scriptFile = NULL;
|
||||
char* fileString = NULL;
|
||||
int fileSize = 0;
|
||||
|
||||
GM_ASSERT(m_machine);
|
||||
|
||||
if( !(scriptFile = fopen(a_fileName, "rb")) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
fseek(scriptFile, 0, SEEK_END);
|
||||
fileSize = ftell(scriptFile);
|
||||
fseek(scriptFile, 0, SEEK_SET);
|
||||
fileString = new char [fileSize+1];
|
||||
fread(fileString, fileSize, 1, scriptFile);
|
||||
fileString[fileSize] = 0; // Terminating null
|
||||
fclose(scriptFile);
|
||||
|
||||
int threadId = GM_INVALID_THREAD;
|
||||
int errors = m_machine->ExecuteString(fileString, &threadId, true, a_fileName);
|
||||
if(errors)
|
||||
{
|
||||
LogAnyMachineErrorMessages();
|
||||
}
|
||||
|
||||
delete [] fileString;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ScriptSys::ExecuteString(const char* a_string)
|
||||
{
|
||||
GM_ASSERT(m_machine);
|
||||
|
||||
int threadId = GM_INVALID_THREAD;
|
||||
int errors = m_machine->ExecuteString(a_string, &threadId, true);
|
||||
if (errors)
|
||||
{
|
||||
LogAnyMachineErrorMessages();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int ScriptSys::Execute(unsigned int a_deltaTimeMS)
|
||||
{
|
||||
int numThreads = m_machine->Execute(a_deltaTimeMS);
|
||||
|
||||
if(m_debugClient.IsConnected())
|
||||
{
|
||||
m_debugSession.Update();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_debugSession.Close();
|
||||
}
|
||||
|
||||
return numThreads;
|
||||
}
|
||||
|
||||
|
||||
void ScriptSys::LogAnyMachineErrorMessages()
|
||||
{
|
||||
bool first = true;
|
||||
const char * message;
|
||||
while((message = m_machine->GetLog().GetEntry(first)))
|
||||
{
|
||||
LogError("%s"GM_NL, message);
|
||||
}
|
||||
m_machine->GetLog().Reset();
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
#ifndef SCRIPTSYS_H
|
||||
#define SCRIPTSYS_H
|
||||
|
||||
//
|
||||
// ScriptSys.h
|
||||
//
|
||||
// Example script system to support scriptable game objects
|
||||
//
|
||||
|
||||
#include "gmThread.h"
|
||||
#include "gmDebug.h"
|
||||
#include "gmArraySimple.h"
|
||||
#include "StdStuff.h"
|
||||
#include "NetClient.h"
|
||||
|
||||
// Fwd decls
|
||||
class GameObj;
|
||||
class ScriptObj;
|
||||
|
||||
// Script system to support and control the virtual machine
|
||||
class ScriptSys
|
||||
{
|
||||
public:
|
||||
|
||||
/// Access this system from anywhere once it has been initialized for convenience
|
||||
static ScriptSys* Get() { return s_instance; }
|
||||
|
||||
ScriptSys();
|
||||
virtual ~ScriptSys();
|
||||
|
||||
/// Get the GM machine
|
||||
gmMachine* GetMachine() { return m_machine; }
|
||||
|
||||
/// Set bindings and Init constant strings
|
||||
static void Init();
|
||||
/// Clean out this structure
|
||||
static void Destroy();
|
||||
|
||||
|
||||
/// Log an error message
|
||||
void __cdecl LogError(const char *a_str, ...);
|
||||
|
||||
/// Log any machine error messages that may be waiting
|
||||
void LogAnyMachineErrorMessages();
|
||||
|
||||
/// Get GameObj that was associated with a thread Id.
|
||||
GameObj* GetGameObjFromThreadId(int a_threadId);
|
||||
|
||||
/// Associate a threadId with a GameObj, logically as a primary thread.
|
||||
void AssociateThreadIdWithGameObj(int a_threadId, GameObj& a_gameObj);
|
||||
/// Disassociate a threadId with a GameObj.
|
||||
void DisassociateThreadIdWithGameObj(int a_threadId);
|
||||
/// Remove the thread Id association, but don't modify the GameObj.
|
||||
/// This can be used internally by GameObj to perform iteration and removal.
|
||||
void RemoveThreadIdButDontTouchGameObj(int a_threadId);
|
||||
|
||||
/// Run a script file
|
||||
bool ExecuteFile(const char* a_fileName);
|
||||
/// Executes a string.
|
||||
bool ExecuteString(const char* a_str);
|
||||
|
||||
/// Update the virtual machine.
|
||||
int Execute(unsigned int a_deltaTimeMS);
|
||||
|
||||
void SetTableNull(const char* a_memberName, gmTableObject* a_table);
|
||||
void SetTableInt(const char* a_memberName, int a_int, gmTableObject* a_table);
|
||||
void SetTableFloat(const char* a_memberName, float a_float, gmTableObject* a_table);
|
||||
void SetTableString(const char* a_memberName, const char* a_string, int a_strLength, gmTableObject* a_table);
|
||||
void SetTableGameObj(const char* a_memberName, GameObj* a_gameObj, gmTableObject* a_table);
|
||||
gmTableObject* SetTableTable(const char* a_memberName, gmTableObject* a_table);
|
||||
|
||||
bool GetTableInt(const char* a_memberName, int& a_int, gmTableObject* a_table);
|
||||
bool GetTableFloat(const char* a_memberName, float& a_float, gmTableObject* a_table);
|
||||
bool GetTableString(const char* a_memberName, String& a_string, gmTableObject* a_table);
|
||||
bool GetTableGameObj(const char* a_memberName, GameObj*& a_gameObj, gmTableObject* a_table);
|
||||
bool GetTableTable(const char* a_memberName, gmTableObject*& a_retTable, gmTableObject* a_table);
|
||||
|
||||
protected:
|
||||
|
||||
/// Machine 'print' binding callback
|
||||
static void GM_CDECL ScriptSysCallback_Print(gmMachine* a_machine, const char* a_string);
|
||||
/// Machine general and exception callback
|
||||
static bool GM_CDECL ScriptSysCallback_Machine(gmMachine* a_machine, gmMachineCommand a_command, const void* a_context);
|
||||
|
||||
/// Debugging support Send a message
|
||||
static void DebuggerSendMessage(gmDebugSession * a_session, const void * a_command, int a_len);
|
||||
/// Debugging support Pump a message
|
||||
static const void* DebuggerPumpMessage(gmDebugSession * a_session, int &a_len);
|
||||
|
||||
gmMachine* m_machine; ///< GM machine instance
|
||||
Map<int, ScriptObj*> m_mapThreadGameObjs; ///< Map script threadId to game object
|
||||
/* // Old code
|
||||
gmArraySimple<ScriptObj*> m_allScriptObjs; ///< All the script objects, for garbage collection handling
|
||||
*/
|
||||
|
||||
nClient m_debugClient; ///< Debugger network client
|
||||
gmDebugSession m_debugSession; ///< Debugger session
|
||||
const char* m_debuggerIP; ///< Debugger IP
|
||||
int m_debuggerPort; ///< Debugger port
|
||||
|
||||
static const int DEBUGGER_DEFAULT_PORT; ///< Debugger port number
|
||||
static const char* DEBUGGER_DEFAULT_IP; ///< Debugger port number
|
||||
static ScriptSys* s_instance; ///< Static instance for convenience
|
||||
};
|
||||
|
||||
|
||||
#endif //SCRIPTSYS_H
|
||||
@@ -0,0 +1,5 @@
|
||||
//
|
||||
// StdStuff.cpp
|
||||
//
|
||||
|
||||
#include "StdStuff.h"
|
||||
@@ -0,0 +1,194 @@
|
||||
#ifndef STDSTUFF_H
|
||||
#define STDSTUFF_H
|
||||
|
||||
//
|
||||
// StdStuff.h
|
||||
//
|
||||
// Merely some containers and standard things you would
|
||||
// find in MFC, STL, or your favourite library/engine.
|
||||
// These were implemented as quickly and minimally as possible
|
||||
// rather than introduce more code or external libraries.
|
||||
//
|
||||
|
||||
#include "gmHash.h"
|
||||
|
||||
// Quick n dirty Map using the available hash table
|
||||
template<class KEY, class VALUE>
|
||||
class Map
|
||||
{
|
||||
public:
|
||||
|
||||
Map()
|
||||
: m_hashTable(1024) // Just an arbitrary number at present
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Map()
|
||||
{
|
||||
m_hashTable.RemoveAndDeleteAll();
|
||||
}
|
||||
|
||||
/// \brief Insert a element associated with a key.
|
||||
/// \param a_key Key to identify data.
|
||||
/// \param a_value Data associated with Key.
|
||||
void SetAt(const KEY& a_key, const VALUE& a_value)
|
||||
{
|
||||
HashNode* node = m_hashTable.Find(a_key);
|
||||
if(node)
|
||||
{
|
||||
node->m_value = a_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
node = new HashNode;
|
||||
node->m_key = a_key;
|
||||
node->m_value = a_value;
|
||||
m_hashTable.Insert(node);
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Find a node in the map.
|
||||
/// \param a_key Key to identiy element.
|
||||
/// \param a_value Found element returned here.
|
||||
/// \return TRUE if found, FALSE if not in map.
|
||||
bool GetAt(const KEY& a_key, VALUE& a_value)
|
||||
{
|
||||
HashNode* node = m_hashTable.Find(a_key);
|
||||
if(node)
|
||||
{
|
||||
a_value = node->m_value;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Remove a node from the map.
|
||||
/// \param a_key Key to identiy element.
|
||||
/// \param a_removedData Found element returned here.
|
||||
/// \return TRUE if found, FALSE if not in map.
|
||||
bool RemoveAt(const KEY& a_key, VALUE& a_removedData)
|
||||
{
|
||||
HashNode* node = m_hashTable.Find(a_key);
|
||||
if(node)
|
||||
{
|
||||
a_removedData = node->m_value;
|
||||
|
||||
m_hashTable.Remove(node);
|
||||
delete node;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Remove a node from the map.
|
||||
/// \param a_key Key to identiy element.
|
||||
/// \return TRUE if found, FALSE if not in map.
|
||||
bool RemoveAt(const KEY& a_key)
|
||||
{
|
||||
HashNode* node = m_hashTable.Find(a_key);
|
||||
if(node)
|
||||
{
|
||||
m_hashTable.Remove(node);
|
||||
delete node;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
struct HashNode : public gmHashNode<KEY, HashNode, HashNode>
|
||||
{
|
||||
VALUE m_value;
|
||||
KEY m_key;
|
||||
|
||||
virtual const KEY& GetKey() const { return m_key; }
|
||||
|
||||
static inline gmuint Hash(const KEY& a_key)
|
||||
{
|
||||
return (unsigned int)a_key;
|
||||
}
|
||||
|
||||
static inline int Compare(const KEY& a_keyA, const KEY& a_keyB)
|
||||
{
|
||||
if(a_keyA < a_keyB)
|
||||
{ return -1; }
|
||||
if(a_keyA > a_keyB)
|
||||
{ return 1; }
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
// Blocking
|
||||
gmHash<KEY, HashNode, HashNode> m_hashTable;
|
||||
|
||||
};
|
||||
|
||||
|
||||
// The most crap string implementation ever
|
||||
class String
|
||||
{
|
||||
public:
|
||||
|
||||
String()
|
||||
{
|
||||
m_buffer = NULL;
|
||||
SetBuffer("");
|
||||
}
|
||||
|
||||
String(const char* a_newString)
|
||||
{
|
||||
m_buffer = NULL;
|
||||
SetBuffer(a_newString);
|
||||
}
|
||||
|
||||
String(const char* a_newString, const int a_newStringLength)
|
||||
{
|
||||
m_buffer = NULL;
|
||||
SetBuffer(a_newString, a_newStringLength);
|
||||
}
|
||||
|
||||
~String()
|
||||
{
|
||||
delete [] m_buffer;
|
||||
}
|
||||
|
||||
operator const char* () const
|
||||
{
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
const char* operator = (const char* a_newString)
|
||||
{
|
||||
SetBuffer(a_newString);
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
const char* operator = (const String& a_newString)
|
||||
{
|
||||
SetBuffer(a_newString);
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void SetBuffer(const char* a_newString, const int a_newStringLength)
|
||||
{
|
||||
delete [] m_buffer;
|
||||
m_buffer = new char [a_newStringLength + 1];
|
||||
memcpy(m_buffer, a_newString, a_newStringLength);
|
||||
m_buffer[a_newStringLength] = 0;
|
||||
}
|
||||
|
||||
void SetBuffer(const char* a_newString)
|
||||
{
|
||||
int newStringLength = strlen(a_newString);
|
||||
SetBuffer(a_newString, newStringLength);
|
||||
}
|
||||
|
||||
char * m_buffer;
|
||||
};
|
||||
|
||||
#endif //STDSTUFF_H
|
||||
@@ -0,0 +1,44 @@
|
||||
// Just a bunch of tests that don't mean anything at present.
|
||||
|
||||
global WhatsMyName = function()
|
||||
{
|
||||
print("m_name = ", .m_name);
|
||||
print("this = ", this);
|
||||
|
||||
if(.IsValid())
|
||||
{
|
||||
.SetPos(23.0f, 56.0f);
|
||||
print("position(", .GetPosX(), ",", .GetPosY(), ")");
|
||||
|
||||
global g_globalObj = this;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
global RunGlobalObject = function ()
|
||||
{
|
||||
g_globalObj:WhatsMyName();
|
||||
};
|
||||
|
||||
|
||||
global ThreadYieldTest = function()
|
||||
{
|
||||
count = 0;
|
||||
while(count < 30)
|
||||
{
|
||||
sleep(0.5f);
|
||||
count += 1;
|
||||
print("count=",count);
|
||||
yield();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Console.SetColor(COLOR_RED, COLOR_BLACK);
|
||||
Console.Print("Red");
|
||||
Console.SetColor(COLOR_GREEN, COLOR_BLACK);
|
||||
Console.Print("Green");
|
||||
Console.Print("\n");
|
||||
Console.SetColor(COLOR_WHITE, COLOR_BLACK);
|
||||
|
||||
print("Script compiled and executed. \n");
|
||||
@@ -0,0 +1,30 @@
|
||||
#include <windows.h>
|
||||
#include "StdStuff.h"
|
||||
#include "App.h"
|
||||
|
||||
// Entry point for Win32 app
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
String test1("hello");
|
||||
test1 = "world";
|
||||
const char* huh = test1;
|
||||
|
||||
App app;
|
||||
|
||||
if(!app.Init())
|
||||
{
|
||||
fprintf(stderr,"Failed App::Init()");
|
||||
return 1;
|
||||
}
|
||||
|
||||
while(app.Update())
|
||||
{
|
||||
}
|
||||
|
||||
app.Destroy();
|
||||
|
||||
printf("App finished, press ENTER to exit.");
|
||||
getchar(); // Wait for key press
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,362 @@
|
||||
# Microsoft Developer Studio Project File - Name="Minimal" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=Minimal - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "Minimal.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "Minimal.mak" CFG="Minimal - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "Minimal - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "Minimal - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName "Perforce Project"
|
||||
# PROP Scc_LocalPath "..\.."
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "Minimal - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /GX /O2 /I "..\..\gm" /I "..\..\platform\win32msvc" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0xc09 /d "NDEBUG"
|
||||
# ADD RSC /l 0xc09 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 winmm.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
|
||||
!ELSEIF "$(CFG)" == "Minimal - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\gm" /I "..\..\platform\win32msvc" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD BASE RSC /l 0xc09 /d "_DEBUG"
|
||||
# ADD RSC /l 0xc09 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 winmm.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "Minimal - Win32 Release"
|
||||
# Name "Minimal - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\main.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "gm"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmArraySimple.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmArraySimple.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmByteCode.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmByteCode.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmByteCodeGen.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmByteCodeGen.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmCodeGen.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmCodeGen.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmCodeGenHooks.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmCodeGenHooks.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmCodeTree.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmCodeTree.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmConfig.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmCrc.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmCrc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmDebug.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmDebug.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmFunctionObject.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmFunctionObject.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmHash.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmHash.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmIncGC.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmIncGC.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmIterator.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmLibHooks.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmLibHooks.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmListDouble.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmListDouble.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmLog.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmLog.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmMachine.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmMachine.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmMachineLib.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmMachineLib.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmMem.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmMem.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmMemChain.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmMemChain.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmMemFixed.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmMemFixed.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmMemFixedSet.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmMemFixedSet.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmOperators.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmOperators.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmParser.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmParser.cpp.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmScanner.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmScanner.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmStream.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmStream.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmStreamBuffer.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmStreamBuffer.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmStringObject.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmStringObject.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmTableObject.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmTableObject.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmThread.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmThread.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmUserObject.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmUserObject.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmUtil.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmUtil.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmVariable.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\gm\gmVariable.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "win32"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\platform\win32msvc\gmConfig_p.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
@@ -0,0 +1,33 @@
|
||||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "Minimal"=.\Minimal.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
begin source code control
|
||||
Perforce Project
|
||||
..\..
|
||||
end source code control
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,78 @@
|
||||
#if 0 // This is trully the smallest app
|
||||
|
||||
#include "gmThread.h" // game monkey script
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
gmMachine machine;
|
||||
machine.ExecuteString("print(`Hello world`);");
|
||||
getchar(); // Keypress before exit
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else // This is a tiny app
|
||||
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h> // multimedia timer (may need winmm.lib)
|
||||
#include "gmThread.h" // game monkey script
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
// Create virtual machine
|
||||
gmMachine* machine = new gmMachine;
|
||||
|
||||
// Get a script from stdin. Some examples:
|
||||
// print("Hello world");
|
||||
// for( i = 0; i < 10; i=i+1 ) { print("i=",i); sleep(1.0); }
|
||||
fprintf(stdout,"Please enter one line of script\n>");
|
||||
const int MAX_SCRIPT_SIZE = 4096;
|
||||
char script[MAX_SCRIPT_SIZE];
|
||||
fgets(script, MAX_SCRIPT_SIZE-1, stdin);
|
||||
|
||||
// Compile the script, but don't run it for now
|
||||
int errors = machine->ExecuteString(script, NULL, false, NULL);
|
||||
// Dump compile time errors to output
|
||||
if(errors)
|
||||
{
|
||||
bool first = true;
|
||||
const char * message;
|
||||
|
||||
while((message = machine->GetLog().GetEntry(first)))
|
||||
{
|
||||
fprintf(stderr, "%s"GM_NL, message);
|
||||
}
|
||||
machine->GetLog().Reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
int deltaTime = 0;
|
||||
int lastTime = timeGetTime();
|
||||
|
||||
// Keep executing script while threads persist
|
||||
while(machine->Execute(deltaTime))
|
||||
{
|
||||
// Update delta time
|
||||
int curTime = timeGetTime();
|
||||
deltaTime = curTime - lastTime;
|
||||
lastTime = curTime;
|
||||
|
||||
// Dump run time errors to output
|
||||
bool first = true;
|
||||
const char * message;
|
||||
while((message = machine->GetLog().GetEntry(first)))
|
||||
{
|
||||
fprintf(stderr, "%s"GM_NL, message);
|
||||
}
|
||||
machine->GetLog().Reset();
|
||||
}
|
||||
}
|
||||
|
||||
delete machine; // Finished with VM
|
||||
|
||||
fprintf(stdout,"Script complete. Press a key to exit.");
|
||||
getchar(); // Keypress before exit
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // Minimal build type
|
||||
Reference in New Issue
Block a user