extensions/sdktools/hooks.cpp
author David Anderson <dvander@alliedmods.net>
Wed Jan 20 04:03:46 2010 -0800 (2010-01-20)
changeset 2910 e8f6e9f3401a
parent 2732 dbe9e8ed3703
child 3084 db8d1162e9cf
permissions -rw-r--r--
Fixed accidental hook against garbage offset (bug 4231, r=fyren).
pred@2711
     1
/**
pred@2711
     2
* vim: set ts=4 :
pred@2711
     3
* =============================================================================
pred@2711
     4
* SourceMod SDKTools Extension
pred@2711
     5
* Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
pred@2711
     6
* =============================================================================
pred@2711
     7
*
pred@2711
     8
* This program is free software; you can redistribute it and/or modify it under
pred@2711
     9
* the terms of the GNU General Public License, version 3.0, as published by the
pred@2711
    10
* Free Software Foundation.
pred@2711
    11
*
pred@2711
    12
* This program is distributed in the hope that it will be useful, but WITHOUT
pred@2711
    13
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
pred@2711
    14
* FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
pred@2711
    15
* details.
pred@2711
    16
*
pred@2711
    17
* You should have received a copy of the GNU General Public License along with
pred@2711
    18
* this program.  If not, see <http://www.gnu.org/licenses/>.
pred@2711
    19
*
pred@2711
    20
* As a special exception, AlliedModders LLC gives you permission to link the
pred@2711
    21
* code of this program (as well as its derivative works) to "Half-Life 2," the
pred@2711
    22
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
pred@2711
    23
* by the Valve Corporation.  You must obey the GNU General Public License in
pred@2711
    24
* all respects for all other code used.  Additionally, AlliedModders LLC grants
pred@2711
    25
* this exception to all derivative works.  AlliedModders LLC defines further
pred@2711
    26
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
pred@2711
    27
* or <http://www.sourcemod.net/license.php>.
pred@2711
    28
*
pred@2711
    29
* Version: $Id$
pred@2711
    30
*/
pred@2711
    31
pred@2711
    32
#include "hooks.h"
pred@2711
    33
#include "extension.h"
pred@2711
    34
pred@2711
    35
CHookManager g_Hooks;
dvander@2910
    36
static bool PRCH_enabled = false;
pred@2711
    37
pred@2711
    38
SH_DECL_MANUALHOOK2_void(PlayerRunCmdHook, 0, 0, 0, CUserCmd *, IMoveHelper *);
pred@2711
    39
pred@2711
    40
CHookManager::CHookManager()
pred@2711
    41
{
pred@2711
    42
	m_usercmdsFwd = NULL;
pred@2711
    43
}
pred@2711
    44
pred@2711
    45
void CHookManager::Initialize()
pred@2711
    46
{
pred@2711
    47
	int offset;
pred@2711
    48
	if (g_pGameConf->GetOffset("PlayerRunCmd", &offset))
pred@2711
    49
	{
pred@2711
    50
		SH_MANUALHOOK_RECONFIGURE(PlayerRunCmdHook, offset, 0, 0);
dvander@2910
    51
		PRCH_enabled = true;
pred@2711
    52
	}
pred@2711
    53
pred@2711
    54
	m_usercmdsFwd = forwards->CreateForward("OnPlayerRunCmd", ET_Event, 6, NULL, Param_Cell, Param_CellByRef, Param_CellByRef, Param_Array, Param_Array, Param_CellByRef);
pred@2711
    55
}
pred@2711
    56
pred@2711
    57
void CHookManager::Shutdown()
pred@2711
    58
{
pred@2711
    59
	forwards->ReleaseForward(m_usercmdsFwd);
pred@2711
    60
}
pred@2711
    61
pred@2711
    62
void CHookManager::OnClientPutInServer(int client)
pred@2711
    63
{
dvander@2910
    64
	if (!PRCH_enabled)
dvander@2910
    65
		return;
dvander@2910
    66
pred@2711
    67
	edict_t *pEdict = PEntityOfEntIndex(client);
pred@2711
    68
	if (!pEdict)
pred@2711
    69
	{
pred@2711
    70
		return;
pred@2711
    71
	}
pred@2711
    72
pred@2711
    73
	IServerUnknown *pUnknown = pEdict->GetUnknown();
pred@2711
    74
	if (!pUnknown)
pred@2711
    75
	{
pred@2711
    76
		return;
pred@2711
    77
	}
pred@2711
    78
pred@2711
    79
	CBaseEntity *pEntity = pUnknown->GetBaseEntity();
pred@2711
    80
	if (!pEntity)
pred@2711
    81
	{
pred@2711
    82
		return;
pred@2711
    83
	}
pred@2711
    84
pred@2711
    85
	SH_ADD_MANUALHOOK_MEMFUNC(PlayerRunCmdHook, pEntity, this, &CHookManager::PlayerRunCmd, false);
pred@2711
    86
}
pred@2711
    87
pred@2711
    88
void CHookManager::OnClientDisconnecting(int client)
pred@2711
    89
{
dvander@2910
    90
	if (!PRCH_enabled)
dvander@2910
    91
		return;
dvander@2910
    92
pred@2711
    93
	edict_t *pEdict = PEntityOfEntIndex(client);
pred@2711
    94
	if (!pEdict)
pred@2711
    95
	{
pred@2711
    96
		return;
pred@2711
    97
	}
pred@2711
    98
pred@2732
    99
	IServerUnknown *pUnknown = pEdict->GetUnknown();
pred@2732
   100
	if (!pUnknown)
pred@2732
   101
	{
pred@2732
   102
		return;
pred@2732
   103
	}
pred@2732
   104
pred@2732
   105
	CBaseEntity *pEntity = pUnknown->GetBaseEntity();
pred@2711
   106
	if (!pEntity)
pred@2711
   107
	{
pred@2711
   108
		return;
pred@2711
   109
	}
pred@2711
   110
pred@2711
   111
	SH_REMOVE_MANUALHOOK_MEMFUNC(PlayerRunCmdHook, pEntity, this, &CHookManager::PlayerRunCmd, false);
pred@2711
   112
}
pred@2711
   113
pred@2711
   114
void CHookManager::PlayerRunCmd(CUserCmd *ucmd, IMoveHelper *moveHelper)
pred@2711
   115
{
pred@2711
   116
	if (m_usercmdsFwd->GetFunctionCount() == 0)
pred@2711
   117
	{
pred@2711
   118
		RETURN_META(MRES_IGNORED);
pred@2711
   119
	}
pred@2711
   120
pred@2711
   121
	CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity);
pred@2711
   122
pred@2711
   123
	if (!pEntity)
pred@2711
   124
	{
pred@2711
   125
		RETURN_META(MRES_IGNORED);
pred@2711
   126
	}
pred@2711
   127
pred@2711
   128
	edict_t *pEdict = gameents->BaseEntityToEdict(pEntity);
pred@2711
   129
pred@2711
   130
	if (!pEdict)
pred@2711
   131
	{
pred@2711
   132
		RETURN_META(MRES_IGNORED);
pred@2711
   133
	}
pred@2711
   134
pred@2711
   135
	int client = IndexOfEdict(pEdict);
pred@2711
   136
pred@2711
   137
pred@2711
   138
	cell_t result = 0;
pred@2711
   139
	/* Impulse is a byte so we copy it back manually */
pred@2711
   140
	cell_t impulse = ucmd->impulse;
pred@2711
   141
	cell_t vel[3] = {sp_ftoc(ucmd->forwardmove), sp_ftoc(ucmd->sidemove), sp_ftoc(ucmd->upmove)};
pred@2711
   142
	cell_t angles[3] = {sp_ftoc(ucmd->viewangles.x), sp_ftoc(ucmd->viewangles.y), sp_ftoc(ucmd->viewangles.z)};
pred@2711
   143
pred@2711
   144
	m_usercmdsFwd->PushCell(client);
pred@2711
   145
	m_usercmdsFwd->PushCellByRef(&ucmd->buttons);
pred@2711
   146
	m_usercmdsFwd->PushCellByRef(&impulse);
pred@2711
   147
	m_usercmdsFwd->PushArray(vel, 3, SM_PARAM_COPYBACK);
pred@2711
   148
	m_usercmdsFwd->PushArray(angles, 3, SM_PARAM_COPYBACK);
pred@2711
   149
	m_usercmdsFwd->PushCellByRef(&ucmd->weaponselect);
pred@2711
   150
	m_usercmdsFwd->Execute(&result);
pred@2711
   151
pred@2711
   152
	ucmd->impulse = impulse;
pred@2711
   153
	ucmd->forwardmove = sp_ctof(vel[0]);
pred@2711
   154
	ucmd->sidemove = sp_ctof(vel[1]);
pred@2711
   155
	ucmd->upmove = sp_ctof(vel[2]);
pred@2711
   156
	ucmd->viewangles.x = sp_ctof(angles[0]);
pred@2711
   157
	ucmd->viewangles.y = sp_ctof(angles[1]);
pred@2711
   158
	ucmd->viewangles.z = sp_ctof(angles[2]);
pred@2711
   159
pred@2711
   160
pred@2711
   161
	if (result == Pl_Handled)
pred@2711
   162
	{
pred@2711
   163
		RETURN_META(MRES_SUPERCEDE);
pred@2711
   164
	}
pred@2711
   165
pred@2711
   166
	RETURN_META(MRES_IGNORED);
pred@2711
   167
}