1/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
2/* If you are missing that file, acquire a complete release at teeworlds.com. */
3#include "eventhandler.h"
4
5#include "entity.h"
6#include "gamecontext.h"
7
8#include <base/system.h>
9#include <base/vmath.h>
10
11//////////////////////////////////////////////////
12// Event handler
13//////////////////////////////////////////////////
14CEventHandler::CEventHandler()
15{
16 m_pGameServer = 0;
17 Clear();
18}
19
20void CEventHandler::SetGameServer(CGameContext *pGameServer)
21{
22 m_pGameServer = pGameServer;
23}
24
25void *CEventHandler::Create(int Type, int Size, CClientMask Mask)
26{
27 if(m_NumEvents == MAX_EVENTS)
28 return 0;
29 if(m_CurrentOffset + Size >= MAX_DATASIZE)
30 return 0;
31
32 void *p = &m_aData[m_CurrentOffset];
33 m_aOffsets[m_NumEvents] = m_CurrentOffset;
34 m_aTypes[m_NumEvents] = Type;
35 m_aSizes[m_NumEvents] = Size;
36 m_aClientMasks[m_NumEvents] = Mask;
37 m_CurrentOffset += Size;
38 m_NumEvents++;
39 return p;
40}
41
42void CEventHandler::Clear()
43{
44 m_NumEvents = 0;
45 m_CurrentOffset = 0;
46}
47
48void CEventHandler::Snap(int SnappingClient)
49{
50 for(int i = 0; i < m_NumEvents; i++)
51 {
52 if(SnappingClient == SERVER_DEMO_CLIENT || m_aClientMasks[i].test(position: SnappingClient))
53 {
54 CNetEvent_Common *pEvent = (CNetEvent_Common *)&m_aData[m_aOffsets[i]];
55 if(!NetworkClipped(pGameServer: GameServer(), SnappingClient, CheckPos: vec2(pEvent->m_X, pEvent->m_Y)))
56 {
57 int Type = m_aTypes[i];
58 int Size = m_aSizes[i];
59 const char *pData = &m_aData[m_aOffsets[i]];
60 if(GameServer()->Server()->IsSixup(ClientId: SnappingClient))
61 EventToSixup(pType: &Type, pSize: &Size, ppData: &pData);
62
63 void *pItem = GameServer()->Server()->SnapNewItem(Type, Id: i, Size);
64 if(pItem)
65 mem_copy(dest: pItem, source: pData, size: Size);
66 }
67 }
68 }
69}
70
71void CEventHandler::EventToSixup(int *pType, int *pSize, const char **ppData)
72{
73 static char s_aEventStore[128];
74 if(*pType == NETEVENTTYPE_DAMAGEIND)
75 {
76 const CNetEvent_DamageInd *pEvent = (const CNetEvent_DamageInd *)(*ppData);
77 protocol7::CNetEvent_Damage *pEvent7 = (protocol7::CNetEvent_Damage *)s_aEventStore;
78 *pType = -protocol7::NETEVENTTYPE_DAMAGE;
79 *pSize = sizeof(*pEvent7);
80
81 pEvent7->m_X = pEvent->m_X;
82 pEvent7->m_Y = pEvent->m_Y;
83
84 pEvent7->m_ClientId = 0;
85 pEvent7->m_Angle = 0;
86
87 // This will need some work, perhaps an event wrapper for damageind,
88 // a scan of the event array to merge multiple damageinds
89 // or a separate array of "damage ind" events that's added in while snapping
90 pEvent7->m_HealthAmount = 1;
91
92 pEvent7->m_ArmorAmount = 0;
93 pEvent7->m_Self = 0;
94
95 *ppData = s_aEventStore;
96 }
97 else if(*pType == NETEVENTTYPE_SOUNDGLOBAL) // No more global sounds for the server
98 {
99 const CNetEvent_SoundGlobal *pEvent = (const CNetEvent_SoundGlobal *)(*ppData);
100 protocol7::CNetEvent_SoundWorld *pEvent7 = (protocol7::CNetEvent_SoundWorld *)s_aEventStore;
101
102 *pType = -protocol7::NETEVENTTYPE_SOUNDWORLD;
103 *pSize = sizeof(*pEvent7);
104
105 pEvent7->m_SoundId = pEvent->m_SoundId;
106 pEvent7->m_X = pEvent->m_X;
107 pEvent7->m_Y = pEvent->m_Y;
108
109 *ppData = s_aEventStore;
110 }
111}
112