bool CModAPI_Component_Items::ProcessEvent(int Type, CNetEvent_Common* pEvent)
{
    switch(Type)
    {
    case NETEVENTTYPE_MODAPI_ANIMATEDTEXT:
    {
        CNetEvent_ModAPI_AnimatedText* pTextEvent = (CNetEvent_ModAPI_AnimatedText*) pEvent;
        if(pTextEvent->m_ItemLayer != GetLayer())
            return false;

        CTextEventState EventState;
        EventState.m_Pos.x = static_cast<float>(pTextEvent->m_X);
        EventState.m_Pos.y = static_cast<float>(pTextEvent->m_Y);
        EventState.m_Size = static_cast<float>(pTextEvent->m_Size);
        EventState.m_Color = ModAPI_IntToColor(pTextEvent->m_Color);
        EventState.m_Alignment = pTextEvent->m_Alignment;
        IntsToStr(pTextEvent->m_aText, 16, &EventState.m_aText[0]);

        EventState.m_AnimationId = pTextEvent->m_AnimationId;
        EventState.m_Offset.x = static_cast<float>(pTextEvent->m_OffsetX);
        EventState.m_Offset.y = static_cast<float>(pTextEvent->m_OffsetY);
        EventState.m_Duration = static_cast<float>(pTextEvent->m_Duration)/1000.f;
        EventState.m_Time = 0.f;

        m_TextEvent.push_back(EventState);
    }
    return true;
    }
}
Exemple #2
0
void CGhost::InitRenderInfos(CGhostItem *pGhost)
{
	char aSkinName[64];
	IntsToStr(&pGhost->m_Skin.m_Skin0, 6, aSkinName);
	CTeeRenderInfo *pRenderInfo = &pGhost->m_RenderInfo;

	int SkinId = m_pClient->m_pSkins->Find(aSkinName);

	if(pGhost->m_Skin.m_UseCustomColor)
	{
		pRenderInfo->m_Texture = m_pClient->m_pSkins->Get(SkinId)->m_ColorTexture;
		pRenderInfo->m_ColorBody = m_pClient->m_pSkins->GetColorV4(pGhost->m_Skin.m_ColorBody);
		pRenderInfo->m_ColorFeet = m_pClient->m_pSkins->GetColorV4(pGhost->m_Skin.m_ColorFeet);
	}
	else
	{
		pRenderInfo->m_Texture = m_pClient->m_pSkins->Get(SkinId)->m_OrgTexture;
		pRenderInfo->m_ColorBody = vec4(1, 1, 1, 1);
		pRenderInfo->m_ColorFeet = vec4(1, 1, 1, 1);
	}

	pRenderInfo->m_ColorBody.a = 0.5f;
	pRenderInfo->m_ColorFeet.a = 0.5f;
	pRenderInfo->m_Size = 64;
}
void CModAPI_Component_Items::RenderModAPIAnimatedTextCharacter(const CNetObj_ModAPI_AnimatedTextCharacter *pPrev, const CNetObj_ModAPI_AnimatedTextCharacter *pCurrent)
{
    if(pCurrent->m_ItemLayer != GetLayer()) return;
    if(!TextRender()||!m_pClient->m_Snap.m_aCharacters[pCurrent->m_ClientId].m_Active) return;

    vec2 Pos = mix(vec2(pPrev->m_X, pPrev->m_Y), vec2(pCurrent->m_X, pCurrent->m_Y), Client()->IntraGameTick());
    vec2 Offset = mix(vec2(pPrev->m_OffsetX, pPrev->m_OffsetY), vec2(pCurrent->m_OffsetX, pCurrent->m_OffsetY), Client()->IntraGameTick());

    if(m_pClient->m_LocalClientID != -1 && m_pClient->m_LocalClientID == pCurrent->m_ClientId)
    {
        Pos = m_pClient->m_LocalCharacterPos + Pos;
    }
    else
    {
        CNetObj_Character PrevChar = m_pClient->m_Snap.m_aCharacters[pCurrent->m_ClientId].m_Prev;
        CNetObj_Character CurChar = m_pClient->m_Snap.m_aCharacters[pCurrent->m_ClientId].m_Cur;
        Pos = mix(vec2(PrevChar.m_X, PrevChar.m_Y), vec2(CurChar.m_X, CurChar.m_Y), Client()->IntraGameTick()) + Pos;
    }

    float Time = Client()->GameTick() + Client()->IntraGameTick() - pCurrent->m_StartTick;
    Time = (Time/static_cast<float>(SERVER_TICK_SPEED)) * 1000.0f;
    Time = Time / (static_cast<float>(pCurrent->m_Duration)/1000.f);

    char aText[64];
    IntsToStr(pCurrent->m_aText, 16, &aText[0]);

    ModAPIGraphics()->DrawAnimatedText(TextRender(), aText, Pos, ModAPI_IntToColor(pCurrent->m_Color), pCurrent->m_Size, pCurrent->m_Alignment, pCurrent->m_AnimationId, Time, Offset);
}
void CModAPI_Component_Items::RenderModAPIText(const CNetObj_ModAPI_Text *pPrev, const CNetObj_ModAPI_Text *pCurrent)
{
    if(pCurrent->m_ItemLayer != GetLayer()) return;
    if(!TextRender()) return;

    vec2 Pos = mix(vec2(pPrev->m_X, pPrev->m_Y), vec2(pCurrent->m_X, pCurrent->m_Y), Client()->IntraGameTick());

    char aText[64];
    IntsToStr(pCurrent->m_aText, 16, &aText[0]);

    ModAPIGraphics()->DrawText(TextRender(), aText, Pos, ModAPI_IntToColor(pCurrent->m_Color), pCurrent->m_Size, pCurrent->m_Alignment);
}
Exemple #5
0
void CComponent_Items::RenderText(const CNetObj_TU_Text *pPrev, const CNetObj_TU_Text *pCurrent)
{
	if(pCurrent->m_ItemLayer != GetLayer()) return;
	if(!TextRender()) return;

	vec2 Pos = mix(vec2(pPrev->m_X, pPrev->m_Y), vec2(pCurrent->m_X, pCurrent->m_Y), Client()->IntraGameTick());
	
	char aText[64];
	IntsToStr(pCurrent->m_aText, 16, &aText[0]);
	
	TUKernel()->AssetsRenderer()->DrawText(aText, Pos, tu::IntToColor(pCurrent->m_Color), pCurrent->m_Size, pCurrent->m_Alignment);
}
void CModAPI_Component_Items::RenderModAPIAnimatedText(const CNetObj_ModAPI_AnimatedText *pPrev, const CNetObj_ModAPI_AnimatedText *pCurrent)
{
    if(pCurrent->m_ItemLayer != GetLayer()) return;
    if(!TextRender()) return;

    vec2 Pos = mix(vec2(pPrev->m_X, pPrev->m_Y), vec2(pCurrent->m_X, pCurrent->m_Y), Client()->IntraGameTick());
    vec2 Offset = mix(vec2(pPrev->m_OffsetX, pPrev->m_OffsetY), vec2(pCurrent->m_OffsetX, pCurrent->m_OffsetY), Client()->IntraGameTick());

    float Time = Client()->GameTick() + Client()->IntraGameTick() - pCurrent->m_StartTick;
    Time = (Time/static_cast<float>(SERVER_TICK_SPEED)) * 1000.0f;
    Time = Time / (static_cast<float>(pCurrent->m_Duration)/1000.f);

    char aText[64];
    IntsToStr(pCurrent->m_aText, 16, &aText[0]);

    ModAPIGraphics()->DrawAnimatedText(TextRender(), aText, Pos, ModAPI_IntToColor(pCurrent->m_Color), pCurrent->m_Size, pCurrent->m_Alignment, pCurrent->m_AnimationId, Time, Offset);
}
void CModAPI_Component_Items::RenderModAPITextCharacter(const CNetObj_ModAPI_TextCharacter *pPrev, const CNetObj_ModAPI_TextCharacter *pCurrent)
{
    if(pCurrent->m_ItemLayer != GetLayer()) return;
    if(!TextRender()||!m_pClient->m_Snap.m_aCharacters[pCurrent->m_ClientId].m_Active) return;

    vec2 Pos = mix(vec2(pPrev->m_X, pPrev->m_Y), vec2(pCurrent->m_X, pCurrent->m_Y), Client()->IntraGameTick());

    if(m_pClient->m_LocalClientID != -1 && m_pClient->m_LocalClientID == pCurrent->m_ClientId)
    {
        Pos = m_pClient->m_LocalCharacterPos + Pos;
    }
    else
    {
        CNetObj_Character PrevChar = m_pClient->m_Snap.m_aCharacters[pCurrent->m_ClientId].m_Prev;
        CNetObj_Character CurChar = m_pClient->m_Snap.m_aCharacters[pCurrent->m_ClientId].m_Cur;
        Pos = mix(vec2(PrevChar.m_X, PrevChar.m_Y), vec2(CurChar.m_X, CurChar.m_Y), Client()->IntraGameTick()) + Pos;
    }

    char aText[64];
    IntsToStr(pCurrent->m_aText, 16, &aText[0]);

    ModAPIGraphics()->DrawText(TextRender(), aText, Pos, ModAPI_IntToColor(pCurrent->m_Color), pCurrent->m_Size, pCurrent->m_Alignment);
}
void CGameClient::OnNewSnapshot()
{
	m_NewTick = true;

	// clear out the invalid pointers
	mem_zero(&g_GameClient.m_Snap, sizeof(g_GameClient.m_Snap));
	m_Snap.m_LocalClientID = -1;

	// secure snapshot
	{
		int Num = Client()->SnapNumItems(IClient::SNAP_CURRENT);
		for(int Index = 0; Index < Num; Index++)
		{
			IClient::CSnapItem Item;
			void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, Index, &Item);
			if(m_NetObjHandler.ValidateObj(Item.m_Type, pData, Item.m_DataSize) != 0)
			{
				if(g_Config.m_Debug)
				{
					char aBuf[256];
					str_format(aBuf, sizeof(aBuf), "invalidated index=%d type=%d (%s) size=%d id=%d", Index, Item.m_Type, m_NetObjHandler.GetObjName(Item.m_Type), Item.m_DataSize, Item.m_ID);
					Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);
				}
				Client()->SnapInvalidateItem(IClient::SNAP_CURRENT, Index);
			}
		}
	}

	ProcessEvents();

	if(g_Config.m_DbgStress)
	{
		if((Client()->GameTick()%100) == 0)
		{
			char aMessage[64];
			int MsgLen = rand()%(sizeof(aMessage)-1);
			for(int i = 0; i < MsgLen; i++)
				aMessage[i] = 'a'+(rand()%('z'-'a'));
			aMessage[MsgLen] = 0;

			CNetMsg_Cl_Say Msg;
			Msg.m_Team = rand()&1;
			Msg.m_pMessage = aMessage;
			Client()->SendPackMsg(&Msg, MSGFLAG_VITAL);
		}
	}

	// go trough all the items in the snapshot and gather the info we want
	{
		m_Snap.m_aTeamSize[TEAM_RED] = m_Snap.m_aTeamSize[TEAM_BLUE] = 0;

		int Num = Client()->SnapNumItems(IClient::SNAP_CURRENT);
		for(int i = 0; i < Num; i++)
		{
			IClient::CSnapItem Item;
			const void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, i, &Item);

			if(Item.m_Type == NETOBJTYPE_CLIENTINFO)
			{
				const CNetObj_ClientInfo *pInfo = (const CNetObj_ClientInfo *)pData;
				int ClientID = Item.m_ID;
				IntsToStr(&pInfo->m_Name0, 4, m_aClients[ClientID].m_aName);
				IntsToStr(&pInfo->m_Clan0, 3, m_aClients[ClientID].m_aClan);
				m_aClients[ClientID].m_Country = pInfo->m_Country;
				IntsToStr(&pInfo->m_Skin0, 6, m_aClients[ClientID].m_aSkinName);

				m_aClients[ClientID].m_UseCustomColor = pInfo->m_UseCustomColor;
				m_aClients[ClientID].m_ColorBody = pInfo->m_ColorBody;
				m_aClients[ClientID].m_ColorFeet = pInfo->m_ColorFeet;

				// prepare the info
				if(m_aClients[ClientID].m_aSkinName[0] == 'x' || m_aClients[ClientID].m_aSkinName[1] == '_')
					str_copy(m_aClients[ClientID].m_aSkinName, "default", 64);

				m_aClients[ClientID].m_SkinInfo.m_ColorBody = m_pSkins->GetColorV4(m_aClients[ClientID].m_ColorBody);
				m_aClients[ClientID].m_SkinInfo.m_ColorFeet = m_pSkins->GetColorV4(m_aClients[ClientID].m_ColorFeet);
				m_aClients[ClientID].m_SkinInfo.m_Size = 64;

				// find new skin
				m_aClients[ClientID].m_SkinID = g_GameClient.m_pSkins->Find(m_aClients[ClientID].m_aSkinName);
				if(m_aClients[ClientID].m_SkinID < 0)
				{
					m_aClients[ClientID].m_SkinID = g_GameClient.m_pSkins->Find("default");
					if(m_aClients[ClientID].m_SkinID < 0)
						m_aClients[ClientID].m_SkinID = 0;
				}

				if(m_aClients[ClientID].m_UseCustomColor)
					m_aClients[ClientID].m_SkinInfo.m_Texture = g_GameClient.m_pSkins->Get(m_aClients[ClientID].m_SkinID)->m_ColorTexture;
				else
				{
					m_aClients[ClientID].m_SkinInfo.m_Texture = g_GameClient.m_pSkins->Get(m_aClients[ClientID].m_SkinID)->m_OrgTexture;
					m_aClients[ClientID].m_SkinInfo.m_ColorBody = vec4(1,1,1,1);
					m_aClients[ClientID].m_SkinInfo.m_ColorFeet = vec4(1,1,1,1);
				}

				m_aClients[ClientID].UpdateRenderInfo();

			}
			else if(Item.m_Type == NETOBJTYPE_PLAYERINFO)
			{
				const CNetObj_PlayerInfo *pInfo = (const CNetObj_PlayerInfo *)pData;

				m_aClients[pInfo->m_ClientID].m_Team = pInfo->m_Team;
				m_aClients[pInfo->m_ClientID].m_Active = true;
				m_Snap.m_paPlayerInfos[pInfo->m_ClientID] = pInfo;
				m_Snap.m_NumPlayers++;

				if(pInfo->m_Local)
				{
					m_Snap.m_LocalClientID = Item.m_ID;
					m_Snap.m_pLocalInfo = pInfo;

					if(pInfo->m_Team == TEAM_SPECTATORS)
					{
						m_Snap.m_SpecInfo.m_Active = true;
						m_Snap.m_SpecInfo.m_SpectatorID = SPEC_FREEVIEW;
					}
				}

				// calculate team-balance
				if(pInfo->m_Team != TEAM_SPECTATORS)
					m_Snap.m_aTeamSize[pInfo->m_Team]++;

			}
			else if(Item.m_Type == NETOBJTYPE_CHARACTER)
			{
				const void *pOld = Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_CHARACTER, Item.m_ID);
				m_Snap.m_aCharacters[Item.m_ID].m_Cur = *((const CNetObj_Character *)pData);
				if(pOld)
				{
					m_Snap.m_aCharacters[Item.m_ID].m_Active = true;
					m_Snap.m_aCharacters[Item.m_ID].m_Prev = *((const CNetObj_Character *)pOld);

					if(m_Snap.m_aCharacters[Item.m_ID].m_Prev.m_Tick)
						Evolve(&m_Snap.m_aCharacters[Item.m_ID].m_Prev, Client()->PrevGameTick());
					if(m_Snap.m_aCharacters[Item.m_ID].m_Cur.m_Tick)
						Evolve(&m_Snap.m_aCharacters[Item.m_ID].m_Cur, Client()->GameTick());
				}
			}
			else if(Item.m_Type == NETOBJTYPE_SPECTATORINFO)
			{
				m_Snap.m_pSpectatorInfo = (const CNetObj_SpectatorInfo *)pData;
				m_Snap.m_pPrevSpectatorInfo = (const CNetObj_SpectatorInfo *)Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_SPECTATORINFO, Item.m_ID);

				m_Snap.m_SpecInfo.m_SpectatorID = m_Snap.m_pSpectatorInfo->m_SpectatorID;
			}
			else if(Item.m_Type == NETOBJTYPE_GAMEINFO)
			{
				static bool s_GameOver = 0;
				m_Snap.m_pGameInfoObj = (const CNetObj_GameInfo *)pData;
				if(!s_GameOver && m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER)
					OnGameOver();
				else if(s_GameOver && !(m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER))
					OnStartGame();
				s_GameOver = m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER;
			}
			else if(Item.m_Type == NETOBJTYPE_GAMEDATA)
			{
				m_Snap.m_pGameDataObj = (const CNetObj_GameData *)pData;
				m_Snap.m_GameDataSnapID = Item.m_ID;
				if(m_Snap.m_pGameDataObj->m_FlagCarrierRed == FLAG_TAKEN)
				{
					if(m_FlagDropTick[TEAM_RED] == 0)
						m_FlagDropTick[TEAM_RED] = Client()->GameTick();
				}
				else if(m_FlagDropTick[TEAM_RED] != 0)
						m_FlagDropTick[TEAM_RED] = 0;
				if(m_Snap.m_pGameDataObj->m_FlagCarrierBlue == FLAG_TAKEN)
				{
					if(m_FlagDropTick[TEAM_BLUE] == 0)
						m_FlagDropTick[TEAM_BLUE] = Client()->GameTick();
				}
				else if(m_FlagDropTick[TEAM_BLUE] != 0)
						m_FlagDropTick[TEAM_BLUE] = 0;
			}
			else if(Item.m_Type == NETOBJTYPE_FLAG)
				m_Snap.m_paFlags[Item.m_ID%2] = (const CNetObj_Flag *)pData;
		}
	}

	// setup local pointers
	if(m_Snap.m_LocalClientID >= 0)
	{
		CSnapState::CCharacterInfo *c = &m_Snap.m_aCharacters[m_Snap.m_LocalClientID];
		if(c->m_Active)
		{
			m_Snap.m_pLocalCharacter = &c->m_Cur;
			m_Snap.m_pLocalPrevCharacter = &c->m_Prev;
			m_LocalCharacterPos = vec2(m_Snap.m_pLocalCharacter->m_X, m_Snap.m_pLocalCharacter->m_Y);
		}
		else if(Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_CHARACTER, m_Snap.m_LocalClientID))
		{
			// player died
			m_pControls->OnPlayerDeath();
		}
	}
	else
	{
		m_Snap.m_SpecInfo.m_Active = true;
		if(Client()->State() == IClient::STATE_DEMOPLAYBACK && DemoPlayer()->GetDemoType() == IDemoPlayer::DEMOTYPE_SERVER &&
			m_DemoSpecID != SPEC_FREEVIEW && m_Snap.m_aCharacters[m_DemoSpecID].m_Active)
			m_Snap.m_SpecInfo.m_SpectatorID = m_DemoSpecID;
		else
			m_Snap.m_SpecInfo.m_SpectatorID = SPEC_FREEVIEW;
	}

	// clear out unneeded client data
	for(int i = 0; i < MAX_CLIENTS; ++i)
	{
		if(!m_Snap.m_paPlayerInfos[i] && m_aClients[i].m_Active)
			m_aClients[i].Reset();
	}

	// update friend state
	for(int i = 0; i < MAX_CLIENTS; ++i)
	{
		if(i == m_Snap.m_LocalClientID || !m_Snap.m_paPlayerInfos[i] || !Friends()->IsFriend(m_aClients[i].m_aName, m_aClients[i].m_aClan, true))
			m_aClients[i].m_Friend = false;
		else
			m_aClients[i].m_Friend = true;
	}

	// sort player infos by score
	mem_copy(m_Snap.m_paInfoByScore, m_Snap.m_paPlayerInfos, sizeof(m_Snap.m_paInfoByScore));
	for(int k = 0; k < MAX_CLIENTS-1; k++) // ffs, bubblesort
	{
		for(int i = 0; i < MAX_CLIENTS-k-1; i++)
		{
			if(m_Snap.m_paInfoByScore[i+1] && (!m_Snap.m_paInfoByScore[i] || m_Snap.m_paInfoByScore[i]->m_Score < m_Snap.m_paInfoByScore[i+1]->m_Score))
			{
				const CNetObj_PlayerInfo *pTmp = m_Snap.m_paInfoByScore[i];
				m_Snap.m_paInfoByScore[i] = m_Snap.m_paInfoByScore[i+1];
				m_Snap.m_paInfoByScore[i+1] = pTmp;
			}
		}
	}
	// sort player infos by team
	int Teams[3] = { TEAM_RED, TEAM_BLUE, TEAM_SPECTATORS };
	int Index = 0;
	for(int Team = 0; Team < 3; ++Team)
	{
		for(int i = 0; i < MAX_CLIENTS && Index < MAX_CLIENTS; ++i)
		{
			if(m_Snap.m_paPlayerInfos[i] && m_Snap.m_paPlayerInfos[i]->m_Team == Teams[Team])
				m_Snap.m_paInfoByTeam[Index++] = m_Snap.m_paPlayerInfos[i];
		}
	}

	CTuningParams StandardTuning;
	CServerInfo CurrentServerInfo;
	Client()->GetServerInfo(&CurrentServerInfo);
	if(CurrentServerInfo.m_aGameType[0] != '0')
	{
		if(str_comp(CurrentServerInfo.m_aGameType, "DM") != 0 && str_comp(CurrentServerInfo.m_aGameType, "TDM") != 0 && str_comp(CurrentServerInfo.m_aGameType, "CTF") != 0)
			m_ServerMode = SERVERMODE_MOD;
		else if(mem_comp(&StandardTuning, &m_Tuning, sizeof(CTuningParams)) == 0)
			m_ServerMode = SERVERMODE_PURE;
		else
			m_ServerMode = SERVERMODE_PUREMOD;
	}

	// add tuning to demo
	if(DemoRecorder()->IsRecording() && mem_comp(&StandardTuning, &m_Tuning, sizeof(CTuningParams)) != 0)
	{
		CMsgPacker Msg(NETMSGTYPE_SV_TUNEPARAMS);
		int *pParams = (int *)&m_Tuning;
		for(unsigned i = 0; i < sizeof(m_Tuning)/sizeof(int); i++)
			Msg.AddInt(pParams[i]);
		Client()->SendMsg(&Msg, MSGFLAG_RECORD|MSGFLAG_NOSEND);
	}

	if(!m_DDRaceMsgSent && m_Snap.m_pLocalInfo)
	{
		CNetMsg_Cl_IsDDRace Msg;
		Client()->SendPackMsg(&Msg, MSGFLAG_VITAL);
		m_DDRaceMsgSent = true;
	}

	if(m_ShowOthers == -1 || (m_ShowOthers != -1 && m_ShowOthers != g_Config.m_ClShowOthers))
	{
		// no need to send, default settings
		//if(!(m_ShowOthers == -1 && g_Config.m_ClShowOthers))
		{
			CNetMsg_Cl_ShowOthers Msg;
			Msg.m_Show = g_Config.m_ClShowOthers;
			Client()->SendPackMsg(&Msg, MSGFLAG_VITAL);
		}

		// update state
		m_ShowOthers = g_Config.m_ClShowOthers;
	}
}
Exemple #9
0
void CGameClient::OnNewSnapshot()
{
    m_NewTick = true;

    // clear out the invalid pointers
    mem_zero(&g_GameClient.m_Snap, sizeof(g_GameClient.m_Snap));
    m_Snap.m_LocalCid = -1;

    // secure snapshot
    {
        int Num = Client()->SnapNumItems(IClient::SNAP_CURRENT);
        for(int Index = 0; Index < Num; Index++)
        {
            IClient::CSnapItem Item;
            void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, Index, &Item);
            if(m_NetObjHandler.ValidateObj(Item.m_Type, pData, Item.m_DataSize) != 0)
            {
                if(g_Config.m_Debug)
                    dbg_msg("game", "invalidated index=%d type=%d (%s) size=%d id=%d", Index, Item.m_Type, m_NetObjHandler.GetObjName(Item.m_Type), Item.m_DataSize, Item.m_Id);
                Client()->SnapInvalidateItem(IClient::SNAP_CURRENT, Index);
            }
        }
    }

    ProcessEvents();

    if(g_Config.m_DbgStress)
    {
        if((Client()->GameTick()%100) == 0)
        {
            char aMessage[64];
            int MsgLen = rand()%(sizeof(aMessage)-1);
            for(int i = 0; i < MsgLen; i++)
                aMessage[i] = 'a'+(rand()%('z'-'a'));
            aMessage[MsgLen] = 0;

            CNetMsg_Cl_Say Msg;
            Msg.m_Team = rand()&1;
            Msg.m_pMessage = aMessage;
            Client()->SendPackMsg(&Msg, MSGFLAG_VITAL);
        }
    }

    // go trough all the items in the snapshot and gather the info we want
    {
        m_Snap.m_aTeamSize[0] = m_Snap.m_aTeamSize[1] = 0;

        int Num = Client()->SnapNumItems(IClient::SNAP_CURRENT);
        for(int i = 0; i < Num; i++)
        {
            IClient::CSnapItem Item;
            const void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, i, &Item);

            if(Item.m_Type == NETOBJTYPE_CLIENTINFO)
            {
                const CNetObj_ClientInfo *pInfo = (const CNetObj_ClientInfo *)pData;
                int Cid = Item.m_Id;
                IntsToStr(&pInfo->m_Name0, 6, m_aClients[Cid].m_aName);
                IntsToStr(&pInfo->m_Skin0, 6, m_aClients[Cid].m_aSkinName);

                m_aClients[Cid].m_UseCustomColor = pInfo->m_UseCustomColor;
                m_aClients[Cid].m_ColorBody = pInfo->m_ColorBody;
                m_aClients[Cid].m_ColorFeet = pInfo->m_ColorFeet;

                // prepare the info
                if(m_aClients[Cid].m_aSkinName[0] == 'x' || m_aClients[Cid].m_aSkinName[1] == '_')
                    str_copy(m_aClients[Cid].m_aSkinName, "default", 64);

                m_aClients[Cid].m_SkinInfo.m_ColorBody = m_pSkins->GetColor(m_aClients[Cid].m_ColorBody);
                m_aClients[Cid].m_SkinInfo.m_ColorFeet = m_pSkins->GetColor(m_aClients[Cid].m_ColorFeet);
                m_aClients[Cid].m_SkinInfo.m_Size = 64;

                // find new skin
                m_aClients[Cid].m_SkinId = g_GameClient.m_pSkins->Find(m_aClients[Cid].m_aSkinName);
                if(m_aClients[Cid].m_SkinId < 0)
                {
                    m_aClients[Cid].m_SkinId = g_GameClient.m_pSkins->Find("default");
                    if(m_aClients[Cid].m_SkinId < 0)
                        m_aClients[Cid].m_SkinId = 0;
                }

                if(m_aClients[Cid].m_UseCustomColor)
                    m_aClients[Cid].m_SkinInfo.m_Texture = g_GameClient.m_pSkins->Get(m_aClients[Cid].m_SkinId)->m_ColorTexture;
                else
                {
                    m_aClients[Cid].m_SkinInfo.m_Texture = g_GameClient.m_pSkins->Get(m_aClients[Cid].m_SkinId)->m_OrgTexture;
                    m_aClients[Cid].m_SkinInfo.m_ColorBody = vec4(1,1,1,1);
                    m_aClients[Cid].m_SkinInfo.m_ColorFeet = vec4(1,1,1,1);
                }

                m_aClients[Cid].UpdateRenderInfo();
                g_GameClient.m_Snap.m_NumPlayers++;

            }
            else if(Item.m_Type == NETOBJTYPE_PLAYERINFO)
            {
                const CNetObj_PlayerInfo *pInfo = (const CNetObj_PlayerInfo *)pData;

                m_aClients[pInfo->m_ClientId].m_Team = pInfo->m_Team;
                m_Snap.m_paPlayerInfos[pInfo->m_ClientId] = pInfo;

                if(pInfo->m_Local)
                {
                    m_Snap.m_LocalCid = Item.m_Id;
                    m_Snap.m_pLocalInfo = pInfo;

                    if (pInfo->m_Team == -1)
                        m_Snap.m_Spectate = true;
                }

                // calculate team-balance
                if(pInfo->m_Team != -1)
                    m_Snap.m_aTeamSize[pInfo->m_Team]++;

            }
            else if(Item.m_Type == NETOBJTYPE_CHARACTER)
            {
                const void *pOld = Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_CHARACTER, Item.m_Id);
                if(pOld)
                {
                    m_Snap.m_aCharacters[Item.m_Id].m_Active = true;
                    m_Snap.m_aCharacters[Item.m_Id].m_Prev = *((const CNetObj_Character *)pOld);
                    m_Snap.m_aCharacters[Item.m_Id].m_Cur = *((const CNetObj_Character *)pData);

                    if(m_Snap.m_aCharacters[Item.m_Id].m_Prev.m_Tick)
                        Evolve(&m_Snap.m_aCharacters[Item.m_Id].m_Prev, Client()->PrevGameTick());
                    if(m_Snap.m_aCharacters[Item.m_Id].m_Cur.m_Tick)
                        Evolve(&m_Snap.m_aCharacters[Item.m_Id].m_Cur, Client()->GameTick());
                }
            }
            else if(Item.m_Type == NETOBJTYPE_GAME)
                m_Snap.m_pGameobj = (CNetObj_Game *)pData;
            else if(Item.m_Type == NETOBJTYPE_FLAG)
                m_Snap.m_paFlags[Item.m_Id%2] = (const CNetObj_Flag *)pData;
        }
    }

    // setup local pointers
    if(m_Snap.m_LocalCid >= 0)
    {
        CSnapState::CCharacterInfo *c = &m_Snap.m_aCharacters[m_Snap.m_LocalCid];
        if(c->m_Active)
        {
            m_Snap.m_pLocalCharacter = &c->m_Cur;
            m_Snap.m_pLocalPrevCharacter = &c->m_Prev;
            m_LocalCharacterPos = vec2(m_Snap.m_pLocalCharacter->m_X, m_Snap.m_pLocalCharacter->m_Y);
        }
    }
    else
        m_Snap.m_Spectate = true;

    CTuningParams StandardTuning;
    CServerInfo CurrentServerInfo;
    Client()->GetServerInfo(&CurrentServerInfo);
    if(CurrentServerInfo.m_aGameType[0] != '0')
    {
        if(str_comp(CurrentServerInfo.m_aGameType, "DM") != 0 && str_comp(CurrentServerInfo.m_aGameType, "TDM") != 0 && str_comp(CurrentServerInfo.m_aGameType, "CTF") != 0)
            m_ServerMode = SERVERMODE_MOD;
        else if(mem_comp(&StandardTuning, &m_Tuning, sizeof(CTuningParams)) == 0)
            m_ServerMode = SERVERMODE_PURE;
        else
            m_ServerMode = SERVERMODE_PUREMOD;
    }


    // update render info
    for(int i = 0; i < MAX_CLIENTS; i++)
        m_aClients[i].UpdateRenderInfo();
}
Exemple #10
0
int CEditorMap::Load(class IStorage *pStorage, const char *pFileName, int StorageType)
{
	CDataFileReader DataFile;
	//DATAFILE *df = datafile_load(filename);
	if(!DataFile.Open(pStorage, pFileName, StorageType))
		return 0;
		
	Clean();

	// check version
	CMapItemVersion *pItem = (CMapItemVersion *)DataFile.FindItem(MAPITEMTYPE_VERSION, 0);
	if(!pItem)
	{
		// import old map
		/*MAP old_mapstuff;
		editor->reset();
		editor_load_old(df, this);
		*/
	}
	else if(pItem->m_Version == 1)
	{
		//editor.reset(false);
		
		// load images
		{
			int Start, Num;
			DataFile.GetType( MAPITEMTYPE_IMAGE, &Start, &Num);
			for(int i = 0; i < Num; i++)
			{
				CMapItemImage *pItem = (CMapItemImage *)DataFile.GetItem(Start+i, 0, 0);
				char *pName = (char *)DataFile.GetData(pItem->m_ImageName);

				// copy base info				
				CEditorImage *pImg = new CEditorImage(m_pEditor);
				pImg->m_External = pItem->m_External;

				if(pItem->m_External)
				{
					char aBuf[256];
					str_format(aBuf, sizeof(aBuf),"mapres/%s.png", pName);
					
					// load external
					CEditorImage ImgInfo(m_pEditor);
					if(m_pEditor->Graphics()->LoadPNG(&ImgInfo, aBuf, IStorage::TYPE_ALL))
					{
						*pImg = ImgInfo;
						pImg->m_TexID = m_pEditor->Graphics()->LoadTextureRaw(ImgInfo.m_Width, ImgInfo.m_Height, ImgInfo.m_Format, ImgInfo.m_pData, CImageInfo::FORMAT_AUTO, 0);
						pImg->m_External = 1;
					}
				}
				else
				{
					pImg->m_Width = pItem->m_Width;
					pImg->m_Height = pItem->m_Height;
					pImg->m_Format = CImageInfo::FORMAT_RGBA;
					
					// copy image data
					void *pData = DataFile.GetData(pItem->m_ImageData);
					pImg->m_pData = mem_alloc(pImg->m_Width*pImg->m_Height*4, 1);
					mem_copy(pImg->m_pData, pData, pImg->m_Width*pImg->m_Height*4);
					pImg->m_TexID = m_pEditor->Graphics()->LoadTextureRaw(pImg->m_Width, pImg->m_Height, pImg->m_Format, pImg->m_pData, CImageInfo::FORMAT_AUTO, 0);
				}

				// copy image name
				if(pName)
					str_copy(pImg->m_aName, pName, 128);

				m_lImages.add(pImg);
				
				// unload image
				DataFile.UnloadData(pItem->m_ImageData);
				DataFile.UnloadData(pItem->m_ImageName);
			}
		}
		
		// load groups
		{
			int LayersStart, LayersNum;
			DataFile.GetType(MAPITEMTYPE_LAYER, &LayersStart, &LayersNum);
			
			int Start, Num;
			DataFile.GetType(MAPITEMTYPE_GROUP, &Start, &Num);
			for(int g = 0; g < Num; g++)
			{
				CMapItemGroup *pGItem = (CMapItemGroup *)DataFile.GetItem(Start+g, 0, 0);
				
				if(pGItem->m_Version < 1 || pGItem->m_Version > CMapItemGroup::CURRENT_VERSION)
					continue;
				
				CLayerGroup *pGroup = NewGroup();
				pGroup->m_ParallaxX = pGItem->m_ParallaxX;
				pGroup->m_ParallaxY = pGItem->m_ParallaxY;
				pGroup->m_OffsetX = pGItem->m_OffsetX;
				pGroup->m_OffsetY = pGItem->m_OffsetY;
				
				if(pGItem->m_Version >= 2)
				{
					pGroup->m_UseClipping = pGItem->m_UseClipping;
					pGroup->m_ClipX = pGItem->m_ClipX;
					pGroup->m_ClipY = pGItem->m_ClipY;
					pGroup->m_ClipW = pGItem->m_ClipW;
					pGroup->m_ClipH = pGItem->m_ClipH;
				}
				
				for(int l = 0; l < pGItem->m_NumLayers; l++)
				{
					CLayer *pLayer = 0;
					CMapItemLayer *pLayerItem = (CMapItemLayer *)DataFile.GetItem(LayersStart+pGItem->m_StartLayer+l, 0, 0);
					if(!pLayerItem)
						continue;
						
					if(pLayerItem->m_Type == LAYERTYPE_TILES)
					{
						CMapItemLayerTilemap *pTilemapItem = (CMapItemLayerTilemap *)pLayerItem;
						CLayerTiles *pTiles = 0;
						
						if(pTilemapItem->m_Flags&1)
						{
							pTiles = new CLayerGame(pTilemapItem->m_Width, pTilemapItem->m_Height);
							MakeGameLayer(pTiles);
							MakeGameGroup(pGroup);
						}
						else
						{
							pTiles = new CLayerTiles(pTilemapItem->m_Width, pTilemapItem->m_Height);
							pTiles->m_pEditor = m_pEditor;
							pTiles->m_Color.r = pTilemapItem->m_Color.r;
							pTiles->m_Color.g = pTilemapItem->m_Color.g;
							pTiles->m_Color.b = pTilemapItem->m_Color.b;
							pTiles->m_Color.a = pTilemapItem->m_Color.a;
						}

						pLayer = pTiles;
						
						pGroup->AddLayer(pTiles);
						void *pData = DataFile.GetData(pTilemapItem->m_Data);
						pTiles->m_Image = pTilemapItem->m_Image;
						pTiles->m_Game = pTilemapItem->m_Flags&1;
						
						mem_copy(pTiles->m_pTiles, pData, pTiles->m_Width*pTiles->m_Height*sizeof(CTile));
						
						if(pTiles->m_Game && pTilemapItem->m_Version == MakeVersion(1, *pTilemapItem))
						{
							for(int i = 0; i < pTiles->m_Width*pTiles->m_Height; i++)
							{
								if(pTiles->m_pTiles[i].m_Index)
									pTiles->m_pTiles[i].m_Index += ENTITY_OFFSET;
							}
						}
						
						DataFile.UnloadData(pTilemapItem->m_Data);
					}
					else if(pLayerItem->m_Type == LAYERTYPE_QUADS)
					{
						CMapItemLayerQuads *pQuadsItem = (CMapItemLayerQuads *)pLayerItem;
						CLayerQuads *pQuads = new CLayerQuads;
						pQuads->m_pEditor = m_pEditor;
						pLayer = pQuads;
						pQuads->m_Image = pQuadsItem->m_Image;
						if(pQuads->m_Image < -1 || pQuads->m_Image >= m_lImages.size())
							pQuads->m_Image = -1;
						void *pData = DataFile.GetDataSwapped(pQuadsItem->m_Data);
						pGroup->AddLayer(pQuads);
						pQuads->m_lQuads.set_size(pQuadsItem->m_NumQuads);
						mem_copy(pQuads->m_lQuads.base_ptr(), pData, sizeof(CQuad)*pQuadsItem->m_NumQuads);
						DataFile.UnloadData(pQuadsItem->m_Data);
					}
					
					if(pLayer)
						pLayer->m_Flags = pLayerItem->m_Flags;
				}
			}
		}
		
		// load envelopes
		{
			CEnvPoint *pPoints = 0;
			
			{
				int Start, Num;
				DataFile.GetType(MAPITEMTYPE_ENVPOINTS, &Start, &Num);
				if(Num)
					pPoints = (CEnvPoint *)DataFile.GetItem(Start, 0, 0);
			}
			
			int Start, Num;
			DataFile.GetType(MAPITEMTYPE_ENVELOPE, &Start, &Num);
			for(int e = 0; e < Num; e++)
			{
				CMapItemEnvelope *pItem = (CMapItemEnvelope *)DataFile.GetItem(Start+e, 0, 0);
				CEnvelope *pEnv = new CEnvelope(pItem->m_Channels);
				pEnv->m_lPoints.set_size(pItem->m_NumPoints);
				mem_copy(pEnv->m_lPoints.base_ptr(), &pPoints[pItem->m_StartPoint], sizeof(CEnvPoint)*pItem->m_NumPoints);
				if(pItem->m_aName[0] != -1)	// compatibility with old maps
					IntsToStr(pItem->m_aName, sizeof(pItem->m_aName)/sizeof(int), pEnv->m_aName);
				m_lEnvelopes.add(pEnv);
			}
		}
	}
	
	return 1;
}
Exemple #11
0
void CGameClient::OnNewSnapshot()
{
	// clear out the invalid pointers
	mem_zero(&m_Snap, sizeof(m_Snap));

	// secure snapshot
	{
		int Num = Client()->SnapNumItems(IClient::SNAP_CURRENT);
		for(int Index = 0; Index < Num; Index++)
		{
			IClient::CSnapItem Item;
			const void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, Index, &Item);
			if(m_NetObjHandler.ValidateObj(Item.m_Type, pData, Item.m_DataSize) != 0)
			{
				if(g_Config.m_Debug)
				{
					char aBuf[256];
					str_format(aBuf, sizeof(aBuf), "invalidated index=%d type=%d (%s) size=%d id=%d", Index, Item.m_Type, m_NetObjHandler.GetObjName(Item.m_Type), Item.m_DataSize, Item.m_ID);
					Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);
				}
				Client()->SnapInvalidateItem(IClient::SNAP_CURRENT, Index);
			}
		}
	}

	ProcessEvents();

	if(g_Config.m_DbgStress)
	{
		if((Client()->GameTick()%100) == 0)
		{
			char aMessage[64];
			int MsgLen = random_int()%(sizeof(aMessage)-1);
			for(int i = 0; i < MsgLen; i++)
				aMessage[i] = 'a'+(random_int()%('z'-'a'));
			aMessage[MsgLen] = 0;

			CNetMsg_Cl_Say Msg;
			Msg.m_Mode = random_int()&1;
			Msg.m_Target = -1;
			Msg.m_pMessage = aMessage;
			Client()->SendPackMsg(&Msg, MSGFLAG_VITAL);
		}
	}

	CTuningParams StandardTuning;
	if(Client()->State() == IClient::STATE_DEMOPLAYBACK)
	{
		m_Tuning = StandardTuning;
		mem_zero(&m_GameInfo, sizeof(m_GameInfo));
	}

	// go trough all the items in the snapshot and gather the info we want
	{
		int Num = Client()->SnapNumItems(IClient::SNAP_CURRENT);
		for(int i = 0; i < Num; i++)
		{
			IClient::CSnapItem Item;
			const void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, i, &Item);

			// demo items
			if(Client()->State() == IClient::STATE_DEMOPLAYBACK)
			{
				if(Item.m_Type == NETOBJTYPE_DE_CLIENTINFO)
				{
					const CNetObj_De_ClientInfo *pInfo = (const CNetObj_De_ClientInfo *)pData;
					int ClientID = Item.m_ID;
					CClientData *pClient = &m_aClients[ClientID];

					if(pInfo->m_Local)
						m_LocalClientID = ClientID;
					pClient->m_Active = true;
					pClient->m_Team  = pInfo->m_Team;
					IntsToStr(pInfo->m_aName, 4, pClient->m_aName);
					IntsToStr(pInfo->m_aClan, 3, pClient->m_aClan);
					pClient->m_Country = pInfo->m_Country;

					for(int p = 0; p < NUM_SKINPARTS; p++)
					{
						IntsToStr(pInfo->m_aaSkinPartNames[p], 6, pClient->m_aaSkinPartNames[p]);
						pClient->m_aUseCustomColors[p] = pInfo->m_aUseCustomColors[p];
						pClient->m_aSkinPartColors[p] = pInfo->m_aSkinPartColors[p];
					}

					m_GameInfo.m_NumPlayers++;
					// calculate team-balance
					if(pClient->m_Team != TEAM_SPECTATORS)
						m_GameInfo.m_aTeamSize[pClient->m_Team]++;
				}
				else if(Item.m_Type == NETOBJTYPE_DE_GAMEINFO)
				{
					const CNetObj_De_GameInfo *pInfo = (const CNetObj_De_GameInfo *)pData;

					m_GameInfo.m_GameFlags = pInfo->m_GameFlags;
					m_GameInfo.m_ScoreLimit = pInfo->m_ScoreLimit;
					m_GameInfo.m_TimeLimit = pInfo->m_TimeLimit;
					m_GameInfo.m_MatchNum = pInfo->m_MatchNum;
					m_GameInfo.m_MatchCurrent = pInfo->m_MatchCurrent;
				}
				else if(Item.m_Type == NETOBJTYPE_DE_TUNEPARAMS)
				{
					const CNetObj_De_TuneParams *pInfo = (const CNetObj_De_TuneParams *)pData;

					mem_copy(&m_Tuning, pInfo->m_aTuneParams, sizeof(m_Tuning));
					m_ServerMode = SERVERMODE_PURE;
				}
			}
			
			// network items
			if(Item.m_Type == NETOBJTYPE_PLAYERINFO)
			{
				const CNetObj_PlayerInfo *pInfo = (const CNetObj_PlayerInfo *)pData;
				int ClientID = Item.m_ID;
				if(m_aClients[ClientID].m_Active)
				{
					m_Snap.m_paPlayerInfos[ClientID] = pInfo;
					m_Snap.m_aInfoByScore[ClientID].m_pPlayerInfo = pInfo;
					m_Snap.m_aInfoByScore[ClientID].m_ClientID = ClientID;

					if(m_LocalClientID == ClientID)
					{
						m_Snap.m_pLocalInfo = pInfo;

						if(m_aClients[ClientID].m_Team == TEAM_SPECTATORS)
						{
							m_Snap.m_SpecInfo.m_Active = true;
							m_Snap.m_SpecInfo.m_SpecMode = SPEC_FREEVIEW;
							m_Snap.m_SpecInfo.m_SpectatorID = -1;
						}
					}
				}
			}
			else if(Item.m_Type == NETOBJTYPE_CHARACTER)
			{
				const void *pOld = Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_CHARACTER, Item.m_ID);
				m_Snap.m_aCharacters[Item.m_ID].m_Cur = *((const CNetObj_Character *)pData);

				// clamp ammo count for non ninja weapon
				if(m_Snap.m_aCharacters[Item.m_ID].m_Cur.m_Weapon != WEAPON_NINJA)
					m_Snap.m_aCharacters[Item.m_ID].m_Cur.m_AmmoCount = clamp(m_Snap.m_aCharacters[Item.m_ID].m_Cur.m_AmmoCount, 0, 10);
				
				if(pOld)
				{
					m_Snap.m_aCharacters[Item.m_ID].m_Active = true;
					m_Snap.m_aCharacters[Item.m_ID].m_Prev = *((const CNetObj_Character *)pOld);

					if(m_Snap.m_aCharacters[Item.m_ID].m_Prev.m_Tick)
						EvolveCharacter(&m_Snap.m_aCharacters[Item.m_ID].m_Prev, Client()->PrevGameTick());
					if(m_Snap.m_aCharacters[Item.m_ID].m_Cur.m_Tick)
						EvolveCharacter(&m_Snap.m_aCharacters[Item.m_ID].m_Cur, Client()->GameTick());
				}

				if(Item.m_ID != m_LocalClientID || Client()->State() == IClient::STATE_DEMOPLAYBACK)
					ProcessTriggeredEvents(m_Snap.m_aCharacters[Item.m_ID].m_Cur.m_TriggeredEvents, vec2(m_Snap.m_aCharacters[Item.m_ID].m_Cur.m_X, m_Snap.m_aCharacters[Item.m_ID].m_Cur.m_Y));
			}
			else if(Item.m_Type == NETOBJTYPE_SPECTATORINFO)
			{
				m_Snap.m_pSpectatorInfo = (const CNetObj_SpectatorInfo *)pData;
				m_Snap.m_pPrevSpectatorInfo = (const CNetObj_SpectatorInfo *)Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_SPECTATORINFO, Item.m_ID);
				m_Snap.m_SpecInfo.m_Active = true;
				m_Snap.m_SpecInfo.m_SpecMode = m_Snap.m_pSpectatorInfo->m_SpecMode;
				m_Snap.m_SpecInfo.m_SpectatorID = m_Snap.m_pSpectatorInfo->m_SpectatorID;
			}
			else if(Item.m_Type == NETOBJTYPE_GAMEDATA)
			{
				m_Snap.m_pGameData = (const CNetObj_GameData *)pData;

				static bool s_GameOver = 0;
				if(!s_GameOver && m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER)
					OnGameOver();
				else if(s_GameOver && !(m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER))
					OnStartGame();
				s_GameOver = m_Snap.m_pGameData->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER;
			}
			else if(Item.m_Type == NETOBJTYPE_GAMEDATATEAM)
			{
				m_Snap.m_pGameDataTeam = (const CNetObj_GameDataTeam *)pData;
			}
			else if(Item.m_Type == NETOBJTYPE_GAMEDATAFLAG)
			{
				m_Snap.m_pGameDataFlag = (const CNetObj_GameDataFlag *)pData;
				m_Snap.m_GameDataFlagSnapID = Item.m_ID;
			}
			else if(Item.m_Type == NETOBJTYPE_FLAG)
				m_Snap.m_paFlags[Item.m_ID%2] = (const CNetObj_Flag *)pData;
		}
	}

	// setup local pointers
	if(m_LocalClientID >= 0)
	{
		CSnapState::CCharacterInfo *c = &m_Snap.m_aCharacters[m_LocalClientID];
		if(c->m_Active)
		{
			m_Snap.m_pLocalCharacter = &c->m_Cur;
			m_Snap.m_pLocalPrevCharacter = &c->m_Prev;
			m_LocalCharacterPos = vec2(m_Snap.m_pLocalCharacter->m_X, m_Snap.m_pLocalCharacter->m_Y);
		}
		else if(Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_CHARACTER, m_LocalClientID))
		{
			// player died
			m_pControls->OnPlayerDeath();
		}
	}
	else
	{
		m_Snap.m_SpecInfo.m_Active = true;
		if(Client()->State() == IClient::STATE_DEMOPLAYBACK && DemoPlayer()->GetDemoType() == IDemoPlayer::DEMOTYPE_SERVER &&
			m_DemoSpecID != -1 && m_Snap.m_aCharacters[m_DemoSpecID].m_Active)
		{
			m_Snap.m_SpecInfo.m_SpecMode = SPEC_PLAYER;
			m_Snap.m_SpecInfo.m_SpectatorID = m_DemoSpecID;
		}
		else
		{
			if (m_DemoSpecMode == SPEC_PLAYER)
			{
				m_Snap.m_SpecInfo.m_SpecMode = SPEC_FREEVIEW;
				m_Snap.m_SpecInfo.m_SpectatorID = -1;
			}
			else
			{
				m_Snap.m_SpecInfo.m_SpecMode = m_DemoSpecMode;
				m_Snap.m_SpecInfo.m_SpectatorID = m_DemoSpecID;
			}
		}
	}

	// sort player infos by score
	for(int k = 0; k < MAX_CLIENTS-1; k++) // ffs, bubblesort
	{
		for(int i = 0; i < MAX_CLIENTS-k-1; i++)
		{
			if(m_Snap.m_aInfoByScore[i+1].m_pPlayerInfo && (!m_Snap.m_aInfoByScore[i].m_pPlayerInfo ||
				m_Snap.m_aInfoByScore[i].m_pPlayerInfo->m_Score < m_Snap.m_aInfoByScore[i+1].m_pPlayerInfo->m_Score))
			{
				CPlayerInfoItem Tmp = m_Snap.m_aInfoByScore[i];
				m_Snap.m_aInfoByScore[i] = m_Snap.m_aInfoByScore[i+1];
				m_Snap.m_aInfoByScore[i+1] = Tmp;
			}
		}
	}

	// calc some player stats
	for(int i = 0; i < MAX_CLIENTS; ++i)
	{
		if(!m_Snap.m_paPlayerInfos[i])
			continue;

		// count not ready players
		if((m_Snap.m_pGameData->m_GameStateFlags&(GAMESTATEFLAG_STARTCOUNTDOWN|GAMESTATEFLAG_PAUSED|GAMESTATEFLAG_WARMUP)) &&
			m_Snap.m_pGameData->m_GameStateEndTick == 0 && m_aClients[i].m_Team != TEAM_SPECTATORS && !(m_Snap.m_paPlayerInfos[i]->m_PlayerFlags&PLAYERFLAG_READY))
			m_Snap.m_NotReadyCount++;

		// count alive players per team
		if((m_GameInfo.m_GameFlags&GAMEFLAG_SURVIVAL) && m_aClients[i].m_Team != TEAM_SPECTATORS && !(m_Snap.m_paPlayerInfos[i]->m_PlayerFlags&PLAYERFLAG_DEAD))
			m_Snap.m_AliveCount[m_aClients[i].m_Team]++;
	}

	if(Client()->State() == IClient::STATE_DEMOPLAYBACK)
	{
		for(int i = 0; i < MAX_CLIENTS; ++i)
		{
			if(m_aClients[i].m_Active)
				m_aClients[i].UpdateRenderInfo(this, true);
		}
	}

	CServerInfo CurrentServerInfo;
	Client()->GetServerInfo(&CurrentServerInfo);
	if(str_comp(CurrentServerInfo.m_aGameType, "DM") != 0 && str_comp(CurrentServerInfo.m_aGameType, "TDM") != 0 && str_comp(CurrentServerInfo.m_aGameType, "CTF") != 0 &&
		str_comp(CurrentServerInfo.m_aGameType, "LMS") != 0 && str_comp(CurrentServerInfo.m_aGameType, "SUR") != 0)
		m_ServerMode = SERVERMODE_MOD;
	else if(mem_comp(&StandardTuning, &m_Tuning, sizeof(CTuningParams)) == 0)
		m_ServerMode = SERVERMODE_PURE;
	else
		m_ServerMode = SERVERMODE_PUREMOD;
}
Exemple #12
0
void CMapReader::Generate(CGenInfo *pInfo)
{
	m_OverallBenchmark.Unpause();
	
	// create folders
	
	char aGeneratedFolder[256];
	sprintf(aGeneratedFolder, "%sgenerated/%s", pInfo->m_aCurrentDir, pInfo->m_aMap);
	
	char aGeneratedMapresFolder[256];
	sprintf(aGeneratedMapresFolder, "%s/mapres", aGeneratedFolder);
	
	MakeDir(aGeneratedFolder);
	MakeDir(aGeneratedMapresFolder);
	
	// check map version
	
	CMapItemVersion *pVersion = (CMapItemVersion *)m_Reader.FindItem(MAPITEMTYPE_VERSION, 0);
	if(!pVersion || pVersion->m_Version != 1)
		return;
	
	// create generating file
	
	char aGenerating[256];
	sprintf(aGenerating, "%s/generating", aGeneratedFolder);
	
	FILE *pGeneratingFile = fopen(aGenerating, "wb");
	if(pGeneratingFile)
		fclose(pGeneratingFile);
	
	// load images
	m_ImagesBenchmark.Unpause();
	
	int ImagesStart;
	int ImagesNum;
	m_Reader.GetType(MAPITEMTYPE_IMAGE, &ImagesStart, &ImagesNum);
	
	CMapItemImage *pImages = NULL;
	
	if(ImagesNum > 0)
	{
		pImages = new CMapItemImage[ImagesNum];
		
		for(int i = ImagesStart; i < ImagesStart+ImagesNum; i++)
		{
			CMapItemImage *pImage = (CMapItemImage *)m_Reader.GetItem(i, NULL, NULL);
			
			if(!pImage->m_External && pInfo->m_DumpEmbedded)
			{
				const char *pName = (char *)m_Reader.GetData(pImage->m_ImageName);
				unsigned char *pData = (unsigned char *)m_Reader.GetData(pImage->m_ImageData);
				
				char aImageFilename[512];
				sprintf(aImageFilename, "%s/%s.png", aGeneratedMapresFolder, pName);
				
				CImageWrite Image;
				Image.Open(aImageFilename, pImage->m_Width, pImage->m_Height);
				Image.SetPixels(pData);
				Image.Save();
			}
			
			pImages[i-ImagesStart] = *pImage;
		}
	}
	
	m_ImagesBenchmark.Pause();
	
	// load groups and layers
	
	int GroupsStart;
	int GroupsNum;
	m_Reader.GetType(MAPITEMTYPE_GROUP, &GroupsStart, &GroupsNum);
	
	int LayersStart;
	int LayersNum;
	m_Reader.GetType(MAPITEMTYPE_LAYER, &LayersStart, &LayersNum);
	
	for(int g = GroupsStart; g < GroupsStart+GroupsNum; g++)
	{
		CMapItemGroup *pGroup = (CMapItemGroup *)m_Reader.GetItem(g, NULL, NULL);
		
		if(pGroup->m_Version < 1 || pGroup->m_Version > 2)
			continue;
		
		for(int l = LayersStart + pGroup->m_StartLayer; l < LayersStart + pGroup->m_StartLayer+pGroup->m_NumLayers; l++)
		{
			if(l >= LayersStart+LayersNum)
				break;
			
			CMapItemLayer *pLayer = (CMapItemLayer *)m_Reader.GetItem(l, NULL, NULL);
			
			if(pLayer->m_Type == LAYERTYPE_TILES)
			{
				m_TilemapsBenchmark.Unpause();
				
				CMapItemLayerTilemap *pTilesLayer = (CMapItemLayerTilemap *)pLayer;
				
				bool GameLayer = (pTilesLayer->m_Flags & TILESLAYERFLAG_GAME) ? true : false;
				
				if((GameLayer && !pInfo->m_DumpGameTilemap) || (!GameLayer && !pInfo->m_DumpTilemaps))
					continue;
				
				if(!GameLayer && pTilesLayer->m_Image < 0)
					continue;
				
				CMapItemImage *pImage = NULL;
				if(!GameLayer)
					pImage = &pImages[pTilesLayer->m_Image];
				
				const char *pTilesetName;
				if(GameLayer)
					pTilesetName = pInfo->m_aEntities;
				else
					pTilesetName = (char *)m_Reader.GetData(pImage->m_ImageName);
				
				CTileset Src;
				if(GameLayer || pImage->m_External)
				{
					char aTilesetFilename[512];
					sprintf(aTilesetFilename, "%smapres/%s.png", pInfo->m_aCurrentDir, pTilesetName);
					
					bool Success = Src.Open(aTilesetFilename);
					if(!Success)
						continue;
				}
				else
				{
					bool Success = Src.OpenFromBuffer((unsigned char *)m_Reader.GetData(pImage->m_ImageData), pImage->m_Width, pImage->m_Height);
					if(!Success)
						continue;
				}
				
				char aTilemapFilename[512];
				if(GameLayer)
					sprintf(aTilemapFilename, "%s/tiles_game_%d.png", aGeneratedFolder, pTilesLayer->m_Data);
				else
					sprintf(aTilemapFilename, "%s/tiles_%d.png", aGeneratedFolder, pTilesLayer->m_Data);
				
				CTilemap Dest;
				bool Success = Dest.Open(aTilemapFilename, pTilesLayer->m_Width, pTilesLayer->m_Height, &Src, pInfo->m_TileSize);
				if(!Success)
					continue;
				
				CTile *pTilesData = (CTile *)m_Reader.GetData(pTilesLayer->m_Data);
				
				for(int x = 0; x < pTilesLayer->m_Width; x++)
				{
					for(int y = 0; y < pTilesLayer->m_Height; y++)
					{
						CTile *pTile = &pTilesData[y*pTilesLayer->m_Width + x];
						
						if(pTile->m_Index == 0)
							continue;
						
						Dest.SetTile(x, y, pTile->m_Index, pTile->m_Flags);
					}
				}
				
				Dest.Colorize(&pTilesLayer->m_Color);
				
				Dest.Save();
				Src.Close();
				
				m_TilemapsBenchmark.Pause();
			}
			
			else if(pLayer->m_Type == LAYERTYPE_QUADS)
			{
				m_QuadsBenchmark.Unpause();
				
				CMapItemLayerQuads *pQuadsLayer = (CMapItemLayerQuads *)pLayer;
				
				if(!pInfo->m_DumpQuads)
					continue;
				
				CImageRead Src;
				
				CMapItemImage *pImage = NULL;
				if(pQuadsLayer->m_Image >= 0)
					pImage = &pImages[pQuadsLayer->m_Image];
				
				if(pQuadsLayer->m_Image >= 0)
				{
					const char *pImageName = (char *)m_Reader.GetData(pImage->m_ImageName);
					
					if(pImage->m_External)
					{
						char aImageFilename[512];
						sprintf(aImageFilename, "%smapres/%s.png", pInfo->m_aCurrentDir, pImageName);
						
						bool Success = Src.Open(aImageFilename);
						if(!Success)
							continue;
					}
					else
					{
						bool Success = Src.OpenFromBuffer((unsigned char *)m_Reader.GetData(pImage->m_ImageData), pImage->m_Width, pImage->m_Height);
						if(!Success)
							continue;
					}
				}
				
				CQuad *pQuadsData = (CQuad *)m_Reader.GetData(pQuadsLayer->m_Data);
				
				for(int q = 0; q < pQuadsLayer->m_NumQuads; q++)
				{
					CQuad *pQuad = &pQuadsData[q];
					
					int MinX = min(min(min(pQuad->m_aPoints[0].x, pQuad->m_aPoints[1].x), pQuad->m_aPoints[2].x), pQuad->m_aPoints[3].x) / 1024;
					int MinY = min(min(min(pQuad->m_aPoints[0].y, pQuad->m_aPoints[1].y), pQuad->m_aPoints[2].y), pQuad->m_aPoints[3].y) / 1024;
					int MaxX = max(max(max(pQuad->m_aPoints[0].x, pQuad->m_aPoints[1].x), pQuad->m_aPoints[2].x), pQuad->m_aPoints[3].x) / 1024;
					int MaxY = max(max(max(pQuad->m_aPoints[0].y, pQuad->m_aPoints[1].y), pQuad->m_aPoints[2].y), pQuad->m_aPoints[3].y) / 1024;
					
					int Width = MaxX-MinX;
					int Height = MaxY-MinY;
					
					if(Width <= 0 || Height <= 0)
						continue;
					
					char aQuadsFilename[512];
					sprintf(aQuadsFilename, "%s/quads_%d_%d.png", aGeneratedFolder, pQuadsLayer->m_Data, q);
					
					CQuads Dest;
					bool Success = Dest.Open(aQuadsFilename, Width, Height, pInfo->m_TileSize);
					if(!Success)
						continue;
					
					if(pQuadsLayer->m_Image < 0)
						Dest.FillWhite();
					else
						Dest.DrawImage(&Src);
					
					Dest.DrawGradient(pQuad->m_aColors);
					
					Dest.Save();
				}
				
				m_QuadsBenchmark.Pause();
			}
		}
	}
	
	// dump metadata

	if(pInfo->m_DumpMetadata)
	{
		m_MetadataBenchmark.Unpause();
		
		CXMLDocument Doc;
		CXMLItem *pMainItem = Doc.Open("map");
		pMainItem->AddAttributeInt("version", pVersion->m_Version);
		
		for(int i = 0; i < ImagesNum; i++)
		{
			const char *pName = (char *)m_Reader.GetData(pImages[i].m_ImageName);

			CXMLItem *pImageItem = pMainItem->AddChild("image");
			pImageItem->AddAttributeInt("version", pImages[i].m_Version);
			pImageItem->AddAttributeInt("width", pImages[i].m_Width);
			pImageItem->AddAttributeInt("height", pImages[i].m_Height);
			pImageItem->AddAttributeBool("external", pImages[i].m_External);
			pImageItem->AddAttributeStr("name", pName);
		}
		
		for(int g = GroupsStart; g < GroupsStart+GroupsNum; g++)
		{
			CMapItemGroup *pGroup = (CMapItemGroup *)m_Reader.GetItem(g, NULL, NULL);
			
			CXMLItem *pGroupItem = pMainItem->AddChild("group");
			pGroupItem->AddAttributeInt("version", pGroup->m_Version);
			pGroupItem->AddAttributeInt("offset_x", pGroup->m_OffsetX);
			pGroupItem->AddAttributeInt("offset_y", pGroup->m_OffsetY);
			pGroupItem->AddAttributeInt("parallax_x", pGroup->m_ParallaxX);
			pGroupItem->AddAttributeInt("parallax_y", pGroup->m_ParallaxY);
			if(pGroup->m_Version >= 2)
			{
				pGroupItem->AddAttributeBool("use_clipping", pGroup->m_UseClipping);
				pGroupItem->AddAttributeInt("clip_x", pGroup->m_ClipX);
				pGroupItem->AddAttributeInt("clip_y", pGroup->m_ClipY);
				pGroupItem->AddAttributeInt("clip_w", pGroup->m_ClipW);
				pGroupItem->AddAttributeInt("clip_h", pGroup->m_ClipH);
			}
			
			for(int l = LayersStart + pGroup->m_StartLayer; l < LayersStart + pGroup->m_StartLayer+pGroup->m_NumLayers; l++)
			{
				if(l >= LayersStart+LayersNum)
					break;
				
				CMapItemLayer *pLayer = (CMapItemLayer *)m_Reader.GetItem(l, NULL, NULL);
				
				CXMLItem *pLayerItem = pGroupItem->AddChild("layer");
				if(pLayer->m_Type == LAYERTYPE_TILES)
					pLayerItem->AddAttributeStr("type", "tiles");
				else if(pLayer->m_Type == LAYERTYPE_QUADS)
					pLayerItem->AddAttributeStr("type", "quads");
				else
					pLayerItem->AddAttributeStr("type", "invalid");
				pLayerItem->AddAttributeBool("detail", pLayer->m_Flags&TILESLAYERFLAG_GAME);
				
				if(pLayer->m_Type == LAYERTYPE_TILES)
				{
					CMapItemLayerTilemap *pTilesLayer = (CMapItemLayerTilemap *)pLayer;
					
					const char *pImageName = "";
					if(pTilesLayer->m_Image >= 0 && pTilesLayer->m_Image < ImagesNum)
						pImageName = (char *)m_Reader.GetData(pImages[pTilesLayer->m_Image].m_ImageName);
					
					pLayerItem->AddAttributeInt("version", pTilesLayer->m_Version);
					pLayerItem->AddAttributeInt("width", pTilesLayer->m_Width);
					pLayerItem->AddAttributeInt("height", pTilesLayer->m_Height);
					pLayerItem->AddAttributeBool("game", pTilesLayer->m_Flags&TILESLAYERFLAG_GAME);
					pLayerItem->AddAttributeInt("color_env", pTilesLayer->m_ColorEnv);
					pLayerItem->AddAttributeInt("color_env_offset", pTilesLayer->m_ColorEnvOffset);
					pLayerItem->AddAttributeStr("image", pImageName);
					pLayerItem->AddAttributeInt("data", pTilesLayer->m_Data);
					
					CXMLItem *pColorItem = pLayerItem->AddChild("color");
					pColorItem->AddAttributeInt("r", pTilesLayer->m_Color.r);
					pColorItem->AddAttributeInt("g", pTilesLayer->m_Color.g);
					pColorItem->AddAttributeInt("b", pTilesLayer->m_Color.b);
					pColorItem->AddAttributeInt("a", pTilesLayer->m_Color.a);
				}
				else if(pLayer->m_Type == LAYERTYPE_QUADS)
				{
					CMapItemLayerQuads *pQuadsLayer = (CMapItemLayerQuads *)pLayer;
					
					const char *pImageName = "";
					if(pQuadsLayer->m_Image >= 0 && pQuadsLayer->m_Image < ImagesNum)
						pImageName = (char *)m_Reader.GetData(pImages[pQuadsLayer->m_Image].m_ImageName);
					
					pLayerItem->AddAttributeInt("version", pQuadsLayer->m_Version);
					pLayerItem->AddAttributeStr("image", pImageName);
					pLayerItem->AddAttributeInt("data", pQuadsLayer->m_Data);
					
					CQuad *pQuadsData = (CQuad *)m_Reader.GetData(pQuadsLayer->m_Data);
					
					for(int q = 0; q < pQuadsLayer->m_NumQuads; q++)
					{
						CQuad *pQuad = &pQuadsData[q];
						
						CXMLItem *pQuadItem = pLayerItem->AddChild("quad");
						pQuadItem->AddAttributeInt("pos_env", pQuad->m_PosEnv);
						pQuadItem->AddAttributeInt("pos_env_offset", pQuad->m_PosEnvOffset);
						pQuadItem->AddAttributeInt("color_env", pQuad->m_ColorEnv);
						pQuadItem->AddAttributeInt("color_env_offset", pQuad->m_ColorEnvOffset);
						pQuadItem->AddAttributeInt("data", q);
						
						for(int k = 0; k < 5; k++)
						{
							CXMLItem *pPointItem = pQuadItem->AddChild("point");
							pPointItem->AddAttributeInt("x", fx2f(pQuad->m_aPoints[k].x));
							pPointItem->AddAttributeInt("y", fx2f(pQuad->m_aPoints[k].y));
						}
						
						for(int k = 0; k < 4; k++)
						{
							CXMLItem *pColorItem = pQuadItem->AddChild("color");
							pColorItem->AddAttributeInt("r", pQuad->m_aColors[k].r);
							pColorItem->AddAttributeInt("g", pQuad->m_aColors[k].g);
							pColorItem->AddAttributeInt("b", pQuad->m_aColors[k].b);
							pColorItem->AddAttributeInt("a", pQuad->m_aColors[k].a);
						}
						
						for(int k = 0; k < 4; k++)
						{
							CXMLItem *pTexcoordItem = pQuadItem->AddChild("texcoord");
							pTexcoordItem->AddAttributeInt("x", fx2f(pQuad->m_aTexcoords[k].x));
							pTexcoordItem->AddAttributeInt("y", fx2f(pQuad->m_aTexcoords[k].y));
						}
					}
				}
			}
		}
		
		int EnvPointsStart;
		int EnvPointsNum;
		m_Reader.GetType(MAPITEMTYPE_ENVPOINTS, &EnvPointsStart, &EnvPointsNum);
		
		CEnvPoint *pPoints = 0;
		if(EnvPointsNum)
			pPoints = (CEnvPoint *)m_Reader.GetItem(EnvPointsStart, NULL, NULL);
		
		int EnvStart;
		int EnvNum;
		m_Reader.GetType(MAPITEMTYPE_ENVELOPE, &EnvStart, &EnvNum);
		
		for(int e = EnvStart; e < EnvStart+EnvNum; e++)
		{
			CMapItemEnvelope *pEnv = (CMapItemEnvelope *)m_Reader.GetItem(e, NULL, NULL);
			
			CXMLItem *pEnvItem = pMainItem->AddChild("envelope");
			pEnvItem->AddAttributeInt("version", pEnv->m_Version);
			if(pEnv->m_Channels == 3)
				pEnvItem->AddAttributeStr("type", "pos");
			else if(pEnv->m_Channels == 4)
				pEnvItem->AddAttributeStr("type", "color");
			else
				pEnvItem->AddAttributeStr("type", "invalid");
			if(pEnv->m_aName[0] != -1)
			{
				char aEnvName[64];
				IntsToStr(pEnv->m_aName, sizeof(pEnv->m_aName)/sizeof(int), aEnvName);
				pEnvItem->AddAttributeStr("name", aEnvName);
			}
			
			for(int p = pEnv->m_StartPoint; p < pEnv->m_StartPoint+pEnv->m_NumPoints; p++)
			{
				CXMLItem *pEnvPointItem = pEnvItem->AddChild("envpoint");
				pEnvPointItem->AddAttributeInt("time", pPoints[p].m_Time);
				if(p != pEnv->m_StartPoint+pEnv->m_NumPoints -1)
				{
					if(pPoints[p].m_Curvetype == CURVETYPE_STEP)
						pEnvPointItem->AddAttributeStr("curvetype", "step");
					else if(pPoints[p].m_Curvetype == CURVETYPE_LINEAR)
						pEnvPointItem->AddAttributeStr("curvetype", "linear");
					else if(pPoints[p].m_Curvetype == CURVETYPE_SLOW)
						pEnvPointItem->AddAttributeStr("curvetype", "slow");
					else if(pPoints[p].m_Curvetype == CURVETYPE_FAST)
						pEnvPointItem->AddAttributeStr("curvetype", "fast");
					else if(pPoints[p].m_Curvetype == CURVETYPE_SMOOTH)
						pEnvPointItem->AddAttributeStr("curvetype", "smooth");
					else
						pEnvPointItem->AddAttributeStr("curvetype", "invalid");
				}
				if(pEnv->m_Channels == 3)
				{
					pEnvPointItem->AddAttributeInt("x", fx2f(pPoints[p].m_aValues[0]));
					pEnvPointItem->AddAttributeInt("y", fx2f(pPoints[p].m_aValues[1]));
					pEnvPointItem->AddAttributeInt("r", fx2f(pPoints[p].m_aValues[2]));
				}
				else if(pEnv->m_Channels == 4)
				{
					pEnvPointItem->AddAttributeInt("r", fx2f(pPoints[p].m_aValues[0])*255);
					pEnvPointItem->AddAttributeInt("g", fx2f(pPoints[p].m_aValues[1])*255);
					pEnvPointItem->AddAttributeInt("b", fx2f(pPoints[p].m_aValues[2])*255);
					pEnvPointItem->AddAttributeInt("a", fx2f(pPoints[p].m_aValues[3])*255);
				}
			}
		}
		
		char aMetadataFilename[512];
		sprintf(aMetadataFilename, "%s/metadata.xml", aGeneratedFolder);
		Doc.Save(aMetadataFilename);
		Doc.Close();
		
		m_MetadataBenchmark.Pause();
	}
	
	if(ImagesNum > 0)
		delete pImages;
	
	remove(aGenerating);
	
	m_OverallBenchmark.Pause();
	
	if(pInfo->m_ShowBenchmark)
	{
		printf("Benchmark results:\n");
		printf("  Images dumping:\t%dms\n", m_ImagesBenchmark.GetTime());
		printf("  Tilemaps dumping:\t%dms\n", m_TilemapsBenchmark.GetTime());
		printf("  Quads dumping:\t%dms\n", m_QuadsBenchmark.GetTime());
		printf("  Metadata dumping:\t%dms\n", m_MetadataBenchmark.GetTime());
		printf("  Overall:\t\t%dms\n", m_OverallBenchmark.GetTime());
	}
}