mirror of
https://gitea.sffempire.ru/Kolyah35/minecraft-pe-0.6.1.git
synced 2026-03-20 06:53:30 +00:00
the whole game
This commit is contained in:
17
src/util/CollectionUtils.h
Executable file
17
src/util/CollectionUtils.h
Executable file
@@ -0,0 +1,17 @@
|
||||
#ifndef COLLECTIONUTILS_H__
|
||||
#define COLLECTIONUTILS_H__
|
||||
|
||||
struct PairKeyFunctor {
|
||||
template <typename T>
|
||||
typename T::first_type operator()(T& pair) const {
|
||||
return pair.first;
|
||||
}
|
||||
};
|
||||
struct PairValueFunctor {
|
||||
template <typename T>
|
||||
typename T::second_type operator()(T& pair) const {
|
||||
return pair.second;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /*COLLECTIONUTILS_H__*/
|
||||
29
src/util/DataIO.cpp
Executable file
29
src/util/DataIO.cpp
Executable file
@@ -0,0 +1,29 @@
|
||||
#include "DataIO.h"
|
||||
|
||||
//
|
||||
// BytesDataOutput
|
||||
//
|
||||
|
||||
void BytesDataOutput::writeString( const std::string& v )
|
||||
{
|
||||
int length = v.length() & 0x7fff;
|
||||
writeShort(length);
|
||||
writeBytes(v.c_str(), length);
|
||||
//LOGI("Writing: %d bytes as String: %s\n", v.length(), v.c_str());
|
||||
}
|
||||
|
||||
//
|
||||
// BytesDataInput
|
||||
//
|
||||
std::string BytesDataInput::readString() {
|
||||
int len = readShort();
|
||||
if (len > MAX_STRING_LENGTH - 1)
|
||||
len = MAX_STRING_LENGTH - 1;
|
||||
char* buffer = new char[len + 1];
|
||||
readBytes(buffer, len);
|
||||
buffer[len] = 0;
|
||||
|
||||
std::string out(buffer);
|
||||
delete[] buffer;
|
||||
return out;
|
||||
}
|
||||
320
src/util/DataIO.h
Executable file
320
src/util/DataIO.h
Executable file
@@ -0,0 +1,320 @@
|
||||
#ifndef DATAIO_H__
|
||||
#define DATAIO_H__
|
||||
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <climits>
|
||||
|
||||
#include "../platform/log.h"
|
||||
|
||||
// Interface for writing primitives to a stream
|
||||
class IDataOutput {
|
||||
public:
|
||||
virtual ~IDataOutput() {}
|
||||
|
||||
// Write a "Pascal" string [Len(Short)][Characters, len={strlen()-1,s.length()}]
|
||||
//virtual void writePStr(const char* v, int len = -1) = 0;
|
||||
//virtual void writeCStr(const char* v, int len = -1) = 0;
|
||||
virtual void writeString(const std::string& v) = 0;
|
||||
virtual void writeFloat(float v) = 0;
|
||||
virtual void writeDouble(double v) = 0;
|
||||
|
||||
virtual void writeByte(char v) = 0;
|
||||
virtual void writeShort(short v) = 0;
|
||||
virtual void writeInt(int v) = 0;
|
||||
virtual void writeLongLong(long long v) = 0;
|
||||
|
||||
virtual void writeBytes(const void* data, int bytes) = 0;
|
||||
};
|
||||
|
||||
|
||||
// Interface for reading primitives from a stream
|
||||
class IDataInput {
|
||||
public:
|
||||
virtual ~IDataInput() {}
|
||||
|
||||
virtual std::string readString() = 0;
|
||||
//virtual void readPStr(char**) = 0;
|
||||
//virtual void readCStr(char** s, int len = -1) = 0;
|
||||
virtual float readFloat() = 0;
|
||||
virtual double readDouble() = 0;
|
||||
|
||||
virtual char readByte() = 0;
|
||||
virtual short readShort() = 0;
|
||||
virtual int readInt() = 0;
|
||||
virtual long long readLongLong() = 0;
|
||||
|
||||
virtual void readBytes(void* data, int bytes) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Redirects all calls to writeBytes
|
||||
*/
|
||||
class BytesDataOutput: public IDataOutput {
|
||||
public:
|
||||
//virtual void writePStr(const char* v, int len = -1);
|
||||
//virtual void writeCStr(const char* v, int len = -1);
|
||||
virtual void writeString(const std::string& v);
|
||||
virtual void writeFloat(float v) {
|
||||
writeBytes(&v, 4);
|
||||
}
|
||||
virtual void writeDouble(double v) {
|
||||
writeBytes(&v, 8);
|
||||
}
|
||||
virtual void writeByte(char v) {
|
||||
writeBytes(&v, 1);
|
||||
}
|
||||
virtual void writeShort(short v) {
|
||||
writeBytes(&v, 2);
|
||||
}
|
||||
virtual void writeInt(int v) {
|
||||
writeBytes(&v, 4);
|
||||
}
|
||||
virtual void writeLongLong(long long v) {
|
||||
writeBytes(&v, 8);
|
||||
}
|
||||
virtual void writeBytes(const void* data, int bytes) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Redirects all calls to readBytes
|
||||
*/
|
||||
class BytesDataInput: public IDataInput {
|
||||
public:
|
||||
//virtual void readPStr(char** s);
|
||||
//virtual void readCStr(char* s, int len = -1);
|
||||
virtual std::string readString();
|
||||
virtual float readFloat() {
|
||||
float o;
|
||||
readBytes(&o, 4);
|
||||
return o;
|
||||
}
|
||||
virtual double readDouble() {
|
||||
double o;
|
||||
readBytes(&o, 8);
|
||||
return o;
|
||||
}
|
||||
virtual char readByte() {
|
||||
char o;
|
||||
readBytes(&o, 1);
|
||||
return o;
|
||||
}
|
||||
virtual short readShort() {
|
||||
short o;
|
||||
readBytes(&o, 2);
|
||||
return o;
|
||||
}
|
||||
virtual int readInt() {
|
||||
int o;
|
||||
readBytes(&o, 4);
|
||||
return o;
|
||||
}
|
||||
virtual long long readLongLong() {
|
||||
long long o;
|
||||
readBytes(&o, 8);
|
||||
return o;
|
||||
}
|
||||
virtual void readBytes(void* data, int bytes) = 0;
|
||||
|
||||
private:
|
||||
static const int MAX_STRING_LENGTH = SHRT_MAX;
|
||||
static char _charBuffer[MAX_STRING_LENGTH];
|
||||
};
|
||||
|
||||
//class MemoryDataInput: public BytesDataInput {
|
||||
//public:
|
||||
// MemoryDataInput(const char* data, int size)
|
||||
// : _buffer(data),
|
||||
// _size(size),
|
||||
// _index(0)
|
||||
// {}
|
||||
// MemoryDataInput(const unsigned char* data, int size)
|
||||
// : _buffer((const char*)data),
|
||||
// _size(size),
|
||||
// _index(0)
|
||||
// {}
|
||||
//
|
||||
// void readBytes(void* data, int bytes) {
|
||||
// if (bytes <= 0) {
|
||||
// if (bytes < 0) LOGE("Error: %d bytes NOT read @ MemoryDataInput::readBytes!\n", bytes);
|
||||
// return;
|
||||
// }
|
||||
// int left = _size - _index;
|
||||
// if (bytes > left) {
|
||||
// LOGE("ERROR: Not enough bytes left in buffer @ MemoryDataInput::readBytes (%d/%d).\n", bytes, left);
|
||||
// _index = _size;
|
||||
// return;
|
||||
// }
|
||||
// memcpy((char*)data, &_buffer[_index], bytes);
|
||||
// _index += bytes;
|
||||
// }
|
||||
//
|
||||
//private:
|
||||
// int _index;
|
||||
// int _size;
|
||||
// const char* _buffer;
|
||||
//};
|
||||
//
|
||||
//
|
||||
//class MemoryDataOutput: public BytesDataOutput {
|
||||
//public:
|
||||
// MemoryDataOutput(char* data, int size)
|
||||
// : _buffer(data),
|
||||
// _size(size),
|
||||
// _index(0)
|
||||
// {}
|
||||
// MemoryDataOutput(unsigned char* data, int size)
|
||||
// : _buffer((char*)data),
|
||||
// _size(size),
|
||||
// _index(0)
|
||||
// {}
|
||||
//
|
||||
// void writeBytes(const void* data, int bytes) {
|
||||
// if (bytes <= 0) {
|
||||
// LOGW("Warning: %d bytes read @ MemoryDataOutput::writeBytes!\n", bytes);
|
||||
// return;
|
||||
// }
|
||||
// int left = _size - _index;
|
||||
// if (bytes > left) {
|
||||
// LOGE("ERROR: Not enough bytes left in buffer @ MemoryDataOutput::writeBytes (%d/%d).\n", bytes, left);
|
||||
// _index = _size;
|
||||
// return;
|
||||
// }
|
||||
// memcpy(&_buffer[_index], (const char*)data, bytes);
|
||||
// _index += bytes;
|
||||
// }
|
||||
//
|
||||
//private:
|
||||
// int _index;
|
||||
// int _size;
|
||||
// char* _buffer;
|
||||
//};
|
||||
|
||||
|
||||
class PrintStream {
|
||||
public:
|
||||
void print(const std::string& s) {
|
||||
}
|
||||
void println(const std::string& s) {
|
||||
print(s); print("\n");
|
||||
}
|
||||
};
|
||||
|
||||
class FileError {
|
||||
public:
|
||||
static const int NOT_OPENED = 1;
|
||||
static const int NOT_FULLY_HANDLED = 2;
|
||||
};
|
||||
//
|
||||
//class FileIO {
|
||||
//public:
|
||||
// FileIO(const std::string& filePath, const char* mode)
|
||||
// : _filePath(filePath),
|
||||
// _opened(false),
|
||||
// _errCode(0),
|
||||
// _fp(0),
|
||||
// _doClose(true)
|
||||
// {
|
||||
// if (mode)
|
||||
// openWithMode(mode);
|
||||
// }
|
||||
// FileIO(FILE* fp)
|
||||
// : _filePath("<fp>"),
|
||||
// _opened(fp != NULL),
|
||||
// _errCode(0),
|
||||
// _fp(fp),
|
||||
// _doClose(false)
|
||||
// {}
|
||||
//
|
||||
// ~FileIO() {
|
||||
// if (_doClose)
|
||||
// close();
|
||||
// }
|
||||
//
|
||||
// bool isValid() {
|
||||
// return _opened;
|
||||
// }
|
||||
//
|
||||
// int getError() {
|
||||
// int err = _errCode;
|
||||
// _errCode = 0;
|
||||
// return err;
|
||||
// }
|
||||
//
|
||||
// bool close() {
|
||||
// if (!_fp)
|
||||
// return false;
|
||||
//
|
||||
// fclose(_fp);
|
||||
// _fp = NULL;
|
||||
// _opened = false;
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
//protected:
|
||||
// void openWithMode(const char* mode) {
|
||||
// if (_fp) return;
|
||||
// _fp = fopen(_filePath.c_str(), mode);
|
||||
// _opened = (_fp != NULL);
|
||||
// }
|
||||
//
|
||||
// std::string _filePath;
|
||||
// int _errCode;
|
||||
// bool _opened;
|
||||
// bool _doClose;
|
||||
//
|
||||
// FILE* _fp;
|
||||
//};
|
||||
//
|
||||
//class FileDataOutput: public BytesDataOutput, public FileIO
|
||||
//{
|
||||
//public:
|
||||
// FileDataOutput(const std::string& filePath)
|
||||
// : FileIO(filePath, "wb"),
|
||||
// bytesWritten(0)
|
||||
// {
|
||||
// }
|
||||
// FileDataOutput(FILE* fp)
|
||||
// : FileIO(fp),
|
||||
// bytesWritten(0)
|
||||
// {}
|
||||
//
|
||||
// virtual void writeBytes(const void* data, int bytes) {
|
||||
// if (!_fp) {
|
||||
// _errCode |= FileError::NOT_OPENED;
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// int bytesWritten = fwrite(data, 1, bytes, _fp);
|
||||
// if (bytesWritten != bytes)
|
||||
// _errCode |= FileError::NOT_FULLY_HANDLED;
|
||||
//
|
||||
// this->bytesWritten += bytesWritten;
|
||||
// }
|
||||
//
|
||||
// int bytesWritten;
|
||||
//};
|
||||
//
|
||||
//class FileDataInput: public BytesDataInput, public FileIO
|
||||
//{
|
||||
//public:
|
||||
// FileDataInput(const std::string& filePath)
|
||||
// : FileIO(filePath, "rb")
|
||||
// {
|
||||
// }
|
||||
// FileDataInput(FILE* fp)
|
||||
// : FileIO(fp)
|
||||
// {}
|
||||
//
|
||||
// virtual void readBytes(void* data, int bytes) {
|
||||
// if (!_fp) {
|
||||
// _errCode |= FileError::NOT_OPENED;
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// if (fread(data, 1, bytes, _fp) != bytes)
|
||||
// _errCode |= FileError::NOT_FULLY_HANDLED;
|
||||
// }
|
||||
//};
|
||||
|
||||
#endif /*DATAIO_H__*/
|
||||
226
src/util/IntHashMap.h
Executable file
226
src/util/IntHashMap.h
Executable file
@@ -0,0 +1,226 @@
|
||||
#ifndef UTIL__IntHashMap_H__
|
||||
#define UTIL__IntHashMap_H__
|
||||
|
||||
template <class V>
|
||||
class IntHashMap
|
||||
{
|
||||
static const int DEFAULT_INITIAL_CAPACITY = 16;
|
||||
static const int MAXIMUM_CAPACITY = 1 << 30;
|
||||
//static const float DEFAULT_LOAD_FACTOR = 0.75f;
|
||||
|
||||
Entry<V>** table;
|
||||
int tableCapacity;
|
||||
int size;
|
||||
|
||||
int threshold;
|
||||
const float loadFactor;
|
||||
|
||||
volatile int modCount;
|
||||
|
||||
public:
|
||||
IntHashMap()
|
||||
: loadFactor(0.75f)
|
||||
{
|
||||
threshold = (int) (DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
|
||||
table = new Entry[DEFAULT_INITIAL_CAPACITY];
|
||||
}
|
||||
|
||||
~IntHashMap() {
|
||||
delete[] table;
|
||||
}
|
||||
|
||||
/*public*/ int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
/*public*/ bool isEmpty() {
|
||||
return size == 0;
|
||||
}
|
||||
|
||||
/*public*/ V get(int key) {
|
||||
int hash = hash(key);
|
||||
for (Entry<V> e = table[indexFor(hash, table.length)]; e != NULL; e = e.next) {
|
||||
if (e.key == key) return e.value;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*public*/ bool containsKey(int key) {
|
||||
return getEntry(key) != NULL;
|
||||
}
|
||||
|
||||
const Entry<V> getEntry(int key) {
|
||||
int hash = hash(key);
|
||||
for (Entry<V> e = table[indexFor(hash, table.length)]; e != NULL; e = e.next) {
|
||||
if (e.key == key) return e;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*public*/ void put(int key, V value) {
|
||||
int hash = hash(key);
|
||||
int i = indexFor(hash, table.length);
|
||||
for (Entry<V> e = table[i]; e != NULL; e = e.next) {
|
||||
if (e.key == key) {
|
||||
e.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
modCount++;
|
||||
addEntry(hash, key, value, i);
|
||||
}
|
||||
|
||||
//@SuppressWarnings("unchecked")
|
||||
/*private*/ void resize(int newCapacity) {
|
||||
Entry<V>[] oldTable = table;
|
||||
int oldCapacity = oldTable.length;
|
||||
if (oldCapacity == MAXIMUM_CAPACITY) {
|
||||
threshold = INT_MAX;//Integer.MAX_VALUE;
|
||||
return;
|
||||
}
|
||||
|
||||
Entry<V>[] newTable = /*new*/ Entry[newCapacity];
|
||||
transfer(newTable);
|
||||
table = newTable;
|
||||
threshold = (int) (newCapacity * loadFactor);
|
||||
}
|
||||
|
||||
/*private*/ void transfer(Entry<V>[] newTable) {
|
||||
Entry<V>[] src = table;
|
||||
int newCapacity = newTable.length;
|
||||
for (int j = 0; j < src.length; j++) {
|
||||
Entry<V> e = src[j];
|
||||
if (e != NULL) {
|
||||
src[j] = NULL;
|
||||
do {
|
||||
Entry<V> next = e.next;
|
||||
int i = indexFor(e.hash, newCapacity);
|
||||
e.next = newTable[i];
|
||||
newTable[i] = e;
|
||||
e = next;
|
||||
} while (e != NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*public*/ V remove(int key) {
|
||||
Entry<V> e = removeEntryForKey(key);
|
||||
return (e == NULL ? NULL : e.value);
|
||||
}
|
||||
|
||||
const Entry<V> removeEntryForKey(int key) {
|
||||
int hash = hash(key);
|
||||
int i = indexFor(hash, table.length);
|
||||
Entry<V> prev = table[i];
|
||||
Entry<V> e = prev;
|
||||
|
||||
while (e != NULL) {
|
||||
Entry<V> next = e.next;
|
||||
if (e.key == key) {
|
||||
modCount++;
|
||||
size--;
|
||||
if (prev == e) table[i] = next;
|
||||
else prev.next = next;
|
||||
return e;
|
||||
}
|
||||
prev = e;
|
||||
e = next;
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
/*public*/ void clear() {
|
||||
modCount++;
|
||||
Entry<V>[] tab = table;
|
||||
for (int i = 0; i < tab.length; i++)
|
||||
tab[i] = NULL;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if this map maps one or more keys to the specified
|
||||
* value.
|
||||
*
|
||||
* @param value value whose presence in this map is to be tested
|
||||
* @return <tt>true</tt> if this map maps one or more keys to the specified
|
||||
* value
|
||||
*/
|
||||
/*public*/ bool containsValue(Object value) {
|
||||
if (value == NULL) return containsNullValue();
|
||||
|
||||
Entry<V>[] tab = table;
|
||||
for (int i = 0; i < tab.length; i++)
|
||||
for (Entry<V> e = tab[i]; e != NULL; e = e.next)
|
||||
if (value.equals(e.value)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*private*/ bool containsNullValue() {
|
||||
Entry<V>[] tab = table;
|
||||
for (int i = 0; i < tab.length; i++)
|
||||
for (Entry<V> e = tab[i]; e != NULL; e = e.next)
|
||||
if (e.value == NULL) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*private*/
|
||||
template <class V>
|
||||
class Entry<V> {
|
||||
const int key;
|
||||
V value;
|
||||
Entry<V>* next;
|
||||
const int hash;
|
||||
|
||||
/**
|
||||
* Creates new entry.
|
||||
*/
|
||||
Entry(int h, int k, V v, Entry<V>* n)
|
||||
: value(v),
|
||||
next(n),
|
||||
key(k),
|
||||
hash(h)
|
||||
{
|
||||
}
|
||||
|
||||
const int getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
const V getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
//@SuppressWarnings("unchecked")
|
||||
bool operator==(const Entry<V>& rhs) {
|
||||
return key == rhs.key && value == rhs.value;
|
||||
}
|
||||
|
||||
const int hashCode() {
|
||||
return hash(key);
|
||||
}
|
||||
|
||||
const std::string toString() {
|
||||
std::stringstream ss;
|
||||
ss << getKey() << "=" << getValue();
|
||||
return ss.str();
|
||||
}
|
||||
}
|
||||
private:
|
||||
static int hash(int h) {
|
||||
h ^= (h >>> 20) ^ (h >>> 12);
|
||||
return h ^ (h >>> 7) ^ (h >>> 4);
|
||||
}
|
||||
|
||||
static int indexFor(int h, int length) {
|
||||
return h & (length - 1);
|
||||
}
|
||||
|
||||
void addEntry(int hash, int key, V value, int bucketIndex) {
|
||||
Entry<V> e = table[bucketIndex];
|
||||
table[bucketIndex] = /*new*/ Entry<V>(hash, key, value, e);
|
||||
if (size++ >= threshold) resize(2 * table.length);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /*UTIL__IntHashMap_H__*/
|
||||
35
src/util/MemUtils.h
Executable file
35
src/util/MemUtils.h
Executable file
@@ -0,0 +1,35 @@
|
||||
#ifndef MEMUTILS_H__
|
||||
#define MEMUTILS_H__
|
||||
|
||||
template <class T>
|
||||
class Ref {
|
||||
public:
|
||||
//~Ref() { //@todo: add this if the pointer is created externally
|
||||
// dec();
|
||||
//}
|
||||
void inc() { ++_count; }
|
||||
void dec() { if (--_count == 0 && _obj) delete _obj; }
|
||||
|
||||
__inline short refCount() { return _count; }
|
||||
__inline bool isUnique() { return _count == 1; }
|
||||
|
||||
__inline T* obj() { return _obj; }
|
||||
|
||||
T& operator->() { return *_obj; }
|
||||
void operator++() { inc(); }
|
||||
void operator--() { dec(); }
|
||||
|
||||
static Ref* create(T* object) { return new Ref(object); }
|
||||
private:
|
||||
Ref(T* object)
|
||||
: _obj(object),
|
||||
_count(1) {}
|
||||
|
||||
Ref(const Ref& rhs);
|
||||
Ref& operator=(const Ref& rhs);
|
||||
|
||||
T* _obj;
|
||||
short _count;
|
||||
};
|
||||
|
||||
#endif /*MEMUTILS_H__*/
|
||||
134
src/util/Mth.cpp
Executable file
134
src/util/Mth.cpp
Executable file
@@ -0,0 +1,134 @@
|
||||
#include "Mth.h"
|
||||
#include "Random.h"
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
|
||||
#include "../Performance.h"
|
||||
|
||||
static Random _rand;
|
||||
|
||||
namespace Mth
|
||||
{
|
||||
const float PI = 3.1415926535897932384626433832795028841971f; // exactly!
|
||||
const float TWO_PI = 2.0f * PI; // exactly!
|
||||
const float DEGRAD = PI / 180.0f;
|
||||
const float RADDEG = 180.0f / PI;
|
||||
|
||||
static float _sin[65536];
|
||||
static const float _sinScale = 65536.0f / (2.0f * PI);
|
||||
|
||||
void initMth() {
|
||||
for (int i = 0; i < 65536; ++i)
|
||||
_sin[i] = ::sin(i / _sinScale);
|
||||
}
|
||||
|
||||
float sqrt(float x) {
|
||||
//Stopwatch& w = Performance::watches.get("sqrt");
|
||||
//w.start();
|
||||
float ret = ::sqrt(x);
|
||||
//w.stop();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __inline float fastInvSqrt(float x) {
|
||||
float xhalf = 0.5f*x;
|
||||
int i = *(int*)&x;
|
||||
i = 0x5f3759df - (i>>1);
|
||||
x = *(float*)&i;
|
||||
x = x*(1.5f - xhalf*x*x);
|
||||
return x;
|
||||
}
|
||||
float invSqrt(float x) {
|
||||
//Stopwatch& w = Performance::watches.get("invSqrt");
|
||||
//w.start();
|
||||
float ret = fastInvSqrt(x);//1.0f / sqrt(x);
|
||||
//w.stop();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int floor(float v) {
|
||||
int i = (int) v;
|
||||
return v < i ? i - 1 : i;
|
||||
}
|
||||
|
||||
float cos(float x) {
|
||||
//Performance::watches.get("cos").start();
|
||||
//float ret = ::cos(x);
|
||||
float ret = _sin[(int) (x * _sinScale + 65536 / 4) & 65535];
|
||||
//Performance::watches.get("cos").stop();
|
||||
return ret;
|
||||
}
|
||||
|
||||
float sin(float x) {
|
||||
//Performance::watches.get("sin").start();
|
||||
//float ret = ::sin(x);
|
||||
float ret = _sin[(int) (x * _sinScale) & 65535];
|
||||
//Performance::watches.get("sin").stop();
|
||||
return ret;
|
||||
}
|
||||
|
||||
float atan(float x) {
|
||||
//Performance::watches.get("atan").start();
|
||||
float ret = ::atan(x);
|
||||
//Performance::watches.get("atan").stop();
|
||||
return ret;
|
||||
}
|
||||
|
||||
float atan2(float dy, float dx) {
|
||||
//Performance::watches.get("atan2").start();
|
||||
float ret = ::atan2(dy, dx);
|
||||
//Performance::watches.get("atan2").stop();
|
||||
return ret;
|
||||
}
|
||||
|
||||
float random(){
|
||||
return _rand.nextFloat();
|
||||
}
|
||||
int random(int n){
|
||||
return _rand.nextInt(n);
|
||||
}
|
||||
|
||||
int intFloorDiv(int a, int b) {
|
||||
if (a < 0) return -((-a - 1) / b) - 1;
|
||||
return a / b;
|
||||
}
|
||||
|
||||
float abs(float a) { return a>=0? a : -a; }
|
||||
float Min(float a, float b) { return a<=b? a : b; }
|
||||
float Max(float a, float b) { return a>=b? a : b; }
|
||||
|
||||
int abs(int a) { return a>=0? a : -a; }
|
||||
int Min(int a, int b) { return a<=b? a : b; }
|
||||
int Max(int a, int b) { return a>=b? a : b; }
|
||||
|
||||
float absDecrease(float value, float with, float min) {
|
||||
if (value > 0) return Max(min, value - with);
|
||||
return Min(value + with, -min);
|
||||
}
|
||||
//float absIncrease(float value, float with, float max);
|
||||
|
||||
int clamp(int v, int low, int high) {
|
||||
if (v > high) return high;
|
||||
return v>low? v : low;
|
||||
}
|
||||
float clamp(float v, float low, float high) {
|
||||
if (v > high) return high;
|
||||
return v>low? v : low;
|
||||
}
|
||||
float lerp(float src, float dst, float alpha) {
|
||||
return src + (dst - src) * alpha;
|
||||
}
|
||||
int lerp(int src, int dst, float alpha) {
|
||||
return src + (int)((dst - src) * alpha);
|
||||
}
|
||||
|
||||
float absMax(float a, float b) {
|
||||
if (a < 0) a = -a;
|
||||
if (b < 0) b = -b;
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
float absMaxSigned(float a, float b) {
|
||||
return abs(a) > abs(b)? a : b;
|
||||
}
|
||||
};
|
||||
98
src/util/Mth.h
Executable file
98
src/util/Mth.h
Executable file
@@ -0,0 +1,98 @@
|
||||
#ifndef MTH_H__
|
||||
#define MTH_H__
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
|
||||
namespace Mth {
|
||||
|
||||
extern const float PI;
|
||||
extern const float TWO_PI;
|
||||
extern const float RADDEG;
|
||||
extern const float DEGRAD;
|
||||
|
||||
void initMth();
|
||||
|
||||
float sqrt(float x);
|
||||
float invSqrt(float x);
|
||||
|
||||
int floor(float x);
|
||||
|
||||
float sin(float x);
|
||||
float cos(float x);
|
||||
|
||||
float atan(float x);
|
||||
float atan2(float dy, float dx);
|
||||
|
||||
float random();
|
||||
int random(int n);
|
||||
|
||||
float abs(float a);
|
||||
float Min(float a, float b);
|
||||
float Max(float a, float b);
|
||||
int abs(int a);
|
||||
int Min(int a, int b);
|
||||
int Max(int a, int b);
|
||||
|
||||
int clamp(int v, int low, int high);
|
||||
float clamp(float v, float low, float high);
|
||||
float lerp(float src, float dst, float alpha);
|
||||
int lerp(int src, int dst, float alpha);
|
||||
|
||||
///@param value The original signed value
|
||||
///@param with The (possibly signed) value to "abs-decrease" <value> with
|
||||
///@param min The minimum value
|
||||
float absDecrease(float value, float with, float min);
|
||||
//float absIncrease(float value, float with, float max);
|
||||
|
||||
float absMax(float a, float b);
|
||||
float absMaxSigned(float a, float b);
|
||||
|
||||
int intFloorDiv(int a, int b);
|
||||
};
|
||||
|
||||
namespace Util
|
||||
{
|
||||
template <class T>
|
||||
int removeAll(std::vector<T>& superset, const std::vector<T>& toRemove) {
|
||||
int subSize = (int)toRemove.size();
|
||||
int removed = 0;
|
||||
|
||||
for (int i = 0; i < subSize; ++i) {
|
||||
T elem = toRemove[i];
|
||||
int size = (int)superset.size();
|
||||
for (int j = 0; j < size; ++j) {
|
||||
if (elem == superset[j]) {
|
||||
superset.erase( superset.begin() + j, superset.begin() + j + 1);
|
||||
++removed;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool remove(std::vector<T>& list, const T& instance) {
|
||||
typename std::vector<T>::iterator it = std::find(list.begin(), list.end(), instance);
|
||||
if (it == list.end())
|
||||
return false;
|
||||
|
||||
list.erase(it);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Could perhaps do a template<template ..>
|
||||
template <class T>
|
||||
bool remove(std::set<T>& list, const T& instance) {
|
||||
typename std::set<T>::iterator it = std::find(list.begin(), list.end(), instance);
|
||||
if (it == list.end())
|
||||
return false;
|
||||
|
||||
list.erase(it);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // MTH_H__
|
||||
227
src/util/PerfRenderer.cpp
Executable file
227
src/util/PerfRenderer.cpp
Executable file
@@ -0,0 +1,227 @@
|
||||
#include "PerfRenderer.h"
|
||||
#include "PerfTimer.h"
|
||||
|
||||
#include "Mth.h"
|
||||
#include "../client/gui/Font.h"
|
||||
#include "../client/renderer/gles.h"
|
||||
#include "../client/renderer/Tesselator.h"
|
||||
#include "../client/Minecraft.h"
|
||||
|
||||
PerfRenderer::PerfRenderer( Minecraft* mc, Font* font )
|
||||
: _mc(mc),
|
||||
_font(font),
|
||||
_debugPath("root"),
|
||||
frameTimePos(0),
|
||||
lastTimer(-1)
|
||||
{
|
||||
for (int i = 0; i < 512; ++i) {
|
||||
frameTimes.push_back(0);
|
||||
tickTimes.push_back(0);
|
||||
}
|
||||
}
|
||||
|
||||
void PerfRenderer::debugFpsMeterKeyPress( int key )
|
||||
{
|
||||
std::vector<PerfTimer::ResultField> list = PerfTimer::getLog(_debugPath);
|
||||
if (list.empty()) return;
|
||||
|
||||
PerfTimer::ResultField node = list[0];
|
||||
list.erase(list.begin());
|
||||
if (key == 0) {
|
||||
if (node.name.length() > 0) {
|
||||
int pos = _debugPath.rfind(".");
|
||||
if (pos != std::string::npos) _debugPath = _debugPath.substr(0, pos);
|
||||
}
|
||||
} else {
|
||||
key--;
|
||||
if (key < (int)list.size() && list[key].name != "unspecified") {
|
||||
if (_debugPath.length() > 0) _debugPath += ".";
|
||||
_debugPath += list[key].name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PerfRenderer::renderFpsMeter( float tickTime )
|
||||
{
|
||||
std::vector<PerfTimer::ResultField> list = PerfTimer::getLog(_debugPath);
|
||||
if (list.empty())
|
||||
return;
|
||||
|
||||
PerfTimer::ResultField node = list[0];
|
||||
list.erase(list.begin());
|
||||
|
||||
long usPer60Fps = 1000000l / 60;
|
||||
if (lastTimer == -1) {
|
||||
lastTimer = getTimeS();
|
||||
}
|
||||
float now = getTimeS();
|
||||
tickTimes[ frameTimePos ] = tickTime;
|
||||
frameTimes[frameTimePos ] = now - lastTimer;
|
||||
lastTimer = now;
|
||||
|
||||
if (++frameTimePos >= (int)frameTimes.size())
|
||||
frameTimePos = 0;
|
||||
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glEnable2(GL_COLOR_MATERIAL);
|
||||
glLoadIdentity2();
|
||||
glOrthof(0, (GLfloat)_mc->width, (GLfloat)_mc->height, 0, 1000, 3000);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity2();
|
||||
glTranslatef2(0, 0, -2000);
|
||||
|
||||
glLineWidth(1);
|
||||
glDisable2(GL_TEXTURE_2D);
|
||||
Tesselator& t = Tesselator::instance;
|
||||
|
||||
t.begin(GL_TRIANGLES);
|
||||
int hh1 = (int) (usPer60Fps / 200);
|
||||
float count = (float)frameTimes.size();
|
||||
t.color(0x20000000);
|
||||
t.vertex(0, (float)(_mc->height - hh1), 0);
|
||||
t.vertex(0, (float)_mc->height, 0);
|
||||
t.vertex(count, (float)_mc->height, 0);
|
||||
t.vertex(count, (float)(_mc->height - hh1), 0);
|
||||
|
||||
t.color(0x20200000);
|
||||
t.vertex(0, (float)(_mc->height - hh1 * 2), 0);
|
||||
t.vertex(0, (float)(_mc->height - hh1), 0);
|
||||
t.vertex(count, (float)(_mc->height - hh1), 0);
|
||||
t.vertex(count, (float)(_mc->height - hh1 * 2), 0);
|
||||
|
||||
t.draw();
|
||||
float totalTime = 0;
|
||||
for (unsigned int i = 0; i < frameTimes.size(); i++) {
|
||||
totalTime += frameTimes[i];
|
||||
}
|
||||
int hh = (int) (totalTime / 200 / frameTimes.size());
|
||||
t.begin();
|
||||
t.color(0x20400000);
|
||||
t.vertex(0, (float)(_mc->height - hh), 0);
|
||||
t.vertex(0, (float)_mc->height, 0);
|
||||
t.vertex(count, (float)_mc->height, 0);
|
||||
t.vertex(count, (float)(_mc->height - hh), 0);
|
||||
t.draw();
|
||||
|
||||
t.begin(GL_LINES);
|
||||
for (unsigned int i = 0; i < frameTimes.size(); i++) {
|
||||
int col = ((i - frameTimePos) & (frameTimes.size() - 1)) * 255 / frameTimes.size();
|
||||
int cc = col * col / 255;
|
||||
cc = cc * cc / 255;
|
||||
int cc2 = cc * cc / 255;
|
||||
cc2 = cc2 * cc2 / 255;
|
||||
if (frameTimes[i] > usPer60Fps) {
|
||||
t.color(0xff000000 + cc * 65536);
|
||||
} else {
|
||||
t.color(0xff000000 + cc * 256);
|
||||
}
|
||||
|
||||
float time = 10 * 1000 * frameTimes[i] / 200;
|
||||
float time2 = 10 * 1000 * tickTimes[i] / 200;
|
||||
|
||||
t.vertex(i + 0.5f, _mc->height - time + 0.5f, 0);
|
||||
t.vertex(i + 0.5f, _mc->height + 0.5f, 0);
|
||||
|
||||
// if (_mc->frameTimes[i]>nsPer60Fps) {
|
||||
t.color(0xff000000 + cc * 65536 + cc * 256 + cc * 1);
|
||||
// } else {
|
||||
// t.color(0xff808080 + cc/2 * 256);
|
||||
// }
|
||||
t.vertex(i + 0.5f, _mc->height - time + 0.5f, 0);
|
||||
t.vertex(i + 0.5f, _mc->height - (time - time2) + 0.5f, 0);
|
||||
}
|
||||
t.draw();
|
||||
//t.end();
|
||||
|
||||
int r = 160;
|
||||
int x = _mc->width - r - 10;
|
||||
int y = _mc->height - r * 2;
|
||||
glEnable(GL_BLEND);
|
||||
t.begin();
|
||||
t.color(0x000000, 200);
|
||||
t.vertex(x - r * 1.1f, y - r * 0.6f - 16, 0);
|
||||
t.vertex(x - r * 1.1f, y + r * 2.0f, 0);
|
||||
t.vertex(x + r * 1.1f, y + r * 2.0f, 0);
|
||||
t.vertex(x + r * 1.1f, y - r * 0.6f - 16, 0);
|
||||
t.draw();
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
float totalPercentage = 0;
|
||||
for (unsigned int i = 0; i < list.size(); i++) {
|
||||
PerfTimer::ResultField& result = list[i];
|
||||
|
||||
int steps = Mth::floor(result.percentage / 4) + 1;
|
||||
|
||||
t.begin(GL_TRIANGLE_FAN);
|
||||
t.color(result.getColor());
|
||||
t.vertex((float)x, (float)y, 0);
|
||||
for (int j = steps; j >= 0; j--) {
|
||||
float dir = (float) ((totalPercentage + (result.percentage * j / steps)) * Mth::PI * 2 / 100);
|
||||
float xx = Mth::sin(dir) * r;
|
||||
float yy = Mth::cos(dir) * r * 0.5f;
|
||||
t.vertex(x + xx, y - yy, 0);
|
||||
//LOGI("xy: %f, %f\n", x+xx, y - yy);
|
||||
}
|
||||
t.draw();
|
||||
t.begin(GL_TRIANGLE_STRIP);
|
||||
t.color((result.getColor() & 0xfefefe) >> 1);
|
||||
for (int j = steps; j >= 0; j--) {
|
||||
float dir = (float) ((totalPercentage + (result.percentage * j / steps)) * Mth::PI * 2 / 100);
|
||||
float xx = Mth::sin(dir) * r;
|
||||
float yy = Mth::cos(dir) * r * 0.5f;
|
||||
t.vertex(x + xx, y - yy, 0);
|
||||
t.vertex(x + xx, y - yy + 10, 0);
|
||||
}
|
||||
t.draw();
|
||||
|
||||
totalPercentage += result.percentage;
|
||||
}
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
{
|
||||
std::stringstream msg;
|
||||
if (node.name != "unspecified") {
|
||||
msg << "[0] ";
|
||||
}
|
||||
if (node.name.length() == 0) {
|
||||
msg << "ROOT ";
|
||||
} else {
|
||||
msg << node.name << " ";
|
||||
}
|
||||
int col = 0xffffff;
|
||||
_font->drawShadow(msg.str(), (float)(x - r), (float)(y - r / 2 - 16), col);
|
||||
std::string msg2 = toPercentString(node.globalPercentage);
|
||||
_font->drawShadow(msg2, (float)(x + r - _font->width(msg2)), (float)(y - r / 2 - 16), col);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < list.size(); i++) {
|
||||
PerfTimer::ResultField& result = list[i];
|
||||
std::stringstream msg;
|
||||
if (result.name != "unspecified") {
|
||||
msg << "[" << (i + 1) << "] ";
|
||||
} else {
|
||||
msg << "[?] ";
|
||||
}
|
||||
|
||||
msg << result.name;
|
||||
float xx = (float)(x - r);
|
||||
float yy = (float)(y + r/2 + i * 8 + 20);
|
||||
_font->drawShadow(msg.str(), xx, yy, result.getColor());
|
||||
std::string msg2 = toPercentString(result.percentage);
|
||||
//LOGI("name: %s: perc: %f == %s @ %d, %d\n", msg.str().c_str(), result.percentage, msg2.c_str(), xx, yy);
|
||||
_font->drawShadow(msg2, xx - 50 - _font->width(msg2), yy, result.getColor());
|
||||
msg2 = toPercentString(result.globalPercentage);
|
||||
_font->drawShadow(msg2, xx - _font->width(msg2), yy, result.getColor());
|
||||
}
|
||||
}
|
||||
|
||||
std::string PerfRenderer::toPercentString( float percentage )
|
||||
{
|
||||
char buf[32] = {0};
|
||||
sprintf(buf, "%3.2f%%", percentage);
|
||||
return buf;
|
||||
}
|
||||
34
src/util/PerfRenderer.h
Executable file
34
src/util/PerfRenderer.h
Executable file
@@ -0,0 +1,34 @@
|
||||
#ifndef NET_UTIL__PerfRenderer_H__
|
||||
#define NET_UTIL__PerfRenderer_H__
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
class Minecraft;
|
||||
class Font;
|
||||
|
||||
//package net.minecraft.client;
|
||||
class PerfRenderer
|
||||
{
|
||||
public:
|
||||
PerfRenderer( Minecraft* mc, Font* font);
|
||||
|
||||
void debugFpsMeterKeyPress(int key);
|
||||
|
||||
void renderFpsMeter(float tickTime);
|
||||
|
||||
private:
|
||||
std::string toPercentString(float percentage);
|
||||
|
||||
Minecraft* _mc;
|
||||
Font* _font;
|
||||
std::string _debugPath;
|
||||
|
||||
std::vector<float> frameTimes;
|
||||
std::vector<float> tickTimes;
|
||||
int frameTimePos;
|
||||
float lastTimer;
|
||||
};
|
||||
|
||||
#endif /*NET_UTIL__PerfRenderer_H__*/
|
||||
123
src/util/PerfTimer.cpp
Executable file
123
src/util/PerfTimer.cpp
Executable file
@@ -0,0 +1,123 @@
|
||||
#include "PerfTimer.h"
|
||||
#include "../platform/time.h"
|
||||
#include <algorithm>
|
||||
|
||||
/*static*/
|
||||
bool
|
||||
PerfTimer::enabled = false;
|
||||
|
||||
std::vector<std::string>
|
||||
PerfTimer::paths;
|
||||
|
||||
std::vector<float>
|
||||
PerfTimer::startTimes;
|
||||
|
||||
std::string
|
||||
PerfTimer::path;
|
||||
|
||||
PerfTimer::TimeMap
|
||||
PerfTimer::times;
|
||||
|
||||
|
||||
/*static*/
|
||||
void PerfTimer::reset()
|
||||
{
|
||||
times.clear();
|
||||
}
|
||||
|
||||
/*static*/
|
||||
void PerfTimer::push( const std::string& name )
|
||||
{
|
||||
if (!enabled) return;
|
||||
if (path.length() > 0) path += ".";
|
||||
path += name;
|
||||
paths.push_back(path);
|
||||
startTimes.push_back(getTimeS());
|
||||
}
|
||||
|
||||
/*static*/
|
||||
void PerfTimer::pop()
|
||||
{
|
||||
if (!enabled) return;
|
||||
float endTime = getTimeS();
|
||||
float startTime = startTimes.back();
|
||||
|
||||
paths.pop_back();
|
||||
startTimes.pop_back();
|
||||
|
||||
float time = endTime - startTime;
|
||||
|
||||
TimeMap::iterator it = times.find(path);
|
||||
if (it != times.end()) {
|
||||
it->second += time;
|
||||
} else {
|
||||
times.insert(std::make_pair(path, time));
|
||||
}
|
||||
|
||||
path = paths.size() > 0 ? paths.back() : "";
|
||||
|
||||
//if (paths.size() == 0) {
|
||||
// for (TimeMap::iterator it = times.begin(); it != times.end(); ++it) {
|
||||
// LOGI("p: %s t: %f\n", it->first.c_str(), it->second);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
/*static*/
|
||||
void PerfTimer::popPush( const std::string& name )
|
||||
{
|
||||
pop();
|
||||
push(name);
|
||||
}
|
||||
|
||||
/*static*/
|
||||
std::vector<PerfTimer::ResultField> PerfTimer::getLog(const std::string& rawPath) {
|
||||
if (!enabled) return std::vector<ResultField>();
|
||||
|
||||
std::string path = rawPath;
|
||||
|
||||
TimeMap::const_iterator itRoot = times.find("root");
|
||||
float globalTime = (itRoot != times.end())? itRoot->second : 0;
|
||||
|
||||
TimeMap::const_iterator itPath = times.find(path);
|
||||
float totalTime2 = (itRoot != times.end())? itRoot->second : -1;
|
||||
|
||||
std::vector<ResultField> result;
|
||||
|
||||
if (path.length() > 0) path += ".";
|
||||
float totalTime = 0;
|
||||
|
||||
for (TimeMap::const_iterator cit = times.begin(); cit != times.end(); ++cit) {
|
||||
const std::string& key = cit->first;
|
||||
const float& time = cit->second;
|
||||
if (key.length() > path.length() && Util::startsWith(key, path) && key.find(".", path.length() + 1) == std::string::npos) {
|
||||
totalTime += time;
|
||||
}
|
||||
}
|
||||
|
||||
float oldTime = totalTime;
|
||||
if (totalTime < totalTime2) totalTime = totalTime2;
|
||||
if (globalTime < totalTime) globalTime = totalTime;
|
||||
|
||||
for (TimeMap::const_iterator cit = times.begin(); cit != times.end(); ++cit) {
|
||||
const std::string& key = cit->first;
|
||||
//const float& time = cit->second;
|
||||
if (key.length() > path.length() && Util::startsWith(key, path) && key.find(".", path.length() + 1) == std::string::npos) {
|
||||
float time = times.find(key)->second;
|
||||
float timePercentage = time * 100.0f / totalTime;
|
||||
float globalPercentage = time * 100.0f / globalTime;
|
||||
std::string name = key.substr(path.length());
|
||||
result.push_back(ResultField(name, timePercentage, globalPercentage));
|
||||
}
|
||||
}
|
||||
|
||||
for (TimeMap::iterator it = times.begin(); it != times.end(); ++it)
|
||||
it->second *= 0.999f;
|
||||
|
||||
if (totalTime > oldTime)
|
||||
result.push_back(ResultField("unspecified", (totalTime - oldTime) * 100.0f / totalTime, (totalTime - oldTime) * 100.0f / globalTime));
|
||||
|
||||
std::sort(result.begin(), result.end());
|
||||
result.insert(result.begin(), ResultField(rawPath, 100, totalTime * 100.0f / globalTime));
|
||||
return result;
|
||||
}
|
||||
62
src/util/PerfTimer.h
Executable file
62
src/util/PerfTimer.h
Executable file
@@ -0,0 +1,62 @@
|
||||
#ifndef NET_UTIL__PerfTimer_H__
|
||||
#define NET_UTIL__PerfTimer_H__
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include "StringUtils.h"
|
||||
|
||||
//package util;
|
||||
#ifdef PROFILER
|
||||
#define TIMER_PUSH(x) PerfTimer::push(x)
|
||||
#define TIMER_POP() PerfTimer::pop()
|
||||
#define TIMER_POP_PUSH(x) PerfTimer::popPush(x)
|
||||
#else
|
||||
#define TIMER_PUSH(x) ((void*)0)
|
||||
#define TIMER_POP() ((void*)0)
|
||||
#define TIMER_POP_PUSH(x) ((void*)0)
|
||||
#endif
|
||||
|
||||
class PerfTimer
|
||||
{
|
||||
typedef std::map<std::string, float> TimeMap;
|
||||
public:
|
||||
class ResultField {
|
||||
public:
|
||||
float percentage;
|
||||
float globalPercentage;
|
||||
std::string name;
|
||||
|
||||
ResultField(const std::string& name, float percentage, float globalPercentage)
|
||||
: name(name),
|
||||
percentage(percentage),
|
||||
globalPercentage(globalPercentage)
|
||||
{}
|
||||
|
||||
bool operator<(const ResultField& rf) const {
|
||||
if (percentage != rf.percentage)
|
||||
return percentage > rf.percentage;
|
||||
return name > rf.name;
|
||||
}
|
||||
|
||||
int getColor() const {
|
||||
return (Util::hashCode(name) & 0xaaaaaa) + 0x444444;
|
||||
}
|
||||
};
|
||||
|
||||
static void reset();
|
||||
|
||||
static void push(const std::string& name);
|
||||
static void pop();
|
||||
static void popPush(const std::string& name);
|
||||
|
||||
static std::vector<ResultField> getLog(const std::string& path);
|
||||
|
||||
static bool enabled;
|
||||
private:
|
||||
static std::vector<std::string> paths;
|
||||
static std::vector<float> startTimes;
|
||||
static std::string path;
|
||||
static TimeMap times;
|
||||
};
|
||||
|
||||
#endif /*NET_UTIL__PerfTimer_H__*/
|
||||
49
src/util/RakDataIO.h
Executable file
49
src/util/RakDataIO.h
Executable file
@@ -0,0 +1,49 @@
|
||||
#ifndef RAKDATAIO_H__
|
||||
#define RAKDATAIO_H__
|
||||
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
#include "DataIO.h"
|
||||
|
||||
// Uses BitStream as a growing buffer
|
||||
class RakDataOutput: public BytesDataOutput {
|
||||
public:
|
||||
//RakDataOutput() {}
|
||||
RakDataOutput(RakNet::BitStream& bitstream)
|
||||
: _bitStream(bitstream)
|
||||
{}
|
||||
|
||||
virtual void writeBytes(const void* data, int bytes) {
|
||||
_bitStream.WriteBits((const unsigned char*)data, bytes * 8);
|
||||
}
|
||||
|
||||
RakNet::BitStream& getBitStream() {
|
||||
return _bitStream;
|
||||
}
|
||||
|
||||
private:
|
||||
RakNet::BitStream& _bitStream;
|
||||
};
|
||||
|
||||
|
||||
class RakDataInput: public BytesDataInput {
|
||||
public:
|
||||
//RakDataOutput() {}
|
||||
RakDataInput(RakNet::BitStream& bitstream)
|
||||
: _bitStream(bitstream)
|
||||
{}
|
||||
|
||||
virtual void readBytes(void* data, int bytes) {
|
||||
_bitStream.ReadBits((unsigned char*) data, bytes * 8);
|
||||
}
|
||||
|
||||
RakNet::BitStream& getBitStream() {
|
||||
return _bitStream;
|
||||
}
|
||||
|
||||
private:
|
||||
RakNet::BitStream& _bitStream;
|
||||
};
|
||||
|
||||
#endif /*RAKDATAIO_H__*/
|
||||
254
src/util/Random.h
Executable file
254
src/util/Random.h
Executable file
@@ -0,0 +1,254 @@
|
||||
#ifndef RANDOM_H__
|
||||
#define RANDOM_H__
|
||||
|
||||
/*
|
||||
A random generator class based on Mersenne-Twister.
|
||||
|
||||
"UPDATE"
|
||||
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/elicense.html
|
||||
---------------------------------------------------------------------
|
||||
|
||||
Commercial Use of Mersenne Twister
|
||||
2001/4/6
|
||||
|
||||
Until 2001/4/6, MT had been distributed under GNU Public License, but
|
||||
after 2001/4/6, we decided to let MT be used for any purpose, including
|
||||
commercial use. 2002-versions mt19937ar.c, mt19937ar-cok.c are considered
|
||||
to be usable freely.
|
||||
|
||||
*/
|
||||
|
||||
#include "../platform/time.h"
|
||||
#include <cmath>
|
||||
|
||||
class Random
|
||||
{
|
||||
public:
|
||||
Random() {
|
||||
setSeed( getTimeMs() );
|
||||
}
|
||||
Random( long seed ) {
|
||||
setSeed( seed );
|
||||
}
|
||||
|
||||
void setSeed( long seed ) {
|
||||
_seed = seed;
|
||||
_mti = N + 1;
|
||||
haveNextNextGaussian = false;
|
||||
nextNextGaussian = 0;
|
||||
init_genrand(seed);
|
||||
}
|
||||
long getSeed() {
|
||||
return _seed;
|
||||
}
|
||||
bool nextBoolean() {
|
||||
return (genrand_int32() & 0x8000000) > 0;
|
||||
}
|
||||
float nextFloat() {
|
||||
return (float)genrand_real2();
|
||||
}
|
||||
double nextDouble() {
|
||||
return genrand_real2();
|
||||
}
|
||||
int nextInt() {
|
||||
return (int)(genrand_int32()>>1);
|
||||
}
|
||||
int nextInt(int n) {
|
||||
return genrand_int32() % n;
|
||||
}
|
||||
int /* long long */ nextLong() {
|
||||
return (int)(genrand_int32()>>1);
|
||||
}
|
||||
int /* long long */ nextLong(int /*long long*/ n) {
|
||||
return genrand_int32() % n;
|
||||
}
|
||||
|
||||
float nextGaussian()
|
||||
{
|
||||
if (haveNextNextGaussian) {
|
||||
haveNextNextGaussian = false;
|
||||
return nextNextGaussian;
|
||||
} else {
|
||||
float v1, v2, s;
|
||||
do {
|
||||
v1 = 2 * nextFloat() - 1; // between -1.0 and 1.0
|
||||
v2 = 2 * nextFloat() - 1; // between -1.0 and 1.0
|
||||
s = v1 * v1 + v2 * v2;
|
||||
} while (s >= 1 || s == 0);
|
||||
float multiplier = std::sqrt(-2 * std::log(s)/s);
|
||||
nextNextGaussian = v2 * multiplier;
|
||||
haveNextNextGaussian = true;
|
||||
return v1 * multiplier;
|
||||
}
|
||||
}
|
||||
private:
|
||||
long _seed;
|
||||
|
||||
/* Period parameters */
|
||||
static const int N = 624;
|
||||
static const int M = 397;
|
||||
static const unsigned int MATRIX_A = 0x9908b0dfUL; /* constant vector a */
|
||||
static const unsigned int UPPER_MASK = 0x80000000UL; /* most significant w-r bits */
|
||||
static const unsigned int LOWER_MASK = 0x7fffffffUL; /* least significant r bits */
|
||||
|
||||
unsigned long _mt[N]; /* the array for the state vector */
|
||||
int _mti; /* _mti==N+1 means _mt[N] is not initialized */
|
||||
|
||||
bool haveNextNextGaussian;
|
||||
float nextNextGaussian;
|
||||
|
||||
/* initializes _mt[N] with a seed */
|
||||
void init_genrand(unsigned long s)
|
||||
{
|
||||
_mt[0] = s & 0xffffffffUL;
|
||||
for (_mti=1; _mti < N; _mti++) {
|
||||
_mt[_mti] =
|
||||
(1812433253UL * (_mt[_mti-1] ^ (_mt[_mti-1] >> 30)) + _mti);
|
||||
/* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
|
||||
/* In the previous versions, MSBs of the seed affect */
|
||||
/* only MSBs of the array _mt[]. */
|
||||
/* 2002/01/09 modified by Makoto Matsumoto */
|
||||
_mt[_mti] &= 0xffffffffUL;
|
||||
/* for >32 bit machines */
|
||||
}
|
||||
}
|
||||
|
||||
/* initialize by an array with array-length */
|
||||
/* init_key is the array for initializing keys */
|
||||
/* key_length is its length */
|
||||
/* slight change for C++, 2004/2/26 */
|
||||
void init_by_array(unsigned long init_key[], int key_length)
|
||||
{
|
||||
int i, j, k;
|
||||
init_genrand(19650218UL);
|
||||
i=1; j=0;
|
||||
k = (N>key_length ? N : key_length);
|
||||
for (; k; k--) {
|
||||
_mt[i] = (_mt[i] ^ ((_mt[i-1] ^ (_mt[i-1] >> 30)) * 1664525UL))
|
||||
+ init_key[j] + j; /* non linear */
|
||||
_mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
|
||||
i++; j++;
|
||||
if (i>=N) { _mt[0] = _mt[N-1]; i=1; }
|
||||
if (j>=key_length) j=0;
|
||||
}
|
||||
for (k=N-1; k; k--) {
|
||||
_mt[i] = (_mt[i] ^ ((_mt[i-1] ^ (_mt[i-1] >> 30)) * 1566083941UL))
|
||||
- i; /* non linear */
|
||||
_mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
|
||||
i++;
|
||||
if (i>=N) { _mt[0] = _mt[N-1]; i=1; }
|
||||
}
|
||||
|
||||
_mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */
|
||||
}
|
||||
|
||||
/* generates a random number on [0,0xffffffff]-interval */
|
||||
unsigned long genrand_int32(void)
|
||||
{
|
||||
unsigned long y;
|
||||
static unsigned long mag01[2]={0x0UL, MATRIX_A};
|
||||
/* mag01[x] = x * MATRIX_A for x=0,1 */
|
||||
|
||||
if (_mti >= N) { /* generate N words at one time */
|
||||
//static Stopwatch sw;
|
||||
//sw.start();
|
||||
int kk;
|
||||
|
||||
if (_mti == N+1) /* if init_genrand() has not been called, */
|
||||
init_genrand(5489UL); /* a default initial seed is used */
|
||||
|
||||
for (kk=0;kk<N-M;kk++) {
|
||||
y = (_mt[kk]&UPPER_MASK)|(_mt[kk+1]&LOWER_MASK);
|
||||
_mt[kk] = _mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL];
|
||||
}
|
||||
for (;kk<N-1;kk++) {
|
||||
y = (_mt[kk]&UPPER_MASK)|(_mt[kk+1]&LOWER_MASK);
|
||||
_mt[kk] = _mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
|
||||
}
|
||||
y = (_mt[N-1]&UPPER_MASK)|(_mt[0]&LOWER_MASK);
|
||||
_mt[N-1] = _mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];
|
||||
|
||||
_mti = 0;
|
||||
//sw.stop();
|
||||
//sw.printEvery(100, "genrand:");
|
||||
}
|
||||
|
||||
y = _mt[_mti++];
|
||||
|
||||
/* Tempering */
|
||||
y ^= (y >> 11);
|
||||
y ^= (y << 7) & 0x9d2c5680UL;
|
||||
y ^= (y << 15) & 0xefc60000UL;
|
||||
y ^= (y >> 18);
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
/* generates a random number on [0,0x7fffffff]-interval */
|
||||
long genrand_int31(void)
|
||||
{
|
||||
return (long)(genrand_int32()>>1);
|
||||
}
|
||||
|
||||
/* generates a random number on [0,1]-real-interval */
|
||||
double genrand_real1(void)
|
||||
{
|
||||
return genrand_int32()*(1.0/4294967295.0);
|
||||
/* divided by 2^32-1 */
|
||||
}
|
||||
|
||||
/* generates a random number on [0,1)-real-interval */
|
||||
double genrand_real2(void)
|
||||
{
|
||||
return genrand_int32()*(1.0/4294967296.0);
|
||||
/* divided by 2^32 */
|
||||
}
|
||||
|
||||
/* generates a random number on (0,1)-real-interval */
|
||||
double genrand_real3(void)
|
||||
{
|
||||
return (((double)genrand_int32()) + 0.5)*(1.0/4294967296.0);
|
||||
/* divided by 2^32 */
|
||||
}
|
||||
|
||||
/* generates a random number on [0,1) with 53-bit resolution*/
|
||||
double genrand_res53(void)
|
||||
{
|
||||
unsigned long a=genrand_int32()>>5, b=genrand_int32()>>6;
|
||||
return(a*67108864.0+b)*(1.0/9007199254740992.0);
|
||||
}
|
||||
/* These real versions are due to Isaku Wada, 2002/01/09 added */
|
||||
|
||||
//
|
||||
// Added helper (and quicker) functions
|
||||
//
|
||||
void rrDiff(float &x) {
|
||||
unsigned long u = genrand_int32();
|
||||
const float xx0 = ( u & 0xffff) / 65536.0f; // 2 x 16 bits
|
||||
const float xx1 = ((u >> 16) & 0xffff) / 65536.0f;
|
||||
x = xx0 - xx1;
|
||||
}
|
||||
void rrDiff(float& x, float& y) {
|
||||
unsigned long u = genrand_int32();
|
||||
const float xx0 = ((u ) & 0xff) / 256.0f; // 4 x 8 bits
|
||||
const float xx1 = ((u >> 8) & 0xff) / 256.0f;
|
||||
const float yy0 = ((u >> 16)& 0xff) / 256.0f;
|
||||
const float yy1 = ((u >> 24)& 0xff) / 256.0f;
|
||||
x = xx0 - xx1;
|
||||
y = yy0 - yy1;
|
||||
}
|
||||
void rrDiff(float& x, float& y, float& z) {
|
||||
unsigned long u = genrand_int32();
|
||||
const float xx0 = ((u ) & 0x1f) / 32.0f; // 6 x 5 bits
|
||||
const float xx1 = ((u >> 5) & 0x1f) / 32.0f;
|
||||
const float yy0 = ((u >> 10)& 0x1f) / 32.0f;
|
||||
const float yy1 = ((u >> 15)& 0x1f) / 32.0f;
|
||||
const float zz0 = ((u >> 20)& 0x1f) / 32.0f;
|
||||
const float zz1 = ((u >> 25)& 0x1f) / 32.0f;
|
||||
x = xx0 - xx1;
|
||||
y = yy0 - yy1;
|
||||
z = zz0 - zz1;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /*RANDOM_H__*/
|
||||
37
src/util/SmoothFloat.h
Executable file
37
src/util/SmoothFloat.h
Executable file
@@ -0,0 +1,37 @@
|
||||
#ifndef UTIL__SmoothFloat_H__
|
||||
#define UTIL__SmoothFloat_H__
|
||||
|
||||
//package util;
|
||||
|
||||
class SmoothFloat
|
||||
{
|
||||
float targetValue;
|
||||
float remainingValue;
|
||||
float lastAmount;
|
||||
|
||||
public:
|
||||
SmoothFloat()
|
||||
: targetValue(0),
|
||||
remainingValue(0),
|
||||
lastAmount(0)
|
||||
{}
|
||||
|
||||
float getNewDeltaValue(float deltaValue, float accelerationAmount) {
|
||||
targetValue += deltaValue;
|
||||
|
||||
deltaValue = (targetValue - remainingValue) * accelerationAmount;
|
||||
lastAmount = lastAmount + (deltaValue - lastAmount) * .5f;
|
||||
if ((deltaValue > 0 && deltaValue > lastAmount) || (deltaValue < 0 && deltaValue < lastAmount)) {
|
||||
deltaValue = lastAmount;
|
||||
}
|
||||
remainingValue += deltaValue;
|
||||
|
||||
return deltaValue;
|
||||
}
|
||||
|
||||
float getTargetValue() {
|
||||
return targetValue;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /*UTIL__SmoothFloat_H__*/
|
||||
73
src/util/StringUtils.cpp
Executable file
73
src/util/StringUtils.cpp
Executable file
@@ -0,0 +1,73 @@
|
||||
#include "StringUtils.h"
|
||||
#include <algorithm>
|
||||
#include "../platform/log.h"
|
||||
|
||||
namespace Util
|
||||
{
|
||||
|
||||
/// @return true if <s> starts with <start>, false if not
|
||||
bool startsWith(const std::string& s, const std::string& start) {
|
||||
const unsigned int len = start.length();
|
||||
return len <= s.length()
|
||||
&& s.substr(0, len) == start;
|
||||
}
|
||||
|
||||
// Naive (e.g. slow and stupid) implementation. @todo: fix
|
||||
/// @return A reference to s
|
||||
std::string& stringReplace(std::string& s, const std::string& src, const std::string& dst, int maxCount /*= -1*/) {
|
||||
int srcLength = src.length();
|
||||
|
||||
while(maxCount--) {
|
||||
std::string::size_type pos = s.find(src);
|
||||
if (pos == std::string::npos)
|
||||
break;
|
||||
s.replace(pos, srcLength, dst);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/// @return A string trimmed from white space characters on both ends
|
||||
std::string stringTrim(const std::string& s) {
|
||||
return stringTrim(s, " \t\n\r", true, true);
|
||||
}
|
||||
|
||||
/// @return A string trimmed from given characters on any end
|
||||
std::string stringTrim(const std::string& s, const std::string& chars, bool left, bool right) {
|
||||
const int len = s.length();
|
||||
const int lenChars = chars.length();
|
||||
|
||||
if (len == 0 || lenChars == 0 || ((left || right) == false))
|
||||
return "";
|
||||
|
||||
int i = 0, j = len-1;
|
||||
|
||||
if (left) {
|
||||
for (; i < len; ++i)
|
||||
if (std::find(chars.begin(), chars.end(), s[i]) == chars.end())
|
||||
break;
|
||||
}
|
||||
if (right) {
|
||||
for (; j >= i; --j)
|
||||
if (std::find(chars.begin(), chars.end(), s[j]) == chars.end())
|
||||
break;
|
||||
}
|
||||
return s.substr(i, j - i + 1);
|
||||
}
|
||||
|
||||
/// @return The "Java" implementation for string hash codes
|
||||
int hashCode(const std::string& s) {
|
||||
const int len = s.length();
|
||||
|
||||
int hash = 0;
|
||||
for (int i = 0; i < len; i++) {
|
||||
hash = ((hash << 5) - hash) + s[i];
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
void removeAll(std::string& s, const char** rep, int repCount) {
|
||||
for (int i = 0; i < repCount; ++i)
|
||||
stringReplace(s, rep[i], "");
|
||||
}
|
||||
|
||||
}; // end namespace Util
|
||||
27
src/util/StringUtils.h
Executable file
27
src/util/StringUtils.h
Executable file
@@ -0,0 +1,27 @@
|
||||
#ifndef STRINGUTILS_H__
|
||||
#define STRINGUTILS_H__
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Util {
|
||||
|
||||
/// @return true if <s> starts with <start>, false if not
|
||||
bool startsWith(const std::string& s, const std::string& start);
|
||||
|
||||
/// @return A reference to s
|
||||
std::string& stringReplace(std::string& s, const std::string& src, const std::string& dst, int maxCount = -1);
|
||||
|
||||
/// @return A string trimmed from white space characters on both ends
|
||||
std::string stringTrim(const std::string& S);
|
||||
|
||||
/// @return A string trimmed from given characters on any end
|
||||
std::string stringTrim(const std::string& S, const std::string& chars, bool left = true, bool right = true);
|
||||
|
||||
void removeAll(std::string& s, const char** rep, int repCount);
|
||||
|
||||
/// @return The "Java" implementation for string hash codes
|
||||
int hashCode(const std::string& s);
|
||||
|
||||
}; // end namespace Util
|
||||
|
||||
#endif /*STRINGUTILS_H__*/
|
||||
103
src/util/WeighedRandom.h
Executable file
103
src/util/WeighedRandom.h
Executable file
@@ -0,0 +1,103 @@
|
||||
#ifndef UTIL__WeighedRandom_H__
|
||||
#define UTIL__WeighedRandom_H__
|
||||
|
||||
//package util;
|
||||
|
||||
#include "Random.h"
|
||||
|
||||
class WeighedRandom
|
||||
{
|
||||
public:
|
||||
class WeighedRandomItem {
|
||||
public:
|
||||
int randomWeight;
|
||||
|
||||
WeighedRandomItem()
|
||||
: randomWeight(-128)
|
||||
{}
|
||||
|
||||
WeighedRandomItem(int randomWeight)
|
||||
: randomWeight(randomWeight)
|
||||
{}
|
||||
|
||||
bool isValid() {
|
||||
return randomWeight >= 0;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
static int getTotalWeight(const T& items) {
|
||||
int totalWeight = 0;
|
||||
|
||||
for (typename T::const_iterator it = items.begin(); it != items.end(); ++it)
|
||||
totalWeight += it->randomWeight;
|
||||
|
||||
return totalWeight;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static const WeighedRandomItem* getRandomItem(Random* random, const T& items, int totalWeight) {
|
||||
int selection = random->nextInt(totalWeight);
|
||||
for (typename T::const_iterator it = items.begin(); it != items.end(); ++it) {
|
||||
selection -= it->randomWeight;
|
||||
if (selection < 0) {
|
||||
return &(*it);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
template<typename T>
|
||||
static const WeighedRandomItem* getRandomItem(Random* random, const T& items) {
|
||||
return getRandomItem(random, items, getTotalWeight(items));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static int getRandomItemIndex(Random* random, const T& items, int totalWeight) {
|
||||
int selection = random->nextInt(totalWeight);
|
||||
for (unsigned int i = 0; i < items.size(); ++i) {
|
||||
selection -= items[i].randomWeight;
|
||||
if (selection < 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
template<typename T>
|
||||
static int getRandomItemIndex(Random* random, const T& items) {
|
||||
return getRandomItemIndex(random, items, getTotalWeight(items));
|
||||
}
|
||||
|
||||
// static int getTotalWeight(WeighedRandomItem items) {
|
||||
// int totalWeight = 0;
|
||||
//
|
||||
// for (unsigned int i = 0; i < items.size(); ++i) {
|
||||
// WeighedRandomItem& item = items[i];
|
||||
// totalWeight += item.randomWeight;
|
||||
// }
|
||||
// return totalWeight;
|
||||
// }
|
||||
|
||||
// static WeighedRandomItem getRandomItem(Random* random, WeighedRandomItem[] items, int totalWeight) {
|
||||
//
|
||||
// if (totalWeight <= 0) {
|
||||
// throw /*new*/ IllegalArgumentException();
|
||||
// }
|
||||
//
|
||||
// int selection = random->nextInt(totalWeight);
|
||||
// for (unsigned int i = 0; i < items.size(); ++i) {
|
||||
// WeighedRandomItem& item = items[i];
|
||||
// //for (WeighedRandomItem item : items) {
|
||||
// selection -= item.randomWeight;
|
||||
// if (selection < 0) {
|
||||
// return item;
|
||||
// }
|
||||
// }
|
||||
// return NULL;
|
||||
// }
|
||||
|
||||
// static WeighedRandomItem getRandomItem(Random* random, WeighedRandomItem[] items) {
|
||||
// return getRandomItem(random, items, getTotalWeight(items));
|
||||
// }
|
||||
};
|
||||
|
||||
#endif /*UTIL__WeighedRandom_H__*/
|
||||
Reference in New Issue
Block a user