Added SendNetworkCommand
Allows for a custom message to be sent over the network without the need for SendNetworkEvent. This includes all the possible valid types of byte, word, long, float, and string.
This commit is contained in:
parent
c62ecc44e2
commit
9565c94cd2
6 changed files with 371 additions and 0 deletions
206
src/events.cpp
206
src/events.cpp
|
|
@ -45,6 +45,51 @@
|
|||
|
||||
EventManager staticEventManager;
|
||||
|
||||
static int ListGetInt(VMVa_List& tags)
|
||||
{
|
||||
if (tags.curindex < tags.numargs)
|
||||
{
|
||||
if (tags.reginfo[tags.curindex] == REGT_FLOAT)
|
||||
return static_cast<int>(tags.args[tags.curindex++].f);
|
||||
|
||||
if (tags.reginfo[tags.curindex] == REGT_INT)
|
||||
return tags.args[tags.curindex++].i;
|
||||
|
||||
ThrowAbortException(X_OTHER, "Invalid parameter in network command function, int expected");
|
||||
}
|
||||
|
||||
return TAG_DONE;
|
||||
}
|
||||
|
||||
static double ListGetDouble(VMVa_List& tags)
|
||||
{
|
||||
if (tags.curindex < tags.numargs)
|
||||
{
|
||||
if (tags.reginfo[tags.curindex] == REGT_FLOAT)
|
||||
return tags.args[tags.curindex++].f;
|
||||
|
||||
if (tags.reginfo[tags.curindex] == REGT_INT)
|
||||
return tags.args[tags.curindex++].i;
|
||||
|
||||
ThrowAbortException(X_OTHER, "Invalid parameter in network command function, float expected");
|
||||
}
|
||||
|
||||
return TAG_DONE;
|
||||
}
|
||||
|
||||
static const FString* ListGetString(VMVa_List& tags)
|
||||
{
|
||||
if (tags.curindex < tags.numargs)
|
||||
{
|
||||
if (tags.reginfo[tags.curindex] == REGT_STRING)
|
||||
return &tags.args[tags.curindex++].s();
|
||||
|
||||
ThrowAbortException(X_OTHER, "Invalid parameter in network command function, string expected");
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void EventManager::CallOnRegister()
|
||||
{
|
||||
for (DStaticEventHandler* handler = FirstEventHandler; handler; handler = handler->next)
|
||||
|
|
@ -176,6 +221,92 @@ bool EventManager::SendNetworkEvent(FString name, int arg1, int arg2, int arg3,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool EventManager::SendNetworkCommand(int cmd, VMVa_List args)
|
||||
{
|
||||
if (gamestate != GS_LEVEL && gamestate != GS_TITLELEVEL)
|
||||
return false;
|
||||
|
||||
// Calculate the size of the message so we know where it ends.
|
||||
unsigned int bytes = 0u;
|
||||
int tag = ListGetInt(args);
|
||||
while (tag != TAG_DONE)
|
||||
{
|
||||
switch (tag)
|
||||
{
|
||||
case NET_BYTE:
|
||||
++bytes;
|
||||
break;
|
||||
|
||||
case NET_WORD:
|
||||
bytes += 2u;
|
||||
break;
|
||||
|
||||
case NET_LONG:
|
||||
case NET_FLOAT:
|
||||
bytes += 4u;
|
||||
break;
|
||||
|
||||
case NET_STRING:
|
||||
++bytes; // Strings will always consume at least one byte.
|
||||
const FString* str = ListGetString(args);
|
||||
if (str != nullptr)
|
||||
bytes += str->Len();
|
||||
break;
|
||||
}
|
||||
|
||||
if (tag != NET_STRING)
|
||||
++args.curindex;
|
||||
|
||||
tag = ListGetInt(args);
|
||||
}
|
||||
|
||||
Net_WriteByte(DEM_ZSC_CMD);
|
||||
Net_WriteLong(cmd); // Using a full int here to allow better prevention of overlapping command ids.
|
||||
Net_WriteWord(bytes);
|
||||
|
||||
constexpr char Default[] = "";
|
||||
|
||||
args.curindex = 0;
|
||||
tag = ListGetInt(args);
|
||||
while (tag != TAG_DONE)
|
||||
{
|
||||
switch (tag)
|
||||
{
|
||||
default:
|
||||
++args.curindex;
|
||||
break;
|
||||
|
||||
case NET_BYTE:
|
||||
Net_WriteByte(ListGetInt(args));
|
||||
break;
|
||||
|
||||
case NET_WORD:
|
||||
Net_WriteWord(ListGetInt(args));
|
||||
break;
|
||||
|
||||
case NET_LONG:
|
||||
Net_WriteLong(ListGetInt(args));
|
||||
break;
|
||||
|
||||
case NET_FLOAT:
|
||||
Net_WriteFloat(ListGetDouble(args));
|
||||
break;
|
||||
|
||||
case NET_STRING:
|
||||
const FString* str = ListGetString(args);
|
||||
if (str != nullptr)
|
||||
Net_WriteString(str->GetChars());
|
||||
else
|
||||
Net_WriteString(Default); // Still have to send something here to be read correctly.
|
||||
break;
|
||||
}
|
||||
|
||||
tag = ListGetInt(args);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EventManager::CheckHandler(DStaticEventHandler* handler)
|
||||
{
|
||||
for (DStaticEventHandler* lhandler = FirstEventHandler; lhandler; lhandler = lhandler->next)
|
||||
|
|
@ -524,6 +655,14 @@ bool EventManager::Responder(const event_t* ev)
|
|||
return false;
|
||||
}
|
||||
|
||||
void EventManager::NetCommand(FNetworkCommand& cmd)
|
||||
{
|
||||
if (ShouldCallStatic(false)) staticEventManager.NetCommand(cmd);
|
||||
|
||||
for (DStaticEventHandler* handler = FirstEventHandler; handler; handler = handler->next)
|
||||
handler->NetCommandProcess(cmd);
|
||||
}
|
||||
|
||||
void EventManager::Console(int player, FString name, int arg1, int arg2, int arg3, bool manual, bool ui)
|
||||
{
|
||||
if (ShouldCallStatic(false)) staticEventManager.Console(player, name, arg1, arg2, arg3, manual, ui);
|
||||
|
|
@ -673,6 +812,49 @@ DEFINE_FIELD_X(ReplacedEvent, FReplacedEvent, Replacee)
|
|||
DEFINE_FIELD_X(ReplacedEvent, FReplacedEvent, Replacement)
|
||||
DEFINE_FIELD_X(ReplacedEvent, FReplacedEvent, IsFinal)
|
||||
|
||||
DEFINE_FIELD_X(NetworkCommand, FNetworkCommand, Player)
|
||||
DEFINE_FIELD_X(NetworkCommand, FNetworkCommand, Command)
|
||||
|
||||
DEFINE_ACTION_FUNCTION(FNetworkCommand, ReadByte)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FNetworkCommand);
|
||||
|
||||
ACTION_RETURN_INT(self->ReadByte());
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(FNetworkCommand, ReadWord)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FNetworkCommand);
|
||||
|
||||
ACTION_RETURN_INT(self->ReadWord());
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(FNetworkCommand, ReadLong)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FNetworkCommand);
|
||||
|
||||
ACTION_RETURN_INT(self->ReadLong());
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(FNetworkCommand, ReadFloat)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FNetworkCommand);
|
||||
|
||||
ACTION_RETURN_FLOAT(self->ReadFloat());
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(FNetworkCommand, ReadString)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(FNetworkCommand);
|
||||
|
||||
FString res = {};
|
||||
auto str = self->ReadString();
|
||||
if (str != nullptr)
|
||||
res = str;
|
||||
|
||||
ACTION_RETURN_STRING(res);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DStaticEventHandler, SetOrder)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DStaticEventHandler);
|
||||
|
|
@ -682,6 +864,16 @@ DEFINE_ACTION_FUNCTION(DStaticEventHandler, SetOrder)
|
|||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DEventHandler, SendNetworkCommand)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(cmd);
|
||||
PARAM_VA_POINTER(va_reginfo);
|
||||
|
||||
VMVa_List args = { param + 1, 0, numparam - 2, va_reginfo + 1 };
|
||||
ACTION_RETURN_BOOL(currentVMLevel->localEventManager->SendNetworkCommand(cmd, args));
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DEventHandler, SendNetworkEvent)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
|
|
@ -1178,6 +1370,20 @@ void DStaticEventHandler::PostUiTick()
|
|||
}
|
||||
}
|
||||
|
||||
void DStaticEventHandler::NetCommandProcess(FNetworkCommand& cmd)
|
||||
{
|
||||
IFVIRTUAL(DStaticEventHandler, NetworkCommandProcess)
|
||||
{
|
||||
if (isEmpty(func))
|
||||
return;
|
||||
|
||||
VMValue params[] = { this, &cmd };
|
||||
VMCall(func, params, 2, nullptr, 0);
|
||||
|
||||
cmd.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
void DStaticEventHandler::ConsoleProcess(int player, FString name, int arg1, int arg2, int arg3, bool manual, bool ui)
|
||||
{
|
||||
if (player < 0)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue