You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
949 lines
27 KiB
949 lines
27 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: Generic in-game abuse reporting |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
|
|
#include "cbase.h" |
|
#include "abuse_report_ui.h" |
|
#include "econ/econ_controls.h" |
|
#include "ienginevgui.h" |
|
#include "vgui/ISurface.h" |
|
#include <vgui_controls/TextEntry.h> |
|
#include <vgui_controls/ComboBox.h> |
|
#include <vgui_controls/RadioButton.h> |
|
#include "vgui_bitmappanel.h" |
|
#include "vgui_avatarimage.h" |
|
#include "gc_clientsystem.h" |
|
#include "econ/tool_items/tool_items.h" |
|
#include "econ/econ_gcmessages.h" |
|
#include "econ/confirm_dialog.h" |
|
#include "tool_items/custom_texture_cache.h" |
|
|
|
vgui::DHANDLE<CAbuseReportDlg> g_AbuseReportDlg; |
|
|
|
CAbuseReportDlg::CAbuseReportDlg( vgui::Panel *parent, AbuseIncidentData_t *pIncidentData ) |
|
: EditablePanel( parent, "AbuseReportSubmitDialog" ) |
|
, m_pSubmitButton( NULL ) |
|
, m_pScreenShot( NULL ) |
|
, m_pScreenShotAttachCheckButton( NULL ) |
|
, m_pOffensiveImage( NULL ) |
|
, m_pDescriptionTextEntry( NULL ) |
|
, m_pPlayerLabel( NULL ) |
|
, m_pPlayerRadio( NULL ) |
|
, m_pGameServerRadio( NULL ) |
|
, m_pPlayerCombo( NULL ) |
|
, m_pAbuseContentLabel( NULL ) |
|
, m_pAbuseContentCombo( NULL ) |
|
, m_pAbuseTypeLabel( NULL ) |
|
, m_pAbuseTypeCombo( NULL ) |
|
, m_pScreenShotBitmap( NULL ) |
|
, m_pAvatarImage( NULL ) |
|
, m_pNoAvatarLabel( NULL ) |
|
, m_pCustomTextureImagePanel( NULL ) |
|
, m_pNoCustomTexturesLabel( NULL ) |
|
, m_pCustomTextureNextButton( NULL ) |
|
, m_pCustomTexturePrevButton( NULL ) |
|
, m_iUserImageIndex( 0 ) |
|
, m_pIncidentData( pIncidentData ) |
|
{ |
|
vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/ClientScheme.res", "ClientScheme" ); |
|
SetScheme(scheme); |
|
SetProportional( true ); |
|
//m_pContainer = new vgui::EditablePanel( this, "Container" ); |
|
|
|
Assert( g_AbuseReportDlg.Get() == NULL ); |
|
g_AbuseReportDlg.Set( this ); |
|
|
|
engine->ExecuteClientCmd("gameui_preventescape"); |
|
} |
|
|
|
CAbuseReportDlg::~CAbuseReportDlg() |
|
{ |
|
Assert( g_AbuseReportDlg.Get() == this ); |
|
if ( g_AbuseReportDlg.Get() == this ) |
|
{ |
|
engine->ExecuteClientCmd("gameui_allowescape"); |
|
g_AbuseReportDlg = NULL; |
|
} |
|
} |
|
|
|
void CAbuseReportDlg::OnCommand( const char *command ) |
|
{ |
|
if ( !Q_stricmp( command, "cancel" ) ) |
|
{ |
|
Close(); |
|
return; |
|
} |
|
if ( !Q_stricmp( command, "discard" ) ) |
|
{ |
|
Close(); |
|
g_AbuseReportMgr->DestroyIncidentData(); |
|
return; |
|
} |
|
if ( !Q_stricmp( command, "submit" ) ) |
|
{ |
|
OnSubmitReport(); |
|
return; |
|
} |
|
if ( !Q_stricmp( command, "nextcustomtexture" ) ) |
|
{ |
|
++m_iUserImageIndex; |
|
UpdateCustomTextures(); |
|
return; |
|
} |
|
|
|
if ( !Q_stricmp( command, "prevcustomtexture" ) ) |
|
{ |
|
--m_iUserImageIndex; |
|
UpdateCustomTextures(); |
|
return; |
|
} |
|
|
|
} |
|
|
|
void CAbuseReportDlg::MakeModal() |
|
{ |
|
TFModalStack()->PushModal( this ); |
|
MakePopup(); |
|
MoveToFront(); |
|
SetKeyBoardInputEnabled( true ); |
|
SetMouseInputEnabled( true ); |
|
|
|
// !KLUDGE! Initially set the dialog to be hidden, so we can take a screenshot! |
|
SetEnabled( m_pIncidentData != NULL ); |
|
//SetVisible( m_pIncidentData != NULL ); |
|
} |
|
|
|
void CAbuseReportDlg::Close() |
|
{ |
|
TFModalStack()->PopModal( this ); |
|
SetVisible( false ); |
|
MarkForDeletion(); |
|
} |
|
|
|
const char *CAbuseReportDlg::GetResFilename() |
|
{ |
|
return "Resource/UI/AbuseReportSubmitDialog.res"; |
|
//return "Resource/UI/QuickplayDialog.res"; |
|
} |
|
|
|
void CAbuseReportDlg::PerformLayout() |
|
{ |
|
BaseClass::PerformLayout(); |
|
|
|
// Center it, keeping requested size |
|
int x, y, ww, wt, wide, tall; |
|
vgui::surface()->GetWorkspaceBounds( x, y, ww, wt ); |
|
GetSize(wide, tall); |
|
SetPos(x + ((ww - wide) / 2), y + ((wt - tall) / 2)); |
|
|
|
// @todo setup |
|
} |
|
|
|
class CCustomTextureImagePanel : public vgui::Panel |
|
{ |
|
public: |
|
CCustomTextureImagePanel( Panel *parent, const char *panelName ) : vgui::Panel( parent, panelName ) |
|
{ |
|
m_ugcHandle = 0; |
|
} |
|
|
|
uint64 m_ugcHandle; |
|
|
|
virtual void Paint() |
|
{ |
|
if ( m_ugcHandle == 0 ) |
|
{ |
|
return; |
|
} |
|
int iTextureHandle = GetCustomTextureGuiHandle( m_ugcHandle ); |
|
if ( iTextureHandle <= 0) |
|
{ |
|
return; |
|
} |
|
|
|
vgui::surface()->DrawSetColor(COLOR_WHITE); |
|
vgui::surface()->DrawSetTexture( iTextureHandle ); |
|
int iWide, iTall; |
|
GetSize( iWide, iTall ); |
|
|
|
vgui::Vertex_t verts[4]; |
|
verts[0].Init( Vector2D( 0, 0 ), Vector2D( 0.0f, 0.0f ) ); |
|
verts[1].Init( Vector2D( iWide, 0 ), Vector2D( 1.0f, 0.0f ) ); |
|
verts[2].Init( Vector2D( iWide, iTall ), Vector2D( 1.0f, 1.0f ) ); |
|
verts[3].Init( Vector2D( 0, iTall ), Vector2D( 0.0f, 1.0f ) ); |
|
|
|
vgui::surface()->DrawTexturedPolygon( 4, verts ); |
|
vgui::surface()->DrawSetColor(COLOR_WHITE); |
|
} |
|
|
|
}; |
|
|
|
class CAbuseReportScreenShotPanel : public CBitmapPanel |
|
{ |
|
public: |
|
CAbuseReportScreenShotPanel( CAbuseReportDlg *pDlg, const char *panelName ) |
|
: CBitmapPanel( pDlg, panelName ) |
|
, m_pDlg( pDlg ) |
|
{} |
|
|
|
CAbuseReportDlg *m_pDlg; |
|
|
|
virtual void Paint() |
|
{ |
|
CBitmapPanel::Paint(); |
|
|
|
const AbuseIncidentData_t::PlayerData_t *p = m_pDlg->GetAccusedPlayerPtr(); |
|
if ( p == NULL || !p->m_bRenderBoundsValid ) |
|
{ |
|
return; |
|
} |
|
int w, t; |
|
GetSize( w, t ); |
|
|
|
int x0 = int( p->m_screenBoundsMin.x * (float)w ); |
|
int y0 = int( p->m_screenBoundsMin.y * (float)t ); |
|
int x1 = int( p->m_screenBoundsMax.x * (float)w ); |
|
int y1 = int( p->m_screenBoundsMax.y * (float)t ); |
|
|
|
vgui::surface()->DrawSetColor( Color(200, 10, 10, 200 ) ); |
|
vgui::surface()->DrawOutlinedRect( x0, y0, x1, y1 ); |
|
vgui::surface()->DrawSetColor( COLOR_WHITE ); |
|
} |
|
}; |
|
|
|
void CAbuseReportDlg::ApplySchemeSettings( vgui::IScheme *pScheme ) |
|
{ |
|
EditablePanel::ApplySchemeSettings( pScheme ); |
|
|
|
m_pScreenShotBitmap = new CAbuseReportScreenShotPanel( this, "ScreenShotBitmap" ); |
|
m_pCustomTextureImagePanel = new CCustomTextureImagePanel( this, "CustomTextureImage" ); |
|
|
|
LoadControlSettings( GetResFilename() ); |
|
|
|
m_pPlayerRadio = dynamic_cast<vgui::RadioButton *>(FindChildByName( "PlayerRadio", true )); |
|
Assert( m_pPlayerRadio ); |
|
if ( m_pPlayerRadio ) |
|
{ |
|
m_pPlayerRadio->SetVisible( m_pIncidentData->m_bCanReportGameServer ); |
|
} |
|
|
|
m_pGameServerRadio = dynamic_cast<vgui::RadioButton *>(FindChildByName( "GameServerRadio", true )); |
|
Assert( m_pGameServerRadio ); |
|
if ( m_pGameServerRadio ) |
|
{ |
|
m_pGameServerRadio->SetVisible( m_pIncidentData->m_bCanReportGameServer ); |
|
} |
|
|
|
m_pPlayerLabel = FindChildByName( "PlayerLabel", true ); |
|
Assert( m_pPlayerLabel ); |
|
|
|
m_pScreenShotAttachCheckButton = dynamic_cast<vgui::CheckButton *>(FindChildByName( "ScreenShotAttachCheckButton", true )); |
|
Assert( m_pScreenShotAttachCheckButton ); |
|
if ( m_pScreenShotAttachCheckButton ) |
|
{ |
|
m_pScreenShotAttachCheckButton->SetSelected( true ); |
|
} |
|
|
|
m_pSubmitButton = dynamic_cast<vgui::Button *>(FindChildByName( "SubmitButton", true )); |
|
Assert( m_pSubmitButton ); |
|
|
|
m_pDescriptionTextEntry = dynamic_cast<vgui::TextEntry *>(FindChildByName( "DescriptionTextEntry", true )); |
|
Assert( m_pDescriptionTextEntry ); |
|
if ( m_pDescriptionTextEntry ) |
|
{ |
|
m_pDescriptionTextEntry->SetMultiline( true ); |
|
} |
|
|
|
m_pAvatarImage = dynamic_cast<CAvatarImagePanel *>(FindChildByName( "AvatarImage", true )); |
|
Assert( m_pAvatarImage ); |
|
|
|
m_pNoAvatarLabel = FindChildByName( "NoAvatarLabel", true ); |
|
Assert( m_pNoAvatarLabel ); |
|
|
|
m_pNoCustomTexturesLabel = FindChildByName( "NoCustomTexturesLabel", true ); |
|
Assert( m_pNoCustomTexturesLabel ); |
|
|
|
m_pCustomTextureNextButton = dynamic_cast<vgui::Button *>(FindChildByName( "CustomTextureNextButton", true )); |
|
Assert( m_pCustomTextureNextButton ); |
|
|
|
m_pCustomTexturePrevButton = dynamic_cast<vgui::Button *>(FindChildByName( "CustomTexturePrevButton", true )); |
|
Assert( m_pCustomTexturePrevButton ); |
|
|
|
m_pPlayerCombo = dynamic_cast<vgui::ComboBox *>(FindChildByName( "PlayerComboBox", true )); |
|
Assert( m_pPlayerCombo ); |
|
|
|
m_pAbuseContentLabel = FindChildByName( "AbuseContentLabel", true ); |
|
Assert( m_pAbuseContentLabel ); |
|
|
|
m_pAbuseContentCombo = dynamic_cast<vgui::ComboBox *>(FindChildByName( "AbuseContentComboBox", true )); |
|
Assert( m_pAbuseContentCombo ); |
|
if ( m_pAbuseContentCombo ) |
|
{ |
|
m_pAbuseContentCombo->AddItem( "#AbuseReport_SelectOne", new KeyValues( "AbuseContent", "code", k_EAbuseReportContentNoSelection ) ); |
|
m_pAbuseContentCombo->AddItem( "#AbuseReport_ContentAvatarImage", new KeyValues( "AbuseContent", "code", k_EAbuseReportContentAvatarImage ) ); |
|
m_pAbuseContentCombo->AddItem( "#AbuseReport_ContentPlayerName", new KeyValues( "AbuseContent", "code", k_EAbuseReportContentPersonaName ) ); |
|
m_pAbuseContentCombo->AddItem( "#AbuseReport_ContentItemDecal", new KeyValues( "AbuseContent", "code", k_EAbuseReportContentUGCImage ) ); |
|
m_pAbuseContentCombo->AddItem( "#AbuseReport_ContentChatText", new KeyValues( "AbuseContent", "code", k_EAbuseReportContentComments ) ); |
|
m_pAbuseContentCombo->AddItem( "#AbuseReport_ContentCheating", new KeyValues( "AbuseContent", "code", k_EAbuseReportContentCheating ) ); |
|
m_pAbuseContentCombo->AddItem( "#AbuseReport_ContentOther", new KeyValues( "AbuseContent", "code", k_EAbuseReportContentUnspecified ) ); |
|
m_pAbuseContentCombo->SilentActivateItemByRow( 0 ); |
|
m_pAbuseContentCombo->SetNumberOfEditLines( m_pAbuseContentCombo->GetItemCount() ); |
|
} |
|
|
|
m_pAbuseTypeLabel = FindChildByName( "AbuseTypeLabel", true ); |
|
Assert( m_pAbuseTypeLabel ); |
|
|
|
m_pAbuseTypeCombo = dynamic_cast<vgui::ComboBox *>(FindChildByName( "AbuseTypeComboBox", true )); |
|
Assert( m_pAbuseTypeCombo ); |
|
|
|
Assert( m_pScreenShotBitmap ); |
|
if ( m_pScreenShotBitmap && m_pIncidentData->m_bitmapScreenshot.IsValid() ) |
|
{ |
|
m_pScreenShotBitmap->SetBitmap( m_pIncidentData->m_bitmapScreenshot ); |
|
} |
|
|
|
PopulatePlayerList(); |
|
SetIsAccusingGameServer( false ); |
|
|
|
SetEnabled( true ); |
|
SetVisible( true ); |
|
} |
|
|
|
bool CAbuseReportDlg::IsAccusingGameServer() |
|
{ |
|
return m_pIncidentData && m_pIncidentData->m_bCanReportGameServer && m_pGameServerRadio && m_pGameServerRadio->IsSelected(); |
|
} |
|
|
|
EAbuseReportContentType CAbuseReportDlg::GetAbuseContentType() |
|
{ |
|
if ( m_pAbuseContentCombo == NULL || IsAccusingGameServer() ) |
|
{ |
|
Assert( m_pAbuseContentCombo ); |
|
return k_EAbuseReportContentNoSelection; |
|
} |
|
KeyValues *pUserData = m_pAbuseContentCombo->GetActiveItemUserData(); |
|
if ( pUserData == NULL ) |
|
{ |
|
return k_EAbuseReportContentNoSelection; |
|
} |
|
return (EAbuseReportContentType)pUserData->GetInt( "code", k_EAbuseReportContentNoSelection ); |
|
} |
|
|
|
EAbuseReportType CAbuseReportDlg::GetAbuseType() |
|
{ |
|
if ( m_pAbuseTypeCombo == NULL || IsAccusingGameServer() ) |
|
{ |
|
Assert( m_pAbuseTypeCombo ); |
|
return k_EAbuseReportTypeNoSelection; |
|
} |
|
KeyValues *pUserData = m_pAbuseTypeCombo->GetActiveItemUserData(); |
|
if ( pUserData == NULL ) |
|
{ |
|
return k_EAbuseReportTypeNoSelection; |
|
} |
|
return (EAbuseReportType)pUserData->GetInt( "code", k_EAbuseReportTypeNoSelection ); |
|
} |
|
|
|
CUtlString CAbuseReportDlg::GetAbuseDescription() |
|
{ |
|
char buf[ 1024 ] = ""; |
|
if ( m_pDescriptionTextEntry ) |
|
{ |
|
m_pDescriptionTextEntry->GetText( buf, ARRAYSIZE(buf) ); |
|
} |
|
|
|
return CUtlString( buf ); |
|
} |
|
|
|
int CAbuseReportDlg::GetAccusedPlayerIndex() |
|
{ |
|
// If accusing a game server, then there's no player |
|
if ( IsAccusingGameServer() ) |
|
{ |
|
return -1; |
|
} |
|
|
|
if ( m_pPlayerCombo == NULL ) |
|
{ |
|
Assert( m_pPlayerCombo ); |
|
return -1; |
|
} |
|
|
|
// Item 0 is the "<select one>" item |
|
return m_pPlayerCombo->GetActiveItem() - 1; |
|
} |
|
|
|
const AbuseIncidentData_t::PlayerData_t *CAbuseReportDlg::GetAccusedPlayerPtr() |
|
{ |
|
int iPlayerIndex = GetAccusedPlayerIndex(); |
|
if ( iPlayerIndex < 0 ) |
|
return NULL; |
|
return &m_pIncidentData->m_vecPlayers[ iPlayerIndex ]; |
|
} |
|
|
|
bool CAbuseReportDlg::GetAttachScreenShot() |
|
{ |
|
if ( m_pScreenShotAttachCheckButton == NULL ) |
|
{ |
|
return false; |
|
} |
|
if ( !m_pScreenShotAttachCheckButton->IsVisible() ) |
|
{ |
|
// We hide the checkbutton when the option is not applicable |
|
return false; |
|
} |
|
return m_pScreenShotAttachCheckButton->IsSelected(); |
|
} |
|
|
|
void CAbuseReportDlg::PopulatePlayerList() |
|
{ |
|
if ( m_pIncidentData == NULL || m_pPlayerCombo == NULL ) |
|
{ |
|
Assert( m_pIncidentData ); |
|
Assert( m_pPlayerCombo ); |
|
return; |
|
} |
|
m_pPlayerCombo->RemoveAll(); |
|
m_pPlayerCombo->AddItem( "#AbuseReport_SelectOne", NULL ); |
|
for ( int i = 0 ; i < m_pIncidentData->m_vecPlayers.Count() ; ++i ) |
|
{ |
|
AbuseIncidentData_t::PlayerData_t *p = &m_pIncidentData->m_vecPlayers[i]; |
|
m_pPlayerCombo->AddItem( p->m_sPersona, NULL ); |
|
} |
|
m_pPlayerCombo->SilentActivateItemByRow( 0 ); |
|
|
|
m_pPlayerCombo->SetNumberOfEditLines( MIN( m_pPlayerCombo->GetItemCount()+1, 12 ) ); |
|
} |
|
|
|
void CAbuseReportDlg::UpdateSubmitButton() |
|
{ |
|
if ( !m_pSubmitButton ) |
|
{ |
|
Assert( m_pSubmitButton ); |
|
return; |
|
} |
|
|
|
bool bEnable = false; |
|
if ( IsAccusingGameServer() ) |
|
{ |
|
bEnable = true; |
|
} |
|
else |
|
{ |
|
EAbuseReportContentType eContent = GetAbuseContentType(); |
|
const AbuseIncidentData_t::PlayerData_t *pAccused = GetAccusedPlayerPtr(); |
|
if ( |
|
eContent >= 0 |
|
&& GetAbuseType() >= 0 |
|
&& pAccused != NULL ) |
|
{ |
|
bEnable = true; |
|
if ( eContent == k_EAbuseReportContentAvatarImage && pAccused->m_iSteamAvatarIndex <= 0 ) |
|
{ |
|
// Cannot accuse somebody of having a bad avatar image, if they |
|
// don't have one set |
|
bEnable = false; |
|
} |
|
} |
|
} |
|
if ( GetAbuseDescription().IsEmpty() ) |
|
{ |
|
bEnable = false; |
|
} |
|
|
|
m_pSubmitButton->SetEnabled( bEnable ); |
|
} |
|
|
|
void CAbuseReportDlg::ContentTypeChanged() |
|
{ |
|
|
|
// Save current abuse type. We want to keep it the same, |
|
// if possible |
|
EAbuseReportType abuseType = GetAbuseType(); |
|
EAbuseReportContentType contentType = GetAbuseContentType(); |
|
|
|
// Show/hide screen shot / image select |
|
bool bShowScreenshot = false; |
|
bool bShowAttach = false; |
|
switch ( contentType ) |
|
{ |
|
default: |
|
Assert( false ); |
|
case k_EAbuseReportContentNoSelection: |
|
case k_EAbuseReportContentPersonaName: |
|
bShowScreenshot = true; |
|
bShowAttach = false; |
|
break; |
|
|
|
case k_EAbuseReportContentUnspecified: |
|
case k_EAbuseReportContentComments: |
|
case k_EAbuseReportContentCheating: |
|
bShowScreenshot = true; |
|
bShowAttach = true; |
|
break; |
|
|
|
case k_EAbuseReportContentAvatarImage: |
|
case k_EAbuseReportContentUGCImage: |
|
bShowScreenshot = false; |
|
bShowAttach = false; |
|
break; |
|
} |
|
|
|
bShowScreenshot = bShowScreenshot && m_pIncidentData->m_bitmapScreenshot.IsValid(); |
|
|
|
// Make sure we have everything we need to upload a screenshot |
|
bShowAttach = bShowAttach |
|
&& bShowScreenshot |
|
&& ( GetAccusedPlayerIndex() >= 0 ) |
|
&& m_pIncidentData->m_bufScreenshotFileData.TellPut() > 0 |
|
&& steamapicontext |
|
&& ( steamapicontext->SteamUtils() != NULL ) |
|
&& ( steamapicontext->SteamRemoteStorage() != NULL ); |
|
|
|
if ( m_pScreenShotBitmap ) |
|
{ |
|
m_pScreenShotBitmap->SetVisible( bShowScreenshot ); |
|
} |
|
if ( m_pScreenShotAttachCheckButton ) |
|
{ |
|
m_pScreenShotAttachCheckButton->SetVisible( bShowAttach ); |
|
} |
|
|
|
UpdateAvatarImage(); |
|
UpdateCustomTextures(); |
|
|
|
// Populate abuse type |
|
if ( m_pAbuseTypeCombo ) |
|
{ |
|
|
|
// If the combo box was invisible, then they didn't really make a purposeful decision |
|
if ( !m_pAbuseTypeCombo->IsVisible() ) |
|
{ |
|
abuseType = k_EAbuseReportTypeNoSelection; |
|
} |
|
m_pAbuseTypeCombo->RemoveAll(); |
|
switch ( contentType ) |
|
{ |
|
default: |
|
Assert( false ); |
|
case k_EAbuseReportContentNoSelection: |
|
m_pAbuseTypeCombo->SetVisible( false ); |
|
abuseType = k_EAbuseReportTypeNoSelection; |
|
m_pAbuseTypeCombo->AddItem( "#AbuseReport_SelectOne", new KeyValues( "AbuseType", "code", k_EAbuseReportTypeNoSelection ) ); |
|
break; |
|
|
|
case k_EAbuseReportContentCheating: |
|
m_pAbuseTypeCombo->SetVisible( false ); |
|
abuseType = k_EAbuseReportTypeCheating; |
|
m_pAbuseTypeCombo->AddItem( "#AbuseReport_TypeCheating", new KeyValues( "AbuseType", "code", k_EAbuseReportTypeCheating ) ); |
|
break; |
|
|
|
case k_EAbuseReportContentUnspecified: |
|
case k_EAbuseReportContentComments: |
|
case k_EAbuseReportContentPersonaName: |
|
case k_EAbuseReportContentAvatarImage: |
|
case k_EAbuseReportContentUGCImage: |
|
m_pAbuseTypeCombo->SetVisible( true ); |
|
m_pAbuseTypeCombo->AddItem( "#AbuseReport_SelectOne", new KeyValues( "AbuseType", "code", k_EAbuseReportTypeNoSelection ) ); |
|
m_pAbuseTypeCombo->AddItem( "#AbuseReport_TypeSpam", new KeyValues( "AbuseType", "code", k_EAbuseReportTypeSpamming ) ); |
|
m_pAbuseTypeCombo->AddItem( "#AbuseReport_TypeAdvertisement", new KeyValues( "AbuseType", "code", k_EAbuseReportTypeAdvertisement ) ); |
|
m_pAbuseTypeCombo->AddItem( "#AbuseReport_TypeLanguage", new KeyValues( "AbuseType", "code", k_EAbuseReportTypeLanguage ) ); |
|
m_pAbuseTypeCombo->AddItem( "#AbuseReport_TypeAdultContent", new KeyValues( "AbuseType", "code", k_EAbuseReportTypeAdultContent ) ); |
|
m_pAbuseTypeCombo->AddItem( "#AbuseReport_TypeHarassment", new KeyValues( "AbuseType", "code", k_EAbuseReportTypeHarassment ) ); |
|
m_pAbuseTypeCombo->AddItem( "#AbuseReport_TypeProhibited", new KeyValues( "AbuseType", "code", k_EAbuseReportTypeProhibited ) ); |
|
m_pAbuseTypeCombo->AddItem( "#AbuseReport_TypeSpoofing", new KeyValues( "AbuseType", "code", k_EAbuseReportTypeSpoofing ) ); |
|
//m_pAbuseTypeCombo->AddItem( "#AbuseReport_TypeCheating", new KeyValues( "AbuseType", "code", k_EAbuseReportTypeCheating ) ); |
|
m_pAbuseTypeCombo->AddItem( "#AbuseReport_TypeInappropriate", new KeyValues( "AbuseType", "code", k_EAbuseReportTypeInappropriate ) ); |
|
m_pAbuseTypeCombo->AddItem( "#AbuseReport_TypeOther", new KeyValues( "AbuseType", "code", k_EAbuseReportTypeUnspecified ) ); |
|
break; |
|
} |
|
|
|
// Now select the proper row |
|
int sel = 0; |
|
for ( int i = 0 ; i < m_pAbuseTypeCombo->GetItemCount() ; ++i ) { |
|
if ( m_pAbuseTypeCombo->GetItemUserData(i)->GetInt("code") == abuseType ) |
|
{ |
|
sel = i; |
|
break; |
|
} |
|
} |
|
m_pAbuseTypeCombo->SilentActivateItemByRow( sel ); |
|
m_pAbuseTypeCombo->SetNumberOfEditLines( m_pAbuseTypeCombo->GetItemCount() ); |
|
if ( m_pAbuseTypeLabel ) |
|
{ |
|
m_pAbuseTypeLabel->SetVisible( m_pAbuseTypeCombo->IsVisible() ); |
|
} |
|
} |
|
|
|
UpdateSubmitButton(); |
|
} |
|
|
|
void CAbuseReportDlg::OnRadioButtonChecked( vgui::Panel *panel ) |
|
{ |
|
if ( panel == m_pPlayerRadio ) |
|
{ |
|
SetIsAccusingGameServer( false ); |
|
} |
|
else if ( panel == m_pGameServerRadio ) |
|
{ |
|
SetIsAccusingGameServer( true ); |
|
} |
|
else |
|
{ |
|
Assert( !"Clicked on unknown radio" ); |
|
} |
|
} |
|
|
|
void CAbuseReportDlg::SetIsAccusingGameServer( bool bAccuseGameServer ) |
|
{ |
|
if ( m_pGameServerRadio && m_pGameServerRadio->IsSelected() != bAccuseGameServer ) |
|
{ |
|
m_pGameServerRadio->SetSelected( bAccuseGameServer ); |
|
} |
|
if ( m_pPlayerRadio && m_pPlayerRadio->IsSelected() == bAccuseGameServer) |
|
{ |
|
m_pPlayerRadio->SetSelected( !bAccuseGameServer ); |
|
} |
|
if ( m_pPlayerLabel ) |
|
{ |
|
m_pPlayerLabel->SetVisible( !bAccuseGameServer ); |
|
} |
|
if ( m_pPlayerCombo ) |
|
{ |
|
m_pPlayerCombo->SetVisible( !bAccuseGameServer ); |
|
} |
|
|
|
PlayerChanged(); |
|
} |
|
|
|
void CAbuseReportDlg::PlayerChanged() |
|
{ |
|
m_iUserImageIndex = 0; |
|
|
|
bool bShow = ( GetAccusedPlayerIndex() >= 0 ); |
|
if ( m_pAbuseContentCombo != NULL ) |
|
{ |
|
m_pAbuseContentCombo->SetVisible( bShow ); |
|
} |
|
if ( m_pAbuseContentLabel != NULL ) |
|
{ |
|
m_pAbuseContentLabel->SetVisible( bShow ); |
|
} |
|
|
|
ContentTypeChanged(); |
|
} |
|
|
|
void CAbuseReportDlg::UpdateAvatarImage() |
|
{ |
|
if ( m_pAvatarImage == NULL || m_pNoAvatarLabel == NULL ) |
|
{ |
|
Assert( m_pAvatarImage ); |
|
Assert( m_pNoAvatarLabel ); |
|
return; |
|
} |
|
|
|
const AbuseIncidentData_t::PlayerData_t *pAccused = GetAccusedPlayerPtr(); |
|
if ( GetAbuseContentType() == k_EAbuseReportContentAvatarImage && pAccused != NULL ) |
|
{ |
|
if ( pAccused->m_iSteamAvatarIndex > 0 ) |
|
{ |
|
m_pAvatarImage->SetShouldDrawFriendIcon( false ); |
|
m_pAvatarImage->SetPlayer( pAccused->m_steamID, k_EAvatarSize184x184 ); |
|
|
|
m_pAvatarImage->SetVisible( true ); |
|
m_pNoAvatarLabel->SetVisible( false ); |
|
} |
|
else |
|
{ |
|
m_pAvatarImage->SetVisible( false ); |
|
m_pNoAvatarLabel->SetVisible( true ); |
|
} |
|
} |
|
else |
|
{ |
|
m_pAvatarImage->SetVisible( false ); |
|
m_pNoAvatarLabel->SetVisible( false ); |
|
} |
|
} |
|
|
|
void CAbuseReportDlg::UpdateCustomTextures() |
|
{ |
|
if ( m_pCustomTextureImagePanel == NULL || m_pNoCustomTexturesLabel == NULL || m_pCustomTextureNextButton == NULL || m_pCustomTexturePrevButton == NULL ) |
|
{ |
|
Assert( m_pCustomTextureImagePanel ); |
|
Assert( m_pNoCustomTexturesLabel ); |
|
Assert( m_pCustomTextureNextButton ); |
|
Assert( m_pCustomTexturePrevButton ); |
|
return; |
|
} |
|
|
|
const AbuseIncidentData_t::PlayerData_t *pAccused = GetAccusedPlayerPtr(); |
|
bool bShowScrollButtons = false; |
|
if ( GetAbuseContentType() == k_EAbuseReportContentUGCImage && pAccused != NULL ) |
|
{ |
|
int iSelectedCustomImage = GetSelectedCustomImage(); |
|
|
|
if ( iSelectedCustomImage >= 0 ) |
|
{ |
|
|
|
// Currently the only thing we support... |
|
Assert( pAccused->m_vecImages[ iSelectedCustomImage].m_eType == AbuseIncidentData_t::k_PlayerImageType_UGC ); |
|
|
|
m_pCustomTextureImagePanel->m_ugcHandle = pAccused->m_vecImages[ iSelectedCustomImage].m_hUGCHandle; |
|
|
|
m_pCustomTextureImagePanel->SetVisible( true ); |
|
m_pNoCustomTexturesLabel->SetVisible( false ); |
|
|
|
int n = pAccused->m_vecImages.Count(); |
|
if ( n > 1 ) |
|
{ |
|
bShowScrollButtons = true; |
|
m_pCustomTextureNextButton->SetEnabled( iSelectedCustomImage < n-1 ); |
|
m_pCustomTexturePrevButton->SetEnabled( iSelectedCustomImage > 0 ); |
|
} |
|
} |
|
else |
|
{ |
|
m_pCustomTextureImagePanel->SetVisible( false ); |
|
m_pNoCustomTexturesLabel->SetVisible( true ); |
|
} |
|
} |
|
else |
|
{ |
|
m_pCustomTextureImagePanel->SetVisible( false ); |
|
m_pNoCustomTexturesLabel->SetVisible( false ); |
|
} |
|
m_pCustomTextureNextButton->SetVisible( bShowScrollButtons ); |
|
m_pCustomTexturePrevButton->SetVisible( bShowScrollButtons ); |
|
} |
|
|
|
int CAbuseReportDlg::GetSelectedCustomImage() |
|
{ |
|
if ( GetAbuseContentType() != k_EAbuseReportContentUGCImage ) |
|
{ |
|
m_iUserImageIndex = 0; |
|
return -1; |
|
} |
|
|
|
const AbuseIncidentData_t::PlayerData_t *pAccused = GetAccusedPlayerPtr(); |
|
if ( pAccused == NULL ) |
|
{ |
|
m_iUserImageIndex = 0; |
|
return -1; |
|
} |
|
|
|
int n = pAccused->m_vecImages.Count(); |
|
if ( n < 1 ) |
|
{ |
|
m_iUserImageIndex = 0; |
|
return -1; |
|
} |
|
|
|
// Wrap currently selected index |
|
m_iUserImageIndex = ( m_iUserImageIndex + n*10 ) % n; |
|
|
|
// Return it |
|
return m_iUserImageIndex; |
|
} |
|
|
|
void CAbuseReportDlg::OnTextChanged( vgui::Panel *panel ) |
|
{ |
|
if ( panel == m_pPlayerCombo ) |
|
{ |
|
PlayerChanged(); |
|
} |
|
else if ( panel == m_pAbuseContentCombo ) |
|
{ |
|
ContentTypeChanged(); |
|
} |
|
else |
|
{ |
|
UpdateSubmitButton(); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Job to do the async work of submitting the report |
|
//----------------------------------------------------------------------------- |
|
class CSubmitAbuseReportJob : public GCSDK::CGCClientJob |
|
{ |
|
public: |
|
bool m_bGameServer; |
|
|
|
|
|
CSubmitAbuseReportJob( ) |
|
: GCSDK::CGCClientJob( GCClientSystem()->GetGCClient() ) |
|
{ |
|
m_bGameServer = false; |
|
} |
|
|
|
virtual bool BYieldingRunGCJob() |
|
{ |
|
EResult result = RunJob(); |
|
|
|
// Tear down our dialogs |
|
CloseWaitingDialog(); |
|
|
|
CAbuseReportDlg *pDlg = g_AbuseReportDlg.Get(); |
|
if ( pDlg ) |
|
{ |
|
pDlg->Close(); |
|
pDlg = NULL; |
|
} |
|
|
|
// And destroy the queued report! |
|
g_AbuseReportMgr->DestroyIncidentData(); |
|
|
|
// now show a dialog box explaining the outcome |
|
switch ( result ) |
|
{ |
|
case k_EResultOK: |
|
ShowMessageBox( "#AbuseReport_SucceededTitle", "#AbuseReport_SucceededMessage", "#GameUI_OK" ); |
|
break; |
|
|
|
case k_EResultLimitExceeded: |
|
ShowMessageBox( |
|
"#AbuseReport_TooMuchFailedTitle", |
|
m_bGameServer ? "#AbuseReport_TooMuchFailedMessageGameServer" : "#AbuseReport_TooMuchFailedMessage", |
|
"#GameUI_OK" |
|
); |
|
break; |
|
|
|
default: |
|
ShowMessageBox( "#AbuseReport_GenericFailureTitle", "#AbuseReport_GenericFailureMessage", "#GameUI_OK" ); |
|
break; |
|
} |
|
|
|
return true; |
|
} |
|
|
|
EResult RunJob() |
|
{ |
|
CAbuseReportDlg *pDlg = g_AbuseReportDlg.Get(); |
|
if ( pDlg == NULL ) |
|
{ |
|
return k_EResultFail; |
|
} |
|
m_bGameServer = pDlg->IsAccusingGameServer(); |
|
EAbuseReportContentType eContentSelected = pDlg->GetAbuseContentType(); |
|
EAbuseReportContentType eContentReported = eContentSelected; |
|
EAbuseReportType eAbuseType = pDlg->GetAbuseType(); |
|
const AbuseIncidentData_t::PlayerData_t *pAccused = pDlg->GetAccusedPlayerPtr(); |
|
const AbuseIncidentData_t *pIncidentData = g_AbuseReportMgr->GetIncidentData(); |
|
CUtlString sAbuseDescription = pDlg->GetAbuseDescription(); |
|
netadr_t adrGameServer = pIncidentData->m_adrGameServer; |
|
CSteamID steamIDGameServer = pIncidentData->m_steamIDGameServer; |
|
uint64 gid = 0; |
|
|
|
// Check if we should upload the screenshot |
|
if ( pDlg->GetAttachScreenShot() && steamapicontext && steamapicontext->SteamUtils() && steamapicontext->SteamRemoteStorage() ) |
|
{ |
|
|
|
// Write the local copy of the file |
|
if ( !steamapicontext->SteamRemoteStorage()->FileWrite( CAbuseReportManager::k_rchScreenShotFilename, pIncidentData->m_bufScreenshotFileData.Base(), pIncidentData->m_bufScreenshotFileData.TellPut() ) ) |
|
{ |
|
Warning( "Failed to save local cloud copy of %s\n", CAbuseReportManager::k_rchScreenShotFilename ); |
|
return k_EResultFail; |
|
} |
|
|
|
// Share it. This initiates the upload to cloud |
|
Msg( "Starting upload of %s to UFS....\n", CAbuseReportManager::k_rchScreenShotFilename ); |
|
SteamAPICall_t hFileShareApiCall = steamapicontext->SteamRemoteStorage()->FileShare( CAbuseReportManager::k_rchScreenShotFilename ); |
|
if ( hFileShareApiCall == k_uAPICallInvalid ) |
|
{ |
|
Warning( "Failed to share %s\n", CAbuseReportManager::k_rchScreenShotFilename ); |
|
return k_EResultFail; |
|
} |
|
|
|
// Check if we're busy |
|
bool bFailed; |
|
RemoteStorageFileShareResult_t result; |
|
while ( !steamapicontext->SteamUtils()->GetAPICallResult(hFileShareApiCall, |
|
&result, sizeof(result), RemoteStorageFileShareResult_t::k_iCallback, &bFailed) ) |
|
{ |
|
BYield(); |
|
} |
|
|
|
// Clear pointer, it could have been destroyed while we were yielding, make sure we don't reference it |
|
pDlg = NULL; |
|
|
|
if ( bFailed || result.m_eResult != k_EResultOK ) |
|
{ |
|
Warning( "Failed to share %s; result code %d\n", CAbuseReportManager::k_rchScreenShotFilename, result.m_eResult ); |
|
return result.m_eResult; |
|
} |
|
|
|
Msg( "%s shared to UGC OK\n", CAbuseReportManager::k_rchScreenShotFilename ); |
|
gid = result.m_hFile; |
|
|
|
// SWitch the content type being reported, so the support tool will know what to |
|
// do with the GID. |
|
eContentReported = k_EAbuseReportContentActorUGCImage; |
|
} |
|
else if ( eContentSelected == k_EAbuseReportContentUGCImage ) |
|
{ |
|
Assert( !m_bGameServer ); |
|
int iImageindex = pDlg->GetSelectedCustomImage(); |
|
Assert( iImageindex >= 0 ); |
|
gid = pAccused->m_vecImages[iImageindex].m_hUGCHandle; |
|
} |
|
|
|
// |
|
// Fill out the report message |
|
// |
|
GCSDK::CProtoBufMsg<CMsgGCReportAbuse> msg( k_EMsgGC_ReportAbuse ); |
|
if ( m_bGameServer ) |
|
{ |
|
msg.Body().set_target_steam_id( steamIDGameServer.ConvertToUint64() ); |
|
msg.Body().set_target_game_server_ip( adrGameServer.GetIPHostByteOrder() ); |
|
msg.Body().set_target_game_server_port( adrGameServer.GetPort() ); |
|
} |
|
else |
|
{ |
|
msg.Body().set_target_steam_id( pAccused->m_steamID.ConvertToUint64() ); |
|
msg.Body().set_content_type( eContentReported ); |
|
msg.Body().set_abuse_type( eAbuseType ); |
|
} |
|
msg.Body().set_description( sAbuseDescription ); |
|
if (gid != 0 ) |
|
{ |
|
msg.Body().set_gid( gid ); |
|
} |
|
|
|
// Send the message to the GC, and await the reply |
|
GCSDK::CProtoBufMsg<CMsgGCReportAbuseResponse> msgReply; |
|
if ( !BYldSendMessageAndGetReply( msg, 10, &msgReply, k_EMsgGC_ReportAbuseResponse ) ) |
|
{ |
|
Warning( "Abuse report failed: Did not get reply from GC\n" ); |
|
return k_EResultTimeout; |
|
} |
|
|
|
EResult result = (EResult)msgReply.Body().result(); |
|
if ( result != k_EResultOK ) |
|
{ |
|
Warning( "Abuse report failed with failure code %d. %s\n", result, msgReply.Body().error_message().c_str() ); |
|
} |
|
|
|
// OK |
|
return result; |
|
} |
|
|
|
}; |
|
|
|
void CAbuseReportDlg::OnSubmitReport() |
|
{ |
|
// throw up a waiting dialog |
|
SetEnabled( false ); |
|
ShowWaitingDialog( new CGenericWaitingDialog( this ), "#AbuseReport_Busy", true, false, 0.0f ); |
|
|
|
// We need to be in the global singleton handle, because that's how the job knows |
|
// to get to us (and how it knows if we've died)! |
|
Assert( g_AbuseReportDlg.Get() == this ); |
|
|
|
// Start a job |
|
CSubmitAbuseReportJob *pJob = new CSubmitAbuseReportJob(); |
|
pJob->StartJob( NULL ); |
|
}
|
|
|