6330: IServer: Add SnapNewItem() template to simplify the API, do some small refactoring r=def- a=Kaffeine

> What is the motivation for the changes of this pull request?

The idea is to simplify and refactor the game code step by step. This is the next step after a similar https://github.com/ddnet/ddnet/pull/5600

The key idea is that all those
```cpp
protocol7::CNetObj_SpectatorInfo *pSpectatorInfo = static_cast<protocol7::CNetObj_SpectatorInfo *>(Server()->SnapNewItem(NETOBJTYPE_SPECTATORINFO, m_ClientID, sizeof(protocol7::CNetObj_SpectatorInfo)));
```
are too verbose and error-prone.

We have the relation between `CNetObj_` classes and their corresponding `NETOBJTYPE_` so we can use it to remove most of the arguments and the cast.
With some small changes in the generated code (e.g. MsgID leveraged from NetMessage to NetObject) we can come to this:
```cpp
auto *pSpectatorInfo = Server()->SnapNewItem<protocol7::CNetObj_SpectatorInfo>(m_ClientID);
```
Yet, we do not use auto and personally I'm skeptic about `auto` in any non-obvious cases so I still keep the class name on the left side. The best show-case of the new API is:
```diff
`@@` -330,7 +330,7 `@@` void CGameContext::CreatePlayerSpawn(vec2 Pos, CClientMask Mask)
 void CGameContext::CreateDeath(vec2 Pos, int ClientID, CClientMask Mask)
 {
        // create the event
-       CNetEvent_Death *pEvent = (CNetEvent_Death *)m_Events.Create(NETEVENTTYPE_DEATH, sizeof(CNetEvent_Death), Mask);
+       CNetEvent_Death *pEvent = m_Events.Create<CNetEvent_Death>(Mask);
        if(pEvent)
        {
                pEvent->m_X = (int)Pos.x;
`@@` -345,7 +345,7 `@@` void CGameContext::CreateSound(vec2 Pos, int Sound, CClientMask Mask)
                return;
 
        // create a sound
-       CNetEvent_SoundWorld *pEvent = (CNetEvent_SoundWorld *)m_Events.Create(NETEVENTTYPE_SOUNDWORLD, sizeof(CNetEvent_SoundWorld), Mask);
+       CNetEvent_SoundWorld *pEvent = m_Events.Create<CNetEvent_SoundWorld>(Mask);
        if(pEvent)
        {
                pEvent->m_X = (int)Pos.x;
`@@` -376,7 +376,7 `@@` bool CGameContext::SnapLaserObject(const CSnapContext &Context, int SnapID, cons
 {
        if(Context.ClientVersion >= VERSION_DDNET_MULTI_LASER)
        {
-               CNetObj_DDNetLaser *pObj = static_cast<CNetObj_DDNetLaser *>(Server()->SnapNewItem(NETOBJTYPE_DDNETLASER, SnapID, sizeof(CNetObj_DDNetLaser)));
+               CNetObj_DDNetLaser *pObj = Server()->SnapNewItem<CNetObj_DDNetLaser>(SnapID);
                if(!pObj)
                        return false;
 
`@@` -390,7 +390,7 `@@` bool CGameContext::SnapLaserObject(const CSnapContext &Context, int SnapID, cons
        }
        else
        {
-               CNetObj_Laser *pObj = static_cast<CNetObj_Laser *>(Server()->SnapNewItem(NETOBJTYPE_LASER, SnapID, sizeof(CNetObj_Laser)));
+               CNetObj_Laser *pObj = Server()->SnapNewItem<CNetObj_Laser>(SnapID);
                if(!pObj)
                        return false;
```


The only difficulty is `protocol7` handling but I think I did it right (I had to change the logic for a bit and I still check it while waiting for your comments).

I can extract any of the commits to another PR if wanted.

As for 305670eecb I do not like to use CGameContext for the network stuff but we already have kinda similar helper functions and e.g. the NetObjHandlers there, and it is still a change to the better. **The long-term goal is to move that stuff to a new class** (e.g. some kind of protocol abstraction class or layer).

## Checklist

- [x] Tested the change ingame
- [ ] Provided screenshots if it is a visual change
- [ ] Tested in combination with possibly related configuration options
- [ ] Written a unit test (especially base/) or added coverage to integration test
- [ ] Considered possible null pointers and out of bounds array indexing
- [x] Changed no physics that affect existing maps
- [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional)


Co-authored-by: Alexander Akulich <akulichalexander@gmail.com>
This commit is contained in:
bors[bot] 2023-02-12 11:40:00 +00:00 committed by GitHub
commit cb68791901
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 173 additions and 251 deletions

View file

@ -220,6 +220,7 @@ class NetObject:
lines += [f"struct {self.struct_name} : public {self.base_struct_name}", "{"]
else:
lines += [f"struct {self.struct_name}", "{"]
lines += [f"\tstatic constexpr int ms_MsgID = {self.enum_name};"]
for v in self.variables:
lines += ["\t"+line for line in v.emit_declaration()]
lines += ["};"]
@ -286,7 +287,6 @@ class NetMessage(NetObject):
def emit_declaration(self):
extra = []
extra += [f"\tint MsgID() const {{ return {self.enum_name}; }}"]
extra += ["\t"]
extra += ["\tbool Pack(CMsgPacker *pPacker) const"]
extra += ["\t{"]

View file

@ -222,6 +222,8 @@ class NetObject:
lines = [f"struct {self.struct_name} : public {self.base_struct_name}", "{"]
else:
lines = [f"struct {self.struct_name}", "{"]
lines += ["\tusing is_sixup = char;"]
lines += [f"\tstatic constexpr int ms_MsgID = {self.enum_name};"]
for v in self.variables:
lines += ["\t"+line for line in v.emit_declaration()]
lines += ["};"]
@ -265,8 +267,6 @@ class NetMessage(NetObject):
return lines
def emit_declaration(self):
extra = []
extra += ["\tusing is_sixup = char;"]
extra += [f"\tint MsgID() const {{ return {self.enum_name}; }}"]
extra += ["\t"]
extra += ["\tbool Pack(CMsgPacker *pPacker) const"]
extra += ["\t{"]

View file

@ -233,7 +233,7 @@ public:
template<class T>
int SendPackMsgActive(T *pMsg, int Flags)
{
CMsgPacker Packer(pMsg->MsgID(), false);
CMsgPacker Packer(T::ms_MsgID, false);
if(pMsg->Pack(&Packer))
return -1;
return SendMsgActive(&Packer, Flags);

View file

@ -2189,7 +2189,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket, int Conn, bool Dummy)
}
}
MsgP.m_pMessage = aBufMsg;
CMsgPacker PackerTimeout(MsgP.MsgID(), false);
CMsgPacker PackerTimeout(&MsgP);
MsgP.Pack(&PackerTimeout);
SendMsg(Conn, &PackerTimeout, MSGFLAG_VITAL);
}

View file

@ -17,6 +17,12 @@ public:
{
Reset();
}
template<typename T>
CMsgPacker(const T *, bool System = false, bool NoTranslate = false) :
CMsgPacker(T::ms_MsgID, System, NoTranslate)
{
}
};
#endif

View file

@ -160,7 +160,7 @@ public:
int SendPackMsgOne(const T *pMsg, int Flags, int ClientID)
{
dbg_assert(ClientID != -1, "SendPackMsgOne called with -1");
CMsgPacker Packer(pMsg->MsgID(), false, protocol7::is_sixup<T>::value);
CMsgPacker Packer(T::ms_MsgID, false, protocol7::is_sixup<T>::value);
if(pMsg->Pack(&Packer))
return -1;
@ -214,6 +214,13 @@ public:
virtual void SnapFreeID(int ID) = 0;
virtual void *SnapNewItem(int Type, int ID, int Size) = 0;
template<typename T>
T *SnapNewItem(int ID)
{
const int Type = protocol7::is_sixup<T>::value ? -T::ms_MsgID : T::ms_MsgID;
return static_cast<T *>(SnapNewItem(Type, ID, sizeof(T)));
}
virtual void SnapSetStaticsize(int ItemType, int Size) = 0;
enum

View file

@ -1690,7 +1690,7 @@ void CGameClient::OnNewSnapshot()
Msg.m_X = x;
Msg.m_Y = y;
Client()->ChecksumData()->m_Zoom = ZoomToSend;
CMsgPacker Packer(Msg.MsgID(), false);
CMsgPacker Packer(&Msg);
Msg.Pack(&Packer);
if(ZoomToSend != m_LastZoom)
Client()->SendMsg(IClient::CONN_MAIN, &Packer, MSGFLAG_VITAL);
@ -2095,7 +2095,7 @@ void CGameClient::SendInfo(bool Start)
Msg.m_UseCustomColor = g_Config.m_ClPlayerUseCustomColor;
Msg.m_ColorBody = g_Config.m_ClPlayerColorBody;
Msg.m_ColorFeet = g_Config.m_ClPlayerColorFeet;
CMsgPacker Packer(Msg.MsgID(), false);
CMsgPacker Packer(&Msg);
Msg.Pack(&Packer);
Client()->SendMsg(IClient::CONN_MAIN, &Packer, MSGFLAG_VITAL);
m_aCheckInfo[0] = -1;
@ -2110,7 +2110,7 @@ void CGameClient::SendInfo(bool Start)
Msg.m_UseCustomColor = g_Config.m_ClPlayerUseCustomColor;
Msg.m_ColorBody = g_Config.m_ClPlayerColorBody;
Msg.m_ColorFeet = g_Config.m_ClPlayerColorFeet;
CMsgPacker Packer(Msg.MsgID(), false);
CMsgPacker Packer(&Msg);
Msg.Pack(&Packer);
Client()->SendMsg(IClient::CONN_MAIN, &Packer, MSGFLAG_VITAL);
m_aCheckInfo[0] = Client()->GameTickSpeed();
@ -2129,7 +2129,7 @@ void CGameClient::SendDummyInfo(bool Start)
Msg.m_UseCustomColor = g_Config.m_ClDummyUseCustomColor;
Msg.m_ColorBody = g_Config.m_ClDummyColorBody;
Msg.m_ColorFeet = g_Config.m_ClDummyColorFeet;
CMsgPacker Packer(Msg.MsgID(), false);
CMsgPacker Packer(&Msg);
Msg.Pack(&Packer);
Client()->SendMsg(IClient::CONN_DUMMY, &Packer, MSGFLAG_VITAL);
m_aCheckInfo[1] = -1;
@ -2144,7 +2144,7 @@ void CGameClient::SendDummyInfo(bool Start)
Msg.m_UseCustomColor = g_Config.m_ClDummyUseCustomColor;
Msg.m_ColorBody = g_Config.m_ClDummyColorBody;
Msg.m_ColorFeet = g_Config.m_ClDummyColorFeet;
CMsgPacker Packer(Msg.MsgID(), false);
CMsgPacker Packer(&Msg);
Msg.Pack(&Packer);
Client()->SendMsg(IClient::CONN_DUMMY, &Packer, MSGFLAG_VITAL);
m_aCheckInfo[1] = Client()->GameTickSpeed();

View file

@ -1041,7 +1041,7 @@ void CCharacter::SnapCharacter(int SnappingClient, int ID)
if(!Server()->IsSixup(SnappingClient))
{
CNetObj_Character *pCharacter = static_cast<CNetObj_Character *>(Server()->SnapNewItem(NETOBJTYPE_CHARACTER, ID, sizeof(CNetObj_Character)));
CNetObj_Character *pCharacter = Server()->SnapNewItem<CNetObj_Character>(ID);
if(!pCharacter)
return;
@ -1066,7 +1066,7 @@ void CCharacter::SnapCharacter(int SnappingClient, int ID)
}
else
{
protocol7::CNetObj_Character *pCharacter = static_cast<protocol7::CNetObj_Character *>(Server()->SnapNewItem(NETOBJTYPE_CHARACTER, ID, sizeof(protocol7::CNetObj_Character)));
protocol7::CNetObj_Character *pCharacter = Server()->SnapNewItem<protocol7::CNetObj_Character>(ID);
if(!pCharacter)
return;
@ -1152,7 +1152,7 @@ void CCharacter::Snap(int SnappingClient)
SnapCharacter(SnappingClient, ID);
CNetObj_DDNetCharacter *pDDNetCharacter = static_cast<CNetObj_DDNetCharacter *>(Server()->SnapNewItem(NETOBJTYPE_DDNETCHARACTER, ID, sizeof(CNetObj_DDNetCharacter)));
CNetObj_DDNetCharacter *pDDNetCharacter = Server()->SnapNewItem<CNetObj_DDNetCharacter>(ID);
if(!pDDNetCharacter)
return;

View file

@ -54,7 +54,7 @@ void CDoor::Snap(int SnappingClient)
CNetObj_EntityEx *pEntData = 0;
if(SnappingClientVersion >= VERSION_DDNET_SWITCH)
pEntData = static_cast<CNetObj_EntityEx *>(Server()->SnapNewItem(NETOBJTYPE_ENTITYEX, GetID(), sizeof(CNetObj_EntityEx)));
pEntData = Server()->SnapNewItem<CNetObj_EntityEx>(GetID());
vec2 From;
int StartTick;
@ -86,30 +86,6 @@ void CDoor::Snap(int SnappingClient)
StartTick = Server()->Tick();
}
if(SnappingClientVersion >= VERSION_DDNET_MULTI_LASER)
{
CNetObj_DDNetLaser *pObj = static_cast<CNetObj_DDNetLaser *>(Server()->SnapNewItem(NETOBJTYPE_DDNETLASER, GetID(), sizeof(CNetObj_DDNetLaser)));
if(!pObj)
return;
pObj->m_ToX = (int)m_Pos.x;
pObj->m_ToY = (int)m_Pos.y;
pObj->m_FromX = (int)From.x;
pObj->m_FromY = (int)From.y;
pObj->m_StartTick = StartTick;
pObj->m_Owner = -1;
pObj->m_Type = LASERTYPE_DOOR;
}
else
{
CNetObj_Laser *pObj = static_cast<CNetObj_Laser *>(Server()->SnapNewItem(NETOBJTYPE_LASER, GetID(), sizeof(CNetObj_Laser)));
if(!pObj)
return;
pObj->m_X = (int)m_Pos.x;
pObj->m_Y = (int)m_Pos.y;
pObj->m_FromX = (int)From.x;
pObj->m_FromY = (int)From.y;
pObj->m_StartTick = StartTick;
}
GameServer()->SnapLaserObject(CSnapContext(SnappingClientVersion), GetID(),
m_Pos, From, StartTick, -1, LASERTYPE_DOOR);
}

View file

@ -189,8 +189,7 @@ void CDragger::Snap(int SnappingClient)
CNetObj_EntityEx *pEntData = 0;
if(SnappingClientVersion >= VERSION_DDNET_SWITCH)
{
pEntData = static_cast<CNetObj_EntityEx *>(Server()->SnapNewItem(NETOBJTYPE_ENTITYEX, GetID(),
sizeof(CNetObj_EntityEx)));
pEntData = Server()->SnapNewItem<CNetObj_EntityEx>(GetID());
if(pEntData)
{
pEntData->m_SwitchNumber = m_Number;
@ -225,30 +224,6 @@ void CDragger::Snap(int SnappingClient)
StartTick = Server()->Tick();
}
if(SnappingClientVersion >= VERSION_DDNET_MULTI_LASER)
{
CNetObj_DDNetLaser *pObj = static_cast<CNetObj_DDNetLaser *>(Server()->SnapNewItem(NETOBJTYPE_DDNETLASER, GetID(), sizeof(CNetObj_DDNetLaser)));
if(!pObj)
return;
pObj->m_ToX = (int)m_Pos.x;
pObj->m_ToY = (int)m_Pos.y;
pObj->m_FromX = (int)m_Pos.x;
pObj->m_FromY = (int)m_Pos.y;
pObj->m_StartTick = StartTick;
pObj->m_Owner = -1;
pObj->m_Type = LASERTYPE_DOOR;
}
else
{
CNetObj_Laser *pObj = static_cast<CNetObj_Laser *>(Server()->SnapNewItem(NETOBJTYPE_LASER, GetID(), sizeof(CNetObj_Laser)));
if(!pObj)
return;
pObj->m_X = (int)m_Pos.x;
pObj->m_Y = (int)m_Pos.y;
pObj->m_FromX = (int)m_Pos.x;
pObj->m_FromY = (int)m_Pos.y;
pObj->m_StartTick = StartTick;
}
GameServer()->SnapLaserObject(CSnapContext(SnappingClientVersion), GetID(),
m_Pos, m_Pos, StartTick, -1, LASERTYPE_DOOR);
}

View file

@ -119,30 +119,7 @@ void CDraggerBeam::Snap(int SnappingClient)
StartTick = Server()->Tick();
}
if(GameServer()->GetClientVersion(SnappingClient) >= VERSION_DDNET_MULTI_LASER)
{
CNetObj_DDNetLaser *pObj = static_cast<CNetObj_DDNetLaser *>(Server()->SnapNewItem(NETOBJTYPE_DDNETLASER, GetID(), sizeof(CNetObj_DDNetLaser)));
if(!pObj)
return;
pObj->m_ToX = (int)m_Pos.x;
pObj->m_ToY = (int)m_Pos.y;
pObj->m_FromX = (int)TargetPos.x;
pObj->m_FromY = (int)TargetPos.y;
pObj->m_StartTick = StartTick;
pObj->m_Owner = -1;
pObj->m_Type = LASERTYPE_DOOR;
}
else
{
CNetObj_Laser *pObj = static_cast<CNetObj_Laser *>(Server()->SnapNewItem(NETOBJTYPE_LASER, GetID(), sizeof(CNetObj_Laser)));
if(!pObj)
return;
pObj->m_X = (int)m_Pos.x;
pObj->m_Y = (int)m_Pos.y;
pObj->m_FromX = (int)TargetPos.x;
pObj->m_FromY = (int)TargetPos.y;
pObj->m_StartTick = StartTick;
}
int SnappingClientVersion = GameServer()->GetClientVersion(SnappingClient);
GameServer()->SnapLaserObject(CSnapContext(SnappingClientVersion), GetID(),
m_Pos, TargetPos, StartTick, -1, LASERTYPE_DOOR);
}

View file

@ -188,30 +188,6 @@ void CGun::Snap(int SnappingClient)
int StartTick = pEntData ? 0 : m_EvalTick;
if(SnappingClientVersion >= VERSION_DDNET_MULTI_LASER)
{
CNetObj_DDNetLaser *pObj = static_cast<CNetObj_DDNetLaser *>(Server()->SnapNewItem(NETOBJTYPE_DDNETLASER, GetID(), sizeof(CNetObj_DDNetLaser)));
if(!pObj)
return;
pObj->m_ToX = (int)m_Pos.x;
pObj->m_ToY = (int)m_Pos.y;
pObj->m_FromX = (int)m_Pos.x;
pObj->m_FromY = (int)m_Pos.y;
pObj->m_StartTick = StartTick;
pObj->m_Owner = -1;
pObj->m_Type = m_Freeze ? LASERTYPE_FREEZE : LASERTYPE_RIFLE;
}
else
{
CNetObj_Laser *pObj = static_cast<CNetObj_Laser *>(Server()->SnapNewItem(NETOBJTYPE_LASER, GetID(), sizeof(CNetObj_Laser)));
if(!pObj)
return;
pObj->m_X = (int)m_Pos.x;
pObj->m_Y = (int)m_Pos.y;
pObj->m_FromX = (int)m_Pos.x;
pObj->m_FromY = (int)m_Pos.y;
pObj->m_StartTick = StartTick;
}
GameServer()->SnapLaserObject(CSnapContext(SnappingClientVersion), GetID(),
m_Pos, m_Pos, StartTick, -1, m_Freeze ? LASERTYPE_FREEZE : LASERTYPE_RIFLE);
}

View file

@ -314,32 +314,10 @@ void CLaser::Snap(int SnappingClient)
if(SnappingClient != SERVER_DEMO_CLIENT && !TeamMask.test(SnappingClient))
return;
if(GameServer()->GetClientVersion(SnappingClient) >= VERSION_DDNET_MULTI_LASER)
{
CNetObj_DDNetLaser *pObj = static_cast<CNetObj_DDNetLaser *>(Server()->SnapNewItem(NETOBJTYPE_DDNETLASER, GetID(), sizeof(CNetObj_DDNetLaser)));
if(!pObj)
return;
pObj->m_ToX = (int)m_Pos.x;
pObj->m_ToY = (int)m_Pos.y;
pObj->m_FromX = (int)m_From.x;
pObj->m_FromY = (int)m_From.y;
pObj->m_StartTick = m_EvalTick;
pObj->m_Owner = m_Owner;
pObj->m_Type = m_Type == WEAPON_LASER ? LASERTYPE_RIFLE : m_Type == WEAPON_SHOTGUN ? LASERTYPE_SHOTGUN : -1;
}
else
{
CNetObj_Laser *pObj = static_cast<CNetObj_Laser *>(Server()->SnapNewItem(NETOBJTYPE_LASER, GetID(), sizeof(CNetObj_Laser)));
if(!pObj)
return;
pObj->m_X = (int)m_Pos.x;
pObj->m_Y = (int)m_Pos.y;
pObj->m_FromX = (int)m_From.x;
pObj->m_FromY = (int)m_From.y;
pObj->m_StartTick = m_EvalTick;
}
int SnappingClientVersion = GameServer()->GetClientVersion(SnappingClient);
int LaserType = m_Type == WEAPON_LASER ? LASERTYPE_RIFLE : m_Type == WEAPON_SHOTGUN ? LASERTYPE_SHOTGUN : -1;
GameServer()->SnapLaserObject(CSnapContext(SnappingClientVersion), GetID(),
m_Pos, m_From, m_EvalTick, m_Owner, LaserType);
}
void CLaser::SwapClients(int Client1, int Client2)

View file

@ -154,30 +154,6 @@ void CLight::Snap(int SnappingClient)
StartTick = Server()->Tick();
}
if(SnappingClientVersion >= VERSION_DDNET_MULTI_LASER)
{
CNetObj_DDNetLaser *pObj = static_cast<CNetObj_DDNetLaser *>(Server()->SnapNewItem(NETOBJTYPE_DDNETLASER, GetID(), sizeof(CNetObj_DDNetLaser)));
if(!pObj)
return;
pObj->m_ToX = (int)m_Pos.x;
pObj->m_ToY = (int)m_Pos.y;
pObj->m_FromX = (int)From.x;
pObj->m_FromY = (int)From.y;
pObj->m_StartTick = StartTick;
pObj->m_Owner = -1;
pObj->m_Type = LASERTYPE_FREEZE;
}
else
{
CNetObj_Laser *pObj = static_cast<CNetObj_Laser *>(Server()->SnapNewItem(NETOBJTYPE_LASER, GetID(), sizeof(CNetObj_Laser)));
if(!pObj)
return;
pObj->m_X = (int)m_Pos.x;
pObj->m_Y = (int)m_Pos.y;
pObj->m_FromX = (int)From.x;
pObj->m_FromY = (int)From.y;
pObj->m_StartTick = StartTick;
}
GameServer()->SnapLaserObject(CSnapContext(SnappingClientVersion), GetID(),
m_Pos, From, StartTick, -1, LASERTYPE_FREEZE);
}

View file

@ -173,10 +173,11 @@ void CPickup::Snap(int SnappingClient)
pChar = GameServer()->GetPlayerChar(GameServer()->m_apPlayers[SnappingClient]->m_SpectatorID);
int SnappingClientVersion = GameServer()->GetClientVersion(SnappingClient);
bool Sixup = SnappingClientVersion == VERSION_NONE ? Server()->IsSixup(SnappingClient) : false;
CNetObj_EntityEx *pEntData = 0;
if(SnappingClientVersion >= VERSION_DDNET_SWITCH && (m_Layer == LAYER_SWITCH || length(m_Core) > 0))
pEntData = static_cast<CNetObj_EntityEx *>(Server()->SnapNewItem(NETOBJTYPE_ENTITYEX, GetID(), sizeof(CNetObj_EntityEx)));
pEntData = Server()->SnapNewItem<CNetObj_EntityEx>(GetID());
if(pEntData)
{
@ -191,30 +192,7 @@ void CPickup::Snap(int SnappingClient)
return;
}
int Size = Server()->IsSixup(SnappingClient) ? 3 * 4 : sizeof(CNetObj_Pickup);
CNetObj_Pickup *pPickup = static_cast<CNetObj_Pickup *>(Server()->SnapNewItem(NETOBJTYPE_PICKUP, GetID(), Size));
if(!pPickup)
return;
pPickup->m_X = (int)m_Pos.x;
pPickup->m_Y = (int)m_Pos.y;
pPickup->m_Type = m_Type;
if(SnappingClientVersion < VERSION_DDNET_WEAPON_SHIELDS)
{
if(m_Type >= POWERUP_ARMOR_SHOTGUN && m_Type <= POWERUP_ARMOR_LASER)
{
pPickup->m_Type = POWERUP_ARMOR;
}
}
if(Server()->IsSixup(SnappingClient))
{
if(m_Type == POWERUP_WEAPON)
pPickup->m_Type = m_Subtype == WEAPON_SHOTGUN ? 3 : m_Subtype == WEAPON_GRENADE ? 2 : 4;
else if(m_Type == POWERUP_NINJA)
pPickup->m_Type = 5;
}
else
pPickup->m_Subtype = m_Subtype;
GameServer()->SnapPickup(CSnapContext(SnappingClientVersion, Sixup), GetID(), m_Pos, m_Type, m_Subtype);
}
void CPickup::Move()

View file

@ -118,30 +118,7 @@ void CPlasma::Snap(int SnappingClient)
if(NetworkClipped(SnappingClient))
return;
if(GameServer()->GetClientVersion(SnappingClient) >= VERSION_DDNET_MULTI_LASER)
{
CNetObj_DDNetLaser *pObj = static_cast<CNetObj_DDNetLaser *>(Server()->SnapNewItem(NETOBJTYPE_DDNETLASER, GetID(), sizeof(CNetObj_DDNetLaser)));
if(!pObj)
return;
pObj->m_ToX = (int)m_Pos.x;
pObj->m_ToY = (int)m_Pos.y;
pObj->m_FromX = (int)m_Pos.x;
pObj->m_FromY = (int)m_Pos.y;
pObj->m_StartTick = m_EvalTick;
pObj->m_Owner = -1;
pObj->m_Type = m_Freeze ? LASERTYPE_FREEZE : LASERTYPE_RIFLE;
}
else
{
CNetObj_Laser *pObj = static_cast<CNetObj_Laser *>(Server()->SnapNewItem(NETOBJTYPE_LASER, GetID(), sizeof(CNetObj_Laser)));
if(!pObj)
return;
pObj->m_X = (int)m_Pos.x;
pObj->m_Y = (int)m_Pos.y;
pObj->m_FromX = (int)m_Pos.x;
pObj->m_FromY = (int)m_Pos.y;
pObj->m_StartTick = m_EvalTick;
}
int SnappingClientVersion = GameServer()->GetClientVersion(SnappingClient);
GameServer()->SnapLaserObject(CSnapContext(SnappingClientVersion), GetID(),
m_Pos, m_Pos, m_EvalTick, -1, m_Freeze ? LASERTYPE_FREEZE : LASERTYPE_RIFLE);
}

View file

@ -307,7 +307,7 @@ void CProjectile::Snap(int SnappingClient)
if(m_LifeSpan == -2)
{
CNetObj_EntityEx *pEntData = static_cast<CNetObj_EntityEx *>(Server()->SnapNewItem(NETOBJTYPE_ENTITYEX, GetID(), sizeof(CNetObj_EntityEx)));
CNetObj_EntityEx *pEntData = Server()->SnapNewItem<CNetObj_EntityEx>(GetID());
if(!pEntData)
return;
@ -350,7 +350,7 @@ void CProjectile::Snap(int SnappingClient)
}
else
{
CNetObj_Projectile *pProj = static_cast<CNetObj_Projectile *>(Server()->SnapNewItem(NETOBJTYPE_PROJECTILE, GetID(), sizeof(CNetObj_Projectile)));
CNetObj_Projectile *pProj = Server()->SnapNewItem<CNetObj_Projectile>(GetID());
if(!pProj)
{
return;

View file

@ -32,6 +32,13 @@ public:
CEventHandler();
void *Create(int Type, int Size, CClientMask Mask = CClientMask().set());
template<typename T>
T *Create(CClientMask Mask = CClientMask().set())
{
return static_cast<T *>(Create(T::ms_MsgID, sizeof(T), Mask));
}
void Clear();
void Snap(int SnappingClient);

View file

@ -239,7 +239,7 @@ void CGameContext::CreateDamageInd(vec2 Pos, float Angle, int Amount, CClientMas
for(int i = 0; i < Amount; i++)
{
float f = mix(s, e, (i + 1) / (float)(Amount + 2));
CNetEvent_DamageInd *pEvent = (CNetEvent_DamageInd *)m_Events.Create(NETEVENTTYPE_DAMAGEIND, sizeof(CNetEvent_DamageInd), Mask);
CNetEvent_DamageInd *pEvent = m_Events.Create<CNetEvent_DamageInd>(Mask);
if(pEvent)
{
pEvent->m_X = (int)Pos.x;
@ -252,7 +252,7 @@ void CGameContext::CreateDamageInd(vec2 Pos, float Angle, int Amount, CClientMas
void CGameContext::CreateHammerHit(vec2 Pos, CClientMask Mask)
{
// create the event
CNetEvent_HammerHit *pEvent = (CNetEvent_HammerHit *)m_Events.Create(NETEVENTTYPE_HAMMERHIT, sizeof(CNetEvent_HammerHit), Mask);
CNetEvent_HammerHit *pEvent = m_Events.Create<CNetEvent_HammerHit>(Mask);
if(pEvent)
{
pEvent->m_X = (int)Pos.x;
@ -263,7 +263,7 @@ void CGameContext::CreateHammerHit(vec2 Pos, CClientMask Mask)
void CGameContext::CreateExplosion(vec2 Pos, int Owner, int Weapon, bool NoDamage, int ActivatedTeam, CClientMask Mask)
{
// create the event
CNetEvent_Explosion *pEvent = (CNetEvent_Explosion *)m_Events.Create(NETEVENTTYPE_EXPLOSION, sizeof(CNetEvent_Explosion), Mask);
CNetEvent_Explosion *pEvent = m_Events.Create<CNetEvent_Explosion>(Mask);
if(pEvent)
{
pEvent->m_X = (int)Pos.x;
@ -319,7 +319,7 @@ void CGameContext::CreateExplosion(vec2 Pos, int Owner, int Weapon, bool NoDamag
void CGameContext::CreatePlayerSpawn(vec2 Pos, CClientMask Mask)
{
// create the event
CNetEvent_Spawn *pEvent = (CNetEvent_Spawn *)m_Events.Create(NETEVENTTYPE_SPAWN, sizeof(CNetEvent_Spawn), Mask);
CNetEvent_Spawn *pEvent = m_Events.Create<CNetEvent_Spawn>(Mask);
if(pEvent)
{
pEvent->m_X = (int)Pos.x;
@ -330,7 +330,7 @@ void CGameContext::CreatePlayerSpawn(vec2 Pos, CClientMask Mask)
void CGameContext::CreateDeath(vec2 Pos, int ClientID, CClientMask Mask)
{
// create the event
CNetEvent_Death *pEvent = (CNetEvent_Death *)m_Events.Create(NETEVENTTYPE_DEATH, sizeof(CNetEvent_Death), Mask);
CNetEvent_Death *pEvent = m_Events.Create<CNetEvent_Death>(Mask);
if(pEvent)
{
pEvent->m_X = (int)Pos.x;
@ -345,7 +345,7 @@ void CGameContext::CreateSound(vec2 Pos, int Sound, CClientMask Mask)
return;
// create a sound
CNetEvent_SoundWorld *pEvent = (CNetEvent_SoundWorld *)m_Events.Create(NETEVENTTYPE_SOUNDWORLD, sizeof(CNetEvent_SoundWorld), Mask);
CNetEvent_SoundWorld *pEvent = m_Events.Create<CNetEvent_SoundWorld>(Mask);
if(pEvent)
{
pEvent->m_X = (int)Pos.x;
@ -372,6 +372,77 @@ void CGameContext::CreateSoundGlobal(int Sound, int Target)
}
}
bool CGameContext::SnapLaserObject(const CSnapContext &Context, int SnapID, const vec2 &To, const vec2 &From, int StartTick, int Owner, int LaserType)
{
if(Context.GetClientVersion() >= VERSION_DDNET_MULTI_LASER)
{
CNetObj_DDNetLaser *pObj = Server()->SnapNewItem<CNetObj_DDNetLaser>(SnapID);
if(!pObj)
return false;
pObj->m_ToX = (int)To.x;
pObj->m_ToY = (int)To.y;
pObj->m_FromX = (int)From.x;
pObj->m_FromY = (int)From.y;
pObj->m_StartTick = StartTick;
pObj->m_Owner = Owner;
pObj->m_Type = LaserType;
}
else
{
CNetObj_Laser *pObj = Server()->SnapNewItem<CNetObj_Laser>(SnapID);
if(!pObj)
return false;
pObj->m_X = (int)To.x;
pObj->m_Y = (int)To.y;
pObj->m_FromX = (int)From.x;
pObj->m_FromY = (int)From.y;
pObj->m_StartTick = StartTick;
}
return true;
}
bool CGameContext::SnapPickup(const CSnapContext &Context, int SnapID, const vec2 &Pos, int Type, int SubType)
{
if(Context.IsSixup())
{
protocol7::CNetObj_Pickup *pPickup = Server()->SnapNewItem<protocol7::CNetObj_Pickup>(SnapID);
if(!pPickup)
return false;
pPickup->m_X = (int)Pos.x;
pPickup->m_Y = (int)Pos.y;
if(Type == POWERUP_WEAPON)
pPickup->m_Type = SubType == WEAPON_SHOTGUN ? protocol7::PICKUP_SHOTGUN : SubType == WEAPON_GRENADE ? protocol7::PICKUP_GRENADE : protocol7::PICKUP_LASER;
else if(Type == POWERUP_NINJA)
pPickup->m_Type = protocol7::PICKUP_NINJA;
}
else
{
CNetObj_Pickup *pPickup = Server()->SnapNewItem<CNetObj_Pickup>(SnapID);
if(!pPickup)
return false;
pPickup->m_X = (int)Pos.x;
pPickup->m_Y = (int)Pos.y;
pPickup->m_Type = Type;
if(Context.GetClientVersion() < VERSION_DDNET_WEAPON_SHIELDS)
{
if(Type >= POWERUP_ARMOR_SHOTGUN && Type <= POWERUP_ARMOR_LASER)
{
pPickup->m_Type = POWERUP_ARMOR;
}
}
pPickup->m_Subtype = SubType;
}
return true;
}
void CGameContext::CallVote(int ClientID, const char *pDesc, const char *pCmd, const char *pReason, const char *pChatmsg, const char *pSixupDesc)
{
// check if a vote is already running
@ -403,7 +474,7 @@ void CGameContext::SendChatTarget(int To, const char *pText, int Flags)
Msg.m_pMessage = pText;
if(g_Config.m_SvDemoChat)
Server()->SendPackMsg(&Msg, MSGFLAG_VITAL | MSGFLAG_NOSEND, -1);
Server()->SendPackMsg(&Msg, MSGFLAG_VITAL | MSGFLAG_NOSEND, SERVER_DEMO_CLIENT);
if(To == -1)
{
@ -462,7 +533,7 @@ void CGameContext::SendChat(int ChatterClientID, int Team, const char *pText, in
// pack one for the recording only
if(g_Config.m_SvDemoChat)
Server()->SendPackMsg(&Msg, MSGFLAG_VITAL | MSGFLAG_NOSEND, -1);
Server()->SendPackMsg(&Msg, MSGFLAG_VITAL | MSGFLAG_NOSEND, SERVER_DEMO_CLIENT);
// send to the clients
for(int i = 0; i < Server()->MaxClients(); i++)
@ -489,7 +560,7 @@ void CGameContext::SendChat(int ChatterClientID, int Team, const char *pText, in
// pack one for the recording only
if(g_Config.m_SvDemoChat)
Server()->SendPackMsg(&Msg, MSGFLAG_VITAL | MSGFLAG_NOSEND, -1);
Server()->SendPackMsg(&Msg, MSGFLAG_VITAL | MSGFLAG_NOSEND, SERVER_DEMO_CLIENT);
// send to the clients
for(int i = 0; i < Server()->MaxClients(); i++)

View file

@ -59,6 +59,21 @@ class IStorage;
struct CAntibotRoundData;
struct CScoreRandomMapResult;
struct CSnapContext
{
CSnapContext(int Version, bool Sixup = false) :
m_ClientVersion(Version), m_Sixup(Sixup)
{
}
int GetClientVersion() const { return m_ClientVersion; }
bool IsSixup() const { return m_Sixup; }
private:
int m_ClientVersion;
bool m_Sixup;
};
class CGameContext : public IGameServer
{
IServer *m_pServer;
@ -213,6 +228,9 @@ public:
void CreateSound(vec2 Pos, int Sound, CClientMask Mask = CClientMask().set());
void CreateSoundGlobal(int Sound, int Target = -1);
bool SnapLaserObject(const CSnapContext &Context, int SnapID, const vec2 &To, const vec2 &From, int StartTick, int Owner = -1, int LaserType = -1);
bool SnapPickup(const CSnapContext &Context, int SnapID, const vec2 &Pos, int Type, int SubType);
enum
{
CHAT_ALL = -2,

View file

@ -532,7 +532,7 @@ void IGameController::Tick()
void IGameController::Snap(int SnappingClient)
{
CNetObj_GameInfo *pGameInfoObj = (CNetObj_GameInfo *)Server()->SnapNewItem(NETOBJTYPE_GAMEINFO, 0, sizeof(CNetObj_GameInfo));
CNetObj_GameInfo *pGameInfoObj = Server()->SnapNewItem<CNetObj_GameInfo>(0);
if(!pGameInfoObj)
return;
@ -571,7 +571,7 @@ void IGameController::Snap(int SnappingClient)
}
}
CNetObj_GameInfoEx *pGameInfoEx = (CNetObj_GameInfoEx *)Server()->SnapNewItem(NETOBJTYPE_GAMEINFOEX, 0, sizeof(CNetObj_GameInfoEx));
CNetObj_GameInfoEx *pGameInfoEx = Server()->SnapNewItem<CNetObj_GameInfoEx>(0);
if(!pGameInfoEx)
return;
@ -600,7 +600,7 @@ void IGameController::Snap(int SnappingClient)
if(Server()->IsSixup(SnappingClient))
{
protocol7::CNetObj_GameData *pGameData = static_cast<protocol7::CNetObj_GameData *>(Server()->SnapNewItem(-protocol7::NETOBJTYPE_GAMEDATA, 0, sizeof(protocol7::CNetObj_GameData)));
protocol7::CNetObj_GameData *pGameData = Server()->SnapNewItem<protocol7::CNetObj_GameData>(0);
if(!pGameData)
return;
@ -615,7 +615,7 @@ void IGameController::Snap(int SnappingClient)
pGameData->m_GameStateEndTick = 0;
protocol7::CNetObj_GameDataRace *pRaceData = static_cast<protocol7::CNetObj_GameDataRace *>(Server()->SnapNewItem(-protocol7::NETOBJTYPE_GAMEDATARACE, 0, sizeof(protocol7::CNetObj_GameDataRace)));
protocol7::CNetObj_GameDataRace *pRaceData = Server()->SnapNewItem<protocol7::CNetObj_GameDataRace>(0);
if(!pRaceData)
return;
@ -634,7 +634,7 @@ void IGameController::Snap(int SnappingClient)
if(Team == TEAM_SUPER)
return;
CNetObj_SwitchState *pSwitchState = static_cast<CNetObj_SwitchState *>(Server()->SnapNewItem(NETOBJTYPE_SWITCHSTATE, Team, sizeof(CNetObj_SwitchState)));
CNetObj_SwitchState *pSwitchState = Server()->SnapNewItem<CNetObj_SwitchState>(Team);
if(!pSwitchState)
return;

View file

@ -323,7 +323,7 @@ void CPlayer::Snap(int SnappingClient)
if(!Server()->Translate(id, SnappingClient))
return;
CNetObj_ClientInfo *pClientInfo = static_cast<CNetObj_ClientInfo *>(Server()->SnapNewItem(NETOBJTYPE_CLIENTINFO, id, sizeof(CNetObj_ClientInfo)));
CNetObj_ClientInfo *pClientInfo = Server()->SnapNewItem<CNetObj_ClientInfo>(id);
if(!pClientInfo)
return;
@ -345,7 +345,7 @@ void CPlayer::Snap(int SnappingClient)
if(!Server()->IsSixup(SnappingClient))
{
CNetObj_PlayerInfo *pPlayerInfo = static_cast<CNetObj_PlayerInfo *>(Server()->SnapNewItem(NETOBJTYPE_PLAYERINFO, id, sizeof(CNetObj_PlayerInfo)));
CNetObj_PlayerInfo *pPlayerInfo = Server()->SnapNewItem<CNetObj_PlayerInfo>(id);
if(!pPlayerInfo)
return;
@ -362,7 +362,7 @@ void CPlayer::Snap(int SnappingClient)
}
else
{
protocol7::CNetObj_PlayerInfo *pPlayerInfo = static_cast<protocol7::CNetObj_PlayerInfo *>(Server()->SnapNewItem(NETOBJTYPE_PLAYERINFO, id, sizeof(protocol7::CNetObj_PlayerInfo)));
protocol7::CNetObj_PlayerInfo *pPlayerInfo = Server()->SnapNewItem<protocol7::CNetObj_PlayerInfo>(id);
if(!pPlayerInfo)
return;
@ -381,7 +381,7 @@ void CPlayer::Snap(int SnappingClient)
{
if(!Server()->IsSixup(SnappingClient))
{
CNetObj_SpectatorInfo *pSpectatorInfo = static_cast<CNetObj_SpectatorInfo *>(Server()->SnapNewItem(NETOBJTYPE_SPECTATORINFO, m_ClientID, sizeof(CNetObj_SpectatorInfo)));
CNetObj_SpectatorInfo *pSpectatorInfo = Server()->SnapNewItem<CNetObj_SpectatorInfo>(m_ClientID);
if(!pSpectatorInfo)
return;
@ -391,7 +391,7 @@ void CPlayer::Snap(int SnappingClient)
}
else
{
protocol7::CNetObj_SpectatorInfo *pSpectatorInfo = static_cast<protocol7::CNetObj_SpectatorInfo *>(Server()->SnapNewItem(NETOBJTYPE_SPECTATORINFO, m_ClientID, sizeof(protocol7::CNetObj_SpectatorInfo)));
protocol7::CNetObj_SpectatorInfo *pSpectatorInfo = Server()->SnapNewItem<protocol7::CNetObj_SpectatorInfo>(m_ClientID);
if(!pSpectatorInfo)
return;
@ -402,7 +402,7 @@ void CPlayer::Snap(int SnappingClient)
}
}
CNetObj_DDNetPlayer *pDDNetPlayer = static_cast<CNetObj_DDNetPlayer *>(Server()->SnapNewItem(NETOBJTYPE_DDNETPLAYER, id, sizeof(CNetObj_DDNetPlayer)));
CNetObj_DDNetPlayer *pDDNetPlayer = Server()->SnapNewItem<CNetObj_DDNetPlayer>(id);
if(!pDDNetPlayer)
return;
@ -418,7 +418,7 @@ void CPlayer::Snap(int SnappingClient)
if(Server()->IsSixup(SnappingClient) && m_pCharacter && m_pCharacter->m_DDRaceState == DDRACE_STARTED &&
GameServer()->m_apPlayers[SnappingClient]->m_TimerType == TIMERTYPE_SIXUP)
{
protocol7::CNetObj_PlayerInfoRace *pRaceInfo = static_cast<protocol7::CNetObj_PlayerInfoRace *>(Server()->SnapNewItem(-protocol7::NETOBJTYPE_PLAYERINFORACE, id, sizeof(protocol7::CNetObj_PlayerInfoRace)));
protocol7::CNetObj_PlayerInfoRace *pRaceInfo = Server()->SnapNewItem<protocol7::CNetObj_PlayerInfoRace>(id);
if(!pRaceInfo)
return;
pRaceInfo->m_RaceStartTick = m_pCharacter->m_StartTime;
@ -434,7 +434,7 @@ void CPlayer::Snap(int SnappingClient)
if(ShowSpec)
{
CNetObj_SpecChar *pSpecChar = static_cast<CNetObj_SpecChar *>(Server()->SnapNewItem(NETOBJTYPE_SPECCHAR, id, sizeof(CNetObj_SpecChar)));
CNetObj_SpecChar *pSpecChar = Server()->SnapNewItem<CNetObj_SpecChar>(id);
if(!pSpecChar)
return;
@ -453,7 +453,7 @@ void CPlayer::FakeSnap()
int FakeID = VANILLA_MAX_CLIENTS - 1;
CNetObj_ClientInfo *pClientInfo = static_cast<CNetObj_ClientInfo *>(Server()->SnapNewItem(NETOBJTYPE_CLIENTINFO, FakeID, sizeof(CNetObj_ClientInfo)));
CNetObj_ClientInfo *pClientInfo = Server()->SnapNewItem<CNetObj_ClientInfo>(FakeID);
if(!pClientInfo)
return;
@ -465,7 +465,7 @@ void CPlayer::FakeSnap()
if(m_Paused != PAUSE_PAUSED)
return;
CNetObj_PlayerInfo *pPlayerInfo = static_cast<CNetObj_PlayerInfo *>(Server()->SnapNewItem(NETOBJTYPE_PLAYERINFO, FakeID, sizeof(CNetObj_PlayerInfo)));
CNetObj_PlayerInfo *pPlayerInfo = Server()->SnapNewItem<CNetObj_PlayerInfo>(FakeID);
if(!pPlayerInfo)
return;
@ -475,7 +475,7 @@ void CPlayer::FakeSnap()
pPlayerInfo->m_Score = -9999;
pPlayerInfo->m_Team = TEAM_SPECTATORS;
CNetObj_SpectatorInfo *pSpectatorInfo = static_cast<CNetObj_SpectatorInfo *>(Server()->SnapNewItem(NETOBJTYPE_SPECTATORINFO, FakeID, sizeof(CNetObj_SpectatorInfo)));
CNetObj_SpectatorInfo *pSpectatorInfo = Server()->SnapNewItem<CNetObj_SpectatorInfo>(FakeID);
if(!pSpectatorInfo)
return;