From fa724913e3511f6f6fbb4754e8a9d6879ed6a587 Mon Sep 17 00:00:00 2001 From: Robert MacGregor Date: Tue, 2 Sep 2014 02:13:03 -0400 Subject: [PATCH] Experimental TCPObject coding; registered in TS as alt* --- .../TSExtension/include/DXAPI/DXAPI.h | 11 +- .../include/DXAPI/GameConnection.h | 17 + .../TSExtension/include/DXAPI/NetConnection.h | 13 + .../TSExtension/include/DXAPI/NetObject.h | 10 + .../TSExtension/include/DXAPI/Player.h | 3 + .../TSExtension/include/DXAPI/Projectile.h | 5 + .../TSExtension/include/DXAPI/ShapeBase.h | 3 + .../TSExtension/include/DXAPI/SimObject.h | 3 +- .../TSExtension/include/DXAPI/TCPObject.h | 14 + .../TSExtension/include/DXConCmds.h | 24 +- .../TSExtension/include/LinkerAPI.h | 110 ++++--- .../TSExtension/source/DXAPI/DXAPI.cpp | 15 - .../source/DXAPI/GameConnection.cpp | 34 ++ .../source/DXAPI/NetConnection.cpp | 8 + .../TSExtension/source/DXAPI/NetObject.cpp | 3 +- .../TSExtension/source/DXAPI/Player.cpp | 3 +- .../TSExtension/source/DXAPI/Projectile.cpp | 19 ++ .../TSExtension/source/DXAPI/ShapeBase.cpp | 3 +- .../TSExtension/source/DXAPI/SimObject.cpp | 28 +- .../TSExtension/source/DXAPI/TCPObject.cpp | 9 + .../TSExtension/source/DXConCmds.cpp | 37 ++- .../TSExtension/source/DXTCPObjects.cpp | 308 ++++++++++++++++++ .../TSExtension/source/LinkerAPI.cpp | 14 +- .../TSExtension/source/dllmain.cpp | 8 + 24 files changed, 587 insertions(+), 115 deletions(-) create mode 100644 Mod Sources/TSExtension/TSExtension/include/DXAPI/GameConnection.h create mode 100644 Mod Sources/TSExtension/TSExtension/include/DXAPI/NetConnection.h create mode 100644 Mod Sources/TSExtension/TSExtension/include/DXAPI/TCPObject.h create mode 100644 Mod Sources/TSExtension/TSExtension/source/DXAPI/GameConnection.cpp create mode 100644 Mod Sources/TSExtension/TSExtension/source/DXAPI/NetConnection.cpp create mode 100644 Mod Sources/TSExtension/TSExtension/source/DXAPI/TCPObject.cpp create mode 100644 Mod Sources/TSExtension/TSExtension/source/DXTCPObjects.cpp diff --git a/Mod Sources/TSExtension/TSExtension/include/DXAPI/DXAPI.h b/Mod Sources/TSExtension/TSExtension/include/DXAPI/DXAPI.h index 154a692..f809a40 100644 --- a/Mod Sources/TSExtension/TSExtension/include/DXAPI/DXAPI.h +++ b/Mod Sources/TSExtension/TSExtension/include/DXAPI/DXAPI.h @@ -27,17 +27,12 @@ #include #include #include +#include +#include +#include namespace DX { //! A typedef referring to some type of unresolved object in the game. typedef void* UnresolvedObject; - - //! Structure representing a static shape in the game. - //typedef struct - //{ - -// } StaticShape; - - void Projectile_explode(Projectile *obj, const Point3F &position, const Point3F &normal, const unsigned int collideType); } // End NameSpace DX \ No newline at end of file diff --git a/Mod Sources/TSExtension/TSExtension/include/DXAPI/GameConnection.h b/Mod Sources/TSExtension/TSExtension/include/DXAPI/GameConnection.h new file mode 100644 index 0000000..9dbfc35 --- /dev/null +++ b/Mod Sources/TSExtension/TSExtension/include/DXAPI/GameConnection.h @@ -0,0 +1,17 @@ +#pragma once + +#include +#include + +#include + +namespace DX +{ + class GameConnection : public NetConnection + { + public: + GameConnection(unsigned int obj); + + ShapeBase getControlObject(void); + }; +} // End NameSpace DX diff --git a/Mod Sources/TSExtension/TSExtension/include/DXAPI/NetConnection.h b/Mod Sources/TSExtension/TSExtension/include/DXAPI/NetConnection.h new file mode 100644 index 0000000..f7ffb9b --- /dev/null +++ b/Mod Sources/TSExtension/TSExtension/include/DXAPI/NetConnection.h @@ -0,0 +1,13 @@ +#pragma once + +#include +#include + +namespace DX +{ + class NetConnection : public SimObject + { + public: + NetConnection(unsigned int obj); + }; +} // End NameSpace DX diff --git a/Mod Sources/TSExtension/TSExtension/include/DXAPI/NetObject.h b/Mod Sources/TSExtension/TSExtension/include/DXAPI/NetObject.h index 05b96d9..f8868eb 100644 --- a/Mod Sources/TSExtension/TSExtension/include/DXAPI/NetObject.h +++ b/Mod Sources/TSExtension/TSExtension/include/DXAPI/NetObject.h @@ -4,9 +4,19 @@ namespace DX { + enum NetFlags + { + IsGhost = 1, + ScopeAlways = 1 << 6, + ScopeLocal = 1 << 7, + Ghostable = 1 << 8 + }; + class NetObject : public SimObject { public: NetObject(unsigned int obj); + + unsigned int &net_flags; }; } // End NameSpace DX diff --git a/Mod Sources/TSExtension/TSExtension/include/DXAPI/Player.h b/Mod Sources/TSExtension/TSExtension/include/DXAPI/Player.h index be033e1..ad49241 100644 --- a/Mod Sources/TSExtension/TSExtension/include/DXAPI/Player.h +++ b/Mod Sources/TSExtension/TSExtension/include/DXAPI/Player.h @@ -22,5 +22,8 @@ namespace DX const bool &is_jumping; //! Player Object Using Toggable Pack bool &is_using_toggledpack; + + //! Player Velocity. + Point3F velocity; }; } // End NameSpace DX diff --git a/Mod Sources/TSExtension/TSExtension/include/DXAPI/Projectile.h b/Mod Sources/TSExtension/TSExtension/include/DXAPI/Projectile.h index 933f20d..222e62d 100644 --- a/Mod Sources/TSExtension/TSExtension/include/DXAPI/Projectile.h +++ b/Mod Sources/TSExtension/TSExtension/include/DXAPI/Projectile.h @@ -1,7 +1,10 @@ #pragma once +#include #include +#include + namespace DX { class Projectile : public GameBase @@ -9,6 +12,8 @@ namespace DX public: Projectile(unsigned int obj); + void explode(const Linker::Point3F &position, const Linker::Point3F &normal, const unsigned int collideType); + //! Velocity. It is constant because modifying it directly breaks the sim. const Point3F velocity; diff --git a/Mod Sources/TSExtension/TSExtension/include/DXAPI/ShapeBase.h b/Mod Sources/TSExtension/TSExtension/include/DXAPI/ShapeBase.h index ccb550e..107d457 100644 --- a/Mod Sources/TSExtension/TSExtension/include/DXAPI/ShapeBase.h +++ b/Mod Sources/TSExtension/TSExtension/include/DXAPI/ShapeBase.h @@ -8,5 +8,8 @@ namespace DX { public: ShapeBase(unsigned int obj); + + //! Heat Level + float &heat_level; }; } // End NameSpace DX \ No newline at end of file diff --git a/Mod Sources/TSExtension/TSExtension/include/DXAPI/SimObject.h b/Mod Sources/TSExtension/TSExtension/include/DXAPI/SimObject.h index 29a8e1f..cbaa611 100644 --- a/Mod Sources/TSExtension/TSExtension/include/DXAPI/SimObject.h +++ b/Mod Sources/TSExtension/TSExtension/include/DXAPI/SimObject.h @@ -8,8 +8,9 @@ namespace DX SimObject(unsigned int obj); void deleteObject(void); + const char *TSCall(const char *name, unsigned int argc, ...); - protected: + const unsigned int &identifier; const unsigned int base_pointer_value; }; } // End NameSpace DX \ No newline at end of file diff --git a/Mod Sources/TSExtension/TSExtension/include/DXAPI/TCPObject.h b/Mod Sources/TSExtension/TSExtension/include/DXAPI/TCPObject.h new file mode 100644 index 0000000..6661c60 --- /dev/null +++ b/Mod Sources/TSExtension/TSExtension/include/DXAPI/TCPObject.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +namespace DX +{ + class TCPObject : public SimObject + { + public: + TCPObject(unsigned int obj); + + unsigned int &state; + }; +} // End NameSpace DX diff --git a/Mod Sources/TSExtension/TSExtension/include/DXConCmds.h b/Mod Sources/TSExtension/TSExtension/include/DXConCmds.h index 5952e35..99b25ff 100644 --- a/Mod Sources/TSExtension/TSExtension/include/DXConCmds.h +++ b/Mod Sources/TSExtension/TSExtension/include/DXConCmds.h @@ -15,19 +15,27 @@ #include // Returns the address of an object in memory -const char* conGetAddress(SimObject *obj, S32 argc, const char *argv[]); +const char* conGetAddress(Linker::SimObject *obj, S32 argc, const char *argv[]); // Player Commands ----------------------------------- -bool conPlayerGetJumpingState(SimObject *obj, S32 argc, const char* argv[]); -bool conPlayerGetJettingState(SimObject *obj, S32 argc, const char* argv[]); +bool conPlayerGetJumpingState(Linker::SimObject *obj, S32 argc, const char* argv[]); +bool conPlayerGetJettingState(Linker::SimObject *obj, S32 argc, const char* argv[]); + +bool conGameConnectionSetHeatLevel(Linker::SimObject *obj, S32 argc, const char *argv[]); // GrenadeProjectile Commands ------------------------ -const char* conGrenadeProjectileGetPosition(SimObject *obj, S32 argc, const char* argv[]); -const char* conGrenadeProjectileGetVelocity(SimObject *obj, S32 argc, const char* argv[]); +const char* conGrenadeProjectileGetPosition(Linker::SimObject *obj, S32 argc, const char* argv[]); +const char* conGrenadeProjectileGetVelocity(Linker::SimObject *obj, S32 argc, const char* argv[]); // Projectile explode ------------------------------- -bool conProjectileExplode(SimObject *obj, S32 argc, const char* argv[]); -bool conProjectileMakeNerf(SimObject *obj, S32 argc, const char* argv[]); +bool conProjectileExplode(Linker::SimObject *obj, S32 argc, const char* argv[]); +bool conProjectileMakeNerf(Linker::SimObject *obj, S32 argc, const char* argv[]); + +// TCPObject Commands ------------------------------- +const char* conTCPObjectConnect(Linker::SimObject *obj, S32 argc, const char *argv[]); +bool conTCPObjectSend(Linker::SimObject *obj, S32 argc, const char *argv[]); +bool conTCPObjectDisconnect(Linker::SimObject *obj, S32 argc, const char *argv[]); // General Commands --------------------------------- -const char* conSprintf(SimObject *obj, S32 argc, const char* argv[]); \ No newline at end of file +const char* conSprintf(Linker::SimObject *obj, S32 argc, const char* argv[]); +bool conTSExtensionUpdate(Linker::SimObject *obj, S32 argc, const char *argv[]); \ No newline at end of file diff --git a/Mod Sources/TSExtension/TSExtension/include/LinkerAPI.h b/Mod Sources/TSExtension/TSExtension/include/LinkerAPI.h index aafe4f9..148259c 100644 --- a/Mod Sources/TSExtension/TSExtension/include/LinkerAPI.h +++ b/Mod Sources/TSExtension/TSExtension/include/LinkerAPI.h @@ -22,74 +22,76 @@ inline dsize_t dStrlen(const char *str) return (dsize_t)strlen(str); } -class Namespace -{ - const char* mName; -}; +//class Namespace +//{ +// const char* mName; +//}; -struct SimObject -{ - SimObject* group; - const char* objectName; //04h: objectName - SimObject* nextNameObject; //8 - SimObject* nextManagerNameObject; //c - SimObject* nextIdObject; //10h: nextIdObject - U32 stuff; //14 - U32 mFlags; //18h - U32 mNotifyList; //actually a pointer - U32 mId; //20h: mId - //more stuff -}; +//class SimIdDictionary +//{ + //enum + //{ + // DefaultTableSize = 4096, + // TableBitMask = 4095 + // }; +// Linker::SimObject *table[DefaultTableSize]; +//}; +//extern SimIdDictionary* gIdDictionary; -class SimIdDictionary +namespace Linker { - enum - { - DefaultTableSize = 4096, - TableBitMask = 4095 - }; - SimObject *table[DefaultTableSize]; -}; -extern SimIdDictionary* gIdDictionary; - -class Point3F -{ - public: - Point3F(F32 *x, F32 *y, F32 *z) + class Point3F { - this->x = x; - this->y = y; - this->z = z; - } + public: + Point3F(F32 *x, F32 *y, F32 *z) + { + this->x = x; + this->y = y; + this->z = z; + } - Point3F(void) + Point3F(void) + { + this->x = 0; + this->y = 0; + this->z = 0; + } + + F32 *x; + F32 *y; + F32 *z; + }; + + struct SimObject { - this->x = 0; - this->y = 0; - this->z = 0; - } - - F32 *x; - F32 *y; - F32 *z; -}; - + SimObject* group; + const char* objectName; //04h: objectName + SimObject* nextNameObject; //8 + SimObject* nextManagerNameObject; //c + SimObject* nextIdObject; //10h: nextIdObject + U32 stuff; //14 + U32 mFlags; //18h + U32 mNotifyList; //actually a pointer + U32 mId; //20h: mId + //more stuff + }; +} //GuiTSCtrl class GuiTSCtrl {}; -void GuiTSCtrl_project(GuiTSCtrl *obj, const Point3F &pt, Point3F *dest); //fake +void GuiTSCtrl_project(GuiTSCtrl *obj, const Linker::Point3F &pt, Linker::Point3F *dest); //fake namespace Sim { - extern SimObject* (*findObject)(U32 id); + extern Linker::SimObject* (*findObject)(U32 id); } //console -typedef const char * (*StringCallback)(SimObject *obj, S32 argc, const char *argv[]); -typedef S32 (*IntCallback)(SimObject *obj, S32 argc, const char *argv[]); -typedef F32 (*FloatCallback)(SimObject *obj, S32 argc, const char *argv[]); -typedef void (*VoidCallback)(SimObject *obj, S32 argc, const char *argv[]); -typedef bool (*BoolCallback)(SimObject *obj, S32 argc, const char *argv[]); +typedef const char * (*StringCallback)(Linker::SimObject *obj, S32 argc, const char *argv[]); +typedef S32 (*IntCallback)(Linker::SimObject *obj, S32 argc, const char *argv[]); +typedef F32 (*FloatCallback)(Linker::SimObject *obj, S32 argc, const char *argv[]); +typedef void (*VoidCallback)(Linker::SimObject *obj, S32 argc, const char *argv[]); +typedef bool (*BoolCallback)(Linker::SimObject *obj, S32 argc, const char *argv[]); //functions @@ -109,7 +111,7 @@ extern void (*errorf)(U32 type, const char* fmt,...); extern const char * (*getVariable)(const char *name); extern const char * (*execute)(S32 argc, const char *argv[]); extern const char * (*executef)(S32 argc, ...); -extern const char * (*executem)(SimObject *object, S32 argc, const char *argv[]); +extern const char * (*executem)(Linker::SimObject *object, S32 argc, const char *argv[]); extern const char * (*evaluate)(const char* string, bool echo, const char *fileName, bool cf); } diff --git a/Mod Sources/TSExtension/TSExtension/source/DXAPI/DXAPI.cpp b/Mod Sources/TSExtension/TSExtension/source/DXAPI/DXAPI.cpp index 8d607d8..6498e5c 100644 --- a/Mod Sources/TSExtension/TSExtension/source/DXAPI/DXAPI.cpp +++ b/Mod Sources/TSExtension/TSExtension/source/DXAPI/DXAPI.cpp @@ -19,20 +19,5 @@ namespace DX { - void Projectile_explode(Projectile *obj, const Point3F &position, const Point3F &normal, const unsigned int collideType) - { - typedef void (__cdecl *explodeFunc)(const Point3F &position, const Point3F &normal, const unsigned int collideType); - static explodeFunc function_call = (explodeFunc)0x62DC30; - __asm - { - push collideType; - push normal; - push position; - mov ecx,obj; - lea eax, function_call; - mov eax, [eax]; - call eax; - } - } } \ No newline at end of file diff --git a/Mod Sources/TSExtension/TSExtension/source/DXAPI/GameConnection.cpp b/Mod Sources/TSExtension/TSExtension/source/DXAPI/GameConnection.cpp new file mode 100644 index 0000000..312a9e0 --- /dev/null +++ b/Mod Sources/TSExtension/TSExtension/source/DXAPI/GameConnection.cpp @@ -0,0 +1,34 @@ +#include + +namespace DX +{ + GameConnection::GameConnection(unsigned int obj) : NetConnection(obj) + { + } + + ShapeBase GameConnection::getControlObject(void) + { + unsigned int result_ptr = 0; + unsigned int my_ptr = this->base_pointer_value; + __asm + { + mov ecx, my_ptr; + add ecx, 3404928; + + test ecx, ecx; + mov edx, ecx; + jz loc_5FDA60_sim; + add edx, 4294967136; + +loc_5FDA60_sim: + mov eax, [edx + 33372]; + test eax, eax; + jnz got_valid_ptr; + +got_valid_ptr: + mov result_ptr, eax; + } + + return ShapeBase(result_ptr); + } +} // End NameSpace DX \ No newline at end of file diff --git a/Mod Sources/TSExtension/TSExtension/source/DXAPI/NetConnection.cpp b/Mod Sources/TSExtension/TSExtension/source/DXAPI/NetConnection.cpp new file mode 100644 index 0000000..5943c89 --- /dev/null +++ b/Mod Sources/TSExtension/TSExtension/source/DXAPI/NetConnection.cpp @@ -0,0 +1,8 @@ +#include + +namespace DX +{ + NetConnection::NetConnection(unsigned int obj) : SimObject(obj) + { + } +} \ No newline at end of file diff --git a/Mod Sources/TSExtension/TSExtension/source/DXAPI/NetObject.cpp b/Mod Sources/TSExtension/TSExtension/source/DXAPI/NetObject.cpp index 5935089..22f5864 100644 --- a/Mod Sources/TSExtension/TSExtension/source/DXAPI/NetObject.cpp +++ b/Mod Sources/TSExtension/TSExtension/source/DXAPI/NetObject.cpp @@ -2,7 +2,8 @@ namespace DX { - NetObject::NetObject(unsigned int obj) : SimObject(obj) + NetObject::NetObject(unsigned int obj) : net_flags(*(unsigned int*)(obj + 64)), + SimObject(obj) { } } \ No newline at end of file diff --git a/Mod Sources/TSExtension/TSExtension/source/DXAPI/Player.cpp b/Mod Sources/TSExtension/TSExtension/source/DXAPI/Player.cpp index 02bf073..c3d9cc8 100644 --- a/Mod Sources/TSExtension/TSExtension/source/DXAPI/Player.cpp +++ b/Mod Sources/TSExtension/TSExtension/source/DXAPI/Player.cpp @@ -6,7 +6,8 @@ namespace DX name(0x00), id(*(unsigned int*)(obj + 32)), is_jetting(*(bool*)(obj + 735)), is_jumping(*(bool*)(obj + 734)), - is_using_toggledpack(*(bool*)(obj + 1172)) + is_using_toggledpack(*(bool*)(obj + 1172)), + velocity(*(float*)(obj + 2392), *(float*)(obj + 2396), *(float*)(obj + 2400)) { } diff --git a/Mod Sources/TSExtension/TSExtension/source/DXAPI/Projectile.cpp b/Mod Sources/TSExtension/TSExtension/source/DXAPI/Projectile.cpp index a3bd7a7..e5cd57b 100644 --- a/Mod Sources/TSExtension/TSExtension/source/DXAPI/Projectile.cpp +++ b/Mod Sources/TSExtension/TSExtension/source/DXAPI/Projectile.cpp @@ -7,4 +7,23 @@ namespace DX GameBase(obj) { } + + void Projectile::explode(const Linker::Point3F &position, const Linker::Point3F &normal, const unsigned int collideType) + { + void *pointer = (void*)this->base_pointer_value; + + typedef void (__cdecl *explodeFunc)(const Linker::Point3F &position, const Linker::Point3F &normal, const unsigned int collideType); + static explodeFunc function_call = (explodeFunc)0x62DC30; + + __asm + { + push collideType; + push normal; + push position; + mov ecx,pointer; + lea eax, function_call; + mov eax, [eax]; + call eax; + } + } } \ No newline at end of file diff --git a/Mod Sources/TSExtension/TSExtension/source/DXAPI/ShapeBase.cpp b/Mod Sources/TSExtension/TSExtension/source/DXAPI/ShapeBase.cpp index 6cc23e1..6b17d7e 100644 --- a/Mod Sources/TSExtension/TSExtension/source/DXAPI/ShapeBase.cpp +++ b/Mod Sources/TSExtension/TSExtension/source/DXAPI/ShapeBase.cpp @@ -2,7 +2,8 @@ namespace DX { - ShapeBase::ShapeBase(unsigned int obj) : GameBase(obj) + ShapeBase::ShapeBase(unsigned int obj) : GameBase(obj), + heat_level(*(float*)(obj + 1972)) { } } \ No newline at end of file diff --git a/Mod Sources/TSExtension/TSExtension/source/DXAPI/SimObject.cpp b/Mod Sources/TSExtension/TSExtension/source/DXAPI/SimObject.cpp index 90f9276..a9e9c7f 100644 --- a/Mod Sources/TSExtension/TSExtension/source/DXAPI/SimObject.cpp +++ b/Mod Sources/TSExtension/TSExtension/source/DXAPI/SimObject.cpp @@ -1,8 +1,13 @@ +#include + #include +#include + namespace DX { - SimObject::SimObject(unsigned int obj) : base_pointer_value(obj) + SimObject::SimObject(unsigned int obj) : identifier(*(unsigned int*)(obj + 32)), + base_pointer_value(obj) { } @@ -11,7 +16,7 @@ namespace DX void *pointer = (void*)this->base_pointer_value; typedef void (__cdecl *deleteObjectFunc)(void); - static deleteObjectFunc function_call = (deleteObjectFunc)0x439DE0; + static deleteObjectFunc function_call = (deleteObjectFunc)0x4268D0; __asm { @@ -21,4 +26,23 @@ namespace DX call eax; } } + + const char *SimObject::TSCall(const char *name, unsigned int argc, ...) + { + char **argv = (char**)malloc(sizeof(char*) * (2 + argc)); + argv[0]= (char*)name; + argv[1] = ""; + + va_list vargs; + va_start(vargs, argc); + + for (unsigned int iteration = 0; iteration < argc; iteration++) + argv[2 + iteration] = va_arg(vargs, char*); + va_end(vargs); + + const char *result = Con::executem((Linker::SimObject*)this->base_pointer_value, 2 + argc, (const char**)argv); + free(argv); + + return result; + } } \ No newline at end of file diff --git a/Mod Sources/TSExtension/TSExtension/source/DXAPI/TCPObject.cpp b/Mod Sources/TSExtension/TSExtension/source/DXAPI/TCPObject.cpp new file mode 100644 index 0000000..cdf6e06 --- /dev/null +++ b/Mod Sources/TSExtension/TSExtension/source/DXAPI/TCPObject.cpp @@ -0,0 +1,9 @@ +#include + +namespace DX +{ + TCPObject::TCPObject(unsigned int obj): state(*(unsigned int*)(obj + 56)), + SimObject(obj) + { + } +} \ No newline at end of file diff --git a/Mod Sources/TSExtension/TSExtension/source/DXConCmds.cpp b/Mod Sources/TSExtension/TSExtension/source/DXConCmds.cpp index 978a908..c5adc2c 100644 --- a/Mod Sources/TSExtension/TSExtension/source/DXConCmds.cpp +++ b/Mod Sources/TSExtension/TSExtension/source/DXConCmds.cpp @@ -5,7 +5,7 @@ #include #include -const char *conGetAddress(SimObject *obj, S32 argc, const char *argv[]) +const char *conGetAddress(Linker::SimObject *obj, S32 argc, const char *argv[]) { // Hmm... char result[256]; @@ -13,39 +13,42 @@ const char *conGetAddress(SimObject *obj, S32 argc, const char *argv[]) return result; } -bool conPlayerGetJumpingState(SimObject *obj, S32 argc, const char* argv[]) +bool conPlayerGetJumpingState(Linker::SimObject *obj, S32 argc, const char* argv[]) { DX::Player operand = DX::Player((unsigned int)obj); return operand.is_jumping; } -bool conPlayerGetJettingState(SimObject *obj, S32 argc, const char* argv[]) +bool conPlayerGetJettingState(Linker::SimObject *obj, S32 argc, const char* argv[]) { DX::Player operand = DX::Player((unsigned int)obj); return operand.is_jetting; } -bool conProjectileExplode(SimObject *obj, S32 argc, const char* argv[]) +bool conGameConnectionSetHeatLevel(Linker::SimObject *obj, S32 argc, const char *argv[]) { - Point3F position; - position.x = 0; - position.y = 0; - position.z = 0; + DX::GameConnection operand = DX::GameConnection((unsigned int)obj); + operand.getControlObject().heat_level = atof(argv[1]); + return true; +} - Point3F normal; - normal.x = 0; - normal.y = 0; - normal.z = 0; +bool conProjectileExplode(Linker::SimObject *obj, S32 argc, const char* argv[]) +{ + Linker::Point3F position(0,0,0); + Linker::Point3F normal(0,0,0); unsigned int collideType = atoi(argv[4]); - //DX::Projectile_explode((DX::Projectile*)obj, position, normal, collideType); + DX::Projectile projectile((unsigned int)obj); + + projectile.net_flags |= DX::NetFlags::ScopeAlways; + projectile.explode(position, normal, collideType); return true; } -bool conProjectileMakeNerf(SimObject *obj, S32 argc, const char* argv[]) +bool conProjectileMakeNerf(Linker::SimObject *obj, S32 argc, const char* argv[]) { DX::GrenadeProjectile grenade = DX::GrenadeProjectile((unsigned int)obj); grenade.hidden = true; @@ -53,7 +56,7 @@ bool conProjectileMakeNerf(SimObject *obj, S32 argc, const char* argv[]) return true; } -const char* conGrenadeProjectileGetPosition(SimObject *obj, S32 argc, const char* argv[]) +const char* conGrenadeProjectileGetPosition(Linker::SimObject *obj, S32 argc, const char* argv[]) { char result[256]; @@ -62,7 +65,7 @@ const char* conGrenadeProjectileGetPosition(SimObject *obj, S32 argc, const char return result; } -const char* conGrenadeProjectileGetVelocity(SimObject *obj, S32 argc, const char* argv[]) +const char* conGrenadeProjectileGetVelocity(Linker::SimObject *obj, S32 argc, const char* argv[]) { char result[256]; @@ -77,7 +80,7 @@ const char* conGrenadeProjectileGetVelocity(SimObject *obj, S32 argc, const char #include #include -const char* conSprintf(SimObject *obj, S32 argc, const char* argv[]) +const char* conSprintf(Linker::SimObject *obj, S32 argc, const char* argv[]) { std::vector input; for (unsigned int i = 2; i < argc; i++) diff --git a/Mod Sources/TSExtension/TSExtension/source/DXTCPObjects.cpp b/Mod Sources/TSExtension/TSExtension/source/DXTCPObjects.cpp new file mode 100644 index 0000000..c9d7d74 --- /dev/null +++ b/Mod Sources/TSExtension/TSExtension/source/DXTCPObjects.cpp @@ -0,0 +1,308 @@ +#include +#include + +#include +#include + +#define TCPOBJECT_MAXCOUNT 256 + +static unsigned int TSEXTENSION_RUNNINGTCPOBJECTCOUNT = 0; +static DX::TCPObject *TSEXTENSION_RUNNINGTCPOBJECTS[TCPOBJECT_MAXCOUNT]; + +inline DX::TCPObject *TCPObject_Find(unsigned int identifier) +{ + // Make sure it's in our list of objects + for (unsigned int iteration = 0; iteration < TSEXTENSION_RUNNINGTCPOBJECTCOUNT; iteration++) + if (TSEXTENSION_RUNNINGTCPOBJECTS[iteration]->identifier == identifier) + return TSEXTENSION_RUNNINGTCPOBJECTS[iteration]; + + return 0x00; +} + +typedef struct +{ + char *target_hostname; + unsigned int target_port; + + unsigned int buffer_length; + char *buffer; + + bool send_retry; + + SOCKET socket; +} ConnectionInformation; + + +inline bool TCPObject_Disconnect(unsigned int identifier) +{ + DX::TCPObject *obj = TCPObject_Find(identifier); + if (!obj) + return false; + + ConnectionInformation *connection = (ConnectionInformation*)obj->state; + + closesocket(connection->socket); + connection->socket = 0; + + // Find us in the array + unsigned int target_index = 0; + for (unsigned int iteration = 0; iteration < TSEXTENSION_RUNNINGTCPOBJECTCOUNT; iteration++) + if (TSEXTENSION_RUNNINGTCPOBJECTS[iteration] == obj) + { + target_index = iteration; + break; + } + + // Fix the array + for (unsigned int iteration = target_index; iteration < TSEXTENSION_RUNNINGTCPOBJECTCOUNT; iteration++) + TSEXTENSION_RUNNINGTCPOBJECTS[iteration] = TSEXTENSION_RUNNINGTCPOBJECTS[iteration + 1]; + TSEXTENSION_RUNNINGTCPOBJECTCOUNT--; + + obj->TSCall("onDisconnect", 0); + return true; +} + +#define TCPOBJECT_BUFFERSIZE 256 +enum TCPObjectEvent +{ + TCPObjectEvent_FailedDNSLookup = 1, + TCPObjectEvent_FailedConnection = 2, + TCPObjectEvent_FailedConnectionNoPort = 3, + TCPObjectEvent_FailedSocketCreation = 4, + TCPObjectEvent_FailedRecv = 5, + TCPObjectEvent_NULL = 6, // Should be the first Good Identifier + TCPObjectEvent_GoodDNSLookup = 7, + TCPObjectEvent_GoodConnection = 8, + TCPObjectEvent_ReceivedData = 9, +}; + +const char* conTCPObjectConnect(Linker::SimObject *obj, S32 argc, const char *argv[]) +{ + DX::TCPObject *operand = new DX::TCPObject((unsigned int)obj); + DX::TCPObject *search_object = TCPObject_Find(operand->identifier); + if (search_object) + { + delete operand; + operand = search_object; + TCPObject_Disconnect(search_object->identifier); + + return false; + } + + // Copy the hostname over + char *desired_hostname = (char*)malloc(strlen(argv[2]) + 1); + memcpy(desired_hostname, argv[2], strlen(argv[2]) + 1); + + // Create the connection info + ConnectionInformation *connection = new ConnectionInformation; + connection->target_hostname = desired_hostname; + connection->buffer = 0x00; + connection->buffer_length = 0; + connection->send_retry = false; + connection->socket = 10; + + // Hack: Store the Ptr to our connection information struct in the old unused state value + operand->state = (unsigned int)connection; + + //ConnectionInformation *connection = (ConnectionInformation*)parameters; + char *target_hostname = strlwr(connection->target_hostname); + + // Is it an IP we got? + bool needs_dns_translation = false; + if (strstr(target_hostname, "ip:")) + target_hostname += 3; // Chop off the 'ip:' segment + else + needs_dns_translation = true; + + // Did we get a port #? + unsigned int desired_port = 0; + char *port_delineator = strstr(target_hostname, ":"); + if (port_delineator) + { + port_delineator[0] = 0x00; // NULL Terminate the IP Segment + port_delineator += 1; + desired_port = atoi(port_delineator); + } + else + { + Con::errorf(0, "No Port"); + operand->TSCall("onConnectFailed", 0); + return "NO_PORT"; + } + + // Perform a DNS Lookup if we need to + if (needs_dns_translation) + { + wchar_t hostname_dns[128]; + std::mbstowcs(hostname_dns, target_hostname, strlen(target_hostname) + 1); + + PDNS_RECORD dns_record; + if (DnsQuery(hostname_dns, DNS_TYPE_A, DNS_QUERY_BYPASS_CACHE, NULL, &dns_record, NULL)) + { + Con::errorf(0, "DNS Resolution Failed"); + operand->TSCall("onDNSFailed", 0); + return "FAILED_DNS"; + } + IN_ADDR result_address; + result_address.S_un.S_addr = dns_record->Data.A.IpAddress; + + // Free the DNS List + DNS_FREE_TYPE freetype; + DnsRecordListFree(dns_record, freetype); + + target_hostname = inet_ntoa(result_address); + } + + SOCKADDR_IN target_host; + target_host.sin_family = AF_INET; + target_host.sin_port = htons(desired_port); + target_host.sin_addr.s_addr = inet_addr(target_hostname); + + Con::errorf(0, "Target %s on port %u SimID %u", target_hostname, desired_port, operand->identifier); + + // Create the Socket + connection->socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (connection->socket == INVALID_SOCKET) + { + Con::errorf(0, "Failed to create Socket!"); + operand->TSCall("onSocketCreationFailed", 0); + return "FAILED_SOCKET_CREATION"; + } + + // Attempt the Connection + if(connect(connection->socket, (SOCKADDR*)&target_host, sizeof(target_host)) != 0) + { + Con::errorf(0, "Failed to connect!"); + operand->TSCall("onConnectFailed", 0); + return "CANNOT_CONNECT"; + } + else + operand->TSCall("onConnected", 0); + + // Set Blocking Mode + u_long imode = 1; + ioctlsocket(connection->socket, FIONBIO, &imode); + + // Stick us in the TCPObject array + TSEXTENSION_RUNNINGTCPOBJECTS[TSEXTENSION_RUNNINGTCPOBJECTCOUNT] = operand; + TSEXTENSION_RUNNINGTCPOBJECTCOUNT++; + + return "unknown_error"; +} + +bool conTCPObjectSend(Linker::SimObject *obj, S32 argc, const char *argv[]) +{ + DX::TCPObject operand((unsigned int)obj); + + Con::errorf(0, "Should Send? - SimID %u", operand.identifier); + //if (!TCPObject_Find(operand.identifier)) + // return false; + + Con::errorf(0, "Sending"); + + ConnectionInformation *connection = (ConnectionInformation*)operand.state; + + // Pause the thread as we're doing an recv in the main thread + if (send(connection->socket, argv[2], strlen(argv[2]), 0) == SOCKET_ERROR) + { + Con::errorf(0, "Failed to send: %u (Socket: %u, SimID: %u)", WSAGetLastError(), connection->socket, operand.identifier); + return false; + } + + return true; +} + +bool conTCPObjectDisconnect(Linker::SimObject *obj, S32 argc, const char *argv[]) +{ + DX::TCPObject operand((unsigned int)obj); + return TCPObject_Disconnect(operand.identifier); +} + +bool conTSExtensionUpdate(Linker::SimObject *obj, S32 argc, const char *argv[]) +{ + // Iterate through any active sockets + static char *character_buffer = (char*)malloc(TCPOBJECT_BUFFERSIZE); + + // List of objects to D/C + //TCPObject_Disconnect + unsigned int disconnected_object_count = 0; + static DX::TCPObject **disconnected_objects = (DX::TCPObject**)malloc(sizeof(DX::TCPObject*) * TCPOBJECT_MAXCOUNT); + + for (unsigned int iteration = 0; iteration < TSEXTENSION_RUNNINGTCPOBJECTCOUNT; iteration++) + { + DX::TCPObject *current_connection = TSEXTENSION_RUNNINGTCPOBJECTS[iteration]; + ConnectionInformation *connection_information = (ConnectionInformation*)current_connection->state; + + // TODO: Kill the TCPObject + if (connection_information->socket == 0) + continue; + + unsigned int data_length = recv(connection_information->socket, character_buffer, TCPOBJECT_BUFFERSIZE, 0); + + int currentError = WSAGetLastError(); + if (currentError != WSAEWOULDBLOCK && currentError != 0) + Con::errorf(0, "Got an error! %u", currentError); + else if (data_length == 0) + { + Con::errorf(0, "Finished receiving?"); + + // Put us on the D/C list + disconnected_objects[disconnected_object_count] = current_connection; + disconnected_object_count++; + + // Stream the data into ::onLine + unsigned int current_start = 0; + for (unsigned int split_iteration = 0; split_iteration < connection_information->buffer_length; split_iteration++) + if (connection_information->buffer[split_iteration] == '\n' || split_iteration == connection_information->buffer_length - 1) + { + unsigned int desired_length = (split_iteration - current_start); + char *current_line = (char*)malloc(desired_length + 1); + memset(current_line, 0x00, desired_length + 1); + memcpy(current_line, &connection_information->buffer[current_start], desired_length); + + current_start = split_iteration + 1; + current_connection->TSCall("onLine", 1, current_line); + free(current_line); + } + + closesocket(connection_information->socket); + connection_information->socket = 0; + free(connection_information->buffer); + } + else if (data_length <= TCPOBJECT_BUFFERSIZE) + { + Con::errorf(0, "Received Data: %u", data_length); + + // If our connection hasn't buffered anything yet + if (connection_information->buffer == 0x00) + { + connection_information->buffer = (char*)malloc(data_length); + memset(connection_information->buffer, 0x00, data_length); + + connection_information->buffer_length = data_length; + memcpy(connection_information->buffer, character_buffer, data_length); + } + else + { + unsigned int new_buffer_length = data_length + connection_information->buffer_length; + char *new_buffer = (char*)malloc(new_buffer_length); + memset(new_buffer, 0x00, new_buffer_length); + + // Copy the two halves + memcpy(new_buffer, connection_information->buffer, connection_information->buffer_length); + memcpy(&new_buffer[connection_information->buffer_length], character_buffer, data_length); + + connection_information->buffer = new_buffer; + connection_information->buffer_length = new_buffer_length; + } + + memset(character_buffer, 0x00, TCPOBJECT_BUFFERSIZE); + } + } + + // Process Disconnect list + for (unsigned int iteration = 0; iteration < disconnected_object_count; iteration++) + TCPObject_Disconnect(disconnected_objects[iteration]->identifier); + + return true; +} \ No newline at end of file diff --git a/Mod Sources/TSExtension/TSExtension/source/LinkerAPI.cpp b/Mod Sources/TSExtension/TSExtension/source/LinkerAPI.cpp index f3f9def..e7409fe 100644 --- a/Mod Sources/TSExtension/TSExtension/source/LinkerAPI.cpp +++ b/Mod Sources/TSExtension/TSExtension/source/LinkerAPI.cpp @@ -1,17 +1,17 @@ #include -SimIdDictionary* gIdDictionary = reinterpret_cast(0x009E9194); +//SimIdDictionary* gIdDictionary = reinterpret_cast(0x009E9194); //439550 namespace Sim { - SimObject* (*findObject)(U32 id) = - (SimObject* (_cdecl *)(U32 id) ) + Linker::SimObject* (*findObject)(U32 id) = + (Linker::SimObject* (_cdecl *)(U32 id) ) 0x439550; } //hackey way to do member functions, .... -void GuiTSCtrl_project(GuiTSCtrl *obj, const Point3F &pt, Point3F *dest) { - typedef void (__cdecl *projFunc)(const Point3F &pt, Point3F *dest); +void GuiTSCtrl_project(GuiTSCtrl *obj, const Linker::Point3F &pt, Linker::Point3F *dest) { + typedef void (__cdecl *projFunc)(const Linker::Point3F &pt, Linker::Point3F *dest); static projFunc p = (projFunc)0x4d0b40; __asm { @@ -55,8 +55,8 @@ const char * (*evaluate)(const char* string, bool echo, const char *fileName, bo (const char * (__cdecl *)(const char* string, bool echo, const char *fileName, bool cf)) 0x426690; -const char * (*executem)(SimObject *object, S32 argc, const char *argv[]) = - (const char * (__cdecl *)(SimObject *object, S32 argc, const char *argv[])) +const char * (*executem)(Linker::SimObject *object, S32 argc, const char *argv[]) = + (const char * (__cdecl *)(Linker::SimObject *object, S32 argc, const char *argv[])) 0x426800; const char * (*getVariable)(const char *name) = diff --git a/Mod Sources/TSExtension/TSExtension/source/dllmain.cpp b/Mod Sources/TSExtension/TSExtension/source/dllmain.cpp index 701a86b..3eb7fcd 100644 --- a/Mod Sources/TSExtension/TSExtension/source/dllmain.cpp +++ b/Mod Sources/TSExtension/TSExtension/source/dllmain.cpp @@ -29,6 +29,7 @@ extern "C" { Con::addMethodB("Player", "isjumping", &conPlayerGetJumpingState,"Returns whether or not the player is jumping", 2, 2); Con::addMethodB("Player", "isjetting", &conPlayerGetJettingState,"Returns whether or not the player is jetting", 2, 2); + Con::addMethodB("GameConnection", "setheat", &conGameConnectionSetHeatLevel,"Sets the heat level", 3, 3); Con::addMethodB("GrenadeProjectile", "explode", &conProjectileExplode,"Explodes the given projectile", 5, 5); Con::addMethodB("Projectile", "explode", &conProjectileExplode,"Explodes the given projectile", 5, 5); @@ -37,7 +38,14 @@ extern "C" Con::addMethodS("GrenadeProjectile", "getvelocity", &conGrenadeProjectileGetVelocity,"Gets the velocity of the GrenadeProjectile", 2, 2); Con::addMethodB("Projectile", "makeNerf", &conProjectileMakeNerf,"Makes the Projectile deal no damage", 2, 2); + // TCPObject + Con::addMethodS("TCPObject", "altConnect", &conTCPObjectConnect, "Connects to a remote server", 3, 3); + Con::addMethodB("TCPObject", "altSend", &conTCPObjectSend, "Sends data to the remote server", 3, 3); + Con::addMethodB("TCPObject", "altDisconnect", &conTCPObjectDisconnect, "Disconnects from the remote server", 2, 2); + + // General Con::addMethodS(NULL, "sprintf", &conSprintf,"Formats a string. See the C sprintf.", 2, 20); + Con::addMethodB(NULL, "tsExtensionUpdate", &conTSExtensionUpdate,"Updates the TSExtension.", 1, 1); // Add this Gvar to signify that TSExtension is active static bool is_active = true;