mirror of
https://github.com/Ragora/T2-CPP.git
synced 2026-01-19 18:14:44 +00:00
Updated TCPObject code to use the STL though it needs bug fixes; added Bahke's contributions
This commit is contained in:
parent
9a0d849461
commit
b4a0fccf42
|
|
@ -38,7 +38,6 @@ namespace DX
|
|||
typedef void* UnresolvedObject;
|
||||
|
||||
const char *GetModPaths(void);
|
||||
|
||||
bool IsFile(const char *filename);
|
||||
|
||||
bool GetRelativePath(const char *filename, char *ret, int buffer_length);
|
||||
|
|
|
|||
|
|
@ -1,12 +1,19 @@
|
|||
#pragma once
|
||||
|
||||
#include <DXAPI/SceneObject.h>
|
||||
|
||||
enum GameBaseMasks {
|
||||
InitialUpdateMask = 1 << 0,
|
||||
DataBlockMask = 1 << 1,
|
||||
ExtendedInfoMask = 1 << 2,
|
||||
NextFreeMask = ExtendedInfoMask << 1
|
||||
};
|
||||
namespace DX
|
||||
{
|
||||
class GameBase : public SceneObject
|
||||
{
|
||||
|
||||
public:
|
||||
GameBase(unsigned int obj);
|
||||
void setProcessTicks(bool proc);
|
||||
};
|
||||
} // End NameSpace DX
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include <DXAPI/Point3F.h>
|
||||
#include <DXAPI/NetConnection.h>
|
||||
|
||||
#include <LinkerAPI.h>
|
||||
#include <DXAPI/ShapeBase.h>
|
||||
|
||||
namespace DX
|
||||
|
|
@ -13,5 +13,6 @@ namespace DX
|
|||
GameConnection(unsigned int obj);
|
||||
|
||||
ShapeBase getControlObject(void);
|
||||
|
||||
};
|
||||
} // End NameSpace DX
|
||||
|
|
|
|||
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
#include <DXAPI/Point3F.h>
|
||||
#include <DXAPI/SimObject.h>
|
||||
#include <DXAPI/NetObject.h>
|
||||
#include <LinkerAPI.h>
|
||||
|
||||
struct GhostInfo;
|
||||
|
||||
namespace DX
|
||||
{
|
||||
|
|
@ -9,5 +13,54 @@ namespace DX
|
|||
{
|
||||
public:
|
||||
NetConnection(unsigned int obj);
|
||||
S32 getGhostIndex(NetObject *obj);
|
||||
GhostInfo * mGhostRefs;
|
||||
};
|
||||
} // End NameSpace DX
|
||||
|
||||
struct GhostRef;
|
||||
struct GhostInfo
|
||||
{
|
||||
public: // required for MSVC
|
||||
|
||||
// NOTE:
|
||||
// if the size of this structure changes, the
|
||||
// NetConnection::getGhostIndex function MUST be changed
|
||||
// to reflect.
|
||||
|
||||
DX::NetObject *obj; // the real object
|
||||
U32 updateMask; // 32 bits of object info
|
||||
GhostRef *updateChain; // chain of updates for this object in packets
|
||||
GhostInfo *nextObjectRef; // next ghost ref for this object (another connection)
|
||||
|
||||
GhostInfo *prevObjectRef; // prev ghost ref for this object
|
||||
DX::NetConnection *connection;
|
||||
GhostInfo *nextLookupInfo;
|
||||
U32 updateSkipCount;
|
||||
|
||||
U32 flags;
|
||||
F32 priority;
|
||||
U32 index;
|
||||
U32 arrayIndex;
|
||||
|
||||
enum Flags
|
||||
{
|
||||
Valid = BIT(0),
|
||||
InScope = BIT(1),
|
||||
ScopeAlways = BIT(2),
|
||||
NotYetGhosted = BIT(3),
|
||||
Ghosting = BIT(4),
|
||||
KillGhost = BIT(5),
|
||||
KillingGhost = BIT(6),
|
||||
ScopedEvent = BIT(7),
|
||||
ScopeLocalAlways = BIT(8),
|
||||
};
|
||||
};
|
||||
struct GhostRef
|
||||
{
|
||||
U32 mask;
|
||||
U32 ghostInfoFlags;
|
||||
GhostInfo *ghost;
|
||||
GhostRef *nextRef;
|
||||
GhostRef *nextUpdateChain;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ 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[]);
|
||||
|
||||
bool conSetProcessTicks(Linker::SimObject *obj, S32 argc, const char* argv[]) ;
|
||||
// GrenadeProjectile Commands ------------------------
|
||||
const char* conGrenadeProjectileGetPosition(Linker::SimObject *obj, S32 argc, const char* argv[]);
|
||||
const char* conGrenadeProjectileGetVelocity(Linker::SimObject *obj, S32 argc, const char* argv[]);
|
||||
|
|
@ -50,6 +50,9 @@ const char *conBinaryObjectGetBufferPointer(Linker::SimObject *obj, S32 argc, co
|
|||
bool conBinaryObjectClose(Linker::SimObject *obj, S32 argc, const char *argv[]);
|
||||
bool conBinaryObjectSave(Linker::SimObject *obj, S32 argc, const char *argv[]);
|
||||
|
||||
// Network Commands ---------------------------------
|
||||
S32 conGetGhostIndex(Linker::SimObject *obj, S32 argc, const char* argv[]);
|
||||
bool conForceUpdate(Linker::SimObject *obj, S32 argc, const char* argv[]);
|
||||
// General Commands ---------------------------------
|
||||
const char* conSprintf(Linker::SimObject *obj, S32 argc, const char* argv[]);
|
||||
bool conTSExtensionUpdate(Linker::SimObject *obj, S32 argc, const char *argv[]);
|
||||
|
|
@ -83,9 +83,12 @@ void GuiTSCtrl_project(GuiTSCtrl *obj, const Linker::Point3F &pt, Linker::Point3
|
|||
|
||||
namespace Sim {
|
||||
extern Linker::SimObject* (*findObject)(U32 id);
|
||||
extern Linker::SimObject* (*findObjectc)(const char* name);
|
||||
}
|
||||
|
||||
//console
|
||||
#define BIT(x) (1 << (x))
|
||||
|
||||
|
||||
typedef const char * (*StringCallback)(Linker::SimObject *obj, S32 argc, const char *argv[]);
|
||||
typedef S32 (*IntCallback)(Linker::SimObject *obj, S32 argc, const char *argv[]);
|
||||
|
|
@ -102,7 +105,7 @@ extern char * (*getReturnBuffer)(U32 bufferSize);
|
|||
|
||||
extern void (*addMethodB)(const char *nsName, const char *name, BoolCallback cb, const char *usage, S32 minArgs, S32 maxArgs);
|
||||
extern void (*addMethodS)(const char *nsName, const char *name, StringCallback cb, const char *usage, S32 minArgs, S32 maxArgs);
|
||||
|
||||
extern void (*addMethodI)(const char *nsName, const char *name, IntCallback cb, const char *usage, S32 minArgs, S32 maxArgs);
|
||||
extern bool (*addVariable)(const char *name, S32 t, void *dp);
|
||||
|
||||
extern void (*printf)(const char* fmt,...);
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
namespace DX
|
||||
{
|
||||
|
||||
const char *GetModPaths(void)
|
||||
{
|
||||
int pointer = *(int*)0x9E8690;
|
||||
|
|
|
|||
|
|
@ -5,4 +5,6 @@ namespace DX
|
|||
GameBase::GameBase(unsigned int obj) : SceneObject(obj)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
} // End NameSpace DX
|
||||
|
|
@ -1,8 +1,29 @@
|
|||
#include <DXAPI/NetConnection.h>
|
||||
|
||||
#include <DXAPI/NetObject.h>
|
||||
#include <LinkerAPI.h>
|
||||
namespace DX
|
||||
{
|
||||
NetConnection::NetConnection(unsigned int obj) : SimObject(obj)
|
||||
{
|
||||
S32 NetConnection::getGhostIndex(NetObject *obj) {
|
||||
unsigned int object_ptr = (unsigned int)obj->base_pointer_value;
|
||||
unsigned int my_ptr = this->base_pointer_value-0xA0;
|
||||
unsigned int ghostid=0;
|
||||
unsigned int function=0x584FB0;
|
||||
__asm
|
||||
{
|
||||
mov ecx,my_ptr
|
||||
mov edx,object_ptr
|
||||
push edx
|
||||
call function
|
||||
mov ghostid, eax
|
||||
}
|
||||
return ghostid;
|
||||
}
|
||||
}
|
||||
|
||||
NetConnection::NetConnection(unsigned int obj) : SimObject(obj)
|
||||
|
||||
{
|
||||
this->mGhostRefs = (GhostInfo *)this->base_pointer_value-0xA0+0x8210;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ namespace DX
|
|||
SimObject::SimObject(unsigned int obj) : identifier(*(unsigned int*)(obj + 32)),
|
||||
base_pointer_value(obj)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void SimObject::deleteObject(void)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ bool conPlayerGetJumpingState(Linker::SimObject *obj, S32 argc, const char* argv
|
|||
|
||||
return operand.is_jumping;
|
||||
}
|
||||
|
||||
bool conPlayerGetJettingState(Linker::SimObject *obj, S32 argc, const char* argv[])
|
||||
{
|
||||
DX::Player operand = DX::Player((unsigned int)obj);
|
||||
|
|
@ -55,7 +54,59 @@ bool conProjectileMakeNerf(Linker::SimObject *obj, S32 argc, const char* argv[])
|
|||
|
||||
return true;
|
||||
}
|
||||
bool conForceUpdate(Linker::SimObject *obj, S32 argc, const char* argv[]) {
|
||||
DX::NetConnection conn = DX::NetConnection((unsigned int)obj);
|
||||
DX::NetObject netobj = DX::NetObject((unsigned int)Sim::findObjectc(argv[2]));
|
||||
if (netobj.base_pointer_value!=0) {
|
||||
S32 index = conn.getGhostIndex(&netobj);
|
||||
if (index > 0) {
|
||||
conn.mGhostRefs[index].updateMask=conn.mGhostRefs[index].updateMask | GameBaseMasks::InitialUpdateMask;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
S32 conGetGhostIndex(Linker::SimObject *obj, S32 argc, const char* argv[]) {
|
||||
DX::NetConnection conn = DX::NetConnection((unsigned int)obj);
|
||||
DX::NetObject netobj = DX::NetObject((unsigned int)Sim::findObjectc(argv[2]));
|
||||
if (netobj.base_pointer_value!=0) {
|
||||
S32 index = conn.getGhostIndex(&netobj);
|
||||
return index;
|
||||
} else {
|
||||
return (unsigned int)Sim::findObjectc(argv[1]);
|
||||
}
|
||||
//conn.mGhostRefs[index].updateMask=conn.mGhostRefs[index].updateMask | GameBaseMasks::InitialUpdateMask;
|
||||
}
|
||||
bool conSetProcessTicks(Linker::SimObject *obj, S32 argc, const char* argv[]) {
|
||||
|
||||
unsigned int result_ptr = 0;
|
||||
unsigned int my_ptr = (unsigned int) obj;
|
||||
if (atoi(argv[2])==1) {
|
||||
__asm
|
||||
{
|
||||
mov eax, my_ptr;
|
||||
add eax, 0x264;
|
||||
mov ebx,eax
|
||||
mov al, 1
|
||||
mov [ebx],al
|
||||
|
||||
}
|
||||
} else {
|
||||
__asm
|
||||
{
|
||||
mov eax, my_ptr;
|
||||
add eax, 0x264;
|
||||
mov ebx,eax
|
||||
mov al, 0
|
||||
mov [ebx],al
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
const char* conGrenadeProjectileGetPosition(Linker::SimObject *obj, S32 argc, const char* argv[])
|
||||
{
|
||||
char result[256];
|
||||
|
|
|
|||
|
|
@ -1,15 +1,21 @@
|
|||
#include <WinSock.h>
|
||||
#include <WinDNS.h>
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
#include <LinkerAPI.h>
|
||||
#include <DXAPI/DXAPI.h>
|
||||
|
||||
#include <WinSock.h>
|
||||
#include <WinDNS.h>
|
||||
|
||||
#define TCPOBJECT_MAXCOUNT 256
|
||||
#define TCPOBJECT_BUFFERSIZE 256
|
||||
#define TCPOBJECT_SENDQUEUELENGTH 64 // Number of elements
|
||||
|
||||
static unsigned int TSEXTENSION_RUNNINGTCPOBJECTCOUNT = 0;
|
||||
static DX::TCPObject *TSEXTENSION_RUNNINGTCPOBJECTS[TCPOBJECT_MAXCOUNT];
|
||||
//! A mapping of object ID's to DX::TCPObject instance pointers.
|
||||
static std::map<int, std::unique_ptr<DX::TCPObject>> sRunningTCPObjects;
|
||||
|
||||
// Since TS wants function call arguments to be of type char*, we use this
|
||||
// helper function to painlessly pass in unsigned int arguments for things
|
||||
|
|
@ -23,28 +29,13 @@ __forceinline static char *S32ToCharPtr(unsigned int in)
|
|||
}
|
||||
|
||||
// Also a helper function to return the status of a socket
|
||||
static bool DXTCP_GetSocketStatus(SOCKET sock)
|
||||
static unsigned int DXTCP_GetSocketTime(SOCKET sock)
|
||||
{
|
||||
fd_set sockets;
|
||||
sockets.fd_array[0] = sock;
|
||||
sockets.fd_count = 1;
|
||||
|
||||
// We don't want to do any waiting at all
|
||||
timeval wait_time;
|
||||
wait_time.tv_sec = 0;
|
||||
wait_time.tv_usec = 0;
|
||||
unsigned int optVal;
|
||||
int optLen = sizeof(unsigned int);
|
||||
|
||||
return select(sock, &sockets, &sockets, NULL, &wait_time) != SOCKET_ERROR;
|
||||
}
|
||||
|
||||
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;
|
||||
getsockopt(sock, SOL_SOCKET, SO_CONNECT_TIME, (char*)&optVal, &optLen);
|
||||
return optVal;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
|
|
@ -53,56 +44,42 @@ typedef struct
|
|||
unsigned int target_port;
|
||||
|
||||
unsigned int buffer_length;
|
||||
char *buffer;
|
||||
|
||||
unsigned int message_count;
|
||||
char *message_queue[TCPOBJECT_SENDQUEUELENGTH];
|
||||
|
||||
std::set<std::string> mOutgoingQueue;
|
||||
std::string mIncomingBuffer;
|
||||
bool is_connected;
|
||||
|
||||
SOCKET socket;
|
||||
} ConnectionInformation;
|
||||
|
||||
|
||||
inline bool TCPObject_Disconnect(unsigned int identifier)
|
||||
inline void TCPObject_Disconnect(DX::TCPObject *obj)
|
||||
{
|
||||
DX::TCPObject *obj = TCPObject_Find(identifier);
|
||||
if (!obj)
|
||||
return false;
|
||||
ConnectionInformation *connectionInfo = (ConnectionInformation*)obj->state;
|
||||
|
||||
ConnectionInformation *connection = (ConnectionInformation*)obj->state;
|
||||
if (connectionInfo->socket == 0)
|
||||
{
|
||||
closesocket(connectionInfo->socket);
|
||||
connectionInfo->socket = 0;
|
||||
|
||||
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--;
|
||||
Con::errorf(0, "Attempted to disconnect an already disconnected TCPObject - %u", obj->identifier);
|
||||
return;
|
||||
}
|
||||
|
||||
obj->CallMethod("onDisconnect", 0);
|
||||
return true;
|
||||
delete connectionInfo;
|
||||
|
||||
// Causes the ptr to our DX::TCPObject to deallocate
|
||||
sRunningTCPObjects.erase(obj->identifier);
|
||||
|
||||
Con::errorf(0, "Processed Disconnect");
|
||||
}
|
||||
|
||||
const char* conTCPObjectConnect(Linker::SimObject *obj, S32 argc, const char *argv[])
|
||||
{
|
||||
DX::TCPObject *operand = TCPObject_Find(atoi(argv[1]));
|
||||
if (operand)
|
||||
{
|
||||
TCPObject_Disconnect(operand->identifier);
|
||||
delete operand;
|
||||
}
|
||||
if (sRunningTCPObjects.count(obj->mId) >= 1)
|
||||
TCPObject_Disconnect(sRunningTCPObjects[obj->mId].get());
|
||||
|
||||
operand = new DX::TCPObject((unsigned int)obj);
|
||||
DX::TCPObject *operand = new DX::TCPObject((unsigned int)obj);
|
||||
|
||||
// Copy the hostname over
|
||||
char *desired_hostname = (char*)malloc(strlen(argv[2]) + 1);
|
||||
|
|
@ -111,10 +88,8 @@ const char* conTCPObjectConnect(Linker::SimObject *obj, S32 argc, const char *ar
|
|||
// Create the connection info
|
||||
ConnectionInformation *connection = new ConnectionInformation;
|
||||
connection->target_hostname = desired_hostname;
|
||||
connection->buffer = 0x00;
|
||||
connection->buffer_length = 0;
|
||||
connection->is_connected = false;
|
||||
connection->message_count = 0;
|
||||
connection->socket = 0;
|
||||
|
||||
// Hack: Store the Ptr to our connection information struct in the old unused state value
|
||||
|
|
@ -182,20 +157,18 @@ const char* conTCPObjectConnect(Linker::SimObject *obj, S32 argc, const char *ar
|
|||
u_long imode = 1;
|
||||
ioctlsocket(connection->socket, FIONBIO, &imode);
|
||||
|
||||
// Stick us in the TCPObject array
|
||||
TSEXTENSION_RUNNINGTCPOBJECTS[TSEXTENSION_RUNNINGTCPOBJECTCOUNT] = operand;
|
||||
TSEXTENSION_RUNNINGTCPOBJECTCOUNT++;
|
||||
sRunningTCPObjects[obj->mId] = std::unique_ptr<DX::TCPObject>(operand);
|
||||
|
||||
// Attempt the Connection
|
||||
connect(connection->socket, (SOCKADDR*)&target_host, sizeof(target_host));
|
||||
if (DXTCP_GetSocketStatus(connection->socket) == SOCKET_ERROR)
|
||||
|
||||
if (getsockopt(connection->socket, SOL_SOCKET, SO_ERROR, NULL, NULL) < 0)
|
||||
{
|
||||
operand->CallMethod("onConnectFailed", 2, S32ToCharPtr(3), S32ToCharPtr(WSAGetLastError()));
|
||||
return "CANNOT_CONNECT";
|
||||
}
|
||||
else
|
||||
{
|
||||
connection->is_connected = true;
|
||||
operand->CallMethod("onConnected", 0);
|
||||
return "SUCCESS";
|
||||
}
|
||||
|
|
@ -207,25 +180,18 @@ bool conTCPObjectSend(Linker::SimObject *obj, S32 argc, const char *argv[])
|
|||
{
|
||||
Con::errorf(0, "Should Send? - SimID %s", argv[1]);
|
||||
|
||||
if (!TCPObject_Find(atoi(argv[1])))
|
||||
if (sRunningTCPObjects.count(obj->mId) == 0)
|
||||
return false;
|
||||
|
||||
DX::TCPObject operand((unsigned int)obj);
|
||||
ConnectionInformation *connection = (ConnectionInformation*)operand.state;
|
||||
DX::TCPObject *operand = sRunningTCPObjects[obj->mId].get();
|
||||
ConnectionInformation *connection = (ConnectionInformation*)operand->state;
|
||||
|
||||
// Since we can be attempting to send data before we're connected, we'll just queue
|
||||
// the data here and send it all in our update function next call
|
||||
if (!connection->is_connected)
|
||||
Con::errorf(0, "Attempted to send before connected.");
|
||||
|
||||
// Tribes 2 probably deallocates the memory associated with the arguments at some point
|
||||
// so we'll copy the send payload into an independent chunk of memory
|
||||
char *send_payload = new char[strlen(argv[2]) + 1];
|
||||
memset(send_payload, 0x00, strlen(argv[2]) + 1);
|
||||
memcpy(send_payload, argv[2], strlen(argv[2]) + 1);
|
||||
|
||||
connection->message_queue[connection->message_count] = send_payload;
|
||||
connection->message_count++;
|
||||
connection->mOutgoingQueue.insert(connection->mOutgoingQueue.end(), argv[2]);
|
||||
|
||||
Con::errorf(0,"Queued data: %s", argv[2]);
|
||||
return true;
|
||||
|
|
@ -233,7 +199,11 @@ bool conTCPObjectSend(Linker::SimObject *obj, S32 argc, const char *argv[])
|
|||
|
||||
bool conTCPObjectDisconnect(Linker::SimObject *obj, S32 argc, const char *argv[])
|
||||
{
|
||||
return TCPObject_Disconnect(atoi(argv[1]));
|
||||
if (sRunningTCPObjects.count(obj->mId) == 0)
|
||||
return false;
|
||||
|
||||
TCPObject_Disconnect(sRunningTCPObjects[obj->mId].get());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool conTSExtensionUpdate(Linker::SimObject *obj, S32 argc, const char *argv[])
|
||||
|
|
@ -242,36 +212,36 @@ bool conTSExtensionUpdate(Linker::SimObject *obj, S32 argc, const char *argv[])
|
|||
static char *incoming_buffer = new char[TCPOBJECT_BUFFERSIZE];
|
||||
|
||||
// List of objects to D/C
|
||||
unsigned int disconnected_object_count = 0;
|
||||
static DX::TCPObject **disconnected_objects = (DX::TCPObject**)malloc(sizeof(DX::TCPObject*) * TCPOBJECT_MAXCOUNT);
|
||||
std::set<std::unique_ptr<DX::TCPObject>> disconnections;
|
||||
|
||||
for (unsigned int iteration = 0; iteration < TSEXTENSION_RUNNINGTCPOBJECTCOUNT; iteration++)
|
||||
for (std::map<int, std::unique_ptr<DX::TCPObject>>::iterator it = sRunningTCPObjects.begin(); it != sRunningTCPObjects.end(); it++)
|
||||
{
|
||||
// Zero out the incoming buffer per iteration
|
||||
memset(incoming_buffer, 0x00, TCPOBJECT_BUFFERSIZE);
|
||||
|
||||
DX::TCPObject *current_connection = TSEXTENSION_RUNNINGTCPOBJECTS[iteration];
|
||||
ConnectionInformation *connection_information = (ConnectionInformation*)current_connection->state;
|
||||
const std::unique_ptr<DX::TCPObject> ¤tConnection = (*it).second;
|
||||
|
||||
// FIXME: ::onConnect is never called if is where we finally realize we're connected
|
||||
// Check if we're ready to be performing network operations
|
||||
if (DXTCP_GetSocketStatus(connection_information->socket))
|
||||
connection_information->is_connected = true;
|
||||
else
|
||||
ConnectionInformation *connectionInfo = (ConnectionInformation*)currentConnection.get()->state;
|
||||
|
||||
const int socketTime = DXTCP_GetSocketTime(connectionInfo->socket);
|
||||
if (socketTime >= 1 && !connectionInfo->is_connected)
|
||||
{
|
||||
Con::errorf(0,"Socket status error!");
|
||||
disconnected_objects[disconnected_object_count] = current_connection;
|
||||
disconnected_object_count++;
|
||||
break;
|
||||
connectionInfo->is_connected = true;
|
||||
currentConnection.get()->CallMethod("onConnected", 0);
|
||||
}
|
||||
|
||||
// Process the send queue first
|
||||
bool connection_is_ready = true;
|
||||
if (connection_information->is_connected && connection_information->message_count != 0)
|
||||
for (unsigned int queue_iteration = 0; queue_iteration < connection_information->message_count; queue_iteration++)
|
||||
if (send(connection_information->socket, connection_information->message_queue[queue_iteration], strlen(connection_information->message_queue[queue_iteration]), 0) == SOCKET_ERROR)
|
||||
if (connectionInfo->is_connected)
|
||||
{
|
||||
for (std::set<std::string>::iterator it = connectionInfo->mOutgoingQueue.begin(); it != connectionInfo->mOutgoingQueue.end(); it++)
|
||||
{
|
||||
const std::string ¤tMessage = *it;
|
||||
Con::errorf(0, "Processing Send: %s", currentMessage.c_str());
|
||||
|
||||
if (send(connectionInfo->socket, currentMessage.c_str(), currentMessage.length(), 0) == SOCKET_ERROR)
|
||||
{
|
||||
int wsa_error = WSAGetLastError();
|
||||
|
||||
// We're not ready yet, just break and we should eventually be ready
|
||||
if (wsa_error == WSAEWOULDBLOCK)
|
||||
{
|
||||
|
|
@ -279,122 +249,75 @@ bool conTSExtensionUpdate(Linker::SimObject *obj, S32 argc, const char *argv[])
|
|||
break;
|
||||
}
|
||||
|
||||
connection_information->is_connected = false;
|
||||
disconnected_objects[disconnected_object_count] = current_connection;
|
||||
disconnected_object_count++;
|
||||
connectionInfo->is_connected = false;
|
||||
disconnections.insert(disconnections.end(), currentConnection.get());
|
||||
Con::errorf(0,"Got a send error! SimID: %u - Error %u", currentConnection->identifier, wsa_error);
|
||||
|
||||
Con::errorf(0,"Got a send error! SimID: %u - Error %u", current_connection->identifier, wsa_error);
|
||||
break;
|
||||
}
|
||||
else
|
||||
delete[] connection_information->message_queue[queue_iteration];
|
||||
|
||||
}
|
||||
|
||||
// Empty the queue
|
||||
connectionInfo->mOutgoingQueue.clear();
|
||||
}
|
||||
|
||||
// We can break if the connection was never made yet or if there was an error processing the message queue
|
||||
if (!connection_information->is_connected || !connection_is_ready)
|
||||
break;
|
||||
if (!connectionInfo->is_connected || !connection_is_ready)
|
||||
continue;
|
||||
|
||||
// FIXME: Under send() error conditions we can't deallocate all of the associated memory
|
||||
connection_information->message_count = 0;
|
||||
unsigned int data_length = recv(connection_information->socket, incoming_buffer, TCPOBJECT_BUFFERSIZE, 0);
|
||||
unsigned int data_length = recv(connectionInfo->socket, incoming_buffer, TCPOBJECT_BUFFERSIZE, 0);
|
||||
|
||||
int currentError = WSAGetLastError();
|
||||
|
||||
Con::errorf(0, "%u", DXTCP_GetSocketTime(connectionInfo->socket));
|
||||
|
||||
if (currentError != WSAEWOULDBLOCK && currentError != 0)
|
||||
{
|
||||
Con::errorf(0, "Got an error! %u - SimID %u", currentError, current_connection->identifier);
|
||||
disconnected_objects[disconnected_object_count] = current_connection;
|
||||
disconnected_object_count++;
|
||||
Con::errorf(0, "Got an error! %u - SimID %u", currentError, currentConnection.get()->identifier);
|
||||
|
||||
disconnections.insert(disconnections.end(), currentConnection.get());
|
||||
}
|
||||
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++;
|
||||
disconnections.insert(disconnections.end(), currentConnection.get());
|
||||
|
||||
// Our actual buffer is +1 bytes in length, so will set the extra byte to 0x00 to ensure NULL termination
|
||||
connection_information->buffer[connection_information->buffer_length] = 0x00;
|
||||
|
||||
Con::errorf(0, "Stream Len: %u Bytes", connection_information->buffer_length);
|
||||
// Stream the data into ::onLine
|
||||
unsigned int current_start = 0;
|
||||
for (unsigned int split_iteration = 0; split_iteration < connection_information->buffer_length; split_iteration++)
|
||||
|
||||
for (unsigned int split_iteration = 0; split_iteration < connectionInfo->mIncomingBuffer.length(); split_iteration++)
|
||||
{
|
||||
bool streaming_line = false;
|
||||
if (connection_information->buffer[split_iteration] == '\n') // || split_iteration == connection_information->buffer_length - 1
|
||||
if (connectionInfo->mIncomingBuffer[split_iteration] == '\r')
|
||||
connectionInfo->mIncomingBuffer[split_iteration] = ' ';
|
||||
|
||||
if (connectionInfo->mIncomingBuffer[split_iteration] == '\n') // || split_iteration == connection_information->buffer_length - 1
|
||||
{
|
||||
connection_information->buffer[split_iteration] = 0x00;
|
||||
streaming_line = true;
|
||||
}
|
||||
else if (split_iteration == connection_information->buffer_length - 1)
|
||||
streaming_line = true;
|
||||
|
||||
//unsigned int desired_length = (split_iteration - current_start);
|
||||
|
||||
//if (desired_length == data_length)
|
||||
// current_connection->TSCall("onLine", 1, connection_information->buffer);
|
||||
//else
|
||||
//{
|
||||
//if(split_iteration != connection_information->buffer_length - 1)
|
||||
// connection_information->buffer[split_iteration] = 0x00;
|
||||
|
||||
if (streaming_line)
|
||||
{
|
||||
// Time to be clever: Since T2 doesn't care what happens to the string after it's passed in, I'm not
|
||||
// Bothering to allocate more memory for the results. I'm just going to manipulate it to appear as
|
||||
// different lines but in reality they're all sourced from the same memory.
|
||||
char *current_line = &connection_information->buffer[current_start];
|
||||
|
||||
Con::errorf(0, "Streamed: %s", current_line);
|
||||
|
||||
// If we just have a blank line (a carriage return), replace it with the space character
|
||||
if (strlen(current_line) == 1 && current_line[0] == 0xD)
|
||||
current_line[0] = 0x20;
|
||||
const std::string currentLine = connectionInfo->mIncomingBuffer.substr(current_start, split_iteration - current_start);
|
||||
|
||||
current_start = split_iteration + 1;
|
||||
current_connection->CallMethod("onLine", 1, current_line);
|
||||
|
||||
Con::errorf(0, "Streaming: %s", currentLine.c_str());
|
||||
currentConnection.get()->CallMethod("onLine", 1, currentLine.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
closesocket(connection_information->socket);
|
||||
connection_information->socket = 0;
|
||||
delete[] 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)
|
||||
{
|
||||
// Allocate our memory with a +1 Byte Size (to ensure it's properly NULL terminated when we stream to ::onLine)
|
||||
connection_information->buffer = new char[data_length + 1];
|
||||
memset(connection_information->buffer, 0x00, data_length + 1);
|
||||
|
||||
connection_information->buffer_length = data_length;
|
||||
memcpy(connection_information->buffer, incoming_buffer, data_length);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int new_buffer_length = data_length + connection_information->buffer_length;
|
||||
char *new_buffer = new char[new_buffer_length + 1];
|
||||
memset(new_buffer, 0x00, new_buffer_length + 1);
|
||||
|
||||
// Copy the two halves
|
||||
memcpy(new_buffer, connection_information->buffer, connection_information->buffer_length);
|
||||
memcpy(&new_buffer[connection_information->buffer_length], incoming_buffer, data_length);
|
||||
|
||||
connection_information->buffer = new_buffer;
|
||||
connection_information->buffer_length = new_buffer_length;
|
||||
}
|
||||
connectionInfo->mIncomingBuffer += incoming_buffer;
|
||||
}
|
||||
}
|
||||
|
||||
// Process Disconnect list
|
||||
for (unsigned int iteration = 0; iteration < disconnected_object_count; iteration++)
|
||||
TCPObject_Disconnect(disconnected_objects[iteration]->identifier);
|
||||
for (std::set<std::unique_ptr<DX::TCPObject>>::iterator it = disconnections.begin(); it != disconnections.end(); it++)
|
||||
TCPObject_Disconnect((*it).get());
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
bool conHTTPObjectDoNothing(Linker::SimObject *obj, S32 argc, const char *argv[])
|
||||
|
|
|
|||
|
|
@ -7,6 +7,9 @@ namespace Sim {
|
|||
Linker::SimObject* (*findObject)(U32 id) =
|
||||
(Linker::SimObject* (_cdecl *)(U32 id) )
|
||||
0x439550;
|
||||
Linker::SimObject* (*findObjectc)(const char* name) =
|
||||
(Linker::SimObject* (_cdecl *)(const char* name) )
|
||||
0x439450;
|
||||
}
|
||||
|
||||
//hackey way to do member functions, ....
|
||||
|
|
@ -31,6 +34,10 @@ char* (*getReturnBuffer)(U32 bufferSize) =
|
|||
(char *(__cdecl *)(U32))
|
||||
0x42caa0;
|
||||
|
||||
void (*addMethodI)(const char *nsName, const char *name, IntCallback cb, const char *usage, S32 minArgs, S32 maxArgs) =
|
||||
(void (__cdecl *)(const char *, const char *,IntCallback,const char *,S32,S32))
|
||||
0x426490;
|
||||
|
||||
void (*addMethodB)(const char *nsName, const char *name, BoolCallback cb, const char *usage, S32 minArgs, S32 maxArgs) =
|
||||
(void (__cdecl *)(const char *, const char *,BoolCallback,const char *,S32,S32))
|
||||
0x426510;
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ extern "C"
|
|||
Con::addMethodB("GameConnection", "setheat", &conGameConnectionSetHeatLevel,"Sets the heat level", 3, 3);
|
||||
|
||||
Con::addMethodB("GrenadeProjectile", "explode", &conProjectileExplode,"Explodes the given projectile", 5, 5);
|
||||
Con::addMethodB("GameBase","setProcessTicks",&conSetProcessTicks,"Sets the flag for processing ticks or not", 3, 3);
|
||||
Con::addMethodB("Projectile", "explode", &conProjectileExplode,"Explodes the given projectile", 5, 5);
|
||||
|
||||
Con::addMethodS("GrenadeProjectile", "getposition", &conGrenadeProjectileGetPosition,"Accurately gets the position of the GrenadeProjectile", 2, 2);
|
||||
|
|
@ -64,7 +65,8 @@ extern "C"
|
|||
Con::addMethodS("BinaryObject", "getbufferlength", &conBinaryObjectGetBufferLength, "Returns the length of the buffer", 2, 2);
|
||||
Con::addMethodS("BinaryObject", "getbufferpointer", &conBinaryObjectGetBufferPointer, "Returns the buffer pointer", 2, 2);
|
||||
Con::addMethodB("BinaryObject", "close", &conBinaryObjectClose, "Closes the binary object", 2, 2);
|
||||
|
||||
Con::addMethodI("NetConnection","getGhostIndex", &conGetGhostIndex, "Gets a ghost index for an object id", 3, 3);
|
||||
Con::addMethodB("NetConnection","conForceUpdate", &conForceUpdate,"Forces an initial update for an object id", 3, 3);
|
||||
// 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);
|
||||
|
|
|
|||
Loading…
Reference in a new issue