parent
b50d6b198c
commit
68f2f010fd
24 changed files with 8524 additions and 8166 deletions
|
|
@ -9,327 +9,295 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
static constexpr int MAXBUF = 4096, PADDING = 18, THRESHOLD = 2, NIL = MAXBUF;
|
||||
// see https://github.com/encode84/ulz/
|
||||
class FastLZ final : NonCopyable {
|
||||
public:
|
||||
static constexpr int EXCESS = 16;
|
||||
static constexpr int WINDOW_BITS = 17;
|
||||
static constexpr int WINDOW_SIZE = cr::bit (WINDOW_BITS);
|
||||
static constexpr int WINDOW_MASK = WINDOW_SIZE - 1;
|
||||
|
||||
class Compress {
|
||||
protected:
|
||||
unsigned long int m_csize;
|
||||
static constexpr int MIN_MATCH = 4;
|
||||
static constexpr int MAX_CHAIN = cr::bit (5);
|
||||
|
||||
uint8 m_buffer[MAXBUF + PADDING - 1];
|
||||
int m_matchPos;
|
||||
int m_matchLen;
|
||||
|
||||
int m_left[MAXBUF + 1];
|
||||
int m_right[MAXBUF + 257];
|
||||
int m_parent[MAXBUF + 1];
|
||||
static constexpr int HASH_BITS = 19;
|
||||
static constexpr int HASH_SIZE = cr::bit (HASH_BITS);
|
||||
static constexpr int NIL = -1;
|
||||
static constexpr int UNCOMPRESS_RESULT_FAILED = -1;
|
||||
|
||||
private:
|
||||
void initTrees (void) {
|
||||
for (int i = MAXBUF + 1; i <= MAXBUF + 256; i++) {
|
||||
m_right[i] = NIL;
|
||||
}
|
||||
int *m_hashTable;
|
||||
int *m_prevTable;
|
||||
|
||||
for (int j = 0; j < MAXBUF; j++) {
|
||||
m_parent[j] = NIL;
|
||||
}
|
||||
public:
|
||||
FastLZ (void) {
|
||||
m_hashTable = new int[HASH_SIZE];
|
||||
m_prevTable = new int[WINDOW_SIZE];
|
||||
}
|
||||
|
||||
void insert (int node) {
|
||||
int i;
|
||||
|
||||
int compare = 1;
|
||||
|
||||
uint8 *key = &m_buffer[node];
|
||||
int temp = MAXBUF + 1 + key[0];
|
||||
|
||||
m_right[node] = m_left[node] = NIL;
|
||||
m_matchLen = 0;
|
||||
|
||||
for (;;) {
|
||||
if (compare >= 0) {
|
||||
if (m_right[temp] != NIL) {
|
||||
temp = m_right[temp];
|
||||
}
|
||||
else {
|
||||
m_right[temp] = node;
|
||||
m_parent[node] = temp;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (m_left[temp] != NIL) {
|
||||
temp = m_left[temp];
|
||||
}
|
||||
else {
|
||||
m_left[temp] = node;
|
||||
m_parent[node] = temp;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 1; i < PADDING; i++) {
|
||||
if ((compare = key[i] - m_buffer[temp + i]) != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i > m_matchLen) {
|
||||
m_matchPos = temp;
|
||||
|
||||
if ((m_matchLen = i) >= PADDING) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_parent[node] = m_parent[temp];
|
||||
m_left[node] = m_left[temp];
|
||||
m_right[node] = m_right[temp];
|
||||
m_parent[m_left[temp]] = node;
|
||||
m_parent[m_right[temp]] = node;
|
||||
|
||||
if (m_right[m_parent[temp]] == temp) {
|
||||
m_right[m_parent[temp]] = node;
|
||||
}
|
||||
else {
|
||||
m_left[m_parent[temp]] = node;
|
||||
}
|
||||
m_parent[temp] = NIL;
|
||||
}
|
||||
|
||||
void erase (int node) {
|
||||
int temp;
|
||||
|
||||
if (m_parent[node] == NIL) {
|
||||
return; // not in tree
|
||||
}
|
||||
|
||||
if (m_right[node] == NIL) {
|
||||
temp = m_left[node];
|
||||
}
|
||||
else if (m_left[node] == NIL) {
|
||||
temp = m_right[node];
|
||||
}
|
||||
else {
|
||||
temp = m_left[node];
|
||||
|
||||
if (m_right[temp] != NIL) {
|
||||
do {
|
||||
temp = m_right[temp];
|
||||
} while (m_right[temp] != NIL);
|
||||
|
||||
m_right[m_parent[temp]] = m_left[temp];
|
||||
m_parent[m_left[temp]] = m_parent[temp];
|
||||
m_left[temp] = m_left[node];
|
||||
m_parent[m_left[node]] = temp;
|
||||
}
|
||||
|
||||
m_right[temp] = m_right[node];
|
||||
m_parent[m_right[node]] = temp;
|
||||
}
|
||||
m_parent[temp] = m_parent[node];
|
||||
|
||||
if (m_right[m_parent[node]] == node) {
|
||||
m_right[m_parent[node]] = temp;
|
||||
}
|
||||
else {
|
||||
m_left[m_parent[node]] = temp;
|
||||
}
|
||||
m_parent[node] = NIL;
|
||||
~FastLZ (void) {
|
||||
delete [] m_hashTable;
|
||||
delete [] m_prevTable;
|
||||
}
|
||||
|
||||
public:
|
||||
Compress (void) : m_csize (0), m_matchPos (0), m_matchLen (0) {
|
||||
memset (m_right, 0, sizeof (m_right));
|
||||
memset (m_left, 0, sizeof (m_left));
|
||||
memset (m_parent, 0, sizeof (m_parent));
|
||||
memset (m_buffer, 0, sizeof (m_buffer));
|
||||
}
|
||||
|
||||
~Compress (void) = default;
|
||||
|
||||
int encode_ (const char *fileName, uint8 *header, int headerSize, uint8 *buffer, int bufferSize) {
|
||||
File fp (fileName, "wb");
|
||||
|
||||
if (!fp.isValid ()) {
|
||||
return -1;
|
||||
int compress (uint8 *in, int inLength, uint8 *out) {
|
||||
for (int i = 0; i < HASH_SIZE; i++) {
|
||||
m_hashTable[i] = NIL;
|
||||
}
|
||||
int i, length, node, ptr, last, cbp, bp = 0;
|
||||
uint8 cb[17] = {0, }, mask, bit;
|
||||
uint8 *op = out;
|
||||
|
||||
fp.write (header, headerSize, 1);
|
||||
initTrees ();
|
||||
int anchor = 0;
|
||||
int cur = 0;
|
||||
|
||||
cb[0] = 0;
|
||||
cbp = mask = 1;
|
||||
ptr = 0;
|
||||
node = MAXBUF - PADDING;
|
||||
while (cur < inLength) {
|
||||
const int maxMatch = inLength - cur;
|
||||
|
||||
for (i = ptr; i < node; i++)
|
||||
m_buffer[i] = ' ';
|
||||
int bestLength = 0;
|
||||
int dist = 0;
|
||||
|
||||
for (length = 0; (length < PADDING) && (bp < bufferSize); length++) {
|
||||
bit = buffer[bp++];
|
||||
m_buffer[node + length] = bit;
|
||||
}
|
||||
if (maxMatch >= MIN_MATCH) {
|
||||
const int limit = cr::max (cur - WINDOW_SIZE, NIL);
|
||||
|
||||
if (length == 0) {
|
||||
return -1;
|
||||
}
|
||||
int chainLength = MAX_CHAIN;
|
||||
int lookup = m_hashTable[hash32 (&in[cur])];
|
||||
|
||||
for (i = 1; i <= PADDING; i++) {
|
||||
insert (node - i);
|
||||
}
|
||||
insert (node);
|
||||
while (lookup > limit) {
|
||||
if (in[lookup + bestLength] == in[cur + bestLength] && load32 (&in[lookup]) == load32 (&in[cur])) {
|
||||
int length = MIN_MATCH;
|
||||
|
||||
do {
|
||||
if (m_matchLen > length) {
|
||||
m_matchLen = length;
|
||||
}
|
||||
if (m_matchLen <= THRESHOLD) {
|
||||
m_matchLen = 1;
|
||||
while (length < maxMatch && in[lookup + length] == in[cur + length]) {
|
||||
length++;
|
||||
}
|
||||
|
||||
cb[0] |= mask;
|
||||
cb[cbp++] = m_buffer[node];
|
||||
}
|
||||
else {
|
||||
cb[cbp++] = (uint8) (m_matchPos & 0xff);
|
||||
cb[cbp++] = (uint8) (((m_matchPos >> 4) & 0xf0) | (m_matchLen - (THRESHOLD + 1)));
|
||||
}
|
||||
if (length > bestLength) {
|
||||
bestLength = length;
|
||||
dist = cur - lookup;
|
||||
|
||||
if ((mask <<= 1) == 0) {
|
||||
for (i = 0; i < cbp; i++) {
|
||||
fp.putch (cb[i]);
|
||||
}
|
||||
m_csize += cbp;
|
||||
cb[0] = 0;
|
||||
cbp = mask = 1;
|
||||
}
|
||||
last = m_matchLen;
|
||||
|
||||
for (i = 0; (i < last) && (bp < bufferSize); i++) {
|
||||
bit = buffer[bp++];
|
||||
erase (ptr);
|
||||
|
||||
m_buffer[ptr] = bit;
|
||||
|
||||
if (ptr < PADDING - 1) {
|
||||
m_buffer[ptr + MAXBUF] = bit;
|
||||
}
|
||||
ptr = (ptr + 1) & (MAXBUF - 1);
|
||||
node = (node + 1) & (MAXBUF - 1);
|
||||
insert (node);
|
||||
}
|
||||
|
||||
while (i++ < last) {
|
||||
erase (ptr);
|
||||
|
||||
ptr = (ptr + 1) & (MAXBUF - 1);
|
||||
node = (node + 1) & (MAXBUF - 1);
|
||||
|
||||
if (length--) {
|
||||
insert (node);
|
||||
}
|
||||
}
|
||||
} while (length > 0);
|
||||
|
||||
if (cbp > 1) {
|
||||
for (i = 0; i < cbp; i++) {
|
||||
fp.putch (cb[i]);
|
||||
}
|
||||
m_csize += cbp;
|
||||
}
|
||||
fp.close ();
|
||||
|
||||
return m_csize;
|
||||
}
|
||||
|
||||
int decode_ (const char *fileName, int headerSize, uint8 *buffer, int bufferSize) {
|
||||
int i, j, k, node;
|
||||
unsigned int flags;
|
||||
int bp = 0;
|
||||
|
||||
uint8 bit;
|
||||
|
||||
File fp (fileName, "rb");
|
||||
|
||||
if (!fp.isValid ()) {
|
||||
return -1;
|
||||
}
|
||||
fp.seek (headerSize, SEEK_SET);
|
||||
|
||||
node = MAXBUF - PADDING;
|
||||
|
||||
for (i = 0; i < node; i++) {
|
||||
m_buffer[i] = ' ';
|
||||
}
|
||||
flags = 0;
|
||||
|
||||
for (;;) {
|
||||
if (((flags >>= 1) & 256) == 0) {
|
||||
int read = fp.getch ();
|
||||
|
||||
if (read == EOF) {
|
||||
break;
|
||||
}
|
||||
bit = static_cast <uint8> (read);
|
||||
flags = bit | 0xff00;
|
||||
}
|
||||
|
||||
if (flags & 1) {
|
||||
int read = fp.getch ();
|
||||
|
||||
if (read == EOF) {
|
||||
break;
|
||||
}
|
||||
bit = static_cast <uint8> (read);
|
||||
buffer[bp++] = bit;
|
||||
|
||||
if (bp > bufferSize) {
|
||||
return -1;
|
||||
}
|
||||
m_buffer[node++] = bit;
|
||||
node &= (MAXBUF - 1);
|
||||
}
|
||||
else {
|
||||
if ((i = fp.getch ()) == EOF) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ((j = fp.getch ()) == EOF) {
|
||||
break;
|
||||
}
|
||||
|
||||
i |= ((j & 0xf0) << 4);
|
||||
j = (j & 0x0f) + THRESHOLD;
|
||||
|
||||
for (k = 0; k <= j; k++) {
|
||||
bit = m_buffer[(i + k) & (MAXBUF - 1)];
|
||||
buffer[bp++] = bit;
|
||||
|
||||
if (bp > bufferSize) {
|
||||
return -1;
|
||||
if (length == maxMatch) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_buffer[node++] = bit;
|
||||
node &= (MAXBUF - 1);
|
||||
|
||||
if (--chainLength == 0) {
|
||||
break;
|
||||
}
|
||||
lookup = m_prevTable[lookup & WINDOW_MASK];
|
||||
}
|
||||
}
|
||||
|
||||
if (bestLength == MIN_MATCH && (cur - anchor) >= (7 + 128)) {
|
||||
bestLength = 0;
|
||||
}
|
||||
|
||||
if (bestLength >= MIN_MATCH && bestLength < maxMatch && (cur - anchor) != 6) {
|
||||
const int next = cur + 1;
|
||||
const int targetLength = bestLength + 1;
|
||||
const int limit = cr::max (next - WINDOW_SIZE, NIL);
|
||||
|
||||
int chainLength = MAX_CHAIN;
|
||||
int lookup = m_hashTable[hash32 (&in[next])];
|
||||
|
||||
while (lookup > limit) {
|
||||
if (in[lookup + bestLength] == in[next + bestLength] && load32 (&in[lookup]) == load32 (&in[next])) {
|
||||
int length = MIN_MATCH;
|
||||
|
||||
while (length < targetLength && in[lookup + length] == in[next + length]) {
|
||||
length++;
|
||||
}
|
||||
|
||||
if (length == targetLength) {
|
||||
bestLength = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (--chainLength == 0) {
|
||||
break;
|
||||
}
|
||||
lookup = m_prevTable[lookup & WINDOW_MASK];
|
||||
}
|
||||
}
|
||||
|
||||
if (bestLength >= MIN_MATCH) {
|
||||
const int length = bestLength - MIN_MATCH;
|
||||
const int token = ((dist >> 12) & 16) + cr::min (length, 15);
|
||||
|
||||
if (anchor != cur) {
|
||||
const int run = cur - anchor;
|
||||
|
||||
if (run >= 7) {
|
||||
add (op, (7 << 5) + token);
|
||||
encode (op, run - 7);
|
||||
}
|
||||
else {
|
||||
add (op, (run << 5) + token);
|
||||
}
|
||||
copy (op, &in[anchor], run);
|
||||
op += run;
|
||||
}
|
||||
else {
|
||||
add (op, token);
|
||||
}
|
||||
|
||||
if (length >= 15) {
|
||||
encode (op, length - 15);
|
||||
}
|
||||
store16 (op, dist);
|
||||
op += 2;
|
||||
|
||||
while (bestLength-- != 0) {
|
||||
const uint32 hash = hash32 (&in[cur]);
|
||||
|
||||
m_prevTable[cur & WINDOW_MASK] = m_hashTable[hash];
|
||||
m_hashTable[hash] = cur++;
|
||||
}
|
||||
anchor = cur;
|
||||
}
|
||||
else {
|
||||
const uint32 hash = hash32 (&in[cur]);
|
||||
|
||||
m_prevTable[cur & WINDOW_MASK] = m_hashTable[hash];
|
||||
m_hashTable[hash] = cur++;
|
||||
}
|
||||
}
|
||||
|
||||
if (anchor != cur) {
|
||||
const int run = cur - anchor;
|
||||
|
||||
if (run >= 7) {
|
||||
add (op, 7 << 5);
|
||||
encode (op, run - 7);
|
||||
}
|
||||
else {
|
||||
add (op, run << 5);
|
||||
}
|
||||
copy (op, &in[anchor], run);
|
||||
op += run;
|
||||
}
|
||||
return op - out;
|
||||
}
|
||||
|
||||
int uncompress (uint8 *in, int inLength, uint8 *out, int outLength) {
|
||||
uint8 *op = out;
|
||||
uint8 *ip = in;
|
||||
|
||||
const uint8 *opEnd = op + outLength;
|
||||
const uint8 *ipEnd = ip + inLength;
|
||||
|
||||
while (ip < ipEnd) {
|
||||
const int token = *ip++;
|
||||
|
||||
if (token >= 32) {
|
||||
int run = token >> 5;
|
||||
|
||||
if (run == 7) {
|
||||
run += decode (ip);
|
||||
}
|
||||
|
||||
if ((opEnd - op) < run || (ipEnd - ip) < run) {
|
||||
return UNCOMPRESS_RESULT_FAILED;
|
||||
}
|
||||
copy (op, ip, run);
|
||||
|
||||
op += run;
|
||||
ip += run;
|
||||
|
||||
if (ip >= ipEnd) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
int length = (token & 15) + MIN_MATCH;
|
||||
|
||||
if (length == (15 + MIN_MATCH)) {
|
||||
length += decode (ip);
|
||||
}
|
||||
|
||||
if ((opEnd - op) < length) {
|
||||
return UNCOMPRESS_RESULT_FAILED;
|
||||
}
|
||||
const int dist = ((token & 16) << 12) + load16 (ip);
|
||||
ip += 2;
|
||||
|
||||
uint8 *cp = op - dist;
|
||||
|
||||
if ((op - out) < dist) {
|
||||
return UNCOMPRESS_RESULT_FAILED;
|
||||
}
|
||||
|
||||
if (dist >= 8) {
|
||||
copy (op, cp, length);
|
||||
op += length;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 4; i++) {
|
||||
*op++ = *cp++;
|
||||
}
|
||||
|
||||
while (length-- != 4) {
|
||||
*op++ = *cp++;
|
||||
}
|
||||
}
|
||||
}
|
||||
fp.close ();
|
||||
|
||||
return bp;
|
||||
return (ip == ipEnd) ? op - out : UNCOMPRESS_RESULT_FAILED;
|
||||
}
|
||||
|
||||
// external decoder
|
||||
static int decode (const char *fileName, int headerSize, uint8 *buffer, int bufferSize) {
|
||||
static Compress compressor;
|
||||
return compressor.decode_ (fileName, headerSize, buffer, bufferSize);
|
||||
private:
|
||||
inline uint16 load16 (void *ptr) {
|
||||
return *reinterpret_cast <const uint16 *> (ptr);
|
||||
}
|
||||
|
||||
// external encoder
|
||||
static int encode (const char *fileName, uint8 *header, int headerSize, uint8 *buffer, int bufferSize) {
|
||||
static Compress compressor;
|
||||
return compressor.encode_ (fileName, header, headerSize, buffer, bufferSize);
|
||||
inline uint32 load32 (void *ptr) {
|
||||
return *reinterpret_cast <const uint32 *> (ptr);
|
||||
}
|
||||
};
|
||||
|
||||
inline void store16 (void *ptr, int val) {
|
||||
*reinterpret_cast <uint16 *> (ptr) = static_cast <uint16> (val);
|
||||
}
|
||||
|
||||
inline void copy64 (void *dst, void *src) {
|
||||
*reinterpret_cast <uint64 *> (dst) = *reinterpret_cast <const uint64 *> (src);
|
||||
}
|
||||
|
||||
inline uint32 hash32 (void *ptr) {
|
||||
return (load32 (ptr) * 0x9E3779B9) >> (32 - HASH_BITS);
|
||||
}
|
||||
|
||||
inline void copy (uint8 *dst, uint8 *src, int count) {
|
||||
copy64 (dst, src);
|
||||
|
||||
for (int i = 8; i < count; i += 8) {
|
||||
copy64 (dst + i, src + i);
|
||||
}
|
||||
}
|
||||
|
||||
inline void add (uint8 *&dst, int val) {
|
||||
*dst++ = static_cast <uint8> (val);
|
||||
}
|
||||
|
||||
inline void encode (uint8 *&ptr, uint32 val) {
|
||||
while (val >= 128) {
|
||||
val -= 128;
|
||||
|
||||
*ptr++ = 128 + (val & 127);
|
||||
val >>= 7;
|
||||
}
|
||||
*ptr++ = static_cast <uint8> (val);
|
||||
}
|
||||
|
||||
inline uint32 decode (uint8 *&ptr) {
|
||||
uint32 val = 0;
|
||||
|
||||
for (int i = 0; i <= 21; i += 7) {
|
||||
const uint32 cur = *ptr++;
|
||||
val += cur << i;
|
||||
|
||||
if (cur < 128) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
};
|
||||
|
|
@ -54,8 +54,9 @@ using int32 = signed long;
|
|||
using uint8 = unsigned char;
|
||||
using uint16 = unsigned short;
|
||||
using uint32 = unsigned long;
|
||||
using uint64 = unsigned long long;
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
using namespace cr::types;
|
||||
|
||||
|
|
@ -71,13 +72,14 @@ constexpr float D2R = PI / 180.0f;
|
|||
constexpr float R2D = 180.0f / PI;
|
||||
|
||||
// from metamod-p
|
||||
static inline bool checkptr (const void *ptr) {
|
||||
static inline bool checkptr (void *ptr) {
|
||||
#ifdef PLATFORM_WIN32
|
||||
if (IsBadCodePtr (reinterpret_cast <FARPROC> (ptr)))
|
||||
if (IsBadCodePtr (reinterpret_cast <FARPROC> (ptr))) {
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
(void) (ptr);
|
||||
#endif
|
||||
|
||||
(void)(ptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -109,6 +111,10 @@ template <typename T> constexpr T abs (const T a) {
|
|||
return a > 0 ? a : -a;
|
||||
}
|
||||
|
||||
template <typename T> constexpr T bit (const T a) {
|
||||
return 1 << a;
|
||||
}
|
||||
|
||||
static inline float powf (const float x, const float y) {
|
||||
union {
|
||||
float d;
|
||||
|
|
@ -124,7 +130,7 @@ static inline float sqrtf (const float value) {
|
|||
}
|
||||
|
||||
static inline float sinf (const float value) {
|
||||
const signed long sign = static_cast <signed long> (value * PI_RECIPROCAL);
|
||||
const auto sign = static_cast <signed long> (value * PI_RECIPROCAL);
|
||||
const float calc = (value - static_cast <float> (sign) * PI);
|
||||
|
||||
const float sqr = square (calc);
|
||||
|
|
@ -135,7 +141,7 @@ static inline float sinf (const float value) {
|
|||
}
|
||||
|
||||
static inline float cosf (const float value) {
|
||||
const signed long sign = static_cast <signed long> (value * PI_RECIPROCAL);
|
||||
const auto sign = static_cast <signed long> (value * PI_RECIPROCAL);
|
||||
const float calc = (value - static_cast <float> (sign) * PI);
|
||||
|
||||
const float sqr = square (calc);
|
||||
|
|
@ -303,7 +309,7 @@ protected:
|
|||
NonCopyable (void) = default;
|
||||
~NonCopyable (void) = default;
|
||||
|
||||
private:
|
||||
public:
|
||||
NonCopyable (const NonCopyable &) = delete;
|
||||
NonCopyable &operator = (const NonCopyable &) = delete;
|
||||
};
|
||||
|
|
@ -323,33 +329,33 @@ public:
|
|||
// see: https://github.com/preshing/RandomSequence/
|
||||
class RandomSequence : public Singleton <RandomSequence> {
|
||||
private:
|
||||
unsigned int m_index;
|
||||
unsigned int m_intermediateOffset;
|
||||
unsigned long long m_divider;
|
||||
uint32 m_index;
|
||||
uint32 m_intermediateOffset;
|
||||
uint64 m_divider;
|
||||
|
||||
private:
|
||||
unsigned int premute (unsigned int x) {
|
||||
static constexpr unsigned int prime = 4294967291u;
|
||||
uint32 premute (uint32 x) {
|
||||
static constexpr uint32 prime = 4294967291u;
|
||||
|
||||
if (x >= prime) {
|
||||
return x;
|
||||
}
|
||||
const unsigned int residue = (static_cast <unsigned long long> (x) * x) % prime;
|
||||
const uint32 residue = (static_cast <unsigned long long> (x) * x) % prime;
|
||||
return (x <= prime / 2) ? residue : prime - residue;
|
||||
}
|
||||
|
||||
unsigned int random (void) {
|
||||
uint32 random (void) {
|
||||
return premute ((premute (m_index++) + m_intermediateOffset) ^ 0x5bf03635);
|
||||
}
|
||||
|
||||
public:
|
||||
RandomSequence (void) {
|
||||
const unsigned int seedBase = static_cast <unsigned int> (time (nullptr));
|
||||
const unsigned int seedOffset = seedBase + 1;
|
||||
const auto seedBase = static_cast <uint32> (time (nullptr));
|
||||
const auto seedOffset = seedBase + 1;
|
||||
|
||||
m_index = premute (premute (seedBase) + 0x682f0161);
|
||||
m_intermediateOffset = premute (premute (seedOffset) + 0x46790905);
|
||||
m_divider = (static_cast <unsigned long long> (1)) << 32;
|
||||
m_divider = (static_cast <uint64> (1)) << 32;
|
||||
}
|
||||
|
||||
template <typename U> inline U getInt (U low, U high) {
|
||||
|
|
@ -367,7 +373,7 @@ public:
|
|||
|
||||
class SimpleColor final : private NonCopyable {
|
||||
public:
|
||||
int red, green, blue;
|
||||
int red = 0, green = 0, blue = 0;
|
||||
|
||||
inline void reset (void) {
|
||||
red = green = blue = 0;
|
||||
|
|
@ -390,7 +396,7 @@ public:
|
|||
inline Vector (float scaler = 0.0f) : x (scaler), y (scaler), z (scaler) {}
|
||||
inline Vector (float inputX, float inputY, float inputZ) : x (inputX), y (inputY), z (inputZ) {}
|
||||
inline Vector (float *other) : x (other[0]), y (other[1]), z (other[2]) {}
|
||||
inline Vector (const Vector &right) : x (right.x), y (right.y), z (right.z) {}
|
||||
inline Vector (const Vector &right) = default;
|
||||
|
||||
public:
|
||||
inline operator float * (void) {
|
||||
|
|
@ -401,33 +407,33 @@ public:
|
|||
return &x;
|
||||
}
|
||||
|
||||
inline const Vector operator + (const Vector &right) const {
|
||||
inline Vector operator + (const Vector &right) const {
|
||||
return Vector (x + right.x, y + right.y, z + right.z);
|
||||
}
|
||||
|
||||
inline const Vector operator - (const Vector &right) const {
|
||||
inline Vector operator - (const Vector &right) const {
|
||||
return Vector (x - right.x, y - right.y, z - right.z);
|
||||
}
|
||||
|
||||
inline const Vector operator - (void) const {
|
||||
inline Vector operator - (void) const {
|
||||
return Vector (-x, -y, -z);
|
||||
}
|
||||
|
||||
friend inline const Vector operator* (const float vec, const Vector &right) {
|
||||
friend inline Vector operator * (const float vec, const Vector &right) {
|
||||
return Vector (right.x * vec, right.y * vec, right.z * vec);
|
||||
}
|
||||
|
||||
inline const Vector operator * (float vec) const {
|
||||
inline Vector operator * (float vec) const {
|
||||
return Vector (vec * x, vec * y, vec * z);
|
||||
}
|
||||
|
||||
inline const Vector operator / (float vec) const {
|
||||
inline Vector operator / (float vec) const {
|
||||
const float inv = 1 / vec;
|
||||
return Vector (inv * x, inv * y, inv * z);
|
||||
}
|
||||
|
||||
// cross product
|
||||
inline const Vector operator ^ (const Vector &right) const {
|
||||
inline Vector operator ^ (const Vector &right) const {
|
||||
return Vector (y * right.z - z * right.y, z * right.x - x * right.z, x * right.y - y * right.x);
|
||||
}
|
||||
|
||||
|
|
@ -478,13 +484,7 @@ public:
|
|||
return !fequal (x, right.x) && !fequal (y, right.y) && !fequal (z, right.z);
|
||||
}
|
||||
|
||||
inline const Vector &operator = (const Vector &right) {
|
||||
x = right.x;
|
||||
y = right.y;
|
||||
z = right.z;
|
||||
|
||||
return *this;
|
||||
}
|
||||
inline Vector &operator = (const Vector &right) = default;
|
||||
|
||||
public:
|
||||
inline float length (void) const {
|
||||
|
|
@ -572,7 +572,7 @@ public:
|
|||
float cosines[max] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
|
||||
// compute the sine and cosine compontents
|
||||
sincosf (deg2rad (x), deg2rad (y), deg2rad (y), sines, cosines);
|
||||
sincosf (deg2rad (x), deg2rad (y), deg2rad (z), sines, cosines);
|
||||
|
||||
if (forward) {
|
||||
forward->x = cosines[pitch] * cosines[yaw];
|
||||
|
|
@ -596,12 +596,12 @@ public:
|
|||
|
||||
class Library final : private NonCopyable {
|
||||
private:
|
||||
void *m_ptr;
|
||||
void *m_ptr = nullptr;
|
||||
|
||||
public:
|
||||
explicit Library (void) : m_ptr (nullptr) { }
|
||||
explicit Library (void) = default;
|
||||
|
||||
Library (const char *filename) : m_ptr (nullptr) {
|
||||
Library (const char *filename) {
|
||||
if (!filename) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -637,12 +637,13 @@ public:
|
|||
if (!isValid ()) {
|
||||
return nullptr;
|
||||
}
|
||||
return (R)
|
||||
return reinterpret_cast <R> (
|
||||
#ifdef PLATFORM_WIN32
|
||||
GetProcAddress (static_cast <HMODULE> (m_ptr), function);
|
||||
GetProcAddress (static_cast <HMODULE> (m_ptr), function)
|
||||
#else
|
||||
dlsym (m_ptr, function);
|
||||
dlsym (m_ptr, function)
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
template <typename R> R handle (void) {
|
||||
|
|
@ -656,11 +657,11 @@ public:
|
|||
|
||||
template <typename A, typename B> class Pair final {
|
||||
public:
|
||||
A first;
|
||||
B second;
|
||||
A first = move (A ());
|
||||
B second = move (B ());
|
||||
|
||||
public:
|
||||
Pair (const A &a, const B &b) : first (cr::move (a)), second (cr::move (b)) {
|
||||
Pair (const A &a, const B &b) : first (move (a)), second (move (b)) {
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
@ -673,13 +674,12 @@ public:
|
|||
static constexpr size_t INVALID_INDEX = static_cast <size_t> (-1);
|
||||
|
||||
protected:
|
||||
T *m_data;
|
||||
size_t m_capacity;
|
||||
size_t m_length;
|
||||
T *m_data = nullptr;
|
||||
size_t m_capacity = 0;
|
||||
size_t m_length = 0;
|
||||
|
||||
public:
|
||||
Array (void) : m_data (nullptr), m_capacity (0), m_length (0) {
|
||||
}
|
||||
Array (void) = default;
|
||||
|
||||
Array (Array &&other) noexcept {
|
||||
m_data = other.m_data;
|
||||
|
|
@ -689,7 +689,7 @@ public:
|
|||
other.reset ();
|
||||
}
|
||||
|
||||
virtual ~Array (void) {
|
||||
~Array (void) {
|
||||
destroy ();
|
||||
}
|
||||
|
||||
|
|
@ -709,7 +709,7 @@ public:
|
|||
if (m_length + growSize < m_capacity) {
|
||||
return true;
|
||||
}
|
||||
size_t maxSize = max <size_t> (m_capacity + sizeof (T), static_cast <size_t> (16));
|
||||
auto maxSize = max <size_t> (m_capacity + sizeof (T), static_cast <size_t> (16));
|
||||
|
||||
while (m_length + growSize > maxSize) {
|
||||
maxSize *= 2;
|
||||
|
|
@ -738,16 +738,16 @@ public:
|
|||
bool res = reserve (newSize);
|
||||
|
||||
while (m_length < newSize) {
|
||||
push (T ());
|
||||
push (move (T ()));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
inline size_t length (void) const {
|
||||
size_t length (void) const {
|
||||
return m_length;
|
||||
}
|
||||
|
||||
inline size_t capacity (void) const {
|
||||
size_t capacity (void) const {
|
||||
return m_capacity;
|
||||
}
|
||||
|
||||
|
|
@ -765,7 +765,11 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
inline T &at (size_t index) {
|
||||
T &at (size_t index) {
|
||||
return m_data[index];
|
||||
}
|
||||
|
||||
const T &at (size_t index) const {
|
||||
return m_data[index];
|
||||
}
|
||||
|
||||
|
|
@ -861,7 +865,7 @@ public:
|
|||
m_length = 0;
|
||||
}
|
||||
|
||||
inline bool empty (void) const {
|
||||
bool empty (void) const {
|
||||
return m_length == 0;
|
||||
}
|
||||
|
||||
|
|
@ -922,6 +926,12 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
void shuffle (void) {
|
||||
for (size_t i = m_length; i >= 1; i--) {
|
||||
swap (m_data[i - 1], m_data[RandomSequence::ref ().getInt (i, m_length - 2)]);
|
||||
}
|
||||
}
|
||||
|
||||
void reverse (void) {
|
||||
for (size_t i = 0; i < m_length / 2; i++) {
|
||||
swap (m_data[i], m_data[m_length - 1 - i]);
|
||||
|
|
@ -1010,15 +1020,15 @@ public:
|
|||
return value.first;
|
||||
}
|
||||
|
||||
inline bool empty (void) const {
|
||||
bool empty (void) const {
|
||||
return !length ();
|
||||
}
|
||||
|
||||
inline size_t length (void) const {
|
||||
size_t length (void) const {
|
||||
return m_length;
|
||||
}
|
||||
|
||||
inline void clear (void) {
|
||||
void clear (void) {
|
||||
base::clear ();
|
||||
}
|
||||
|
||||
|
|
@ -1081,7 +1091,12 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
// some fast string class
|
||||
class String final : private Array <char> {
|
||||
public:
|
||||
static constexpr size_t INVALID_INDEX = Array <char>::INVALID_INDEX;
|
||||
|
||||
private:
|
||||
using base = Array <char>;
|
||||
|
||||
|
|
@ -1097,9 +1112,9 @@ private:
|
|||
}
|
||||
|
||||
public:
|
||||
String (String &&other) noexcept : base (move (other)) { }
|
||||
|
||||
String (void) = default;
|
||||
String (String &&other) noexcept : base (move (other)) { }
|
||||
~String (void) = default;
|
||||
|
||||
public:
|
||||
|
|
@ -1119,12 +1134,12 @@ public:
|
|||
String &assign (const char *str, size_t length = 0) {
|
||||
length = length > 0 ? length : strlen (str);
|
||||
|
||||
clear ();
|
||||
resize (length);
|
||||
|
||||
memcpy (m_data, str, length);
|
||||
terminate ();
|
||||
base::clear ();
|
||||
base::reserve (length + 1);
|
||||
|
||||
if (base::push (const_cast <char *> (str), length)) {
|
||||
terminate ();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -1133,7 +1148,7 @@ public:
|
|||
}
|
||||
|
||||
String &assign (const char chr) {
|
||||
resize (2);
|
||||
resize (1);
|
||||
m_data[0] = chr;
|
||||
|
||||
return *this;
|
||||
|
|
@ -1143,11 +1158,9 @@ public:
|
|||
if (empty ()) {
|
||||
return assign (str);
|
||||
}
|
||||
const size_t maxLength = strlen (str) + 1;
|
||||
|
||||
resize (length () + maxLength);
|
||||
strncat (m_data, str, maxLength);
|
||||
|
||||
if (push (const_cast <char *> (str), strlen (str))) {
|
||||
terminate ();
|
||||
};
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -1168,6 +1181,10 @@ public:
|
|||
return base::length ();
|
||||
}
|
||||
|
||||
size_t capacity (void) const {
|
||||
return base::capacity ();
|
||||
}
|
||||
|
||||
bool empty (void) const {
|
||||
return !length ();
|
||||
}
|
||||
|
|
@ -1198,11 +1215,19 @@ public:
|
|||
return atoi (chars ());
|
||||
}
|
||||
|
||||
inline void terminate (void) {
|
||||
float toFloat (void) const {
|
||||
return static_cast <float> (atof (chars ()));
|
||||
}
|
||||
|
||||
void terminate (void) {
|
||||
m_data[m_length] = '\0';
|
||||
}
|
||||
|
||||
inline char &at (size_t index) {
|
||||
char &at (size_t index) {
|
||||
return m_data[index];
|
||||
}
|
||||
|
||||
const char &at (size_t index) const {
|
||||
return m_data[index];
|
||||
}
|
||||
|
||||
|
|
@ -1211,33 +1236,30 @@ public:
|
|||
}
|
||||
|
||||
int32 compare (const char *what) const {
|
||||
return strcmp (begin (), what);
|
||||
return strcmp (m_data, what);
|
||||
}
|
||||
|
||||
bool contains (const String &what) const {
|
||||
return strstr (m_data, what.begin ()) != nullptr;
|
||||
}
|
||||
|
||||
template <size_t BufferSize = 512> void format (const char *fmt, ...) {
|
||||
va_list ap;
|
||||
char buffer[BufferSize];
|
||||
template <typename ...Args> void assign (const char *fmt, Args ...args) {
|
||||
const size_t size = snprintf (nullptr, 0, fmt, args...);
|
||||
|
||||
va_start (ap, fmt);
|
||||
vsnprintf (buffer, bufsize (buffer), fmt, ap);
|
||||
va_end (ap);
|
||||
reserve (size + 1);
|
||||
resize (size);
|
||||
|
||||
assign (buffer);
|
||||
snprintf (&m_data[0], size + 1, fmt, args...);
|
||||
}
|
||||
|
||||
template <size_t BufferSize = 512> void formatAppend (const char *fmt, ...) {
|
||||
va_list ap;
|
||||
char buffer[BufferSize];
|
||||
template <typename ...Args> void append (const char *fmt, Args ...args) {
|
||||
const size_t size = snprintf (nullptr, 0, fmt, args...) + m_length;
|
||||
const size_t len = m_length;
|
||||
|
||||
va_start (ap, fmt);
|
||||
vsnprintf (buffer, bufsize (buffer), fmt, ap);
|
||||
va_end (ap);
|
||||
reserve (size + 1);
|
||||
resize (size);
|
||||
|
||||
append (buffer);
|
||||
snprintf (&m_data[len], size + 1, fmt, args...);
|
||||
}
|
||||
|
||||
size_t insert (size_t at, const String &str) {
|
||||
|
|
@ -1248,14 +1270,32 @@ public:
|
|||
return 0;
|
||||
}
|
||||
|
||||
size_t find (const String &search, size_t pos) const {
|
||||
if (pos > length ()) {
|
||||
return INVALID_INDEX;
|
||||
size_t find (char val, size_t pos) const {
|
||||
for (size_t i = pos; i < m_length; i++) {
|
||||
if (m_data[i] == val) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return INVALID_INDEX;
|
||||
}
|
||||
|
||||
size_t find (const String &search, size_t pos) const {
|
||||
size_t len = search.length ();
|
||||
|
||||
for (size_t i = pos; len + i <= length (); i++) {
|
||||
if (strncmp (m_data + i, search.chars (), len) == 0) {
|
||||
if (len > m_length || pos > m_length) {
|
||||
return INVALID_INDEX;
|
||||
}
|
||||
|
||||
for (size_t i = pos; i <= m_length - len; i++) {
|
||||
size_t at = 0;
|
||||
|
||||
for (; search.m_data[at]; at++) {
|
||||
if (m_data[i + at] != search.m_data[at]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!search.m_data[at]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
|
@ -1268,7 +1308,7 @@ public:
|
|||
}
|
||||
size_t numReplaced = 0, posIndex = 0;
|
||||
|
||||
while (posIndex < length ()) {
|
||||
while (posIndex < m_length) {
|
||||
posIndex = find (what, posIndex);
|
||||
|
||||
if (posIndex == INVALID_INDEX) {
|
||||
|
|
@ -1283,28 +1323,96 @@ public:
|
|||
return numReplaced;
|
||||
}
|
||||
|
||||
String substr (size_t start, size_t count = INVALID_INDEX) {
|
||||
String substr (size_t start, size_t count = INVALID_INDEX) const {
|
||||
String result;
|
||||
|
||||
if (start >= length () || empty ()) {
|
||||
return result;
|
||||
if (start >= m_length || empty ()) {
|
||||
return move (result);
|
||||
}
|
||||
if (count == INVALID_INDEX) {
|
||||
count = length () - start;
|
||||
count = m_length - start;
|
||||
}
|
||||
else if (start + count >= length ()) {
|
||||
count = length () - start;
|
||||
else if (start + count >= m_length) {
|
||||
count = m_length - start;
|
||||
}
|
||||
result.resize (count);
|
||||
|
||||
transfer (&result[0], &m_data[start], count);
|
||||
// copy, not move
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
result[i] = m_data[start + i];
|
||||
}
|
||||
result[count] = '\0';
|
||||
|
||||
return result;
|
||||
return move (result);
|
||||
}
|
||||
|
||||
char &operator[] (size_t index) {
|
||||
return at (index);
|
||||
String &rtrim (const char *chars = "\r\n\t ") {
|
||||
if (empty ()) {
|
||||
return *this;
|
||||
}
|
||||
char *str = end () - 1;
|
||||
|
||||
while (*str != 0) {
|
||||
if (isTrimChar (*str, chars)) {
|
||||
erase (str - begin ());
|
||||
str--;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
String <rim (const char *chars = "\r\n\t ") {
|
||||
if (empty ()) {
|
||||
return *this;
|
||||
}
|
||||
char *str = begin ();
|
||||
|
||||
while (isTrimChar (*str, chars)) {
|
||||
str++;
|
||||
}
|
||||
|
||||
if (begin () != str) {
|
||||
erase (0, str - begin ());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
String &trim (const char *chars = "\r\n\t ") {
|
||||
return rtrim (chars).ltrim (chars);
|
||||
}
|
||||
|
||||
Array <String> split (const String &delim) const {
|
||||
Array <String> tokens;
|
||||
size_t prev = 0, pos = 0;
|
||||
|
||||
do {
|
||||
pos = find (delim, prev);
|
||||
|
||||
if (pos == INVALID_INDEX) {
|
||||
pos = m_length;
|
||||
}
|
||||
tokens.push (move (substr (prev, pos - prev)));
|
||||
|
||||
prev = pos + delim.length ();
|
||||
} while (pos < m_length && prev < m_length);
|
||||
|
||||
return move (tokens);
|
||||
}
|
||||
|
||||
String &lowercase (void) {
|
||||
for (auto &ch : *this) {
|
||||
ch = static_cast <char> (tolower (ch));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
String &uppercase (void) {
|
||||
for (auto &ch : *this) {
|
||||
ch = static_cast <char> (toupper (ch));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend String operator + (const String &lhs, const String &rhs) {
|
||||
|
|
@ -1384,79 +1492,51 @@ public:
|
|||
return append (rhs);
|
||||
}
|
||||
|
||||
String &trimRight (const char *chars = "\r\n\t ") {
|
||||
if (empty ()) {
|
||||
return *this;
|
||||
}
|
||||
char *str = end () - 1;
|
||||
|
||||
while (*str != 0) {
|
||||
if (isTrimChar (*str, chars)) {
|
||||
erase (str - begin ());
|
||||
str--;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
char &operator [] (size_t index) {
|
||||
return at (index);
|
||||
}
|
||||
|
||||
String &trimLeft (const char *chars = "\r\n\t ") {
|
||||
if (empty ()) {
|
||||
return *this;
|
||||
}
|
||||
char *str = begin ();
|
||||
|
||||
while (isTrimChar (*str, chars)) {
|
||||
str++;
|
||||
}
|
||||
|
||||
if (begin () != str) {
|
||||
erase (0, str - begin ());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
String &trim (const char *chars = "\r\n\t ") {
|
||||
return trimLeft (chars).trimRight (chars);
|
||||
}
|
||||
|
||||
Array <String> split (const char *delimiter) {
|
||||
Array <String> tokens;
|
||||
size_t len, index = 0;
|
||||
|
||||
do {
|
||||
index += strspn (&m_data[index], delimiter);
|
||||
len = strcspn (&m_data[index], delimiter);
|
||||
|
||||
if (len > 0) {
|
||||
tokens.push (move (substr (index, len)));
|
||||
}
|
||||
index += len;
|
||||
} while (len > 0);
|
||||
|
||||
return tokens;
|
||||
const char &operator [] (size_t index) const {
|
||||
return at (index);
|
||||
}
|
||||
|
||||
public:
|
||||
static void trimChars (char *str) {
|
||||
size_t pos = 0;
|
||||
char *dest = str;
|
||||
|
||||
while (str[pos] <= ' ' && str[pos] > 0) {
|
||||
pos++;
|
||||
char *begin (void) {
|
||||
return base::begin ();
|
||||
}
|
||||
|
||||
while (str[pos]) {
|
||||
*(dest++) = str[pos];
|
||||
pos++;
|
||||
char *begin (void) const {
|
||||
return base::begin ();
|
||||
}
|
||||
*(dest--) = '\0';
|
||||
|
||||
while (dest >= str && *dest <= ' ' && *dest > 0) {
|
||||
*(dest--) = '\0';
|
||||
char *end (void) {
|
||||
return base::end ();
|
||||
}
|
||||
|
||||
char *end (void) const {
|
||||
return base::end ();
|
||||
}
|
||||
|
||||
public:
|
||||
static String join (const Array <String> &sequence, const String &delim, size_t start = 0) {
|
||||
if (sequence.empty ()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (sequence.length () == 1) {
|
||||
return sequence.at (0);
|
||||
}
|
||||
String result;
|
||||
|
||||
for (size_t index = start; index < sequence.length (); index++) {
|
||||
if (index != start) {
|
||||
result += delim + sequence[index];
|
||||
}
|
||||
else {
|
||||
result += sequence[index];
|
||||
}
|
||||
}
|
||||
return move (result);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -1553,17 +1633,16 @@ public:
|
|||
|
||||
class File : private NonCopyable {
|
||||
private:
|
||||
FILE *m_handle;
|
||||
size_t m_size;
|
||||
FILE *m_handle = nullptr;
|
||||
size_t m_size = 0;
|
||||
|
||||
public:
|
||||
File (void) : m_handle (nullptr), m_size (0) {}
|
||||
|
||||
File (const String &fileName, const String &mode = "rt") : m_handle (nullptr), m_size (0){
|
||||
File (void) = default;
|
||||
File (const String &fileName, const String &mode = "rt") {
|
||||
open (fileName, mode);
|
||||
}
|
||||
|
||||
virtual ~File (void) {
|
||||
~File (void) {
|
||||
close ();
|
||||
}
|
||||
|
||||
|
|
@ -1594,14 +1673,24 @@ public:
|
|||
return fflush (m_handle) ? false : true;
|
||||
}
|
||||
|
||||
int getch (void) {
|
||||
return fgetc (m_handle);
|
||||
char getch (void) {
|
||||
return static_cast <char> (fgetc (m_handle));
|
||||
}
|
||||
|
||||
char *gets (char *buffer, int count) {
|
||||
return fgets (buffer, count, m_handle);
|
||||
}
|
||||
|
||||
bool getLine (String &line) {
|
||||
line.clear ();
|
||||
char ch;
|
||||
|
||||
while ((ch = getch ()) != '\n' && ch != EOF && !eof ()) {
|
||||
line += ch;
|
||||
}
|
||||
return !eof ();
|
||||
}
|
||||
|
||||
int writeFormat (const char *format, ...) {
|
||||
assert (m_handle != nullptr);
|
||||
|
||||
|
|
@ -1714,14 +1803,13 @@ public:
|
|||
|
||||
class MemFile : private NonCopyable {
|
||||
private:
|
||||
size_t m_size;
|
||||
size_t m_pos;
|
||||
uint8 *m_buffer;
|
||||
size_t m_size = 0;
|
||||
size_t m_pos = 0;
|
||||
uint8 *m_buffer = nullptr;
|
||||
|
||||
public:
|
||||
MemFile (void) : m_size (0) , m_pos (0) , m_buffer (nullptr) {}
|
||||
|
||||
MemFile (const String &filename) : m_size (0) , m_pos (0) , m_buffer (nullptr) {
|
||||
MemFile (void) = default;
|
||||
MemFile (const String &filename) {
|
||||
open (filename);
|
||||
}
|
||||
|
||||
|
|
@ -1748,14 +1836,14 @@ public:
|
|||
m_buffer = nullptr;
|
||||
}
|
||||
|
||||
int getch (void) {
|
||||
char getch (void) {
|
||||
if (!m_buffer || m_pos >= m_size) {
|
||||
return -1;
|
||||
}
|
||||
int readCh = m_buffer[m_pos];
|
||||
m_pos++;
|
||||
|
||||
return readCh;
|
||||
return static_cast <char> (readCh);
|
||||
}
|
||||
|
||||
char *gets (char *buffer, size_t count) {
|
||||
|
|
@ -1781,6 +1869,16 @@ public:
|
|||
return index ? buffer : nullptr;
|
||||
}
|
||||
|
||||
bool getLine (String &line) {
|
||||
line.clear ();
|
||||
char ch;
|
||||
|
||||
while ((ch = getch ()) != '\n' && ch != EOF && m_pos < m_size) {
|
||||
line += ch;
|
||||
}
|
||||
return m_pos < m_size;
|
||||
}
|
||||
|
||||
size_t read (void *buffer, size_t size, size_t count = 1) {
|
||||
if (!m_buffer || m_size <= m_pos || !buffer || !size || !count) {
|
||||
return 0;
|
||||
|
|
@ -1818,7 +1916,7 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
inline size_t getSize (void) const {
|
||||
size_t getSize (void) const {
|
||||
return m_size;
|
||||
}
|
||||
|
||||
|
|
@ -1827,8 +1925,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
}};
|
||||
|
||||
namespace cr {
|
||||
namespace types {
|
||||
|
|
@ -1836,4 +1933,4 @@ namespace types {
|
|||
using StringArray = cr::classes::Array <cr::classes::String>;
|
||||
using IntArray = cr::classes::Array <int>;
|
||||
|
||||
}}
|
||||
}};
|
||||
|
|
|
|||
243
include/engine.h
243
include/engine.h
|
|
@ -10,22 +10,22 @@
|
|||
#pragma once
|
||||
|
||||
// line draw
|
||||
enum DrawLineType {
|
||||
enum DrawLineType : int {
|
||||
DRAW_SIMPLE,
|
||||
DRAW_ARROW,
|
||||
DRAW_NUM
|
||||
};
|
||||
|
||||
// trace ignore
|
||||
enum TraceIgnore {
|
||||
enum TraceIgnore : int {
|
||||
TRACE_IGNORE_NONE = 0,
|
||||
TRACE_IGNORE_GLASS = (1 << 0),
|
||||
TRACE_IGNORE_MONSTERS = (1 << 1),
|
||||
TRACE_IGNORE_GLASS = cr::bit (0),
|
||||
TRACE_IGNORE_MONSTERS = cr::bit (1),
|
||||
TRACE_IGNORE_EVERYTHING = TRACE_IGNORE_GLASS | TRACE_IGNORE_MONSTERS
|
||||
};
|
||||
|
||||
// variable type
|
||||
enum VarType {
|
||||
enum VarType : int {
|
||||
VT_NORMAL = 0,
|
||||
VT_READONLY,
|
||||
VT_PASSWORD,
|
||||
|
|
@ -34,7 +34,7 @@ enum VarType {
|
|||
};
|
||||
|
||||
// netmessage functions
|
||||
enum NetMsgId {
|
||||
enum NetMsgId : int {
|
||||
NETMSG_UNDEFINED = -1,
|
||||
NETMSG_VGUI = 1,
|
||||
NETMSG_SHOWMENU = 2,
|
||||
|
|
@ -61,6 +61,36 @@ enum NetMsgId {
|
|||
NETMSG_NUM = 25
|
||||
};
|
||||
|
||||
// supported cs's
|
||||
enum GameFlags : int {
|
||||
GAME_CSTRIKE16 = cr::bit (0), // counter-strike 1.6 and above
|
||||
GAME_XASH_ENGINE = cr::bit (1), // counter-strike 1.6 under the xash engine (additional flag)
|
||||
GAME_CZERO = cr::bit (2), // counter-strike: condition zero
|
||||
GAME_LEGACY = cr::bit (3), // counter-strike 1.3-1.5 with/without steam
|
||||
GAME_MOBILITY = cr::bit (4), // additional flag that bot is running on android (additional flag)
|
||||
GAME_OFFICIAL_CSBOT = cr::bit (5), // additional flag that indicates official cs bots are in game
|
||||
GAME_METAMOD = cr::bit (6), // game running under meta\mod
|
||||
GAME_CSDM = cr::bit (7), // csdm mod currently in use
|
||||
GAME_CSDM_FFA = cr::bit (8), // csdm mod with ffa mode
|
||||
GAME_REGAMEDLL = cr::bit (9), // server dll is a regamedll
|
||||
GAME_SUPPORT_SVC_PINGS = cr::bit (10), // on that game version we can fake bots pings
|
||||
GAME_SUPPORT_BOT_VOICE = cr::bit (11) // on that game version we can use chatter
|
||||
};
|
||||
|
||||
|
||||
// defines map type
|
||||
enum MapFlags : int {
|
||||
MAP_AS = cr::bit (0),
|
||||
MAP_CS = cr::bit (1),
|
||||
MAP_DE = cr::bit (2),
|
||||
MAP_ES = cr::bit (3),
|
||||
MAP_KA = cr::bit (4),
|
||||
MAP_FY = cr::bit (5),
|
||||
|
||||
// additional flags
|
||||
MAP_HAS_DOORS = cr::bit (6)
|
||||
};
|
||||
|
||||
// variable reg pair
|
||||
struct VarPair {
|
||||
VarType type;
|
||||
|
|
@ -79,6 +109,14 @@ struct MessageBlock {
|
|||
int regMsgs[NETMSG_NUM];
|
||||
};
|
||||
|
||||
// referentia vector info
|
||||
struct RefVector {
|
||||
Vector forward, right, up;
|
||||
};
|
||||
|
||||
// entity prototype
|
||||
using EntityFunction = void (*) (entvars_t *);
|
||||
|
||||
// compare language
|
||||
struct LangComprarer {
|
||||
size_t operator () (const String &key) const {
|
||||
|
|
@ -96,15 +134,14 @@ struct LangComprarer {
|
|||
};
|
||||
|
||||
// provides utility functions to not call original engine (less call-cost)
|
||||
class Engine : public Singleton <Engine> {
|
||||
class Game final : public Singleton <Game> {
|
||||
private:
|
||||
int m_drawModels[DRAW_NUM];
|
||||
int m_spawnCount[TEAM_UNASSIGNED];
|
||||
|
||||
// bot client command
|
||||
char m_arguments[256];
|
||||
bool m_isBotCommand;
|
||||
int m_argumentCount;
|
||||
StringArray m_botArgs;
|
||||
|
||||
edict_t *m_startEntity;
|
||||
edict_t *m_localEntity;
|
||||
|
|
@ -112,19 +149,27 @@ private:
|
|||
Array <VarPair> m_cvars;
|
||||
HashMap <String, String, LangComprarer> m_language;
|
||||
|
||||
Library m_gameLib;
|
||||
MessageBlock m_msgBlock;
|
||||
bool m_precached;
|
||||
|
||||
int m_gameFlags;
|
||||
int m_mapFlags;
|
||||
|
||||
float m_slowFrame; // per second updated frame
|
||||
public:
|
||||
Engine (void);
|
||||
~Engine (void);
|
||||
RefVector vec;
|
||||
|
||||
public:
|
||||
Game (void);
|
||||
~Game (void);
|
||||
|
||||
public:
|
||||
// precaches internal stuff
|
||||
void precache (void);
|
||||
|
||||
// initialize levels
|
||||
void levelInitialize (void);
|
||||
void levelInitialize (edict_t *ents, int max);
|
||||
|
||||
// prints data to servers console
|
||||
void print (const char *fmt, ...);
|
||||
|
|
@ -135,6 +180,9 @@ public:
|
|||
// prints center message to all players
|
||||
void centerPrint (const char *fmt, ...);
|
||||
|
||||
// prints center message to specified player
|
||||
void centerPrint (edict_t *ent, const char *fmt, ...);
|
||||
|
||||
// prints message to client console
|
||||
void clientPrint (edict_t *ent, const char *fmt, ...);
|
||||
|
||||
|
|
@ -189,122 +237,170 @@ public:
|
|||
// checks whether softwared rendering is enabled
|
||||
bool isSoftwareRenderer (void);
|
||||
|
||||
// load the cs binary in non metamod mode
|
||||
bool loadCSBinary (void);
|
||||
|
||||
// do post-load stuff
|
||||
bool postload (void);
|
||||
|
||||
// detects if csdm mod is in use
|
||||
void detectDeathmatch (void);
|
||||
|
||||
// executes stuff every 1 second
|
||||
void slowFrame (void);
|
||||
|
||||
// begin message handler
|
||||
void beginMessage (edict_t *ent, int dest, int type);
|
||||
|
||||
// public inlines
|
||||
public:
|
||||
// get the current time on server
|
||||
inline float timebase (void) {
|
||||
return g_pGlobals->time;
|
||||
float timebase (void) const {
|
||||
return globals->time;
|
||||
}
|
||||
|
||||
// get "maxplayers" limit on server
|
||||
inline int maxClients (void) {
|
||||
return g_pGlobals->maxClients;
|
||||
int maxClients (void) const {
|
||||
return globals->maxClients;
|
||||
}
|
||||
|
||||
// get the fakeclient command interface
|
||||
inline bool isBotCmd (void) {
|
||||
bool isBotCmd (void) const {
|
||||
return m_isBotCommand;
|
||||
}
|
||||
|
||||
// gets custom engine args for client command
|
||||
inline const char *botArgs (void) {
|
||||
if (strncmp ("say ", m_arguments, 4) == 0) {
|
||||
return &m_arguments[4];
|
||||
}
|
||||
else if (strncmp ("say_team ", m_arguments, 9) == 0) {
|
||||
return &m_arguments[9];
|
||||
}
|
||||
return m_arguments;
|
||||
const char *botArgs (void) const {
|
||||
static String args;
|
||||
args = String::join (m_botArgs, " ", m_botArgs[0] == "say" || m_botArgs[0] == "say_team" ? 1 : 0);
|
||||
|
||||
return args.chars ();
|
||||
}
|
||||
|
||||
// gets custom engine argv for client command
|
||||
inline const char *botArgv (int num) {
|
||||
return getField (m_arguments, static_cast <size_t> (num));
|
||||
const char *botArgv (size_t index) const {
|
||||
if (index >= m_botArgs.length ()) {
|
||||
return "";
|
||||
}
|
||||
return m_botArgs[index].chars ();
|
||||
}
|
||||
|
||||
// gets custom engine argc for client command
|
||||
inline int botArgc (void) {
|
||||
return m_argumentCount;
|
||||
int botArgc (void) const {
|
||||
return m_botArgs.length ();
|
||||
}
|
||||
|
||||
// gets edict pointer out of entity index
|
||||
inline edict_t *entityOfIndex (const int index) {
|
||||
edict_t *entityOfIndex (const int index) {
|
||||
return static_cast <edict_t *> (m_startEntity + index);
|
||||
};
|
||||
|
||||
// gets edict index out of it's pointer
|
||||
inline int indexOfEntity (const edict_t *ent) {
|
||||
int indexOfEntity (const edict_t *ent) {
|
||||
return static_cast <int> (ent - m_startEntity);
|
||||
};
|
||||
|
||||
// verify entity isn't null
|
||||
inline bool isNullEntity (const edict_t *ent) {
|
||||
bool isNullEntity (const edict_t *ent) {
|
||||
return !ent || !indexOfEntity (ent) || ent->free;
|
||||
}
|
||||
|
||||
// get the wroldspawn entity
|
||||
inline edict_t *getStartEntity (void) {
|
||||
edict_t *getStartEntity (void) {
|
||||
return m_startEntity;
|
||||
}
|
||||
|
||||
// get spawn count for team
|
||||
inline int getSpawnCount (int team) {
|
||||
int getSpawnCount (int team) const {
|
||||
return m_spawnCount[team];
|
||||
}
|
||||
|
||||
// gets the player team
|
||||
inline int getTeam (edict_t *ent) {
|
||||
extern Client g_clients[MAX_ENGINE_PLAYERS];
|
||||
return g_clients[indexOfEntity (ent) - 1].team;
|
||||
}
|
||||
int getTeam (edict_t *ent);
|
||||
|
||||
// adds translation pair from config
|
||||
inline void addTranslation (const String &original, const String &translated) {
|
||||
void addTranslation (const String &original, const String &translated) {
|
||||
m_language.put (original, translated);
|
||||
}
|
||||
|
||||
// resets the message capture mechanism
|
||||
inline void resetMessages (void) {
|
||||
void resetMessages (void) {
|
||||
m_msgBlock.msg = NETMSG_UNDEFINED;
|
||||
m_msgBlock.state = 0;
|
||||
m_msgBlock.bot = 0;
|
||||
};
|
||||
|
||||
// sets the currently executed message
|
||||
inline void setCurrentMessageId (int message) {
|
||||
void setCurrentMessageId (int message) {
|
||||
m_msgBlock.msg = message;
|
||||
}
|
||||
|
||||
// set the bot entity that receive this message
|
||||
inline void setCurrentMessageOwner (int id) {
|
||||
void setCurrentMessageOwner (int id) {
|
||||
m_msgBlock.bot = id;
|
||||
}
|
||||
|
||||
// find registered message id
|
||||
inline int getMessageId (int type) {
|
||||
int getMessageId (int type) {
|
||||
return m_msgBlock.regMsgs[type];
|
||||
}
|
||||
|
||||
// assigns message id for message type
|
||||
inline void setMessageId (int type, int id) {
|
||||
void setMessageId (int type, int id) {
|
||||
m_msgBlock.regMsgs[type] = id;
|
||||
}
|
||||
|
||||
// tries to set needed message id
|
||||
inline void captureMessage (int type, int msgId) {
|
||||
void captureMessage (int type, int msgId) {
|
||||
if (type == m_msgBlock.regMsgs[msgId]) {
|
||||
setCurrentMessageId (msgId);
|
||||
}
|
||||
}
|
||||
|
||||
// sets the precache to uninitialize
|
||||
inline void setUnprecached (void) {
|
||||
void setUnprecached (void) {
|
||||
m_precached = false;
|
||||
}
|
||||
|
||||
// static utility functions
|
||||
private:
|
||||
const char *getField (const char *string, size_t id);
|
||||
// gets the local entity (host edict)
|
||||
edict_t *getLocalEntity (void) {
|
||||
return m_localEntity;
|
||||
}
|
||||
|
||||
// sets the local entity (host edict)
|
||||
void setLocalEntity (edict_t *ent) {
|
||||
m_localEntity = ent;
|
||||
}
|
||||
|
||||
// builds referential vector
|
||||
void makeVectors (const Vector &in) {
|
||||
in.makeVectors (&vec.forward, &vec.right, &vec.up);
|
||||
}
|
||||
|
||||
// what kind of map we're running ?
|
||||
bool isMap (const int map) const {
|
||||
return (m_mapFlags & map) == map;
|
||||
}
|
||||
|
||||
// what kind of game engine / game dll / mod / tool we're running ?
|
||||
bool is (const int type) const {
|
||||
return (m_gameFlags & type) == type;
|
||||
}
|
||||
|
||||
// adds game flag
|
||||
void addGameFlag (const int type) {
|
||||
m_gameFlags |= type;
|
||||
}
|
||||
|
||||
// gets the map type
|
||||
bool mapIs (const int type) const {
|
||||
return (m_mapFlags & type) == type;
|
||||
}
|
||||
|
||||
// get loaded gamelib
|
||||
Library &getLib (void) {
|
||||
return m_gameLib;
|
||||
}
|
||||
};
|
||||
|
||||
// simplify access for console variables
|
||||
|
|
@ -314,35 +410,35 @@ public:
|
|||
|
||||
public:
|
||||
ConVar (const char *name, const char *initval, VarType type = VT_NOSERVER, bool regMissing = false, const char *regVal = nullptr) : m_eptr (nullptr) {
|
||||
Engine::ref ().pushVarToRegStack (name, initval, type, regMissing, regVal, this);
|
||||
Game::ref ().pushVarToRegStack (name, initval, type, regMissing, regVal, this);
|
||||
}
|
||||
|
||||
inline bool boolean (void) const {
|
||||
bool boolean (void) const {
|
||||
return m_eptr->value > 0.0f;
|
||||
}
|
||||
|
||||
inline int integer (void) const {
|
||||
int integer (void) const {
|
||||
return static_cast <int> (m_eptr->value);
|
||||
}
|
||||
|
||||
inline float flt (void) const {
|
||||
float flt (void) const {
|
||||
return m_eptr->value;
|
||||
}
|
||||
|
||||
inline const char *str (void) const {
|
||||
const char *str (void) const {
|
||||
return m_eptr->string;
|
||||
}
|
||||
|
||||
inline void set (float val) const {
|
||||
g_engfuncs.pfnCVarSetFloat (m_eptr->name, val);
|
||||
void set (float val) {
|
||||
engfuncs.pfnCVarSetFloat (m_eptr->name, val);
|
||||
}
|
||||
|
||||
inline void set (int val) const {
|
||||
void set (int val) {
|
||||
set (static_cast <float> (val));
|
||||
}
|
||||
|
||||
inline void set (const char *val) const {
|
||||
g_engfuncs.pfnCvar_DirectSet (m_eptr, const_cast <char *> (val));
|
||||
void set (const char *val) {
|
||||
engfuncs.pfnCvar_DirectSet (m_eptr, const_cast <char *> (val));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -366,36 +462,36 @@ public:
|
|||
|
||||
public:
|
||||
MessageWriter &start (int dest, int type, const Vector &pos = Vector::null (), edict_t *to = nullptr) {
|
||||
g_engfuncs.pfnMessageBegin (dest, type, pos, to);
|
||||
engfuncs.pfnMessageBegin (dest, type, pos, to);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void end (void) {
|
||||
g_engfuncs.pfnMessageEnd ();
|
||||
engfuncs.pfnMessageEnd ();
|
||||
}
|
||||
|
||||
MessageWriter &writeByte (int val) {
|
||||
g_engfuncs.pfnWriteByte (val);
|
||||
engfuncs.pfnWriteByte (val);
|
||||
return *this;
|
||||
}
|
||||
|
||||
MessageWriter &writeChar (int val) {
|
||||
g_engfuncs.pfnWriteChar (val);
|
||||
engfuncs.pfnWriteChar (val);
|
||||
return *this;
|
||||
}
|
||||
|
||||
MessageWriter &writeShort (int val) {
|
||||
g_engfuncs.pfnWriteShort (val);
|
||||
engfuncs.pfnWriteShort (val);
|
||||
return *this;
|
||||
}
|
||||
|
||||
MessageWriter &writeCoord (float val) {
|
||||
g_engfuncs.pfnWriteCoord (val);
|
||||
engfuncs.pfnWriteCoord (val);
|
||||
return *this;
|
||||
}
|
||||
|
||||
MessageWriter &writeString (const char *val) {
|
||||
g_engfuncs.pfnWriteString (val);
|
||||
engfuncs.pfnWriteString (val);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -409,26 +505,25 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
class LightMeasure final : public Singleton <LightMeasure> {
|
||||
private:
|
||||
lightstyle_t m_lightstyle[MAX_LIGHTSTYLES];
|
||||
int m_lightstyleValue[MAX_LIGHTSTYLEVALUE];
|
||||
bool m_doAnimation;
|
||||
bool m_doAnimation = false;
|
||||
|
||||
SimpleColor m_point;
|
||||
model_t *m_worldModel;
|
||||
model_t *m_worldModel = nullptr;
|
||||
|
||||
public:
|
||||
LightMeasure (void) : m_doAnimation (false), m_worldModel (nullptr) {
|
||||
LightMeasure (void) {
|
||||
initializeLightstyles ();
|
||||
|
||||
m_point.reset ();
|
||||
}
|
||||
|
||||
public:
|
||||
void initializeLightstyles (void);
|
||||
void animateLight (void);
|
||||
void updateLight (int style, char *value);
|
||||
|
||||
float getLightLevel (const Vector &point);
|
||||
float getSkyColor (void);
|
||||
|
|
@ -437,18 +532,18 @@ private:
|
|||
template <typename S, typename M> bool recursiveLightPoint (const M *node, const Vector &start, const Vector &end);
|
||||
|
||||
public:
|
||||
inline void resetWorldModel (void) {
|
||||
void resetWorldModel (void) {
|
||||
m_worldModel = nullptr;
|
||||
}
|
||||
|
||||
inline void setWorldModel (model_t *model) {
|
||||
void setWorldModel (model_t *model) {
|
||||
if (m_worldModel) {
|
||||
return;
|
||||
}
|
||||
m_worldModel = model;
|
||||
}
|
||||
|
||||
inline void enableAnimation (bool enable) {
|
||||
void enableAnimation (bool enable) {
|
||||
m_doAnimation = enable;
|
||||
}
|
||||
};
|
||||
|
|
@ -112,7 +112,6 @@ typedef struct {
|
|||
|
||||
extern gamedll_funcs_t *gpGamedllFuncs;
|
||||
extern mutil_funcs_t *gpMetaUtilFuncs;
|
||||
extern meta_globals_t *gpMetaGlobals;
|
||||
extern metamod_funcs_t gMetaFunctionTable;
|
||||
|
||||
#define MDLL_FUNC gpGamedllFuncs->dllapi_table
|
||||
|
|
|
|||
|
|
@ -16,23 +16,24 @@
|
|||
#ifndef SDKUTIL_H
|
||||
#define SDKUTIL_H
|
||||
|
||||
extern globalvars_t *g_pGlobals;
|
||||
extern enginefuncs_t g_engfuncs;
|
||||
extern globalvars_t *globals;
|
||||
extern enginefuncs_t engfuncs;
|
||||
extern gamefuncs_t dllapi;
|
||||
|
||||
// Use this instead of ALLOC_STRING on constant strings
|
||||
#define STRING(offset) (const char *)(g_pGlobals->pStringBase + (int)offset)
|
||||
#define STRING(offset) (const char *)(globals->pStringBase + (int)offset)
|
||||
|
||||
// form fwgs-hlsdk
|
||||
static inline int MAKE_STRING (const char *val) {
|
||||
long long ptrdiff = val - STRING (0);
|
||||
|
||||
if (ptrdiff > INT_MAX || ptrdiff < INT_MIN) {
|
||||
return g_engfuncs.pfnAllocString (val);
|
||||
return engfuncs.pfnAllocString (val);
|
||||
}
|
||||
return static_cast <int> (ptrdiff);
|
||||
}
|
||||
|
||||
#define ENGINE_STR(str) (const_cast <char *> (STRING (g_engfuncs.pfnAllocString (str))))
|
||||
#define ENGINE_STR(str) (const_cast <char *> (STRING (engfuncs.pfnAllocString (str))))
|
||||
|
||||
// Dot products for view cone checking
|
||||
#define VIEW_FIELD_FULL (float)-1.0 // +-180 degrees
|
||||
|
|
|
|||
|
|
@ -1,73 +0,0 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) YaPB Development Team.
|
||||
//
|
||||
// This software is licensed under the BSD-style license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
|
||||
// https://yapb.ru/license
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
extern bool g_canSayBombPlanted;
|
||||
extern bool g_bombPlanted;
|
||||
extern bool g_bombSayString;
|
||||
extern bool g_roundEnded;
|
||||
extern bool g_waypointOn;
|
||||
extern bool g_autoWaypoint;
|
||||
extern bool g_botsCanPause;
|
||||
extern bool g_editNoclip;
|
||||
extern bool g_gameWelcomeSent;
|
||||
|
||||
extern float g_autoPathDistance;
|
||||
extern float g_timeBombPlanted;
|
||||
extern float g_timeNextBombUpdate;
|
||||
extern float g_lastChatTime;
|
||||
extern float g_timeRoundEnd;
|
||||
extern float g_timeRoundMid;
|
||||
extern float g_timeRoundStart;
|
||||
extern float g_timePerSecondUpdate;
|
||||
extern float g_lastRadioTime[MAX_TEAM_COUNT];
|
||||
|
||||
extern int g_mapFlags;
|
||||
extern int g_gameFlags;
|
||||
|
||||
extern int g_highestDamageCT;
|
||||
extern int g_highestDamageT;
|
||||
extern int g_highestKills;
|
||||
|
||||
extern int g_normalWeaponPrefs[NUM_WEAPONS];
|
||||
extern int g_rusherWeaponPrefs[NUM_WEAPONS];
|
||||
extern int g_carefulWeaponPrefs[NUM_WEAPONS];
|
||||
extern int g_grenadeBuyPrecent[NUM_WEAPONS - 23];
|
||||
extern int g_botBuyEconomyTable[NUM_WEAPONS - 15];
|
||||
extern int g_radioSelect[MAX_ENGINE_PLAYERS];
|
||||
extern int g_lastRadio[MAX_TEAM_COUNT];
|
||||
extern int g_storeAddbotVars[4];
|
||||
extern int *g_weaponPrefs[];
|
||||
|
||||
extern Array <StringArray> g_chatFactory;
|
||||
extern Array <Array <ChatterItem>> g_chatterFactory;
|
||||
extern Array <BotName> g_botNames;
|
||||
extern Array <KeywordFactory> g_replyFactory;
|
||||
|
||||
extern WeaponSelect g_weaponSelect[NUM_WEAPONS + 1];
|
||||
extern WeaponProperty g_weaponDefs[MAX_WEAPONS + 1];
|
||||
|
||||
extern Client g_clients[MAX_ENGINE_PLAYERS];
|
||||
extern MenuText g_menus[BOT_MENU_TOTAL_MENUS];
|
||||
extern Task g_taskFilters[TASK_MAX];
|
||||
|
||||
extern Experience *g_experienceData;
|
||||
|
||||
extern edict_t *g_hostEntity;
|
||||
extern Library g_gameLib;
|
||||
|
||||
extern gamefuncs_t g_functionTable;
|
||||
|
||||
static inline bool isEmptyStr (const char *input) {
|
||||
if (input == nullptr) {
|
||||
return true;
|
||||
}
|
||||
return *input == '\0';
|
||||
}
|
||||
|
|
@ -87,7 +87,10 @@
|
|||
// @todo: sse should be working ok on x86 android?
|
||||
#if defined(__ANDROID__)
|
||||
#define PLATFORM_ANDROID
|
||||
#undef PLATFORM_HAS_SSE2
|
||||
|
||||
#if defined (__arm__) || defined (__aarch64__ )
|
||||
#undef PLATFORM_HAS_SSE2
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
#error "Platform unrecognized."
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
// general product information
|
||||
#define PRODUCT_NAME "Yet Another POD-Bot"
|
||||
#define PRODUCT_SHORT_NAME "YaPB"
|
||||
#define PRODUCT_VERSION "2.10"
|
||||
#define PRODUCT_VERSION "2.91"
|
||||
#define PRODUCT_AUTHOR "YaPB Dev Team"
|
||||
#define PRODUCT_URL "https://yapb.ru/"
|
||||
#define PRODUCT_EMAIL "d@entix.io"
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
#define PRODUCT_GIT_HASH "unspecified_hash"
|
||||
#define PRODUCT_GIT_COMMIT_AUTHOR "unspecified_author"
|
||||
#define PRODUCT_GIT_COMMIT_ID 0000
|
||||
#define PRODUCT_VERSION_DWORD_INTERNAL 2, 10
|
||||
#define PRODUCT_VERSION_DWORD_INTERNAL 2, 91
|
||||
#define PRODUCT_VERSION_DWORD PRODUCT_VERSION_DWORD_INTERNAL, PRODUCT_GIT_COMMIT_ID
|
||||
#define PRODUCT_SUPPORT_VERSION "Beta 6.6 - Condition Zero"
|
||||
#define PRODUCT_COMMENTS "http://github.com/jeefo/yapb/"
|
||||
|
|
|
|||
1809
include/yapb.h
1809
include/yapb.h
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue