diff --git a/dlls/fakemeta/fakemeta_amxx.cpp b/dlls/fakemeta/fakemeta_amxx.cpp index 4d49d04d..5de5573c 100755 --- a/dlls/fakemeta/fakemeta_amxx.cpp +++ b/dlls/fakemeta/fakemeta_amxx.cpp @@ -1,4 +1,5 @@ #include "fakemeta_amxx.h" +#include "sh_stack.h" edict_t *g_player_edicts[33]; // Used for INDEXENT() forward. @@ -21,6 +22,16 @@ void OnAmxxAttach() g_kvd_glb.kvd = &g_kvd_2; } +extern CStack g_FreeTRs; +void OnAmxxDetach() +{ + while (!g_FreeTRs.empty()) + { + delete g_FreeTRs.front(); + g_FreeTRs.pop(); + } +} + int GetHullBounds(int hullnumber, float *mins, float *maxs); // sawce: Do not null out the forward for ServerActivate. It's required for the INDEXENT() fix. (I don't think ServerActivate is planned on being forwarded anyway) void ServerActivate(edict_t *pEdictList, int edictCount, int clientMax) diff --git a/dlls/fakemeta/fm_tr2.cpp b/dlls/fakemeta/fm_tr2.cpp index 1e0a9f93..c553caa3 100644 --- a/dlls/fakemeta/fm_tr2.cpp +++ b/dlls/fakemeta/fm_tr2.cpp @@ -1,4 +1,5 @@ #include "fakemeta_amxx.h" +#include "sh_stack.h" TraceResult g_tr_2; KeyValueData g_kvd_2; @@ -1214,8 +1215,39 @@ static cell AMX_NATIVE_CALL set_uc(AMX *amx, cell *params) return 0; } +CStack g_FreeTRs; + +static cell AMX_NATIVE_CALL create_tr2(AMX *amx, cell *params) +{ + TraceResult *tr; + if (g_FreeTRs.empty()) + { + tr = new TraceResult; + } else { + tr = g_FreeTRs.front(); + g_FreeTRs.pop(); + } + memset(tr, 0, sizeof(TraceResult)); + return reinterpret_cast(tr); +} + +static cell AMX_NATIVE_CALL free_tr2(AMX *amx, cell *params) +{ + TraceResult *tr = reinterpret_cast(params[1]); + if (!tr) + { + return 0; + } + + g_FreeTRs.push(tr); + + return 1; +} + AMX_NATIVE_INFO ext2_natives[] = { + {"create_tr2", create_tr2}, + {"free_tr2", free_tr2}, {"get_tr2", get_tr2}, {"set_tr2", set_tr2}, {"get_kvd", get_kvd}, diff --git a/dlls/fakemeta/sdk/moduleconfig.h b/dlls/fakemeta/sdk/moduleconfig.h index 5f794cf5..c42e1aa6 100755 --- a/dlls/fakemeta/sdk/moduleconfig.h +++ b/dlls/fakemeta/sdk/moduleconfig.h @@ -52,7 +52,7 @@ #define FN_AMXX_ATTACH OnAmxxAttach /** AMXX Detach (unload) */ -//#define FN_AMXX_DETACH OnAmxxDetach +#define FN_AMXX_DETACH OnAmxxDetach /** All plugins loaded * Do forward functions init here (MF_RegisterForward) diff --git a/dlls/fakemeta/sdk/sh_stack.h b/dlls/fakemeta/sdk/sh_stack.h new file mode 100644 index 00000000..c01021f7 --- /dev/null +++ b/dlls/fakemeta/sdk/sh_stack.h @@ -0,0 +1,219 @@ +/* ======== SourceMM ======== +* Copyright (C) 2004-2005 Metamod:Source Development Team +* No warranties of any kind +* +* License: zlib/libpng +* +* Author(s): Pavol "PM OnoTo" Marko +* ============================ +*/ + +#ifndef __SH_STACK_H__ +#define __SH_STACK_H__ + +#define SH_STACK_DEFAULT_SIZE 4 + +//namespace SourceHook +//{/ + // Vector + template class CStack + { + T *m_Elements; + size_t m_AllocatedSize; + size_t m_UsedSize; + public: + friend class iterator; + class iterator + { + CStack *m_pParent; + size_t m_Index; + public: + iterator(CStack *pParent, size_t id) : m_pParent(pParent), m_Index(id) + { + } + + iterator(CStack *pParent) : m_pParent(pParent), m_Index(0) + { + } + + iterator() : m_pParent(NULL), m_Index(0) + { + } + + T &operator *() + { + return m_pParent->m_Elements[m_Index]; + } + const T &operator *() const + { + return m_pParent->m_Elements[m_Index]; + } + + T * operator->() + { + return m_pParent->m_Elements + m_Index; + } + + const T * operator->() const + { + return m_pParent->m_Elements + m_Index; + } + + iterator & operator++() // preincrement + { + ++m_Index; + return (*this); + } + + iterator operator++(int) // postincrement + { + iterator tmp = *this; + ++m_Index; + return tmp; + } + + iterator & operator--() // predecrement + { + --m_Index; + return (*this); + } + + iterator operator--(int) // postdecrememnt + { + iterator tmp = *this; + --m_Index; + return tmp; + } + + bool operator==(const iterator & right) const + { + return (m_pParent == right.m_pParent && m_Index == right.m_Index); + } + + bool operator!=(const iterator & right) const + { + return !(*this == right); + } + }; + CStack() : m_Elements(new T[SH_STACK_DEFAULT_SIZE]), + m_AllocatedSize(SH_STACK_DEFAULT_SIZE), + m_UsedSize(0) + { + } + CStack(size_t size) : m_Elements(new T[size]), + m_AllocatedSize(size), + m_UsedSize(0) + { + } + + CStack(const CStack &other) : m_Elements(NULL), + m_AllocatedSize(0), + m_UsedSize(0) + { + reserve(other.m_AllocatedSize); + m_UsedSize = other.m_UsedSize; + for (size_t i = 0; i < m_UsedSize; ++i) + m_Elements[i] = other.m_Elements[i]; + } + + ~CStack() + { + if (m_Elements) + delete [] m_Elements; + } + + void operator=(const CStack &other) + { + if (m_AllocatedSize < other.m_AllocatedSize) + { + if (m_Elements) + delete [] m_Elements; + m_Elements = new T[other.m_AllocatedSize]; + m_AllocatedSize = other.m_AllocatedSize; + } + m_UsedSize = other.m_UsedSize; + for (size_t i = 0; i < m_UsedSize; ++i) + m_Elements[i] = other.m_Elements[i]; + } + + bool push(const T &val) + { + if (m_UsedSize + 1 == m_AllocatedSize) + { + // zOHNOES! REALLOCATE! + m_AllocatedSize *= 2; + T *newElements = new T[m_AllocatedSize]; + if (!newElements) + { + m_AllocatedSize /= 2; + return false; + } + if (m_Elements) + { + for (size_t i = 0; i < m_UsedSize; ++i) + newElements[i] = m_Elements[i]; + delete [] m_Elements; + } + m_Elements = newElements; + } + m_Elements[m_UsedSize++] = val; + return true; + } + void pop() + { + --m_UsedSize; + } + + T &front() + { + return m_Elements[m_UsedSize - 1]; + } + + const T &front() const + { + return m_Elements[m_UsedSize - 1]; + } + + iterator begin() + { + return iterator(this, 0); + } + iterator end() + { + return iterator(this, m_UsedSize); + } + + size_t size() + { + return m_UsedSize; + } + size_t capacity() + { + return m_AllocatedSize; + } + bool empty() + { + return m_UsedSize == 0 ? true : false; + } + bool reserve(size_t size) + { + if (size > m_AllocatedSize) + { + T *newElements = new T[size]; + if (!newElements) + return false; + if (m_Elements) + { + for (size_t i = 0; i < m_UsedSize; ++i) + newElements[i] = m_Elements[i]; + delete [] m_Elements; + } + m_Elements = newElements; + m_AllocatedSize = size; + } + return true; + } + }; +//}; //namespace SourceHook + +#endif diff --git a/plugins/include/fakemeta.inc b/plugins/include/fakemeta.inc index 0c3a5a3d..ea900e4b 100755 --- a/plugins/include/fakemeta.inc +++ b/plugins/include/fakemeta.inc @@ -103,6 +103,26 @@ native set_tr(TraceResult:tr_member, {Float,_}:...); native get_tr2(tr_handle, TraceResult:tr_member, {Float,_}:...); native set_tr2(tr_handle, TraceResult:tr_member, {Float,_}:...); +/** + * Creates a traceresult handle. This value should never be altered. + * The handle can be used in get/set_tr2 and various traceresult engine functions. + * + * NOTE: You must call free_tr2() on every handle made with create_tr2(). + * + * @return A new TraceResult handle. + */ +native create_tr2(); + +/** + * Frees a traceresult handle created with free_tr2(). Do not call + * this more than once per handle, or on handles not created through + * create_tr2(). + * + * @param tr_handle TraceResult handle created via create_tr2(). + * @noreturn + */ +native free_tr2(tr_handle); + //Same as above, use either a kvd_handle or 0 for global reserved kvd data //kvd_handle is passed by the kvd hook, last param native get_kvd(kvd_handle, KeyValueData:member, {Float,_}:...);