diff --git a/dlls/fakemeta/CVector.h b/dlls/fakemeta/CVector.h index d6b87eb5..45f0d548 100755 --- a/dlls/fakemeta/CVector.h +++ b/dlls/fakemeta/CVector.h @@ -70,32 +70,58 @@ template class CVector // change size if (size == m_Size) return true; + + if (!size) + { + if (m_Data) + { + delete [] m_Data; + m_Data = NULL; + m_Size = 0; + } + return true; + } + T *newData = new T[size]; if (!newData) return false; if (m_Data) { - size_t end = (m_Size < size) ? (m_Size) : size; + size_t end = (m_CurrentUsedSize < size) ? (m_CurrentUsedSize) : size; for (size_t i=0; i m_Size) + m_CurrentUsedSize = m_Size; + return true; } void FreeMemIfPossible() { + if (!m_Data) + return; + if (!m_CurrentUsedSize) + { + ChangeSize(0); + return; + } + + size_t newSize = m_Size; + while (m_CurrentUsedSize <= newSize / 2) + newSize /= 2; + + if (newSize != m_Size) + ChangeSize(newSize); } protected: T *m_Data; size_t m_Size; size_t m_CurrentUsedSize; - size_t m_CurrentSize; public: class iterator { @@ -189,7 +215,7 @@ public: iterator & operator-=(size_t offset) { - m_Ptr += offset; + m_Ptr -= offset; return (*this); } @@ -203,10 +229,10 @@ public: iterator operator-(size_t offset) const { iterator tmp(*this); - tmp.m_Ptr += offset; + tmp.m_Ptr -= offset; return tmp; } - + T & operator[](size_t offset) { return (*(*this + offset)); @@ -277,12 +303,12 @@ public: return m_Size; } - iterator begin() + iterator begin() const { return iterator(m_Data); } - iterator end() + iterator end() const { return iterator(m_Data + m_CurrentUsedSize); } @@ -296,7 +322,9 @@ public: bool reserve(size_t newSize) { - return ChangeSize(newSize); + if (newSize > m_Size) + return ChangeSize(newSize); + return true; } bool push_back(const T & elem) @@ -317,14 +345,15 @@ public: --m_CurrentUsedSize; if (m_CurrentUsedSize < 0) m_CurrentUsedSize = 0; - // :TODO: free memory sometimes + + FreeMemIfPossible(); } bool resize(size_t newSize) { if (!ChangeSize(newSize)) return false; - FreeMemIfPossible(); + m_CurrentUsedSize = newSize; return true; } @@ -397,15 +426,13 @@ public: return m_Data[m_CurrentUsedSize - 1]; } - bool insert(iterator where, const T & value) + iterator insert(iterator where, const T & value) { - // we have to insert before - // if it is begin, don't decrement - if (where != m_Data) - --where; // validate iter - if (where < m_Data || where >= (m_Data + m_CurrentUsedSize)) - return false; + if (where < m_Data || where > (m_Data + m_CurrentUsedSize)) + return iterator(0); + + size_t ofs = where - begin(); ++m_CurrentUsedSize; if (!GrowIfNeeded()) @@ -414,33 +441,49 @@ public: return false; } - memmove(where.base() + 1, where.base(), m_CurrentUsedSize - (where - m_Data)); - memcpy(where.base(), &value, sizeof(T)); - return true; + where = begin() + ofs; + + // Move subsequent entries + for (T *ptr = m_Data + m_CurrentUsedSize - 2; ptr >= where.base(); --ptr) + *(ptr + 1) = *ptr; + + *where.base() = value; + + return where; } - void erase(iterator where) + iterator erase(iterator where) { // validate iter if (where < m_Data || where >= (m_Data + m_CurrentUsedSize)) - return false; + return iterator(0); + + size_t ofs = where - begin(); if (m_CurrentUsedSize > 1) { // move - memmove(where.base(), where.base() + 1, m_CurrentUsedSize - 1); + T *theend = m_Data + m_CurrentUsedSize; + for (T *ptr = where.base() + 1; ptr < theend; ++ptr) + *(ptr - 1) = *ptr; } --m_CurrentUsedSize; - // :TODO: free memory sometimes + + FreeMemIfPossible(); + + return begin() + ofs; } void clear() { m_Size = 0; m_CurrentUsedSize = 0; - delete [] m_Data; - m_Data = NULL; + if (m_Data) + { + delete [] m_Data; + m_Data = NULL; + } } }; diff --git a/dlls/fakemeta/forward.cpp b/dlls/fakemeta/forward.cpp index dbdd58b3..28fb952f 100755 --- a/dlls/fakemeta/forward.cpp +++ b/dlls/fakemeta/forward.cpp @@ -491,7 +491,36 @@ SIMPLE_INT_HOOK_EDICT_EDICT(ShouldCollide); +static cell AMX_NATIVE_CALL unregister_forward(AMX *amx, cell *params) +{ + int func = params[1]; + int func_id = params[2]; + int post = params[3]; + if (func >= FM_LAST_DONT_USE_ME || func < 1) + { + MF_LogError(amx, AMX_ERR_NATIVE, "Invalid function: %d", func); + return 0; + } + + CVector::iterator begin, end=Engine[func].end(); + + for (begin=Engine[func].begin(); begin!=end; begin++) + { + if ((*begin) == func_id) + { + Engine[func].erase(begin); + if (!Engine[func].size()) + { + //:TODO: we should probably clear this here! + //but, we have no reverse lookup possible. + } + return 1; + } + } + + return 0; +} static cell AMX_NATIVE_CALL register_forward(AMX *amx, cell *params) @@ -501,7 +530,7 @@ static cell AMX_NATIVE_CALL register_forward(AMX *amx, cell *params) int post = params[3]; if (func >= FM_LAST_DONT_USE_ME || func < 1) { - MF_RaiseAmxError(amx, AMX_ERR_NATIVE); + MF_LogError(amx, AMX_ERR_NATIVE, "Invalid function: %d", func); return 0; } @@ -1099,7 +1128,10 @@ static cell AMX_NATIVE_CALL register_forward(AMX *amx, cell *params) } if (!fId) + { + MF_LogError(amx, AMX_ERR_NATIVE, "Function not found (%d, %s)", func, funcname); return 0; + } if (post) { @@ -1108,11 +1140,12 @@ static cell AMX_NATIVE_CALL register_forward(AMX *amx, cell *params) Engine[func].push_back(fId); } - return 1; + return fId; } AMX_NATIVE_INFO forward_natives[] = { { "register_forward", register_forward }, + { "unregister_forward", unregister_forward }, { "forward_return", fm_return }, { NULL, NULL } }; diff --git a/plugins/include/fakemeta.inc b/plugins/include/fakemeta.inc index d477fa63..b34f57bf 100755 --- a/plugins/include/fakemeta.inc +++ b/plugins/include/fakemeta.inc @@ -35,9 +35,17 @@ native Float:get_pdata_float(_index,_Offset,_linuxdiff=5); native set_pdata_float(_index,_Offset,Float:_Value,_linuxdiff=5); -/* Registers a forward */ +/* Registers a forward. + * Returns an id you can pass to unregister_forward + */ native register_forward(_forwardType,_function[],_post=0); +/* Unregisters a forward. + * The registerId must be from register_forward, and + * post/forwardtype must match what you registered the forward as. + */ +native unregister_forward(_forwardType, registerId, post=0); + /* Returns data for metamod */ native forward_return(type,{Float,Sql,Result,_}:...);