| 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 | ////////////////////////////////////////////////// |
| 14 | CEventHandler::CEventHandler() |
| 15 | { |
| 16 | m_pGameServer = nullptr; |
| 17 | Clear(); |
| 18 | } |
| 19 | |
| 20 | void CEventHandler::SetGameServer(CGameContext *pGameServer) |
| 21 | { |
| 22 | m_pGameServer = pGameServer; |
| 23 | } |
| 24 | |
| 25 | void *CEventHandler::Create(int Type, int Size, CClientMask Mask) |
| 26 | { |
| 27 | if(m_NumEvents == MAX_EVENTS) |
| 28 | return nullptr; |
| 29 | if(m_CurrentOffset + Size >= MAX_DATASIZE) |
| 30 | return nullptr; |
| 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 | |
| 42 | void CEventHandler::Clear() |
| 43 | { |
| 44 | m_NumEvents = 0; |
| 45 | m_CurrentOffset = 0; |
| 46 | } |
| 47 | |
| 48 | void 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 | |
| 71 | void 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 | |