Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attach events & rotation fix #3353

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Client/mods/deathmatch/logic/CClientGame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2637,6 +2637,8 @@ void CClientGame::AddBuiltInEvents()
m_Events.AddEvent("onClientElementModelChange", "oldModel, newModel", nullptr, false);
m_Events.AddEvent("onClientElementDimensionChange", "oldDimension, newDimension", nullptr, false);
m_Events.AddEvent("onClientElementInteriorChange", "oldInterior, newInterior", nullptr, false);
m_Events.AddEvent("onClientElementAttach", "attachSource, attachOffsetX, attachOffsetY, attachOffsetZ, attachOffsetRX, attachOffsetRY, attachOffsetRZ", nullptr, false);
m_Events.AddEvent("onClientElementDetach", "detachSource, detachWorldX, detachWorldY, detachWorldZ, detachWorldRX, detachWorldRY, detachWorldRZ", nullptr, false);

// Player events
m_Events.AddEvent("onClientPlayerJoin", "", NULL, false);
Expand Down
59 changes: 44 additions & 15 deletions Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1364,35 +1364,64 @@ bool CStaticFunctionDefinitions::AttachElements(CClientEntity& Entity, CClientEn
RUN_CHILDREN(AttachElements(**iter, AttachedToEntity, vecPosition, vecRotation))

// Can these elements be attached?
if (Entity.IsAttachToable() && AttachedToEntity.IsAttachable() && !AttachedToEntity.IsAttachedToElement(&Entity) &&
Entity.GetDimension() == AttachedToEntity.GetDimension())
if (!Entity.IsAttachToable() || !AttachedToEntity.IsAttachable() || AttachedToEntity.IsAttachedToElement(&Entity) ||
Entity.GetDimension() != AttachedToEntity.GetDimension())
{
ConvertDegreesToRadians(vecRotation);
return false;
}

Entity.SetAttachedOffsets(vecPosition, vecRotation);
Entity.AttachTo(&AttachedToEntity);
CLuaArguments Arguments;
Arguments.PushElement(&AttachedToEntity);
Arguments.PushNumber(vecPosition.fX);
Arguments.PushNumber(vecPosition.fY);
Arguments.PushNumber(vecPosition.fZ);
Arguments.PushNumber(vecRotation.fX);
Arguments.PushNumber(vecRotation.fY);
Arguments.PushNumber(vecRotation.fZ);

if (!Entity.CallEvent("onClientElementAttach", Arguments, true))
return false;

return true;
}
ConvertDegreesToRadians(vecRotation);

return false;
Entity.SetAttachedOffsets(vecPosition, vecRotation);
Entity.AttachTo(&AttachedToEntity);

return true;
}

bool CStaticFunctionDefinitions::DetachElements(CClientEntity& Entity, CClientEntity* pAttachedToEntity)
{
RUN_CHILDREN(DetachElements(**iter, pAttachedToEntity))

CClientEntity* pActualAttachedToEntity = Entity.GetAttachedTo();
if (pActualAttachedToEntity)
if (!pActualAttachedToEntity || (pAttachedToEntity && pActualAttachedToEntity != pAttachedToEntity))
{
if (pAttachedToEntity == NULL || pActualAttachedToEntity == pAttachedToEntity)
{
Entity.AttachTo(NULL);
return true;
}
return false;
}

return false;
CVector vecPosition;
CVector vecRotation;

Entity.GetPosition(vecPosition);
Entity.GetRotationDegrees(vecRotation);

CLuaArguments Arguments;
Arguments.PushElement(pActualAttachedToEntity);
Arguments.PushNumber(vecPosition.fX);
Arguments.PushNumber(vecPosition.fY);
Arguments.PushNumber(vecPosition.fZ);
Arguments.PushNumber(vecRotation.fX);
Arguments.PushNumber(vecRotation.fY);
Arguments.PushNumber(vecRotation.fZ);

if (!Entity.CallEvent("onClientElementDetach", Arguments, true))
{
return false;
}

Entity.AttachTo(NULL);
return true;
}

bool CStaticFunctionDefinitions::SetElementAttachedOffsets(CClientEntity& Entity, CVector& vecPosition, CVector& vecRotation)
Expand Down
102 changes: 85 additions & 17 deletions Client/mods/deathmatch/logic/rpc/CElementRPCs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -314,32 +314,100 @@ void CElementRPCs::SetElementDimension(CClientEntity* pSource, NetBitStreamInter
void CElementRPCs::AttachElements(CClientEntity* pSource, NetBitStreamInterface& bitStream)
{
ElementID usAttachedToID;
CVector vecPosition, vecRotation;
if (bitStream.Read(usAttachedToID) && bitStream.Read(vecPosition.fX) && bitStream.Read(vecPosition.fY) && bitStream.Read(vecPosition.fZ) &&
bitStream.Read(vecRotation.fX) && bitStream.Read(vecRotation.fY) && bitStream.Read(vecRotation.fZ))

CVector vecPosition;
CVector vecRotation;

if (!(bitStream.Read(usAttachedToID) && bitStream.Read(vecPosition.fX) && bitStream.Read(vecPosition.fY) && bitStream.Read(vecPosition.fZ) &&
bitStream.Read(vecRotation.fX) && bitStream.Read(vecRotation.fY) && bitStream.Read(vecRotation.fZ)))
{
CClientEntity* pAttachedToEntity = CElementIDs::GetElement(usAttachedToID);
if (pAttachedToEntity)
{
pSource->SetAttachedOffsets(vecPosition, vecRotation);
pSource->AttachTo(pAttachedToEntity);
}
return;
}

CClientEntity* pAttachedToEntity = CElementIDs::GetElement(usAttachedToID);
if (!pAttachedToEntity)
{
return;
}

ConvertRadiansToDegrees(vecRotation);

CLuaArguments Arguments;
Arguments.PushElement(pAttachedToEntity);
Arguments.PushNumber(vecPosition.fX);
Arguments.PushNumber(vecPosition.fY);
Arguments.PushNumber(vecPosition.fZ);
Arguments.PushNumber(vecRotation.fX);
Arguments.PushNumber(vecRotation.fY);
Arguments.PushNumber(vecRotation.fZ);

if (!pSource->CallEvent("onClientElementAttach", Arguments, true))
{
return;
}

ConvertDegreesToRadians(vecRotation);

pSource->SetAttachedOffsets(vecPosition, vecRotation);
pSource->AttachTo(pAttachedToEntity);
}

void CElementRPCs::DetachElements(CClientEntity* pSource, NetBitStreamInterface& bitStream)
{
unsigned char ucTimeContext;
if (bitStream.Read(ucTimeContext))
if (!bitStream.Read(ucTimeContext))
{
pSource->SetSyncTimeContext(ucTimeContext);
pSource->AttachTo(NULL);
return;
}

CVector vecPosition;
if (bitStream.Read(vecPosition.fX) && bitStream.Read(vecPosition.fY) && bitStream.Read(vecPosition.fZ))
{
pSource->SetPosition(vecPosition);
}
ElementID usAttachedToID;
CClientEntity* pAttachedToEntity = CElementIDs::GetElement(usAttachedToID);

CVector vecPosition;
CVector vecRotation;

bitStream.Read(vecPosition.fX);
bitStream.Read(vecPosition.fY);
bitStream.Read(vecPosition.fZ);

if (g_pNet->CanServerBitStream((eBitStreamVersion::DetachElementsRotation)))
{
bitStream.Read(vecRotation.fX);
bitStream.Read(vecRotation.fY);
bitStream.Read(vecRotation.fZ);
}
else
{
vecRotation.fX = 0;
vecRotation.fY = 0;
vecRotation.fZ = 0;
}

CLuaArguments Arguments;
Arguments.PushElement(pAttachedToEntity);
Arguments.PushNumber(vecPosition.fX);
Arguments.PushNumber(vecPosition.fY);
Arguments.PushNumber(vecPosition.fZ);
Arguments.PushNumber(vecRotation.fX);
Arguments.PushNumber(vecRotation.fY);
Arguments.PushNumber(vecRotation.fZ);

if (!pSource->CallEvent("onClientElementDetach", Arguments, true))
{
return;
}

pSource->SetSyncTimeContext(ucTimeContext);
pSource->AttachTo(NULL);

if (vecPosition.fX != 0.0f || vecPosition.fY != 0.0f || vecPosition.fZ != 0.0f)
{
pSource->SetPosition(vecPosition);
}

if (vecRotation.fX != 0.0f || vecRotation.fY != 0.0f || vecRotation.fZ != 0.0f)
{
pSource->SetRotationDegrees(vecRotation);
}
}

Expand Down
2 changes: 2 additions & 0 deletions Server/mods/deathmatch/logic/CGame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1608,6 +1608,8 @@ void CGame::AddBuiltInEvents()
m_Events.AddEvent("onElementModelChange", "oldModel, newModel", NULL, false);
m_Events.AddEvent("onElementDimensionChange", "oldDimension, newDimension", nullptr, false);
m_Events.AddEvent("onElementInteriorChange", "oldInterior, newInterior", nullptr, false);
m_Events.AddEvent("onElementAttach", "attachSource, attachOffsetX, attachOffsetY, attachOffsetZ, attachOffsetRX, attachOffsetRY, attachOffsetRZ", nullptr, false);
m_Events.AddEvent("onElementDetach", "detachSource, detachWorldX, detachWorldY, detachWorldZ, detachWorldRX, detachWorldRY, detachWorldRZ", nullptr, false);

// Radar area events

Expand Down
100 changes: 67 additions & 33 deletions Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1515,56 +1515,90 @@ bool CStaticFunctionDefinitions::AttachElements(CElement* pElement, CElement* pA
assert(pElement);
assert(pAttachedToElement);

if (pElement->IsAttachToable() && pAttachedToElement->IsAttachable() && !pAttachedToElement->IsAttachedToElement(pElement) &&
pElement->GetDimension() == pAttachedToElement->GetDimension())
if (!pElement->IsAttachToable() || !pAttachedToElement->IsAttachable() || pAttachedToElement->IsAttachedToElement(pElement) ||
pElement->GetDimension() != pAttachedToElement->GetDimension())
{
pElement->SetAttachedOffsets(vecPosition, vecRotation);
ConvertDegreesToRadians(vecRotation);
pElement->AttachTo(pAttachedToElement);
return false;
}

CBitStream BitStream;
BitStream.pBitStream->Write(pAttachedToElement->GetID());
BitStream.pBitStream->Write(vecPosition.fX);
BitStream.pBitStream->Write(vecPosition.fY);
BitStream.pBitStream->Write(vecPosition.fZ);
BitStream.pBitStream->Write(vecRotation.fX);
BitStream.pBitStream->Write(vecRotation.fY);
BitStream.pBitStream->Write(vecRotation.fZ);
m_pPlayerManager->BroadcastOnlyJoined(CElementRPCPacket(pElement, ATTACH_ELEMENTS, *BitStream.pBitStream));
CLuaArguments Arguments;
Arguments.PushElement(pAttachedToElement);
Arguments.PushNumber(vecPosition.fX);
Arguments.PushNumber(vecPosition.fY);
Arguments.PushNumber(vecPosition.fZ);
Arguments.PushNumber(vecRotation.fX);
Arguments.PushNumber(vecRotation.fY);
Arguments.PushNumber(vecRotation.fZ);

return true;
if (!pElement->CallEvent("onElementAttach", Arguments))
{
return false;
}

return false;
ConvertDegreesToRadians(vecRotation);

pElement->SetAttachedOffsets(vecPosition, vecRotation);
pElement->AttachTo(pAttachedToElement);

CBitStream BitStream;
BitStream.pBitStream->Write(pAttachedToElement->GetID());
BitStream.pBitStream->Write(vecPosition.fX);
BitStream.pBitStream->Write(vecPosition.fY);
BitStream.pBitStream->Write(vecPosition.fZ);
BitStream.pBitStream->Write(vecRotation.fX);
BitStream.pBitStream->Write(vecRotation.fY);
BitStream.pBitStream->Write(vecRotation.fZ);
m_pPlayerManager->BroadcastOnlyJoined(CElementRPCPacket(pElement, ATTACH_ELEMENTS, *BitStream.pBitStream));

return true;
}

bool CStaticFunctionDefinitions::DetachElements(CElement* pElement, CElement* pAttachedToElement)
{
assert(pElement);

CElement* pActualAttachedToElement = pElement->GetAttachedToElement();
if (pActualAttachedToElement)
if (!pActualAttachedToElement || (pAttachedToElement && pActualAttachedToElement != pAttachedToElement))
{
if (pAttachedToElement == NULL || pActualAttachedToElement == pAttachedToElement)
{
// Detach it. Also generate a new time context to prevent sync screwup from
// old packes arriving.
CVector vecPosition = pElement->GetPosition();
pElement->AttachTo(NULL);
pElement->GenerateSyncTimeContext();
return false;
}

CBitStream BitStream;
BitStream.pBitStream->Write(pElement->GetSyncTimeContext());
BitStream.pBitStream->Write(vecPosition.fX);
BitStream.pBitStream->Write(vecPosition.fY);
BitStream.pBitStream->Write(vecPosition.fZ);
m_pPlayerManager->BroadcastOnlyJoined(CElementRPCPacket(pElement, DETACH_ELEMENTS, *BitStream.pBitStream));
CVector vecPosition = pElement->GetPosition();
CVector vecRotation;

return true;
}
pElement->GetRotation(vecRotation);
ConvertRadiansToDegrees(vecRotation);

CLuaArguments Arguments;
Arguments.PushElement(pActualAttachedToElement);
Arguments.PushNumber(vecPosition.fX);
Arguments.PushNumber(vecPosition.fY);
Arguments.PushNumber(vecPosition.fZ);
Arguments.PushNumber(vecRotation.fX);
Arguments.PushNumber(vecRotation.fY);
Arguments.PushNumber(vecRotation.fZ);

if (!pElement->CallEvent("onElementDetach", Arguments))
{
return false;
}

return false;
// Detach it. Also generate a new time context to prevent sync screwup from
// old packets arriving.
pElement->AttachTo(NULL);
pElement->GenerateSyncTimeContext();

CBitStream BitStream;
BitStream.pBitStream->Write(pElement->GetSyncTimeContext());
BitStream.pBitStream->Write(vecPosition.fX);
BitStream.pBitStream->Write(vecPosition.fY);
BitStream.pBitStream->Write(vecPosition.fZ);
BitStream.pBitStream->Write(vecRotation.fX);
BitStream.pBitStream->Write(vecRotation.fY);
BitStream.pBitStream->Write(vecRotation.fZ);
m_pPlayerManager->BroadcastOnlyJoined(CElementRPCPacket(pElement, DETACH_ELEMENTS, *BitStream.pBitStream));
Nico8340 marked this conversation as resolved.
Show resolved Hide resolved

return true;
}

bool CStaticFunctionDefinitions::SetElementAlpha(CElement* pElement, unsigned char ucAlpha)
Expand Down
4 changes: 4 additions & 0 deletions Shared/sdk/net/bitstream.h
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,10 @@ enum class eBitStreamVersion : unsigned short
// 2023-10-12
CPlayerJoinCompletePacket_ServerName,

// Send rotation on detachElements
// 2024-04-12
DetachElementsRotation,

// This allows us to automatically increment the BitStreamVersion when things are added to this enum.
// Make sure you only add things above this comment.
Next,
Expand Down