mirror of
https://github.com/azerothcore/mod-ale
synced 2025-11-29 15:38:17 +08:00
Some fixes for TC and changes overall Pass map object to hook via function arguments The map object is no longer stored inside the instance data table. Fix mistake in base64 decoder It was failing whenever it encountered a '=' character, which is completely valid. Make ElunaInstanceAI::Load always load something When it failed to load data, it was leaving nothing on the stack. Since subsequent code expected Load to always load something, this was causing issues. Now, when Load fails to load anything, it just leaves a new empty table on the stack. Also: the error messages for Load have been improved. Modify lua-marshal to allow saving of functions/userdata. Some additional code was needed to save functions due to the inclusion of a reference to _ENV within their upvalues (since Lua 5.2). During encoding, a placeholder is left where the _ENV reference would be. During decoding, a reference to the current _G is swapped with the placeholder. Make ElunaInstanceAI::Load re-initialize if data failed to load. Also improve error messages by not including the raw data. Improve storage format of upvalues Instead of storing the upvalues by name, store by index. A wrapper is still used in case the upvalue is nil, to prevent holes in the upvalues table. A special field in the upvalues table, "E", is used to store the index of the _ENV reference (if there was one). A reference to the current globals table is set as the upvalue upon decoding. Remove wrapping from upvalue storing, instead save amount of upvalues
182 lines
5.8 KiB
C++
182 lines
5.8 KiB
C++
/*
|
|
* Copyright (C) 2010 - 2015 Eluna Lua Engine <http://emudevs.com/>
|
|
* This program is free software licensed under GPL version 3
|
|
* Please see the included DOCS/LICENSE.md for more information
|
|
*/
|
|
|
|
#include "ElunaUtility.h"
|
|
#include "World.h"
|
|
#include "Object.h"
|
|
#include "Unit.h"
|
|
|
|
uint32 ElunaUtil::GetCurrTime()
|
|
{
|
|
#ifndef TRINITY
|
|
return WorldTimer::getMSTime();
|
|
#else
|
|
return getMSTime();
|
|
#endif
|
|
}
|
|
|
|
uint32 ElunaUtil::GetTimeDiff(uint32 oldMSTime)
|
|
{
|
|
#ifndef TRINITY
|
|
return WorldTimer::getMSTimeDiff(oldMSTime, GetCurrTime());
|
|
#else
|
|
return GetMSTimeDiffToNow(oldMSTime);
|
|
#endif
|
|
}
|
|
|
|
ElunaUtil::ObjectGUIDCheck::ObjectGUIDCheck(ObjectGuid guid) : _guid(guid)
|
|
{
|
|
}
|
|
|
|
bool ElunaUtil::ObjectGUIDCheck::operator()(WorldObject* object)
|
|
{
|
|
return object->GET_GUID() == _guid;
|
|
}
|
|
|
|
ElunaUtil::ObjectDistanceOrderPred::ObjectDistanceOrderPred(WorldObject const* pRefObj, bool ascending) : m_refObj(pRefObj), m_ascending(ascending)
|
|
{
|
|
}
|
|
bool ElunaUtil::ObjectDistanceOrderPred::operator()(WorldObject const* pLeft, WorldObject const* pRight) const
|
|
{
|
|
return m_ascending ? m_refObj->GetDistanceOrder(pLeft, pRight) : !m_refObj->GetDistanceOrder(pLeft, pRight);
|
|
}
|
|
|
|
ElunaUtil::WorldObjectInRangeCheck::WorldObjectInRangeCheck(bool nearest, WorldObject const* obj, float range,
|
|
uint16 typeMask, uint32 entry, uint32 hostile) :
|
|
i_obj(obj), i_hostile(hostile), i_entry(entry), i_range(range), i_typeMask(typeMask), i_nearest(nearest)
|
|
{
|
|
}
|
|
WorldObject const& ElunaUtil::WorldObjectInRangeCheck::GetFocusObject() const
|
|
{
|
|
return *i_obj;
|
|
}
|
|
bool ElunaUtil::WorldObjectInRangeCheck::operator()(WorldObject* u)
|
|
{
|
|
if (i_typeMask && !u->isType(TypeMask(i_typeMask)))
|
|
return false;
|
|
if (i_entry && u->GetEntry() != i_entry)
|
|
return false;
|
|
if (i_obj->GET_GUID() == u->GET_GUID())
|
|
return false;
|
|
if (!i_obj->IsWithinDistInMap(u, i_range))
|
|
return false;
|
|
if (Unit* unit = u->ToUnit())
|
|
{
|
|
#ifdef CMANGOS
|
|
if (!unit->isAlive())
|
|
return false;
|
|
#else
|
|
if (!unit->IsAlive())
|
|
return false;
|
|
#endif
|
|
if (i_hostile)
|
|
{
|
|
if (const Unit* obj = i_obj->ToUnit())
|
|
{
|
|
if ((i_hostile == 1) != obj->IsHostileTo(unit))
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
if (i_nearest)
|
|
i_range = i_obj->GetDistance(u);
|
|
return true;
|
|
}
|
|
|
|
static char encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
|
|
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
|
|
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
|
|
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
|
|
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
|
|
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
|
|
'w', 'x', 'y', 'z', '0', '1', '2', '3',
|
|
'4', '5', '6', '7', '8', '9', '+', '/'};
|
|
static char decoding_table[256];
|
|
static int mod_table[] = {0, 2, 1};
|
|
|
|
static void build_decoding_table()
|
|
{
|
|
for (int i = 0; i < 64; i++)
|
|
decoding_table[(unsigned char)encoding_table[i]] = i;
|
|
}
|
|
|
|
void ElunaUtil::EncodeData(const unsigned char* data, size_t input_length, std::string& output)
|
|
{
|
|
size_t output_length = 4 * ((input_length + 2) / 3);
|
|
char* buffer = new char[output_length];
|
|
|
|
for (size_t i = 0, j = 0; i < input_length;)
|
|
{
|
|
uint32_t octet_a = i < input_length ? (unsigned char)data[i++] : 0;
|
|
uint32_t octet_b = i < input_length ? (unsigned char)data[i++] : 0;
|
|
uint32_t octet_c = i < input_length ? (unsigned char)data[i++] : 0;
|
|
|
|
uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
|
|
|
|
buffer[j++] = encoding_table[(triple >> (3 * 6)) & 0x3F];
|
|
buffer[j++] = encoding_table[(triple >> (2 * 6)) & 0x3F];
|
|
buffer[j++] = encoding_table[(triple >> (1 * 6)) & 0x3F];
|
|
buffer[j++] = encoding_table[(triple >> (0 * 6)) & 0x3F];
|
|
}
|
|
|
|
for (int i = 0; i < mod_table[input_length % 3]; i++)
|
|
buffer[output_length - 1 - i] = '=';
|
|
|
|
output.assign(buffer, output_length); // Need length because `buffer` is not terminated!
|
|
delete[] buffer;
|
|
}
|
|
|
|
unsigned char* ElunaUtil::DecodeData(const char *data, size_t *output_length)
|
|
{
|
|
if (decoding_table['B'] == 0)
|
|
build_decoding_table();
|
|
|
|
size_t input_length = strlen(data);
|
|
|
|
if (input_length % 4 != 0)
|
|
return NULL;
|
|
|
|
// Make sure there's no invalid characters in the data.
|
|
for (size_t i = 0; i < input_length; ++i)
|
|
{
|
|
unsigned char byte = data[i];
|
|
|
|
if (byte == '=')
|
|
continue;
|
|
|
|
// Every invalid character (and 'A') will map to 0 (due to `calloc`).
|
|
if (decoding_table[byte] == 0 && byte != 'A')
|
|
return NULL;
|
|
}
|
|
|
|
*output_length = input_length / 4 * 3;
|
|
if (data[input_length - 1] == '=') (*output_length)--;
|
|
if (data[input_length - 2] == '=') (*output_length)--;
|
|
|
|
unsigned char *decoded_data = new unsigned char[*output_length];
|
|
if (!decoded_data)
|
|
return NULL;
|
|
|
|
for (size_t i = 0, j = 0; i < input_length;)
|
|
{
|
|
uint32_t sextet_a = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]];
|
|
uint32_t sextet_b = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]];
|
|
uint32_t sextet_c = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]];
|
|
uint32_t sextet_d = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]];
|
|
|
|
uint32_t triple = (sextet_a << (3 * 6))
|
|
+ (sextet_b << (2 * 6))
|
|
+ (sextet_c << (1 * 6))
|
|
+ (sextet_d << (0 * 6));
|
|
|
|
if (j < *output_length) decoded_data[j++] = (triple >> (2 * 8)) & 0xFF;
|
|
if (j < *output_length) decoded_data[j++] = (triple >> (1 * 8)) & 0xFF;
|
|
if (j < *output_length) decoded_data[j++] = (triple >> (0 * 8)) & 0xFF;
|
|
}
|
|
|
|
return decoded_data;
|
|
}
|