This commit is contained in:
watrabi
2025-10-28 14:05:46 -04:00
parent 977f1ff4b8
commit c93494f795
452 changed files with 47860 additions and 152 deletions
+25
View File
@@ -0,0 +1,25 @@
/* Copyright 2003-2005 ROBLOX Corporation, All Rights Reserved */
#pragma once
//#include "Util/SoundWorld.h"
#include <string>
namespace RBX {
class Action
{
public:
enum ActionType { NO_ACTION = 0,
PAUSE_ACTION,
LOSE_ACTION,
DRAW_ACTION,
WIN_ACTION,
NUM_ACTION_TYPES };
private:
Action();
};
} // namespace RBX
+203
View File
@@ -0,0 +1,203 @@
#pragma once
#include <string>
#include <sstream>
#include <rapidjson/document.h>
#include <boost/unordered_set.hpp>
#include <boost/algorithm/string/replace.hpp>
#include "FastLog.h"
#include "RbxFormat.h"
DYNAMIC_FASTFLAG(InfluxDb09Enabled)
namespace RBX {
namespace Analytics {
void setUserId(int id);
void setPlaceId(int id);
void setAppVersion(const std::string& version);
void setLocation(const std::string& loc);
void setReporter(const std::string& rep);
namespace EphemeralCounter
{
void reportStats(const std::string& category, float value, bool blocking = false);
void reportCountersCSV(const std::string& counterNamesCSV, bool blocking = false);
void reportCounter(const std::string& counterName, int amount, bool blocking = false);
}
namespace GoogleAnalytics
{
// Allow for easy initialization based on a lottery number.
// Calls setCanUseAnalytics and init.
void lotteryInit(const std::string &accountPropertyID, int lotteryThreshold, const std::string& productName = "", int robloxAnalyticsLottery = -1, const std::string &sessionKey = "sessionID=");
// Must be called before using the singleton.
void init(const std::string &accountPropertyID, const std::string& productName = "");
bool getCanUse();
void setCanUse();
void sendEventRoblox(const char* category, const char* action = "custom", const char* label = "none", int value = 0, bool sync = false);
void trackEvent(const char *category, const char *action = "custom", const char *label = "none", int value = 0, bool sync = false);
void trackEventWithoutThrottling(const char *category, const char *action = "custom", const char *label = "none", int value = 0, bool sync = false);
void trackUserTiming(const char *category, const char *variable, int milliseconds, const char *label = "none", bool sync = false);
const std::string& getSessionId();
} // namespace GoogleAnalytics
namespace InfluxDb {
struct Point
{
std::string name;
std::string json;
Point(const std::string& name_, const rapidjson::Value& value) : name(name_)
{
using namespace rapidjson;
switch (value.GetType())
{
case kNullType:
json = "null";
break;
case kFalseType:
json = "false";
break;
case kTrueType:
json = "true";
break;
case kObjectType:
case kArrayType:
throw std::runtime_error("Arrays and objects are not valid value types.");
break;
case kStringType:
if (DFFlag::InfluxDb09Enabled)
{
// we must escape double quotes
std::string sval = value.GetString();
boost::replace_all(sval, "\"", "\\\"");
json = std::string("\"") + sval + "\"";
}
else
{
json = std::string("\"") + value.GetString() + "\"";
}
break;
case kNumberType:
{
const rapidjson::Value& v = value;
std::stringstream ss;
if (v.IsDouble())
{
ss << v.GetDouble();
}
else if (v.IsInt())
{
ss << v.GetInt();
if (DFFlag::InfluxDb09Enabled)
{
ss << 'i'; // signals integer type
}
}
else if (v.IsInt64())
{
ss << v.GetInt64();
if (DFFlag::InfluxDb09Enabled)
{
ss << 'i'; // signals integer type
}
}
else if (v.IsUint())
{
ss << v.GetUint();
if (DFFlag::InfluxDb09Enabled)
{
ss << 'i'; // signals integer type
}
}
else if (v.IsUint64())
{
ss << v.GetUint64();
if (DFFlag::InfluxDb09Enabled)
{
ss << 'i'; // signals integer type
}
}
else
{
throw std::runtime_error("Unknown number type.");
}
ss >> json;
}
break;
default:
throw std::runtime_error("Unknown rapidjson value type.");
break;
}
}
bool operator==(const Point& other) const {
return this->name == other.name;
}
};
std::size_t hash_value(const Point& p);
void init();
void reportPoints(const std::string& resource, const boost::unordered_set<Point>& points, int throttleHundredthsPercentage, bool blocking = false, const std::string& userIdOverride = "");
void reportPointsV2(const std::string& resource, const boost::unordered_set<Point>& points, int throttleHundredthsPercentage, bool blocking = false, const std::string& userIdOverride = "");
class Points
{
boost::unordered_set<Point> pointList;
std::string userIdOverride;
public:
Points() {}
~Points() {}
void setUserIdOverride(const int id)
{
userIdOverride = RBX::format("%d", id);
}
void addPoint(const std::string& name, const rapidjson::Value& value, bool override = false)
{
Point newPoint = Point(name, value);
std::pair<boost::unordered_set<Point>::iterator, bool> res = pointList.insert(newPoint);
if (override && !res.second)
{
pointList.erase(res.first);
pointList.insert(newPoint);
}
}
void report(const std::string& resource, int throttleHundredthsPercentage, bool blocking = false)
{
if (!pointList.empty())
{
if (DFFlag::InfluxDb09Enabled)
reportPointsV2(resource, pointList, throttleHundredthsPercentage, blocking, userIdOverride);
else
reportPoints(resource, pointList, throttleHundredthsPercentage, blocking, userIdOverride);
pointList.clear();
}
}
const boost::unordered_set<Point>& getPoints() { return pointList; }
};
} // namespace InfluxDb
} // namespace Analytics
} // namespace RBX
+22
View File
@@ -0,0 +1,22 @@
#pragma once
#include "Util/ContentId.h"
namespace RBX {
class AnimationId : public ContentId
{
public:
AnimationId(const ContentId& id):ContentId(id) {}
AnimationId(const char* id):ContentId(id) {}
AnimationId(const std::string& id):ContentId(id) {}
AnimationId() {}
bool isActive() const { return toString().substr(0, 9)=="active://"; }
static AnimationId nullAnimation() {
static AnimationId t; // note - the name in the contentId will get a boost call_once
return t;
}
};
}
+127
View File
@@ -0,0 +1,127 @@
#pragma once
#include "FastLog.h"
#include "Util/AsyncHttpQueue.h"
#include "rbx/make_shared.h"
namespace RBX
{
template<typename CachedContent, bool Log=false>
class AsyncHttpCache
:public AsyncHttpQueue
{
public:
AsyncHttpCache(Instance* owner, boost::function<bool(const std::string&, std::string*)> getLocalFile, int threadCount, int cacheSize)
:AsyncHttpQueue(owner, getLocalFile, threadCount)
,contentCache(cacheSize)
{}
shared_ptr<const Reflection::ValueArray> getRequestedUrls()
{
shared_ptr<Reflection::ValueArray> result(rbx::make_shared<Reflection::ValueArray>());
{
{
boost::mutex::scoped_lock lock(contentCacheMutex);
for (typename ContentCache::List_Iter iter = contentCache.begin(); iter != contentCache.end(); ++iter)
{
ContentId id(iter->first);
if (id.isHttp())
result->push_back(id.toString());
}
}
{
boost::recursive_mutex::scoped_lock lock(requestSync);
std::list< FailedUrl >::const_iterator end = failedUrls.end();
for (std::list< FailedUrl >::const_iterator iter = failedUrls.begin(); iter!=end; ++iter)
{
result->push_back(iter->url);
}
}
}
return result;
}
void setCacheSize(int count)
{
boost::mutex::scoped_lock lock(contentCacheMutex);
contentCache.resize(count);
}
bool findCacheItem(const std::string& id, CachedContent* result)
{
boost::mutex::scoped_lock lock(contentCacheMutex);
return contentCache.fetch(id, result);
}
void removeCacheItem(const std::string& id)
{
boost::mutex::scoped_lock lock(contentCacheMutex);
contentCache.remove(id);
}
void invalidateCacheItemOrFailure(const std::string& id)
{
{
boost::mutex::scoped_lock lock(contentCacheMutex);
contentCache.remove(id);
}
{
boost::recursive_mutex::scoped_lock lock(requestSync);
std::list<FailedUrl>::iterator found = failedUrls.end();
for (std::list<FailedUrl>::iterator itr = failedUrls.begin();
itr != failedUrls.end() && found == failedUrls.end(); ++itr)
{
if (itr->url == id)
{
found = itr;
}
}
if (found != failedUrls.end())
failedUrls.erase(found);
}
}
void insertCacheItem(const std::string& id, const CachedContent& result)
{
boost::mutex::scoped_lock lock(contentCacheMutex);
contentCache.insert(id, result);
}
void renameCacheItem(const std::string& id, const std::string& newId)
{
boost::mutex::scoped_lock lock(contentCacheMutex);
CachedContent content;
if (contentCache.fetch(id, &content))
{
//"rename" the entry.
contentCache.remove(id);
contentCache.insert(newId, content);
}
}
void clearCache()
{
{
boost::mutex::scoped_lock lock(contentCacheMutex);
contentCache.clear();
}
{
boost::recursive_mutex::scoped_lock lock(requestSync);
failedUrls.clear();
}
}
void printContentNames()
{
boost::mutex::scoped_lock lock(contentCacheMutex);
contentCache.printContentNames();
}
protected:
/*override*/ void registerContent(const std::string& url, shared_ptr<const std::string> response, shared_ptr<const std::string> filename)
{
if(Log) FASTLOGS(FLog::HttpQueue, "URL(%s)", url.c_str());
boost::mutex::scoped_lock lock(contentCacheMutex);
contentCache.insert(url, CachedContent(response, filename));
}
typedef SizeEnforcedLRUCache<std::string, CachedContent> ContentCache;
boost::mutex contentCacheMutex; //synchronizes the contentCache
ContentCache contentCache;
};
}
+134
View File
@@ -0,0 +1,134 @@
#pragma once
#include <stdio.h>
#include <string>
#include <istream>
#include <memory>
#include <vector>
#include "util/name.h"
#include "rbx/boost.hpp"
#include "rbx/rbxTime.h"
#include "Util/contentid.h"
#include "Util/HeartbeatInstance.h"
#include "Util/LRUCache.h"
#include "Util/ThreadPool.h"
#include "Util/Http.h"
#include "V8Tree/Service.h"
LOGGROUP(HttpQueue)
namespace RBX {
class DataModel;
class HttpQueueStatsItem;
class AsyncHttpQueue
: public boost::enable_shared_from_this<AsyncHttpQueue>
, public boost::noncopyable
{
shared_ptr<HttpQueueStatsItem> statsItem;
public:
typedef enum { Waiting, Succeeded, Failed } RequestResult;
typedef enum { AsyncInline, AsyncNone, AsyncRead, AsyncWrite} ResultJob;
typedef boost::function<void(RequestResult, std::istream*, shared_ptr<const std::string> response, shared_ptr<std::exception> exception)> RequestCallback;
struct CallbackWrapper
{
RequestCallback callback;
ResultJob jobType;
CallbackWrapper(RequestCallback callback, ResultJob jobType)
:callback(callback)
,jobType(jobType)
{}
};
void setThreadPool(int count);
void setCachePolicy(const HttpCache::Policy policy) { cachePolicy = policy; }
bool isRequestQueueEmpty();
bool isUrlBad(const std::string& id);
void asyncRequest(const std::string& id, float priority, RequestCallback* callback, ResultJob jobType, bool ignoreBadRequests=false, const std::string& expectedType = "");
bool syncRequest(const std::string& id, const std::string& expectedType = "");
static void dispatchGenericCallback(boost::function<void(DataModel*)> theCallback, Instance* instance, ResultJob jobType);
static void dispatchCallback(RequestCallback theCallback, Instance* instance,
RequestResult result, boost::shared_ptr<const std::string> data, ResultJob jobType, shared_ptr<std::exception> exception);
AsyncHttpQueue(Instance* owner,boost::function<bool(const std::string& url, std::string* result)> getLocalFile, int threadCount);
virtual ~AsyncHttpQueue();
void onHeartbeat(const Heartbeat& heartbeatEvent);
int getRequestQueueSize() const;
shared_ptr<const Reflection::ValueArray> getFailedUrls();
shared_ptr<const Reflection::ValueArray> getRequestQueueUrls();
void resetStatsItem(ServiceProvider* provider);
double getAvgTimeInQueue() { return avgTimeInQueue.value(); }
double getAvgRequestCompleteTime() { return avgRequestCompleteTime.value(); }
int getNumSlowRequests() {return numSlowRequests;}
protected:
virtual void registerContent(const std::string& url, shared_ptr<const std::string> response, shared_ptr<const std::string> filename)
{}
struct Request
{
std::string url;
std::vector<CallbackWrapper> callbacks;
float priority;
std::string expectedType; // used in header
boost::shared_ptr<Http> http; // keep a handle so we can cancel.
RBX::Time startTime; // the time when this request was issued
bool operator==(const std::string& url) const { return this->url==url; }
};
RunningAverage<double> avgTimeInQueue; // in msec
RunningAverage<double> avgRequestCompleteTime; // in msec
int numSlowRequests;
struct FailedUrl
{
std::string url;
RBX::Time expiration;
FailedUrl(const char* url);
bool expired() const;
};
typedef std::list< Request > RequestList;
typedef RequestList::iterator RequestHandle;
struct AsyncRetryTask
{
double retryTime;
RequestHandle request;
AsyncRetryTask(RequestHandle request , double retryTime)
:request(request), retryTime(retryTime)
{}
};
mutable boost::recursive_mutex requestSync; // synchronizes the requestQueue and failedUrls queue, and threadPool
// also used to protect modification of the http shared pointer.
RequestList requestQueue; // queue of requested URLs
std::list< FailedUrl > failedUrls; // List of bad URLs
boost::scoped_ptr<PriorityThreadPool> threadPool;
boost::recursive_mutex asyncRetrySync;
std::queue<AsyncRetryTask> asyncRetryTasks;
double currentWallTime;
static void processRequests(boost::weak_ptr<AsyncHttpQueue> httpQueue, RequestHandle request, boost::shared_ptr<rbx::spin_mutex> lock);
void addAsyncRetryTask(RequestHandle request);
Instance* owner;
boost::function<bool(const std::string& url, std::string* result)> getLocalFile;
HttpCache::Policy cachePolicy;
};
}
+61
View File
@@ -0,0 +1,61 @@
#pragma once
// Class that can average 512 prior values using only 9 floats for storage
#include <vector>
namespace RBX {
template<typename T>
class Average {
private:
size_t samples;
size_t tag;
std::vector<T> history;
public:
Average(size_t samples, T initValue) : samples(samples), tag(0)
{
history.resize(samples, initValue);
}
void sample(T value, bool advanceBuffer = true)
{
history[tag] = value;
if (advanceBuffer) {
tag = (tag + 1) % samples;
}
}
T getAverage() const
{
T answer = T();
for (size_t i = 0; i < samples; ++i) {
answer += history[i];
}
return answer / static_cast<float>(samples);
}
size_t size() const {
return samples;
}
const T& getValue(size_t index) const {
return history[index];
}
void resetValues(const T& value) {
for (size_t i = 0; i < samples; ++i) {
history[i] = value;
}
}
void resetValues(size_t samplesNew, const T& value) {
for (size_t i = 0; i < samples; ++i) {
history[i] = value;
}
history.resize(samplesNew, value);
samples = samplesNew;
}
};
} // namespace
+37
View File
@@ -0,0 +1,37 @@
/* Copyright 2003-2009 ROBLOX Corporation, All Rights Reserved */
#pragma once
#include "Util/NormalId.h"
namespace RBX {
//A utility class for holding a set of "Faces" associated with an object (top, bottom, left, right, front, back)
class Axes
{
public:
static int axisToMask(Vector3::Axis axis);
static Vector3::Axis normalIdToAxis(NormalId normalId);
static NormalId axisToNormalId(Vector3::Axis axis);
public:
Axes(int axisMask = 0);
void clear() { axisMask = 0; }
void setAxisByNormalId(NormalId normalId, bool value);
bool getAxisByNormalId(NormalId normalId) const;
void setAxis(Vector3::Axis axis, bool value);
bool getAxis(Vector3::Axis axis) const;
bool operator==(const Axes& other) const {
return axisMask == other.axisMask;
}
bool operator!=(const Axes& other) const {
return axisMask != other.axisMask;
}
int axisMask;
};
}
+21
View File
@@ -0,0 +1,21 @@
#pragma once
#include "boost/cstdint.hpp"
namespace RBX {
struct Base64BinaryInputStream {
private:
const char* source;
boost::uint16_t buffer;
size_t readableBitsInBuffer;
static unsigned char decode(unsigned char charFromString);
public:
Base64BinaryInputStream(const char* source);
// numBitsToRead needs to be >= 1 and <= 8.
void ReadBits(unsigned char* out, size_t numBitsToRead);
};
}
+31
View File
@@ -0,0 +1,31 @@
#pragma once
#include <sstream>
namespace RBX {
struct Base64BinaryOutputStream {
private:
static const char* kTranslateToBase64;
std::ostringstream result;
unsigned char buffer;
size_t bitsUsed;
public:
Base64BinaryOutputStream();
// NOT A REAL IMPLEMENTATION -- ONLY PRESENT TO SATISFY TEMPLATES
size_t GetNumberOfBytesUsed() const;
// numBitsToAdd must be >= 0 and <= 8. Only the character immediately
// pointed to by data will be read
void WriteBits(const unsigned char* data, size_t numBitsToAdd);
// make sure to call this method exactly once: when you will no longer
// call WriteBits again on this object.
void done(std::string* out);
};
}
+65
View File
@@ -0,0 +1,65 @@
#pragma once
#include "rbx/Debug.h"
#include <map>
// Poor man's version of a Bi-MultiMap. Restriction is that each "pair" can only be here once
// Assumes we can have many A's, many B's
// Need to re-write with dual indexed multi-set or some other data structure
namespace RBX {
template <typename Left, typename Right>
class BiMultiMap {
public:
typedef std::multimap<Left, Right> InternalMap;
typedef typename InternalMap::iterator InternalMapIt;
InternalMap internalMap;
bool pairInMap(const Left& left, const Right& right) {
InternalMapIt it;
for (it = internalMap.lower_bound(left); it != internalMap.upper_bound(left); ++it) {
if (it->second == right) {
return true;
}
}
return false;
}
void insertPair(const Left& left, const Right& right) {
RBXASSERT_SLOW(!pairInMap(left, right));
internalMap.insert(std::make_pair(left, right));
}
void removePair(const Left& left, const Right& right) {
RBXASSERT_SLOW(pairInMap(left, right));
typename InternalMap::iterator it;
for (it = internalMap.lower_bound(left); it != internalMap.upper_bound(left); ++it) {
if (it->second == right) {
internalMap.erase(it);
RBXASSERT(!pairInMap(left, right));
return;
}
}
RBXASSERT(0);
}
bool empty() const {
return internalMap.empty();
}
bool emptyLeft(const Left& left) const {
return (internalMap.lower_bound(left) == internalMap.upper_bound(left));
}
template<class Func>
inline void visitEachLeft(const Left& left, const Func& func) const {
typename InternalMap::const_iterator it;
for (it = internalMap.lower_bound(left); it != internalMap.upper_bound(left); ++it) {
const Right& right = it->second;
func(left, right);
}
}
};
} // namespace RBX
+49
View File
@@ -0,0 +1,49 @@
#pragma once
#include <string>
namespace RBX {
// use this for properties that contain binary data so that they're serialized to XML without roundtrip issues
class BinaryString
{
public:
BinaryString()
{
}
explicit BinaryString(const std::string& value)
: internalValue(value)
{
}
const std::string& value() const
{
return internalValue;
}
void set(const char* buffer, unsigned int size)
{
internalValue.assign(buffer, size);
}
bool operator==(const BinaryString& other) const
{
return internalValue == other.internalValue;
}
bool operator!=(const BinaryString& other) const
{
return internalValue != other.internalValue;
}
bool operator<(const BinaryString& other) const
{
return internalValue < other.internalValue;
}
private:
std::string internalValue;
};
}
+335
View File
@@ -0,0 +1,335 @@
/* Copyright 2003-2006 ROBLOX Corporation, All Rights Reserved */
#pragma once
#include "G3D/Color3.h"
#include "G3D/Color4.h"
#include "G3D/Color3uint8.h"
#include "G3D/Color4uint8.h"
#include <vector>
namespace RBX {
// A collection of official ROBLOX colors
class BrickColor
{
class BrickMap;
public:
enum Number {
brick_1 = 1,
brick_2 = 2,
brick_3 = 3,
brick_5 = 5,
brick_6 = 6,
brick_9 = 9,
brick_11 = 11,
brick_12 = 12,
brick_18 = 18,
brick_21 = 21,
brick_22 = 22,
brick_23 = 23,
brick_24 = 24,
brick_25 = 25,
brick_26 = 26,
brick_27 = 27,
brick_28 = 28,
brick_29 = 29,
brick_36 = 36,
brick_37 = 37,
brick_38 = 38,
brick_39 = 39,
brick_40 = 40,
brick_41 = 41,
brick_42 = 42,
brick_43 = 43,
brick_44 = 44,
brick_45 = 45,
brick_47 = 47,
brick_48 = 48,
brick_49 = 49,
brick_50 = 50,
brick_100 = 100,
brick_101 = 101,
brick_102 = 102,
brick_103 = 103,
brick_104 = 104,
brick_105 = 105,
brick_106 = 106,
brick_107 = 107,
brick_108 = 108,
brick_110 = 110,
brick_111 = 111,
brick_112 = 112,
brick_113 = 113,
brick_115 = 115,
brick_116 = 116,
brick_118 = 118,
brick_119 = 119,
brick_120 = 120,
brick_121 = 121,
brick_123 = 123,
brick_124 = 124,
brick_125 = 125,
brick_126 = 126,
brick_127 = 127,
brick_128 = 128,
brick_131 = 131,
brick_133 = 133,
brick_134 = 134,
brick_135 = 135,
brick_136 = 136,
brick_137 = 137,
brick_138 = 138,
brick_140 = 140,
brick_141 = 141,
brick_143 = 143,
brick_145 = 145,
brick_146 = 146,
brick_147 = 147,
brick_148 = 148,
brick_149 = 149,
brick_150 = 150,
brick_151 = 151,
brick_153 = 153,
brick_154 = 154,
brick_157 = 157,
brick_158 = 158,
brick_168 = 168,
brick_176 = 176,
brick_178 = 178,
brick_179 = 179,
brick_180 = 180,
brick_190 = 190,
brick_191 = 191,
brick_192 = 192,
brick_193 = 193,
brick_194 = 194,
brick_195 = 195,
brick_196 = 196,
brick_198 = 198,
brick_199 = 199,
brick_200 = 200,
brick_208 = 208,
brick_209 = 209,
brick_210 = 210,
brick_211 = 211,
brick_212 = 212,
brick_213 = 213,
brick_216 = 216,
brick_217 = 217,
brick_218 = 218,
brick_219 = 219,
brick_220 = 220,
brick_221 = 221,
brick_222 = 222,
brick_223 = 223,
brick_224 = 224,
brick_225 = 225,
brick_226 = 226,
brick_232 = 232,
brick_268 = 268,
brick_301 = 301,
brick_302 = 302,
brick_303 = 303,
brick_304 = 304,
brick_305 = 305,
brick_306 = 306,
brick_307 = 307,
brick_308 = 308,
brick_309 = 309,
brick_310 = 310,
brick_311 = 311,
brick_312 = 312,
brick_313 = 313,
brick_314 = 314,
brick_315 = 315,
brick_316 = 316,
brick_317 = 317,
brick_318 = 318,
brick_319 = 319,
brick_320 = 320,
brick_321 = 321,
brick_322 = 322,
brick_323 = 323,
brick_324 = 324,
brick_325 = 325,
//brick_326 = 326,
brick_327 = 327,
brick_328 = 328,
brick_329 = 329,
brick_330 = 330,
brick_331 = 331,
brick_332 = 332,
brick_333 = 333,
brick_334 = 334,
brick_335 = 335,
brick_336 = 336,
brick_337 = 337,
brick_338 = 338,
brick_339 = 339,
brick_340 = 340,
brick_341 = 341,
brick_342 = 342,
brick_343 = 343,
brick_344 = 344,
brick_345 = 345,
brick_346 = 346,
brick_347 = 347,
brick_348 = 348,
brick_349 = 349,
brick_350 = 350,
brick_351 = 351,
brick_352 = 352,
brick_353 = 353,
brick_354 = 354,
brick_355 = 355,
brick_356 = 356,
brick_357 = 357,
brick_358 = 358,
brick_359 = 359,
brick_360 = 360,
brick_361 = 361,
brick_362 = 362,
brick_363 = 363,
brick_364 = 364,
brick_365 = 365,
roblox_1001 = 1001,
roblox_1002 = 1002,
roblox_1003 = 1003,
roblox_1004 = 1004,
roblox_1005 = 1005,
roblox_1006 = 1006,
roblox_1007 = 1007,
roblox_1008 = 1008,
roblox_1009 = 1009,
roblox_1010 = 1010,
roblox_1011 = 1011,
roblox_1012 = 1012,
roblox_1013 = 1013,
roblox_1014 = 1014,
roblox_1015 = 1015,
roblox_1016 = 1016,
roblox_1017 = 1017,
roblox_1018 = 1018,
roblox_1019 = 1019,
roblox_1020 = 1020,
roblox_1021 = 1021,
roblox_1022 = 1022,
roblox_1023 = 1023,
roblox_1024 = 1024,
roblox_1025 = 1025,
roblox_1026 = 1026,
roblox_1027 = 1027,
roblox_1028 = 1028,
roblox_1029 = 1029,
roblox_1030 = 1030,
roblox_1031 = 1031,
roblox_1032 = 1032
};
Number number;
typedef std::vector< BrickColor > Colors;
static const Colors& colorPalette(); // colors shown in UI
static const Colors& renderingPalette(); // colors supported by renderer
static const Colors& allColors(); // all known colors
// returns the 0-based index of the color
size_t getClosestRenderingPaletteIndex() const; // closest "supported" palette index by the GFX engine.
size_t getClosestPaletteIndex() const; // closest palette index from the _whole_ palette list.
static const size_t paletteSize = 128; // supported by UI and data model.
static const size_t paletteSizeMSB = 7; // == log2(paletteSize)
static void setRenderingSupportedPaletteSize(size_t maxSupportedColors);
// Constructor/Factory
BrickColor(Number number):number(number) {
}
BrickColor():number(brick_194) {
}
explicit BrickColor(int number);
static BrickColor closest(G3D::Color3uint8 color);
static BrickColor closest(G3D::Color4uint8 color);
static BrickColor closest(G3D::Color3 color);
static BrickColor closest(G3D::Color4 color);
static BrickColor parse(const char* name);
static BrickColor random();
inline static BrickColor brickWhite()
{
return brick_1;
}
inline static BrickColor brickGray()
{
return brick_194;
}
inline static BrickColor brickDarkGray()
{
return brick_199;
}
inline static BrickColor brickBlack()
{
return brick_26;
}
inline static BrickColor brickRed()
{
return brick_21;
}
inline static BrickColor brickYellow()
{
return brick_24;
}
inline static BrickColor brickGreen()
{
return brick_28;
}
inline static BrickColor baseplateGreen()
{
return brick_37;
}
inline static BrickColor brickBlue()
{
return brick_23;
}
inline static BrickColor defaultColor()
{
return BrickColor();
}
// Assignment
BrickColor& operator=(const BrickColor& other)
{
number = other.number;
return *this;
}
//Query
G3D::Color4uint8 color4uint8() const;
G3D::Color3uint8 color3uint8() const;
G3D::Color4 color4() const;
G3D::Color3 color3() const;
const std::string& name() const;
// returns the number as an int, not an ARGB
int asInt() const { return number; }
// Comparison
bool operator==(const BrickColor& other) const {
return number==other.number;
}
bool operator!=(const BrickColor& other) const {
return number!=other.number;
}
bool operator>(const BrickColor& other) const {
return number>other.number;
}
bool operator<(const BrickColor& other) const {
return number<other.number;
}
};
std::size_t hash_value(const BrickColor& c);
} // namespace
+35
View File
@@ -0,0 +1,35 @@
/* Copyright 2003-2006 ROBLOX Corporation, All Rights Reserved */
// TODO - move to datamodel, out of UTIL
#pragma once
#include "Util/G3DCore.h"
#include "Util/IHasLocation.h"
#include <vector>
namespace RBX {
class Primitive;
class Camera;
class RBXBaseClass CameraSubject : public virtual IHasLocation
{
public:
CameraSubject() {}
virtual ~CameraSubject() {}
// Old Camera Subject Stuff
/*implement*/ virtual void onCameraHeartbeat(const Vector3& cameraLocation, const Vector3& focusPoint) {}
/*implement*/ virtual const CoordinateFrame getRenderLocation() = 0; // goes to the rendering location, not the regular location
/*implement*/ virtual const Vector3 getRenderSize() = 0;
/*implement*/ virtual void onCameraNear(float distance) {}
/*implement*/ virtual void getCameraIgnorePrimitives(std::vector<const Primitive*>& primitives) {}
/*implement*/ virtual void getSelectionIgnorePrimitives(std::vector<const Primitive*>& primitives) {}
/*implement*/ virtual void stepRotationalVelocity(Vector3& cameraLocation, Vector3& focusLocation) {}
protected:
class ContactManager* getContactManager();
};
} // namespace
+48
View File
@@ -0,0 +1,48 @@
/* Copyright 2003-2005 ROBLOX Corporation, All Rights Reserved */
#pragma once
#include "G3D/Vector3.h"
#include "V8Tree/Instance.h"
namespace RBX
{
class CellID
{
private:
bool isNil;
RBX::Vector3 location;
shared_ptr<Instance> terrainPart;
public:
CellID();
CellID( bool isNil, const RBX::Vector3& location, shared_ptr<Instance> terrainPart )
:isNil(isNil)
,location(location)
,terrainPart(terrainPart)
{
}
CellID( bool newIsNil, float newLocation[3], shared_ptr<Instance> newTerrainPart );
~CellID();
bool operator ==(const CellID& other) const
{
if (isNil != other.isNil)
return false;
if (location != other.location)
return false;
if (terrainPart != other.terrainPart)
return false;
return true;
}
bool getIsNil() const { return isNil; }
void setIsNil( bool newIsNil ) { isNil = newIsNil; }
G3D::Vector3 getLocation() const { return location; }
void setLocation( RBX::Vector3 newLocation ) { location = newLocation; }
shared_ptr<Instance> getTerrainPart() const { return terrainPart; }
void setTerrainPart( shared_ptr<Instance> newTerrainPart ) { terrainPart = newTerrainPart; }
static CellID fromParameters( bool newIsNil, float newLocation[3], shared_ptr<Instance> newTerrainPart ) { return CellID( newIsNil, newLocation, newTerrainPart ); }
};
}
+108
View File
@@ -0,0 +1,108 @@
#pragma once
#include <ctime>
#include "rbx/TaskScheduler.Job.h"
#include <util/HeapValue.h>
namespace RBX
{
bool vmProtectedDetectCheatEngineIcon();
class HwndScanner
{
struct fullWindowInfo {
DWORD winWidth;
DWORD winHeight;
DWORD pid;
DWORD active;
std::string title;
bool kickEarly;
static size_t compareByPid ( fullWindowInfo lhs, fullWindowInfo rhs);
};
std::vector<fullWindowInfo> hwndScanResults;
static BOOL CALLBACK makeHwndVector(HWND hwnd, LPARAM lParam);
public:
HwndScanner();
int scan();
bool detectTitle() const;
// This method will always return false on Windows8.
bool detectFakeAttach() const;
bool detectEarlyKick() const;
};
class FileScanner
{
std::time_t baseTime;
std::string tempFolder;
public:
FileScanner();
bool detectLogUpdate() const;
};
extern bool ceDetected;
extern bool ceHwndChecks;
static const unsigned int kCeStructKey = 0x23A7F;
static const unsigned char kCeCharKey = 0x55;
HANDLE setupCeLogWatcher();
// A job to profile this detection method and optionally enable it.
class VerifyConnectionJob : public RBX::TaskScheduler::Job
{
public:
VerifyConnectionJob();
/*override*/ RBX::Time::Interval sleepTime(const Stats& stats);
/*override*/ Job::Error error(const Stats& stats);
/*override*/ TaskScheduler::StepResult step(const Stats& stats);
/*override*/ double getPriorityFactor();
};
bool isSandboxie();
bool isCeBadDll();
// This class does dbvm detection and also breaks on certain dll injection methods.
class DbvmCanary
{
private:
HANDLE canaryCage;
HANDLE canaryHandle;
CONTEXT ctx;
size_t hashValue;
static void canary(HANDLE* mutex);
inline size_t hashDbgRegs(CONTEXT& ctx)
{
return (ctx.Dr0*54321) + (ctx.Dr1*98765) ^ (ctx.Dr2*6543) - (ctx.Dr3*987);
}
public:
DbvmCanary();
void checkAndLocalUpdate();
void kernelUpdate();
};
class SpeedhackDetect
{
private:
DWORD k32base;
DWORD k32size;
public:
SpeedhackDetect();
bool isSpeedhack();
};
extern HeapValue<uintptr_t> vehHookLocationHv;
extern HeapValue<uintptr_t> vehStubLocationHv;
extern void* vehHookContinue;
void addWriteBreakpoint(uintptr_t addr);
void removeWriteBreakpoint(uintptr_t addr);
__declspec(align(4096)) extern int writecopyTrap[4096];
} // namespace RBX
+136
View File
@@ -0,0 +1,136 @@
#pragma once
#include "G3DCore.h"
#include "rbx/Debug.h"
#include "Voxel/Cell.h"
#include "Voxel/Util.h"
#include "Util/StreamRegion.h"
#include "Util/SpatialRegion.h"
namespace RBX {
class ClusterChunksIterator
{
public:
ClusterChunksIterator()
: indexOfNextCellToIssue(0)
, internalSize(0)
{
}
explicit ClusterChunksIterator(const std::vector<SpatialRegion::Id>& chunks)
: chunks(chunks)
, indexOfNextCellToIssue(0)
, internalSize(chunks.size() * kChunkSize)
{
}
// single chunk
explicit ClusterChunksIterator(const SpatialRegion::Id& chunk)
: indexOfNextCellToIssue(0)
, internalSize(kChunkSize)
{
chunks.push_back(chunk);
}
static inline void nextCellInIterationOrder(const Vector3int16& cellpos, Vector3int16* out)
{
unsigned int index = (cellpos.x & 0x1f) | ((cellpos.z & 0x1f) << 5) | ((cellpos.y & 0x0f) << 10);
if (index == kChunkSize - 1)
{
// last cell in a chunk, it does not matter what we return except that it has to be a different chunk
*out = cellpos + Vector3int16(1, 0, 0);
}
else
{
unsigned int next = index + 1;
Vector3int16 local = Vector3int16((next & 0x1f), ((next >> 10) & 0xf), ((next >> 5) & 0x1f));
*out = SpatialRegion::globalVoxelCoordinateFromRegionAndRelativeCoordinate(SpatialRegion::regionContainingVoxel(cellpos), local);
}
}
inline void pop(Vector3int16* out)
{
RBXASSERT(internalSize > 0);
Vector3int16 local = Vector3int16((indexOfNextCellToIssue & 0x1f), ((indexOfNextCellToIssue >> 10) & 0xf), ((indexOfNextCellToIssue >> 5) & 0x1f));
*out = SpatialRegion::globalVoxelCoordinateFromRegionAndRelativeCoordinate(chunks[indexOfNextCellToIssue / kChunkSize], local);
indexOfNextCellToIssue++;
internalSize--;
}
inline bool chk(const Vector3int16& pos) const
{
return internalSize > 0;
}
size_t size() const
{
return internalSize;
}
private:
std::vector<SpatialRegion::Id> chunks;
size_t indexOfNextCellToIssue;
size_t internalSize;
enum { kChunkSize = Voxel::kXZ_CHUNK_SIZE * Voxel::kXZ_CHUNK_SIZE * Voxel::kY_CHUNK_SIZE };
};
// Cell iterator for 1/4 of a chunk.
struct OneQuarterClusterChunkCellIterator
{
Vector3int16 cellOffset;
unsigned short internalCell;
unsigned short internalSize;
StreamRegion::Id regionId;
OneQuarterClusterChunkCellIterator()
{
setToStartOfStreamRegion(StreamRegion::Id(0,0,0));
}
void setToStartOfStreamRegion(const StreamRegion::Id &_regionId)
{
regionId = _regionId;
internalSize = StreamRegion::getTotalVoxelVolumeOfARegion();
internalCell = 0;
cellOffset = StreamRegion::getMinVoxelCoordinateInsideRegion(regionId);
}
static inline void cellFromIndex(const Vector3int16 &cellOffset, unsigned int index, Vector3int16* out) {
(*out) = cellOffset + Vector3int16(
(index & 0xf),
((index >> 8) & 0xf),
((index >> 4) & 0xf));
}
static inline void nextCellInIterationOrder(const Vector3int16& cellpos, Vector3int16* out)
{
Vector3int16 offset = StreamRegion::getMinVoxelCoordinateInsideRegion(StreamRegion::regionContainingVoxel(cellpos));
Vector3int16 delta = cellpos - offset;
int index = delta.x | (delta.y << 8) | (delta.z << 4);
//RBXASSERT(index+1 < (int)StreamRegion::getTotalVoxelVolumeOfARegion());
cellFromIndex(offset, index+1, out);
}
inline void pop(Vector3int16* out) {
RBXASSERT(internalSize);
cellFromIndex(cellOffset, internalCell, out);
++internalCell;
--internalSize;
}
inline bool chk(const Vector3int16 &cellPos) const
{
return (internalSize > 0) && (StreamRegion::regionContainingVoxel(cellPos) == regionId);
}
inline size_t size() const {
return internalSize;
}
};
}
+70
View File
@@ -0,0 +1,70 @@
#pragma once
#include "Util/G3DCore.h"
/*
see http://web.media.mit.edu/~wad/color/palette.html
This is an optimal 16 color palette
Black RGB: 0, 0, 0
Dk. Gray RGB: 87, 87, 87
Red RGB: 173, 35, 35
Blue RGB: 42, 75, 215
Green RGB: 29, 105, 20
Brown RGB: 129, 74, 25
Purple RGB: 129, 38, 192
Lt. Gray RGB: 160, 160, 160
Lt. Green RGB: 129, 197, 122
Lt. Blue RGB: 157, 175, 255
Cyan RGB: 41, 208, 208
Orange RGB: 255, 146, 51
Yellow RGB: 255, 238, 51
Tan RGB: 233, 222, 187
Pink RGB: 255, 205, 243
White RGB: 255, 255, 255
*/
namespace RBX {
class Color {
private:
G3D::Color3 rgb;
Color() {}
Color(unsigned char r, unsigned char g, unsigned char b) : rgb(static_cast<float>(r)/255.0f, static_cast<float>(g)/255.0f, static_cast<float>(b)/255.0f) {}
const G3D::Color3& color3() {return rgb;}
public:
static const G3D::Color3& getColorByIndex(int i);
inline static const G3D::Color3& black() {return getColorByIndex(0);}
inline static const G3D::Color3& darkGray() {return getColorByIndex(1);}
inline static const G3D::Color3& red() {return getColorByIndex(2);}
inline static const G3D::Color3& blue() {return getColorByIndex(3);}
inline static const G3D::Color3& green() {return getColorByIndex(4);}
inline static const G3D::Color3& brown() {return getColorByIndex(5);}
inline static const G3D::Color3& purple() {return getColorByIndex(6);}
inline static const G3D::Color3& lightGray() {return getColorByIndex(7);}
inline static const G3D::Color3& lightGreen() {return getColorByIndex(8);}
inline static const G3D::Color3& lightBlue() {return getColorByIndex(9);}
inline static const G3D::Color3& cyan() {return getColorByIndex(10);}
inline static const G3D::Color3& orange() {return getColorByIndex(11);}
inline static const G3D::Color3& yellow() {return getColorByIndex(12);}
inline static const G3D::Color3& tan() {return getColorByIndex(13);}
inline static const G3D::Color3& pink() {return getColorByIndex(14);}
inline static const G3D::Color3& white() {return getColorByIndex(15);}
static const G3D::Color3& colorFromIndex8(int index);
static const G3D::Color3 colorFromInt(unsigned int i);
static const G3D::Color3 colorFromString(const std::string& s);
static const G3D::Color3 colorFromPointer(void* pointer);
static const G3D::Color3 colorFromTemperature(float temperature); // 0.0 = cold, 1.0 = hot
static const G3D::Color3 colorFromError(double value); // 0.0 == not important, 10.0 == very important;
};
}
+25
View File
@@ -0,0 +1,25 @@
#pragma once
namespace RBX {
template <typename Enum, typename Storage> class CompactEnum
{
public:
CompactEnum()
{
}
CompactEnum(Enum value): data(value)
{
}
operator Enum() const
{
return static_cast<Enum>(data);
}
private:
Storage data;
};
}
+68
View File
@@ -0,0 +1,68 @@
/* Copyright 2003-2005 ROBLOX Corporation, All Rights Reserved */
#pragma once
//#include "Util/SoundWorld.h"
#include <string>
namespace RBX {
// A property that computes and caches its value
template <class Type, class O>
class ComputeProp
{
private:
Type val;
bool dirty;
O* object;
typedef Type (O::*GetFunc)();
GetFunc getFunc;
public:
ComputeProp(O* object, GetFunc getFunc) :
dirty(true),
object(object),
getFunc(getFunc)
{}
inline Type getValue()
{
if (dirty) {
val = (object->*getFunc)();
dirty = false;
}
return val;
}
inline Type getLastComputedValue() const
{
RBXASSERT(!dirty);
return val;
}
inline operator Type()
{
return getValue();
}
inline Type* getValuePointer()
{
getValue();
return &val;
}
inline Type& getValueRef()
{
getValue();
return val;
}
bool setDirty()
{
bool didSomething = !dirty;
dirty = true;
return didSomething;
}
bool getDirty() const
{
return dirty;
}
};
} // namespace RBX
+134
View File
@@ -0,0 +1,134 @@
#pragma once
#include "rbx/Debug.h"
#include "rbx/atomic.h"
#ifdef __RBX_NOT_RELEASE
#define RBX_USE_CONCURRENCY_VALIDATOR(expr) (expr)
#else
#define RBX_USE_CONCURRENCY_VALIDATOR(expr) ((void)0)
#endif
namespace RBX {
class ConcurrencyValidator
{
private:
rbx::atomic<int> writing;
std::string writeLocation;
mutable rbx::atomic<int> reading;
public:
ConcurrencyValidator() : writing(0), reading(0)
{
}
~ConcurrencyValidator() {
RBXASSERT(writing == 0);
RBXASSERT(reading == 0);
}
private:
friend class WriteValidator;
friend class ReadOnlyValidator;
bool preRead() const {
++reading;
long wasWriting = writing;
if (wasWriting != 0) {RBXASSERT(false && "writing check failed in preRead");}
return true;
}
bool postRead() const {
long wasWriting = writing;
if (wasWriting != 0) {RBXASSERT(false && "wasWriting check failed in postRead");}
if (writing != 0) {RBXASSERT(false && "writing check failed in postRead");}
--reading;
return true;
}
bool preWrite() {
long wasWriting = writing;
long wasReading = reading;
if (wasReading != 0) {RBXASSERT(false && "wasReading check failed in preWrite");}
if (wasWriting != 0) {RBXASSERT(false && "wasWriting check failed in preWrite");}
if (writing != 0) {RBXASSERT(false && "writing check failed in preWrite");}
long result = ++writing;
if (result != 1) {RBXASSERT(false && "InterlocedIncrement returned not -1 in preWrite");}
return true;
}
bool preWrite(const std::string& writeWhere) {
bool okWrite = preWrite();
if (okWrite) {
writeLocation = writeWhere;
}
return okWrite;
}
bool postWrite() {
long wasWriting = writing;
long wasReading = reading;
if (wasWriting != 1) {RBXASSERT(false && "wasWriting check failed in postWrite");}
if (writing != 1) {RBXASSERT(false && "writing check failed in postWrite");}
if (wasReading != 0) {RBXASSERT(false && "wasReading check failed in postWrite");}
if (reading != 0) {RBXASSERT(false && "reading check failed in postWrite");}
long result = --writing;
if (result != 0) {RBXASSERT(false && "InterlocedIncrement returned not 0 in postWrite");}
if (reading != 0) {RBXASSERT(false && "reading check failed in postWrite");}
return true;
}
};
class ReadOnlyValidator
{
private:
const ConcurrencyValidator& concurrencyValidator;
public:
ReadOnlyValidator(const ConcurrencyValidator& c) : concurrencyValidator(c) {
RBX_USE_CONCURRENCY_VALIDATOR(concurrencyValidator.preRead());
}
~ReadOnlyValidator() {
RBX_USE_CONCURRENCY_VALIDATOR(concurrencyValidator.postRead());
}
};
class WriteValidator
{
private:
ConcurrencyValidator& concurrencyValidator;
public:
WriteValidator(ConcurrencyValidator& c) : concurrencyValidator(c) {
RBX_USE_CONCURRENCY_VALIDATOR(concurrencyValidator.preWrite());
}
WriteValidator(ConcurrencyValidator& c, const std::string& writeWhere) : concurrencyValidator(c) {
RBX_USE_CONCURRENCY_VALIDATOR(concurrencyValidator.preWrite(writeWhere));
}
WriteValidator(ConcurrencyValidator& c, const char* writeWhere) : concurrencyValidator(c) {
RBX_USE_CONCURRENCY_VALIDATOR(concurrencyValidator.preWrite(writeWhere));
}
~WriteValidator() {
RBX_USE_CONCURRENCY_VALIDATOR(concurrencyValidator.postWrite());
}
};
} // namespace
+55
View File
@@ -0,0 +1,55 @@
#pragma once
#include "V8Tree/Instance.h"
#include "V8Tree/Service.h"
namespace RBX {
extern const char* const sContentFilter;
class ContentFilter
: public DescribedNonCreatable<ContentFilter, Instance, sContentFilter, Reflection::ClassDescriptor::RUNTIME_LOCAL>
, public Service
{
public:
typedef enum { Waiting, Succeeded, Failed } FilterResult;
static const unsigned MAX_CONTENT_FILTER_SIZE;
private:
struct ResultEntry
{
bool result;
int usageCount;
ResultEntry(bool result=false)
:result(result),usageCount(0)
{}
};
typedef std::map<std::string, ResultEntry> ResultsDictionary;
typedef std::set<std::string> RequestSet;
ResultsDictionary resultsDictionary;
RequestSet requestSet;
std::string url;
unsigned maxOutstandingRequests;
unsigned maxTableSize;
static void truncateString(std::string& text);
//Returns false if it doesn't know yet, may truncate the string
bool isContentFilterReady(const std::string& value);
bool isStringSafe(std::string& value);
void cleanTable();
public:
ContentFilter();
~ContentFilter();
FilterResult getStringState(std::string& value);
void setFilterUrl(std::string);
void setFilterLimits(int,int);
void doFilterRequest(std::string value);
void saveFilterResult(std::string value, bool result);
};
}
+2 -2
View File
@@ -195,7 +195,7 @@ namespace RBX
std::string host = parsed.host();
std::string path = parsed.path();
static const std::string testsite_domain = "pizzaboxer.fun";
static const std::string testsite_domain = "robloxlabs.com";
const RBX::Url baseUrlParsed = RBX::Url::fromString(baseUrl);
@@ -278,7 +278,7 @@ namespace RBX
if (boost::istarts_with(path, paths[i]) && (path.size() == pathLength || path[pathLength] == '?'))
{
static const char* domain = ".pizzaboxer.fun";
static const char* domain = ".robloxlabs.com";
if (DFFlag::UrlReconstructToAssetGame)
{
+80
View File
@@ -0,0 +1,80 @@
/* Copyright 2003-2005 ROBLOX Corporation, All Rights Reserved */
#ifndef _4B0F5828DADB441bA2D2FDCBCB5538A6
#define _4B0F5828DADB441bA2D2FDCBCB5538A6
#include "stdio.h"
#include "util/name.h"
#include <string>
#include <istream>
#include <memory>
#include <vector>
#include "rbx/boost.hpp"
#include <boost/shared_ptr.hpp>
#include <boost/scoped_ptr.hpp>
using boost::shared_ptr;
namespace RBX {
class ContentId
{
public:
static ContentId fromUrl(const std::string& url);
static ContentId fromAssets(const char* filePath); // filePath is a relative pathname within the "Content" directory
static ContentId fromGameAssetName(const std::string& gameAssetName);
// Constructors are explicit to encourage you to use static constructors above if the string isn't a fully qualified URL
explicit ContentId(const char* id)
:id(id) { CorrectBackslash(this->id); }
explicit ContentId(const std::string& id)
:id(id) { CorrectBackslash(this->id); }
ContentId() {}
void clear()
{
id.clear();
}
const char* c_str() const {
return id.c_str();
}
const std::string& toString() const {
return id;
}
void convertToLegacyContent(const std::string& baseUrl);
void convertAssetId(const std::string& baseUrl, int universeId);
bool reconstructUrl(const std::string& baseUrl, const char* const paths[], const int pathCount);
bool reconstructAssetUrl(const std::string& baseUrl);
std::string getAssetId() const;
std::string getAssetName() const;
std::string getUnConvertedAssetName() const;
bool isNull() const { return id.size()==0; }
bool isAsset() const { return id.compare(0, 11, "rbxasset://") == 0; }
bool isAssetId() const { return id.compare(0, 13, "rbxassetid://") == 0; }
bool isHttp() const { return id.compare(0, 4, "http") == 0; }
bool isFile() const { return id.compare(0, 7, "file://") == 0; }
bool isRbxHttp() const { return id.compare(0, 10, "rbxhttp://") == 0; }
bool isAppContent() const { return id.compare(0, 9, "rbxapp://") == 0; }
bool isNamedAsset() const;
bool isConvertedNamedAsset() const;
friend bool operator<(const ContentId& a, const ContentId& b);
friend bool operator==(const ContentId& a, const ContentId& b);
friend bool operator!=(const ContentId& a, const ContentId& b);
private:
static void CorrectBackslash(std::string& id);
std::string id;
};
std::size_t hash_value(const ContentId& id);
}// namespace
#endif
+51
View File
@@ -0,0 +1,51 @@
#pragma once
#include "Util/AsyncHttpQueue.h"
#include "v8datamodel/DataModelJob.h"
#include "rbx/threadsafe.h"
namespace RBX
{
class DataModel;
class ContentProviderJob : public DataModelJob
{
public:
enum ExecutionMode
{
JobMode,
ImmediateMode
};
private:
boost::function<TaskScheduler::StepResult(std::string,shared_ptr<const std::string>)> processFunc;
boost::function<void(std::string)> errorFunc;
struct ContentProviderTask
{
std::string id;
shared_ptr<const std::string> data;
};
bool aborted;
rbx::safe_queue<ContentProviderTask> tasks;
ExecutionMode execMode;
TaskScheduler::StepResult processTask(const ContentProviderTask& task);
public:
ContentProviderJob(shared_ptr<DataModel> dataModel, const char* name,
boost::function<TaskScheduler::StepResult(std::string,shared_ptr<const std::string>)> processFunc,
boost::function<void(std::string)> errorFunc);
/*override*/ Time::Interval sleepTime(const Stats& stats);
/*override*/ Job::Error error(const Stats& stats);
/*override*/ TaskScheduler::StepResult stepDataModelJob(const Stats& stats);
void abort();
void addTask(const std::string& id, AsyncHttpQueue::RequestResult result, std::istream* filestream, shared_ptr<const std::string> data);
void setExecutionMode(ExecutionMode execMode);
};
}
+215
View File
@@ -0,0 +1,215 @@
#pragma once
#include "Util/LRUCache.h"
namespace RBX
{
enum CacheSizeEnforceMethod { CACHE_ENFORCE_MEMORY_SIZE, CACHE_ENFORCE_OBJECT_COUNT };
template<class Key,class Data>
class ControlledLRUCache
{
private:
unsigned long maxSize;
CacheSizeEnforceMethod enforceMethod;
boost::scoped_ptr< LRUCache<Key,Data> > evictableCache; // items that are processed and ok to delete from cache
boost::scoped_ptr< LRUCache<Key,Data> > pinnedCache; // items that are pending processing/use
public:
public:
ControlledLRUCache( const unsigned long maxSize, CacheSizeEnforceMethod method = CACHE_ENFORCE_OBJECT_COUNT) : maxSize(maxSize), enforceMethod(method)
{
if (method == CACHE_ENFORCE_OBJECT_COUNT)
evictableCache.reset(new SizeEnforcedLRUCache<Key, Data>(maxSize));
else if (method == CACHE_ENFORCE_MEMORY_SIZE)
evictableCache.reset(new MemEnforcedLRUCache<Key, Data>(maxSize));
else
RBXASSERT(false);
pinnedCache.reset(new LRUCache<Key, Data>());
}
~ControlledLRUCache()
{}
inline const unsigned long size()
{
return evictableCache->size() + pinnedCache->size();
}
inline const unsigned long memSize()
{
return evictableCache->memSize() + pinnedCache->memSize();
}
void clear()
{
evictableCache.clear();
pinnedCache.clear();
}
inline bool exists( const Key &key ) const
{
return (evictableCache->exists(key) || pinnedCache->exists(key));
}
inline bool remove( const Key &key )
{
bool result = false;
result = evictableCache->remove(key) || result;
result = pinnedCache->remove(key) || result;
return result;
}
inline void markEvictable(const Key& key)
{
Data data;
unsigned long size;
if(pinnedCache->fetch(key, &data, &size)){
internalMakeEvictable(key, data, size);
}
}
inline bool fetch( const Key &key, Data* result, bool makeEvictable)
{
if(evictableCache->fetch(key, result))
return true;
unsigned long size;
if(pinnedCache->fetch(key, result, &size)){
if(!makeEvictable)
return true;
//Make it evictable by moving it into the evictableCache
internalMakeEvictable(key, *result, size);
return true;
}
//Didn't find it, return false
return false;
}
inline void resize( unsigned long newSize)
{
maxSize = newSize;
evictableCache->resize(newSize);
pinnedCache->resize(newSize);
unsigned long curSize = (enforceMethod == CACHE_ENFORCE_MEMORY_SIZE) ? memSize() : size();
while((curSize > newSize) && (evictableCache->size() > 0))
{
evictableCache->removeLeastRecentlyUsed();
curSize = (enforceMethod == CACHE_ENFORCE_MEMORY_SIZE) ? memSize() : size();
}
RBXASSERT((enforceMethod == CACHE_ENFORCE_MEMORY_SIZE ? memSize() : size()) <= newSize);
}
inline void insert( const Key &key, const Data &data, unsigned long dataSize = 0 )
{
//First remove it from evictableCache, since it will go into pinnedCache now
evictableCache->remove(key);
pinnedCache->remove(key);
unsigned int new_size = (enforceMethod == CACHE_ENFORCE_MEMORY_SIZE) ? (this->memSize() + dataSize) : (this->size() + 1);
if(new_size > maxSize) {
//We are full, see if we have evictable space
if(evictableCache->size() > 0){
//Something is evictable, kick it out
evictableCache->removeLeastRecentlyUsed();
}
}
pinnedCache->insert(key, data, dataSize);
}
inline bool isFull()
{
return pinnedCache->size() >= maxSize;
}
inline bool evictAll()
{
if(!pinnedCache->empty()){
evictableCache->insert(pinnedCache->begin(), pinnedCache->end());
pinnedCache->clear();
return true;
}
return false;
}
private:
void internalMakeEvictable(const Key& key, const Data& data, unsigned long dataSize)
{
evictableCache->insert(key,data, dataSize);
pinnedCache->remove(key);
RBXASSERT(size() <= maxSize);
}
};
template<class Key,class Data>
class ConcurrentControlledLRUCache
{
private:
RBX::ControlledLRUCache<Key, Data> cache;
boost::mutex mutex;
unsigned long resetCounter;
unsigned long heartbeatCounter;
public:
ConcurrentControlledLRUCache(unsigned long size, unsigned long resetCounter, CacheSizeEnforceMethod enforceMethod = CACHE_ENFORCE_OBJECT_COUNT)
:cache(size, enforceMethod)
,resetCounter(resetCounter)
,heartbeatCounter(0)
{}
inline bool fetch( const Key &key, Data* result, bool makeEvictable)
{
boost::mutex::scoped_lock lock(mutex);
return cache.fetch(key, result, makeEvictable);
}
inline void resize( unsigned long newSize)
{
boost::mutex::scoped_lock lock(mutex);
cache.resize(newSize);
}
inline void insert( const Key &key, const Data &data, unsigned long dataSize = 0)
{
boost::mutex::scoped_lock lock(mutex);
return cache.insert(key, data, dataSize);
}
inline bool remove( const Key &key )
{
boost::mutex::scoped_lock lock(mutex);
return cache.remove(key);
}
inline void markEvictable(const Key& key)
{
boost::mutex::scoped_lock lock(mutex);
cache.markEvictable(key);
}
inline bool isFull()
{
boost::mutex::scoped_lock lock(mutex);
return cache.isFull();
}
inline bool evictAll()
{
boost::mutex::scoped_lock lock(mutex);
return cache.evictAll();
}
inline void onHeartbeat()
{
if(++heartbeatCounter >= resetCounter){
heartbeatCounter = 0;
evictAll();
}
}
};
}
+2
View File
@@ -0,0 +1,2 @@
#pragma once
+3 -3
View File
@@ -303,7 +303,7 @@ static NSString* kHttpRunLoopMode = @"RobloxHttpController";
if (kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber10_8)
{
if ([protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
return [protectionSpace.host rangeOfString:@".pizzaboxer.fun"].location != NSNotFound;
return [protectionSpace.host rangeOfString:@".robloxlabs.com"].location != NSNotFound;
}
return NO;
}
@@ -313,7 +313,7 @@ static NSString* kHttpRunLoopMode = @"RobloxHttpController";
if (kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber10_8)
{
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust] &&
([challenge.protectionSpace.host rangeOfString:@".pizzaboxer.fun"].location != NSNotFound))
([challenge.protectionSpace.host rangeOfString:@".robloxlabs.com"].location != NSNotFound))
{
// trust the credentials...
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
@@ -353,7 +353,7 @@ int rbx_isRobloxSite(const char* url)
if (!isRobloxUrl)
{
textRange =[host rangeOfString:@".pizzaboxer.fun"];
textRange =[host rangeOfString:@".robloxlabs.com"];
isRobloxUrl = textRange.location != NSNotFound;
}
+84
View File
@@ -0,0 +1,84 @@
#pragma once
#include "rbx/Debug.h"
#include <vector>
namespace RBX {
/**
* Wrapper around std::vector that allows for quick insert and pop from both
* front and back. This container never attempts to reduce the amount of
* memory it uses, so it may not be suitable for queues that do not have a
* reasonable upper bound in size.
*/
template<class T>
struct DoubleEndedVector {
private:
size_t head;
size_t internalSize;
std::vector<T> data;
size_t dataSizeMask;
void grow() {
if (internalSize == data.size()) {
std::vector<T> replacement(std::max((size_t)32, internalSize * 2));
if (data.size() > 0) {
size_t firstSegment = data.size() - head;
size_t secondSegment = internalSize - firstSegment;
RBXASSERT(firstSegment + secondSegment == data.size());
std::copy(&data[head], &data[head] + firstSegment, &replacement[0]);
std::copy(&data[0], &data[0] + secondSegment, &replacement[firstSegment]);
}
head = 0;
data.swap(replacement);
RBXASSERT((data.size() & (data.size() - 1)) == 0);
dataSizeMask = data.size() - 1;
}
}
public:
DoubleEndedVector() : head(0), internalSize(0), data(), dataSizeMask(0) {}
size_t size() const {
return internalSize;
}
bool push_back(const T& inputData) {
grow();
data[(head + internalSize) & dataSizeMask] = inputData;
internalSize++;
return true;
}
bool push_front(const T& inputData) {
grow();
size_t newHead = (head - 1) & dataSizeMask;
data[newHead] = inputData;
head = newHead;
internalSize++;
return true;
}
void pop_front(T* out) {
RBXASSERT(internalSize > 0);
(*out) = data[head];
head = (head + 1) & dataSizeMask;
internalSize--;
}
inline T& operator[](const unsigned int& idx) {
return data[(head + idx) & dataSizeMask];
}
inline const T& operator[](const unsigned int& idx) const {
return data[(head + idx) & dataSizeMask];
}
};
}
+8
View File
@@ -0,0 +1,8 @@
#pragma once
#include <stdexcept>
namespace RBX
{
}
+68
View File
@@ -0,0 +1,68 @@
#pragma once
#include "Util/G3DCore.h"
namespace RBX {
// ToDo - templatize this
class floatERA {
private:
float weight;
float avg;
public:
floatERA()
: weight(.5f)
{
reset();
}
floatERA(float weight)
: weight(weight)
{
reset();
}
void reset() {
avg = 0.0f;
}
float pushAndGetAverage(float value) {
avg = (weight * (value - avg)) + avg;
return avg;
}
float getAverage() {return avg;}
};
class Vector3ERA {
private:
float weight;
Vector3 avg;
public:
Vector3ERA()
:weight(.5f)
{} // Vector inits to zeros
Vector3ERA(float weight)
: weight(weight)
{} // Vector3 inits to zeros;
void reset(const Vector3& value) {
avg = value;
}
void reset() {
reset(Vector3::zero());
}
void push(const Vector3& value) {
avg += weight * (value - avg);
}
const Vector3& getAverage() {return avg;}
};
}
+239
View File
@@ -0,0 +1,239 @@
#pragma once
#include "Util/NormalId.h"
#include "Util/G3DCore.h"
#include "rbx/Debug.h"
#include "Util/Math.h"
namespace RBX {
class Extents {
private:
Vector3 low;
Vector3 high;
public:
Extents() // initialize to negativeInfiniteExtents;
: low(Vector3::maxFinite())
, high(-Vector3::maxFinite())
{}
Extents(const Vector3& _min, const Vector3& _max)
: low(_min)
, high(_max)
{
RBXASSERT_SLOW(low == low.min(high));
RBXASSERT_SLOW(high == high.max(low));
}
bool isNanInf() const
{
return (Math::isNanInfVector3(low) || Math::isNanInfVector3(high));
}
static Extents fromCenterCorner(const Vector3& center, const Vector3& corner) {
return Extents(center-corner, center+corner);
}
static Extents fromCenterRadius(const Vector3& center, float radius) {
return fromCenterCorner(center, Vector3(radius, radius, radius));
}
bool operator==(const Extents& other) const {
return ((low == other.low) && (high == other.high));
}
bool operator!=(const Extents& other) const {
return !(*this == other);
}
static Extents vv(const Vector3& v0, const Vector3& v1) {
Extents e;
e.low = v0.min(v1);
e.high = v0.max(v1);
return e;
}
const Vector3& min() const {return low;}
const Vector3& max() const {return high;}
Vector3int16 getCornerIndex(int i) const;
Vector3 getCorner(int i) const;
Vector3 size() const {
return high - low;
}
Vector3 center() const {
return 0.5 * (low + high);
}
Vector3 bottomCenter() const {
Vector3 answer = center();
answer.y = low.y;
return answer;
}
Vector3 topCenter() const {
Vector3 answer = center();
answer.y = high.y;
return answer;
}
float longestSide() const {
Vector3 s = size();
return G3D::max(G3D::max(s.x, s.y), s.z);
}
float volume() const {
Vector3 s = size();
return s.x * s.y * s.z;
}
float areaXZ() const {
Vector3 s = size();
return s.x * s.z;
}
bool isNull() const {
return low.x > high.x || low.y > high.y || low.z > high.z;
}
Extents toWorldSpace(const CoordinateFrame& offset) const;
Extents express(const CoordinateFrame& myFrame, const CoordinateFrame& expressInFrame) const;
// faceId's are in order of x, y, z, -x, -y, -z
Vector3 faceCenter(NormalId faceId) const;
/**
Returns the four corners of a face (0 <= f < 6).
The corners are returned to form a counter clockwise quad facing outwards.
*/
void getFaceCorners(
NormalId faceId,
Vector3& v0,
Vector3& v1,
Vector3& v2,
Vector3& v3) const;
Plane getPlane(NormalId normalId) const;
// clip the vector to be inside the Extents
Vector3 clip(const Vector3& clipVector) const {
return clipVector.clamp(low, high);
}
float computeClosestSqDistanceToPoint(const Vector3& point) const;
// minimum amount to move innerExtents and keep them within Extents
Vector3 clamp(const Extents& innerExtents) const;
NormalId closestFace(const Vector3& point);
void unionWith(const Extents& other) { // Extents& operator&= (const Extents& other) {
low = low.min(other.low);
high = high.max(other.high);
}
Extents clampInsideOf(const Extents& other) const; // Extents& operator&= (const Extents& other) {
void shift(const Vector3& shiftVector) {// Extents& operator+= (const Vector3& shiftVector) {
low += shiftVector;
high += shiftVector;
}
void scale(float x) { // Extents& operator*= (float x) {
low *= x;
high *= x;
}
void expand(float x) {
low -= Vector3(x,x,x);
high += Vector3(x,x,x);
}
void expand(const Vector3& p) {
low -= p;
high += p;
}
void expandToContain(const Vector3& p) {
low = low.min(p);
high = high.max(p);
}
void expandToContain(const Extents& e) {
low = low.min(e.low);
high = high.max(e.high);
}
bool contains(const Vector3& point) const {
return ( (point.x >= low.x)
&& (point.y >= low.y)
&& (point.z >= low.z)
&& (point.x <= high.x)
&& (point.y <= high.y)
&& (point.z <= high.z) );
}
bool fuzzyContains(const Vector3& point, float slop) const {
return ( (point.x >= (low.x - slop))
&& (point.y >= (low.y - slop))
&& (point.z >= (low.z - slop))
&& (point.x <= (high.x + slop))
&& (point.y <= (high.y + slop))
&& (point.z <= (high.z + slop)) );
}
bool overlapsOrTouches(const Extents& other) const { // true if sides are exactly equal (touching)
return ( (this->low.x > other.high.x)
|| (this->low.y > other.high.y)
|| (this->low.z > other.high.z)
|| (this->high.y < other.low.y)
|| (this->high.x < other.low.x)
|| (this->high.z < other.low.z)) ? false : true;
}
static bool overlapsOrTouches(const Extents& e0, const Extents& e1) {return e0.overlapsOrTouches(e1);}
bool clampToOverlap(const Extents& other) {
if ( (this->low.x >= other.high.x)
|| (this->low.y >= other.high.y)
|| (this->low.z >= other.high.z)
|| (this->high.y <= other.low.y)
|| (this->high.x <= other.low.x)
|| (this->high.z <= other.low.z))
return false; // not overlap
low = low.clamp(other.low, other.high);
high = high.clamp(other.low, other.high);
return true;
}
bool separatedByMoreThan(const Extents& other, float distance) const;
static const Extents& zero() {
static Extents e(Vector3::zero(), Vector3::zero());
return e;
}
static const Extents& unit() {
static Extents e(Vector3(-1,-1,-1), Vector3(1,1,1));
return e;
}
static const Extents& negativeMaxExtents() {
static Extents e; // default constructor builds this;
return e;
}
static const Extents& maxExtents() {
static Extents e(-Vector3::maxFinite(), Vector3::maxFinite());
return e;
}
};
} // namespace
+173
View File
@@ -0,0 +1,173 @@
#pragma once
#include "Util/Vector3int32.h"
#include "Util/Extents.h"
#include "rbx/Debug.h"
namespace RBX {
class ExtentsInt32 {
public:
Vector3int32 low;
Vector3int32 high;
ExtentsInt32()
: low(Vector3int32::maxInt())
, high(Vector3int32::minInt())
{}
ExtentsInt32(const Vector3int32& _min, const Vector3int32& _max)
: low(_min)
, high(_max)
{
RBXASSERT_SLOW(low == low.min(high));
RBXASSERT_SLOW(high == high.max(low));
}
bool operator==(const ExtentsInt32& other) const {
return ((low == other.low) && (high == other.high));
}
bool operator!=(const ExtentsInt32& other) const {
return !(*this == other);
}
ExtentsInt32& operator= (const ExtentsInt32& other) {
low = other.low;
high = other.high;
return *this;
}
ExtentsInt32 shiftRight(int shift) const {
RBXASSERT_SLOW(shift >= 0);
RBXASSERT_SLOW(shift <= 32);
return ExtentsInt32(low >> shift, high >> shift);
}
ExtentsInt32 shiftRight(const Vector3int32& shift) const {
return ExtentsInt32(low >> shift, high >> shift);
}
ExtentsInt32 shiftLeft(int shift) const {
RBXASSERT_SLOW(shift >= 0);
RBXASSERT_SLOW(shift <= 32);
return ExtentsInt32(low << shift, high << shift);
}
ExtentsInt32 shiftLeft(const Vector3int32& shift) const {
return ExtentsInt32(low << shift, high << shift);
}
static ExtentsInt32 vv(const Vector3int32& v0, const Vector3int32& v1) {
ExtentsInt32 e;
e.low = v0.min(v1);
e.high = v0.max(v1);
return e;
}
const Vector3int32& min() const {return low;}
const Vector3int32& max() const {return high;}
Vector3int32 getCorner(int i) const;
Vector3int32 size() const {
return high - low;
}
Vector3int32 center() const {
return ((low + high) >> 1);
}
Vector3int32 bottomCenter() const {
Vector3int32 answer = center();
answer.y = low.y;
return answer;
}
Vector3int32 topCenter() const {
Vector3int32 answer = center();
answer.y = high.y;
return answer;
}
int longestSide() const {
Vector3int32 s = size();
return std::max(std::max(s.x, s.y), s.z);
}
int volume() const {
Vector3int32 s = size();
long long int answer = s.x * s.y * s.z;
RBXASSERT(answer < INT_MAX);
return static_cast<int>(answer);
}
static ExtentsInt32 unionExtents(const ExtentsInt32& a, const ExtentsInt32& b) {
return ExtentsInt32(a.low.min(b.low), a.high.max(b.high));
}
void shift(const Vector3int32& shiftVector) {
low = low + shiftVector;
high = high + shiftVector;
}
void expand(int x) {
low = low - Vector3int32(x,x,x);
high = high + Vector3int32(x,x,x);
}
const Vector3int32& operator[] (int i) const {
return ((Vector3int32*)this)[i];
}
Vector3int32& operator[] (int i) {
return ((Vector3int32*)this)[i];
}
operator Vector3int32* () {
return (Vector3int32*)this;
}
operator const Vector3int32* () const {
return (Vector3int32*)this;
}
bool contains(int x, int y, int z) const {
return ( (x >= low.x)
&& (y >= low.y)
&& (z >= low.z)
&& (x <= high.x)
&& (y <= high.y)
&& (z <= high.z) );
}
bool contains(const Vector3int32& point) const {
return contains(point.x, point.y, point.z);
}
bool overlapsOrTouches(const ExtentsInt32& other) const { // true if sides are exactly equal (touching)
return ( (this->low.x > other.high.x)
|| (this->low.y > other.high.y)
|| (this->low.z > other.high.z)
|| (this->high.y < other.low.y)
|| (this->high.x < other.low.x)
|| (this->high.z < other.low.z)) ? false : true;
}
static bool overlapsOrTouches(const ExtentsInt32& e0, const ExtentsInt32& e1) {return e0.overlapsOrTouches(e1);}
Extents toExtents() const {
return Extents(low.toVector3(), high.toVector3());
}
static const ExtentsInt32& zero() {
static ExtentsInt32 e(Vector3int32::zero(), Vector3int32::zero());
return e;
}
static const ExtentsInt32& empty() {
static ExtentsInt32 e; // constructor sets negatives
return e;
}
};
} // namespace
+76
View File
@@ -0,0 +1,76 @@
#pragma once
#include "Util/G3DCore.h"
#include "Util/NormalId.h"
#include "rbx/Debug.h"
namespace RBX {
class Extents;
class Face
{
private:
Vector3 c0, c1, c2, c3;
Face(const Vector3& c0, const Vector3& c1, const Vector3& c2, const Vector3& c3)
: c0(c0), c1(c1), c2(c2), c3(c3)
{}
Vector3 getAxis(int i) const {
RBXASSERT((i == 0) || (i==1));
return i == 0 ? getU() : getV();
}
void minMax(const Vector3& point, const Vector3& normal, float& min, float& max) const;
Face operator* (float fScalar) const {
return Face(fScalar*c0, fScalar*c1, fScalar*c2, fScalar*c3);
}
Face operator* (const Vector3& vector3) const {
return Face(vector3*c0, vector3*c1, vector3*c2, vector3*c3);
}
public:
Face() {}
Face(const Face& other)
: c0(other.c0), c1(other.c1), c2(other.c2), c3(other.c3)
{}
static Face fromExtentsSide(const Extents& e, NormalId faceId);
void snapToGrid(float grid);
Vector3& operator[] (int i);
const Vector3& operator[] (int i) const;
Vector3 getU() const {return (c1 - c0).direction();}
Vector3 getV() const {return (c3 - c0).direction();}
Vector3 getNormal() const {return getU().cross(getV()).direction();}
Vector2 size() const {return Vector2((c1-c0).magnitude(), (c3-c0).magnitude());}
Vector3 center() const {return 0.5 * (c0 + c2);}
// Create new faces
Face toWorldSpace(const CoordinateFrame& objectCoord) const;
Face toObjectSpace(const CoordinateFrame& objectCoord) const;
Face projectOverlapOnMe(const Face& other) const;
// Tests
bool fuzzyContainsInExtrusion(const Vector3& point, float tolerance) const;
static bool cornersAligned(const Face& f0, const Face& f1, float tolerance);
static bool hasOverlap(const Face& f0, const Face& f1, float byAtLeast);
static bool overlapWithinPlanes(const Face& f0, const Face& f1, float tolerance);
};
} // namespace RBX
+29
View File
@@ -0,0 +1,29 @@
/* Copyright 2003-2009 ROBLOX Corporation, All Rights Reserved */
#pragma once
#include "Util/NormalId.h"
namespace RBX {
//A utility class for holding a set of "Faces" associated with an object (top, bottom, left, right, front, back)
class Faces
{
public:
Faces(int normalIdMask = 0);
void clear() { normalIdMask = NORM_NONE_MASK; }
void setNormalId(NormalId normalId, bool value);
bool getNormalId(NormalId normalId) const;
bool operator==(const Faces& other) const {
return normalIdMask == other.normalIdMask;
}
bool operator!=(const Faces& other) const {
return normalIdMask != other.normalIdMask;
}
int normalIdMask;
};
}
+32
View File
@@ -0,0 +1,32 @@
#pragma once
#include "FastLog.h"
#include <string>
#include <boost/filesystem.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/system/error_code.hpp>
DYNAMIC_LOGGROUP(FileSystem)
namespace RBX
{
enum FileSystemDir
{
DirAppData = 0,
DirPicture,
DirVideo,
DirExe
};
namespace FileSystem
{
boost::filesystem::path getUserDirectory(bool create, FileSystemDir dir, const char *subDirectory = 0);
boost::filesystem::path getCacheDirectory(bool create, const char* subDirectory);
boost::filesystem::path getTempFilePath();
boost::filesystem::path getLogsDirectory();
void clearCacheDirectory(const char* subDirectory);
};
} // namespace RBX
+1 -1
View File
@@ -81,7 +81,7 @@ boost::filesystem::path getBaseCacheDirectory(bool create)
boost::filesystem::path path = boost::filesystem::temp_directory_path();
#ifndef RBX_PLATFORM_IOS
path /= "watrbx";
path /= "Roblox";
#endif
#if defined(_DEBUG) || defined(_NOOPT)
+71
View File
@@ -0,0 +1,71 @@
/* Copyright 2003-2005 ROBLOX Corporation, All Rights Reserved */
#pragma once
#include "boost/array.hpp"
#include "rbx/Debug.h"
namespace RBX {
/* USAGE
*/
template<class T, std::size_t N>
class FixedArray
{
private:
boost::array<T, N> data;
size_t num;
public:
FixedArray()
: num(0)
{}
void push_back(const T& x) {
RBXASSERT_VERY_FAST(num < N);
data[num] = x;
++num;
}
void fastRemove(size_t i) {
RBXASSERT_VERY_FAST(i < num);
RBXASSERT_VERY_FAST(num <= N);
data[i] = data[num - 1];
--num;
}
void replace(size_t i, const T& x) {
RBXASSERT_VERY_FAST(i < num);
RBXASSERT_VERY_FAST(num <= N);
data[i] = x;
}
void fastClear() {
num = 0;
}
T operator[](size_t i) {
RBXASSERT_VERY_FAST(i < num);
return data[i];
}
const T operator[](size_t i) const {
RBXASSERT_VERY_FAST(i < num);
return data[i];
}
size_t size() const {
return num;
}
size_t capacity() const
{
return N;
}
};
}// namespace
+36
View File
@@ -0,0 +1,36 @@
#pragma once
namespace RBX {
template<class ElementType, int size=8>
struct FixedSizeCircularBuffer {
private:
ElementType data[size];
unsigned int head;
unsigned int pushed;
public:
FixedSizeCircularBuffer() : head(0), pushed(0) {}
void push(const ElementType& newData) {
head = (head + size - 1) % size;
data[head] = newData;
if (pushed < size) { pushed++; }
}
bool find(const ElementType& key, unsigned int* outIndex) {
for (unsigned int i = 0; i < pushed; ++i) {
if (data[(head + i) % size] == key) {
(*outIndex) = i;
return true;
}
}
return false;
}
const ElementType& operator[](const unsigned int& index) const {
return data[(head + index) % size];
}
};
}
+71
View File
@@ -0,0 +1,71 @@
/* Copyright 2003-2005 ROBLOX Corporation, All Rights Reserved */
#ifndef _70F7A2EE1B6E4dd0AF07E4BFA609A3D1
#define _70F7A2EE1B6E4dd0AF07E4BFA609A3D1
#include "G3D/Vector2.h"
#include "G3D/Vector3.h"
#include "G3D/Vector4.h"
#include "G3D/Matrix3.h"
#include "G3D/Matrix4.h"
#include "G3D/Vector3int16.h"
#include "G3D/Vector2int16.h"
#include "G3D/Color4uint8.h"
#include "G3D/Color3uint8.h"
#include "G3D/CoordinateFrame.h"
#include "G3D/Plane.h"
#include "G3D/Line.h"
#include "G3D/LineSegment.h"
#include "G3D/AABox.h"
#include "G3D/Box.h"
#include "RbxG3D/RbxCamera.h"
#include "G3D/Color3.h"
#include "G3D/Color4.h"
#include "G3D/g3dmath.h"
#include "G3D/Rect2D.h"
#include "G3D/Sphere.h"
#include "G3D/vectorMath.h"
#include "G3D/Debug.h"
// TODO: this can cause namespace collisions:
//using G3D::Array;
namespace RBX {
typedef G3D::Vector2 Vector2;
typedef G3D::Vector3 Vector3;
typedef G3D::Vector4 Vector4;
typedef G3D::Vector2int16 Vector2int16;
typedef G3D::Vector3int16 Vector3int16;
typedef G3D::Color4uint8 Color4uint8;
typedef G3D::Color3uint8 Color3uint8;
typedef G3D::Matrix3 Matrix3;
typedef G3D::Matrix4 Matrix4;
typedef G3D::CoordinateFrame CoordinateFrame;
typedef RBX::RbxRay Ray;
typedef G3D::Plane Plane;
typedef G3D::Line Line;
typedef G3D::LineSegment LineSegment;
typedef G3D::Color3 Color3;
typedef G3D::Color4 Color4;
typedef G3D::Rect2D Rect2D;
typedef G3D::Box Box;
typedef G3D::AABox AABox;
typedef G3D::Sphere Sphere;
enum IntersectResult
{
irNone = 0,
irPartial =1,
irFull = 2
};
}
namespace G3D
{
std::size_t hash_value(const G3D::Vector3& v);
std::size_t hash_value(const G3D::Vector3int16& v);
}
#endif
+12
View File
@@ -0,0 +1,12 @@
/* Copyright 2003-2007 ROBLOX Corporation, All Rights Reserved */
#pragma once
namespace RBX {
namespace Network {
typedef enum {GAME_SERVER, DPHYS_GAME_SERVER, CLIENT, DPHYS_CLIENT, WATCH_ONLINE, VISIT_SOLO, EDIT, LOCAL_PLAY} GameMode;
}
}
+255
View File
@@ -0,0 +1,255 @@
#pragma once
#include <string>
#include <stdlib.h>
#include "util/name.h"
#include "util/Object.h"
#include "rbx/intrusive_ptr_target.h"
#include <boost/intrusive_ptr.hpp>
namespace RBX
{
// A simple class that is a globally unique identifier
class Guid : boost::noncopyable
{
public:
struct Scope
{
public:
Scope() { setNull(); }
void setNull() { name = &RBX::Name::getNullName(); }
bool isNull() const {
return *name == RBX::Name::getNullName();
}
void set( const std::string& s )
{
name = &RBX::Name::declare(s.c_str());
}
void set( const char* s )
{
name = &RBX::Name::declare(s);
}
const RBX::Name* getName() const {
return name;
}
int compare(const Scope& other) const
{
return name->compare(*other.name);
}
bool operator ==(const Scope& other) const {
return name->compare(*other.name) == 0;
}
bool operator <(const Scope& other) const {
return name->compare(*other.name) < 0;
}
static const Scope& null();
private:
static Scope nullScope;
const RBX::Name* name;
};
struct Data
{
Scope scope;
int index;
bool operator ==(const Data& other) const;
bool operator <(const Data& other) const;
// For debugging only. A string that is not guaranteed to be unique
std::string readableString(int scopeLength = 4) const;
};
private:
Data data;
public:
Guid();
bool operator ==(const Guid& other) const { return data == other.data; }
bool operator <(const Guid& other) const { return data < other.data; }
// Compare 2 pairs of Guids. a0-a1 and b0-b1 are commutativity. Any item may be NULL
static int compare(const Guid* a, const Guid* b);
static int compare(const Guid* a0, const Guid* a1, const Guid* b0, const Guid* b1);
// Used for serialization:
void assign(Data data);
void extract(Data &data) const { data = this->data; }
void copyDataFrom(const Guid& other) {
Data data;
other.extract(data);
this->assign(data);
}
// For debugging only. A string that is not guaranteed to be unique
std::string readableString(int scopeLength = 4) const { return data.readableString(scopeLength); }
static const RBX::Guid::Scope& getLocalScope();
static void generateRBXGUID(RBX::Guid::Scope& result);
// Creates a string like this: RBXc200e36038c511ceae6208002b2b79ef
static void generateRBXGUID(std::string& result);
// Creates a string like this: {c200e360-38c5-11ce-ae62-08002b2b79ef}
static void generateStandardGUID(std::string& result);
};
inline size_t hash_value(const Guid::Data& data)
{
size_t result = 0;
boost::hash_combine(result, data.scope.getName());
boost::hash_combine(result, data.index);
return result;
}
// A base class for objects that contain a Guid and that want lookup-by-Guid
template<class T>
class RBXBaseClass GuidItem
{
public:
// A Registry maintains lookup information for Guids.
// Each instance can belong to only one Registry.
// Usually a Registry is associated with a DataModel
class Registry
: public rbx::quick_intrusive_ptr_target<Registry>
{
friend class GuidItem;
typedef boost::unordered_map<Guid::Data, weak_ptr<T> > Map;
Map map;
RBX::mutex mutex;
Registry()
{}
public:
static boost::intrusive_ptr<Registry> create()
{
return boost::intrusive_ptr<Registry>(new Registry());
}
~Registry()
{
RBXASSERT(map.size() ==0);
}
// Returns true for empty Guid data, false for unregistered Guid data
bool lookupByGuid(const Guid::Data& data, shared_ptr<T> &result)
{
if(data.scope.isNull())
{
result.reset();
return true;
}
RBX::mutex::scoped_lock lock(mutex);
typename Map::const_iterator iter = GuidItem::Registry::map.find(data);
if (iter!=map.end())
{
result = iter->second.lock();
}
else
{
result.reset();
}
return !!result;
}
shared_ptr<T> getByGuid(const Guid::Data& data)
{
shared_ptr<T> result;
lookupByGuid(data, result);
return result;
}
// Ensure that this Guid is in the registry (thread-safe)
void registerGuid(const T* item)
{
reg(item);
}
// Assigns a new guid to item. (not thread-safe)
void assignGuid(T* item, const Guid::Data& guidData)
{
if (item->registry)
item->registry->unregister(item);
item->guid.assign(guidData);
reg(item);
item->onGuidChanged();
}
void tryUnregister(GuidItem* item)
{
// In ClientReplicator::streamOutInstance(), we are traverse all the part's descendants and unregister them
// It is possible some descendants have been already GC'd and unregistered earlier from the same GC loop in GCJob::gcRegion()
// Here we simply skip it if the item has already been unregistered.
if (item->registry)
{
unregister(item);
}
}
void unregister(GuidItem* item)
{
RBXASSERT(item->registry.get()==this);
Guid::Data data;
item->guid.extract(data);
{
RBX::mutex::scoped_lock lock(mutex);
int num = map.erase(data);
RBXASSERT(num == 1);
}
item->registry.reset();
}
private:
void reg(const T* item)
{
if (!item->registry)
{
Guid::Data data;
item->guid.extract(data);
RBX::mutex::scoped_lock lock(mutex);
if (!item->registry) // thread-safe check
{
map[data] = weak_from(const_cast<T*>(item));
item->registry = this;
}
}
else
RBXASSERT(item->registry.get()==this);
}
};
friend class Registry;
private:
mutable boost::intrusive_ptr<Registry> registry;
Guid guid;
public:
GuidItem()
{
}
~GuidItem()
{
if (registry)
registry->unregister(this);
}
const Guid& getGuid() const
{
return guid;
}
};
};
+9
View File
@@ -0,0 +1,9 @@
#pragma once
extern "C" {
#ifndef _WIN32
#include <wwwsys.h>
#endif
#include <HTParse.h>
}
+59
View File
@@ -0,0 +1,59 @@
#ifndef _28C82C86EA754d62AF934FA46C3698ED
#define _28C82C86EA754d62AF934FA46C3698ED
#include <functional>
#include <algorithm>
#include <string>
#include "rbx/Debug.h"
#include "Util/Object.h"
#include "Util/Memory.h"
namespace RBX {
namespace Reflection
{
class DescribedBase;
}
// Used to reference RBX::Reflection::DescribedBase in the XmlElement class
class InstanceHandle {
shared_ptr<Reflection::DescribedBase> target;
public:
InstanceHandle() {}
InstanceHandle(Reflection::DescribedBase* target);
InstanceHandle(shared_ptr<Reflection::DescribedBase> target):target(target) {}
InstanceHandle(const InstanceHandle& other):target(other.target) {}
InstanceHandle& operator=(const InstanceHandle& value) {
target = value.target;
return *this;
}
InstanceHandle& operator=(shared_ptr<Reflection::DescribedBase> value) {
target = value;
return *this;
}
bool empty() const;
shared_ptr<Reflection::DescribedBase> getTarget() const { return target; }
void linkTo(shared_ptr<Reflection::DescribedBase> target);
bool operator==(const InstanceHandle& other) const { return operatorEqual(other); }
bool operator!=(const InstanceHandle& other) const { return !operatorEqual(other); }
bool operator<(const InstanceHandle& other) const{ return operatorLess(other); }
bool operator>(const InstanceHandle& other) const{ return operatorGreater(other); }
protected:
bool operatorEqual(const InstanceHandle& other) const;
bool operatorLess(const InstanceHandle& other) const;
bool operatorGreater(const InstanceHandle& other) const;
};
}
#endif
+18
View File
@@ -0,0 +1,18 @@
#pragma once
#include <string>
// A simple hash function from Robert Sedgwicks Algorithms in C book.
namespace RBX {
class Hash {
public:
static unsigned int hash(const void* data, size_t bytes);
static unsigned int hash(const std::string& str);
static void hashAppend(unsigned int& currentHash, const void* data, size_t bytes);
static void hashAppend(unsigned int& currentHash, unsigned int append);
};
} // namespace
+38
View File
@@ -0,0 +1,38 @@
#pragma once
#include <boost/scoped_ptr.hpp>
#include "ObscureValue.h"
#include "FastLog.h"
namespace RBX {
// Wrapper around boost::scoped_ptr that allows it to be used like
// a normal reference to the type (i.e. T& instead of T*).
// Also mildly obscures stored values so that they are harder to find
// with a memory scan.
template<typename T> class HeapValue {
boost::scoped_ptr<ObscureValue<T> > storage;
public:
explicit HeapValue(const T& value) : storage(new ObscureValue<T>(value)) {
}
operator const T() const {
return *storage;
}
HeapValue& operator=(const T& other) {
*storage = other;
return *this;
}
private:
// Disable no-arg construction, copy, and regular assign.
// Some of these may be safe, but they are not needed yet,
// and the safety of this class is easier to understand without
// them.
HeapValue();
HeapValue(const HeapValue&);
HeapValue& operator=(const HeapValue&);
};
}
+35
View File
@@ -0,0 +1,35 @@
/* Copyright 2003-2005 ROBLOX Corporation, All Rights Reserved */
#pragma once
#include "rbx/signal.h"
#include "Util/G3DCore.h"
// hook up by overriding onServiceProvider call in this pattern:
//
// /*override*/ void onServiceProvider(ServiceProvider* oldProvider, ServiceProvider* newProvider) {
// Super::onServiceProvider(oldProvider, newProvider);
// onServiceProviderHeartbeatInstance(oldProvider, newProvider); // hooks up heartbeat
// }
//
namespace RBX {
class Heartbeat;
class ServiceProvider;
class HeartbeatInstance
{
private:
rbx::signals::scoped_connection heartbeatConnection;
protected:
// call this inside onServiceProvider
void onServiceProviderHeartbeatInstance(ServiceProvider* oldProvider, ServiceProvider* newProvider);
/*implement*/ virtual void onHeartbeat(const Heartbeat& event) = 0;
public:
HeartbeatInstance() {}
virtual ~HeartbeatInstance() {}
};
} // namespace RBX
+37
View File
@@ -0,0 +1,37 @@
/* Copyright 2003-2005 ROBLOX Corporation, All Rights Reserved */
#pragma once
#include "Util/G3DCore.h"
#include "Util/NormalId.h"
#include "appdraw/HandleType.h"
namespace RBX {
class Extents;
class HandleHitTest
{
public:
static bool hitTestHandleLocal( const Extents& localExtents,
const CoordinateFrame& location,
HandleType handleType,
const Ray& gridRay,
Vector3& hitPointWorld,
NormalId& localNormalId,
const int normalIdMask = NORM_ALL_MASK);
static bool hitTestHandleWorld( const Extents& worldExtents,
HandleType handleType,
const Ray& gridRay,
Vector3& hitPointWorld,
NormalId& worldNormalId,
const int normalIdMask = NORM_ALL_MASK);
static bool hitTestMoveHandleWorld(const Extents& worldExtents,
const RbxRay& gridRay,
Vector3& hitPointWorld,
NormalId& worldNormalId,
const int normalIdMask = NORM_ALL_MASK);
};
} // namespace RBX
+22
View File
@@ -0,0 +1,22 @@
#pragma once
namespace RBX {
class Primitive;
// Fail: Stop the hit test - don't bore any further down
// Ignore: Keep testing
// Hit: Found something
class HitTestFilter {
public:
typedef enum Result { STOP_TEST,
IGNORE_PRIM,
INCLUDE_PRIM} Result;
virtual Result filterResult(const Primitive* testMe) const = 0;
virtual ~HitTestFilter()
{}
};
} // namespace
+229
View File
@@ -0,0 +1,229 @@
#pragma once
#include <string>
#include <boost/filesystem.hpp>
#include "rbx/atomic.h"
#include "rbx/CEvent.h"
#include "rbx/RunningAverage.h"
#include "rbx/rbxTime.h"
#include "util/HttpAux.h"
DYNAMIC_FASTFLAG(UseAssetTypeHeader)
namespace RBX
{
namespace HttpCache
{
enum Policy
{
// No caching by default.
PolicyDefault,
// Cache based on the final URL (after all 302s).
PolicyFinalRedirect,
};
} // namespace HttpCache
class mutex;
class http_status_error:
public std::runtime_error
{
public:
int statusCode;
http_status_error(int statusCode);
http_status_error(int statusCode, const std::string& message);
};
class Http
{
public:
typedef enum { Uninitialized=-1 ,WinInet=0, WinHttp=1, XboxHttp=2 } API;
enum CookieSharingPolicy
{
CookieSharingUndefined = 0x0,
CookieSharingMultipleProcessesRead = 0x1,
CookieSharingMultipleProcessesWrite = 0x2,
CookieSharingSingleProcessMultipleThreads = 0x4,
};
inline friend CookieSharingPolicy operator|(CookieSharingPolicy a, CookieSharingPolicy b)
{
return static_cast<CookieSharingPolicy>(static_cast<int>(a) | static_cast<int>(b));
}
inline friend CookieSharingPolicy operator|=(CookieSharingPolicy a, CookieSharingPolicy b)
{
return static_cast<CookieSharingPolicy>(static_cast<int>(a) | static_cast<int>(b));
}
static std::string accessKey;
static std::string gameSessionID; // additional header to be sent in POST requests to roblox
static std::string gameID;
static std::string placeID;
static std::string requester;
static std::string rbxUserAgent;
static int playerCount;
static bool useDefaultTimeouts;
// Defined in Utilities.cpp.
static const std::string kGameSessionHeaderKey;
static const std::string kGameIdHeaderKey;
static const std::string kPlaceIdHeaderKey;
static const std::string kRequesterHeaderKey;
static const std::string kPlayerCountHeaderKey;
static const std::string kAccessHeaderKey;
static const std::string kAssetTypeKey;
static const std::string kRBXAuthenticationNegotiation;
static const std::string kContentTypeDefaultUnspecified;
static const std::string kContentTypeUrlEncoded;
static const std::string kContentTypeApplicationJson;
static const std::string kContentTypeApplicationXml;
static const std::string kContentTypeTextPlain;
static const std::string kContentTypeTextXml;
private:
static API defaultApi;
static CookieSharingPolicy cookieSharingPolicy;
std::string alternateUrl; // Used if a CDN fails to deliver and we can try an alternate URL for gets
HttpCache::Policy cachePolicy;
int connectTimeoutMillis;
int responseTimeoutMillis;
int sendTimeoutMillis;
int dataSendTimeoutMillis;
API instanceApi;
static RBX::mutex *robloxResponceLock;
static RBX::mutex *cdnResponceLock;
static std::string lastCsrfToken;
static boost::mutex lastCsrfTokenMutex;
class MutexGuard
{
public:
MutexGuard();
~MutexGuard();
};
static MutexGuard lockGuard;
void init();
public:
static void init(API api, CookieSharingPolicy cookieSharingPolicy);
static void SetUseStatistics(bool value);
static void SetUseCurl(bool value);
static rbx::atomic<int> cdnSuccessCount;
static rbx::atomic<int> cdnFailureCount;
static rbx::atomic<int> alternateCdnSuccessCount;
static rbx::atomic<int> alternateCdnFailureCount;
static double lastCdnFailureTimeSpan;
static rbx::atomic<int> robloxSuccessCount;
static rbx::atomic<int> robloxFailureCount;
static WindowAverage<double, double> robloxResponce;
static WindowAverage<double, double> cdnResponce;
static RBX::mutex *getRobloxResponceLock();
static RBX::mutex *getCdnResponceLock();
std::string url;
Http():instanceApi(defaultApi),url("") { init(); }
Http(const char* url):instanceApi(defaultApi),url(url) { init(); }
Http(const char* url, API api):instanceApi(api),url(url) { init(); }
Http(const std::string& url):instanceApi(defaultApi),url(url) { init(); }
Http(const std::string& url, API api):instanceApi(api),url(url) { init(); }
bool recordStatistics;
bool shouldRetry;
HttpAux::AdditionalHeaders additionalHeaders;
bool doNotUseCachedResponse;
std::string authDomainUrl;
void setAuthDomain(std::string domain)
{
authDomainUrl = domain;
additionalHeaders[kRBXAuthenticationNegotiation] = domain;
}
void setExpectedAssetType(const std::string& type)
{
if (DFFlag::UseAssetTypeHeader && !type.empty())
additionalHeaders[kAssetTypeKey] = type;
}
static void setCookiesForDomain(const std::string& domain, const std::string& cookies);
static void getCookiesForDomain(const std::string& domain, std::string& cookies);
void setResponseTimeout(int timeout) { responseTimeoutMillis = timeout; }
void setSendTimeout(int timeout) { sendTimeoutMillis = timeout; }
void setDataSendTimeout(int timeout) { dataSendTimeoutMillis = timeout; }
void setConnectionTimeout(int timeout) { connectTimeoutMillis = timeout; }
void setCachePolicy(const HttpCache::Policy policy) { cachePolicy = policy; }
// Async
void post(const std::string& input, const std::string& contentType, bool compress, boost::function<void(std::string*, std::exception*)> handler, bool externalRequest = false);
void post(boost::shared_ptr<std::istream> input, const std::string& contentType, bool compress, boost::function<void(std::string *, std::exception*)> handler, bool externalRequest = false);
void get(boost::function<void(std::string*, std::exception*)> handler, bool allowExternal = false);
// Sync
void post(std::istream& input, const std::string& contentType, bool compress, std::string& response, bool externalRequest = false);
void get(std::string& response, bool allowExternal = false);
static bool isExternalRequest(const char* url);
static bool trustCheck(const char* url, bool allowExternal = false);
static bool trustCheckBrowser(const char* url);
static bool isScript(const char* url);
static bool isRobloxSite(const char* url);
static bool isStrictlyRobloxSite(const char* url);
static bool isMoneySite(const char* url);
// Utility
static std::string urlEncode(const std::string& s);
// urlDecode is only tested to work on strings produced from urlEncode
static std::string urlDecode(const std::string& fragment);
void applyAdditionalHeaders(RBX::HttpAux::AdditionalHeaders& outHeaders);
private:
void httpGetPost(bool isPost, std::istream& dataStream, const std::string& contentType, bool compressData, const HttpAux::AdditionalHeaders& additionalHeaders, bool allowExternal, std::string& response, bool forceNativeHttp = false);
#if defined(RBX_PLATFORM_DURANGO)
void httpGetPostXbox(bool isPost, std::istream& dataStream, const std::string& contentType, bool compressData, const HttpAux::AdditionalHeaders& additionalHeaders, bool allowExternal, HttpCache::Policy cachePolicy, std::string& response);
#elif defined(_WIN32)
void httpGetPostWinInet(bool isPost, std::istream& dataStream, const std::string& contentType, bool compressData, const HttpAux::AdditionalHeaders& additionalHeaders, bool allowExternal, std::string& response);
void httpGetPostWinHttp(bool isPost, std::istream& dataStream, const std::string& contentType, bool compressData, const HttpAux::AdditionalHeaders& additionalHeaders, bool allowExternal, std::string& response);
#elif defined(__APPLE__)
void httpGetPostImpl(bool isPost, std::istream& dataStream, const std::string& contentType, bool compressData, const HttpAux::AdditionalHeaders& additionalHeaders, bool allowExternal, std::string& response);
#endif
bool doHttpGetPostWithNativeFallbackForReporting(bool isPost, std::istream& dataStream, const std::string& contentType, bool compressData, const HttpAux::AdditionalHeaders& additionalHeaders, bool allowExternal, std::string& response);
void ThrowIfFailure(bool success, const char* message);
#ifdef _WIN32
static void setCookiesForDomainWinInet(const std::string& domain, const std::string& cookies);
#endif
public:
#ifdef _WIN32
void onWinHttpRedirect(unsigned long dwInternetStatus, std::string redirectUrl);
#endif
static void ThrowIfFailure(bool success, const char* url, const char* message);
#if defined(_WIN32) && !defined(RBX_PLATFORM_DURANGO)
static void ThrowLastError(int error, const char* url, const char* message);
#endif
static void setProxy(const std::string& host, long port = 0);
// These methods are not safe to be called from static initializers, because they rely on
// static member variables (which don't have order guarantees wrt other static initializers).
static std::string getLastCsrfToken();
static void setLastCsrfToken(const std::string& newToken);
};
}
+57
View File
@@ -0,0 +1,57 @@
#pragma once
#include <string>
#include <istream>
#include <boost/thread/future.hpp>
#include <boost/unordered_map.hpp>
#include "util/HttpAux.h"
namespace RBX
{
typedef boost::shared_future<std::string> HttpFuture;
class HttpOptions
{
friend class HttpAsync;
public:
HttpOptions()
: external(false)
, doNotUseCachedResponse(false)
{
}
void addHeader(const std::string& key, const std::string& value);
void setExternal(bool value);
void setDoNotUseCachedResponse();
private:
HttpAux::AdditionalHeaders headers;
bool external;
bool doNotUseCachedResponse;
};
class HttpPostData
{
friend class HttpAsync;
public:
HttpPostData(const std::string& contents, const std::string& contentType, bool compress);
HttpPostData(const boost::shared_ptr<std::istream>& contents, const std::string& contentType, bool compress);
private:
boost::shared_ptr<std::istream> data;
std::string contentType;
bool compress;
};
class HttpAsync
{
public:
static HttpFuture get(const std::string& url, const HttpOptions& options = HttpOptions());
static HttpFuture getWithRetries(const std::string& url, int retryCount, const HttpOptions& options = HttpOptions());
static HttpFuture post(const std::string& url, const HttpPostData& postData, const HttpOptions& options = HttpOptions());
};
}
+12
View File
@@ -0,0 +1,12 @@
#pragma once
#include <string>
#include <boost/unordered_map.hpp>
namespace RBX
{
namespace HttpAux
{
typedef boost::unordered_map<std::string, std::string> AdditionalHeaders;
} // namespace HttpAux
} // namespace RBX
+207
View File
@@ -0,0 +1,207 @@
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include "util/Http.h"
#include "util/HttpAux.h"
#include "util/FileSystem.h"
#include "util/NamedMutex.h"
#include "rbx/Debug.h"
#include <boost/filesystem.hpp>
namespace RBX
{
namespace HttpPlatformImpl
{
namespace Cache
{
// Given a url, provide hashed file location on disk.
boost::filesystem::path cacheFilePath(const char* url);
struct Header
{
#define RBX_CACHE_FILE_MAGIC 0x52425848 // RBXH
#define RBX_CACHE_FILE_VERSION 0x1
#define RBX_CACHE_URL_MAX_LENGTH 1024U
const uint32_t magic;
const uint32_t version;
const uint32_t urlBytes;
const uint8_t url[RBX_CACHE_URL_MAX_LENGTH]; // not null-terminated
const uint32_t responseCode;
const uint32_t responseHeadersSize;
const uint32_t responseHeadersHash;
const uint32_t responseBodySize;
const uint32_t responseBodyHash;
const uint32_t reserved;
};
class Data
{
const uint8_t* underlying;
const size_t bytes;
public:
Data(const uint8_t* data, const size_t bytes) :
underlying(data), bytes(bytes)
{}
Data(const char* data, const size_t bytes) :
underlying(reinterpret_cast<const uint8_t*>(data)), bytes(bytes)
{
RBXASSERT(sizeof(char) == sizeof(uint8_t));
}
uint8_t operator[](size_t index) const
{
return underlying[index];
}
const uint8_t* data() const
{
return underlying;
}
std::string toString() const
{
std::string result;
result.assign(underlying, underlying+bytes);
return result;
}
size_t size() const
{
return bytes;
}
};
// The data in this structure is read-only, and if you
// want to update the underlying data, you must do it via
// the update() method.
struct CacheEntry // Word-aligned data structure
{
Header cacheHeader;
uint8_t data[1];
const Data getResponseHeader() const;
const Data getResponseBody() const;
CacheEntry(const Header& cacheHeader, const Data& responseHeaders, const Data& responseBody);
};
class CacheResult
{
boost::shared_ptr<CacheEntry> cacheEntry;
size_t cacheSize;
const std::string invalidReason;
public:
explicit CacheResult(const std::string& invalidReason) : invalidReason(invalidReason)
{}
explicit CacheResult( shared_ptr<CacheEntry> entry, size_t size)
: cacheEntry(entry), cacheSize(size)
{
RBXASSERT(size);
}
bool isValid() const
{
return NULL != cacheEntry;
}
const std::string& getInvalidReason() const
{
return invalidReason;
}
const Header& getCacheHeader() const
{
return cacheEntry->cacheHeader;
}
const Data getResponseHeader() const
{
return cacheEntry->getResponseHeader();
}
const Data getResponseBody() const
{
return cacheEntry->getResponseBody();
}
const size_t size() const
{
return cacheSize;
}
// Converts the URL to a known location on disk and tries to open and return that file.
// Returns NULL if file could not be opened.
static CacheResult open(const char* assetUrl, const char* cdnUrl);
// Atomically update the file with new data and returned a new CacheEntry to it.
static CacheResult update(const char* assetUrl, const char* cdnUrl, const uint32_t responseCode, const Data& headers, const Data& body);
};
struct CacheCleanOptions
{
size_t numFilesRequiredBeforeCleaning;
size_t numFilesToKeep;
size_t numGigaBytesAvailableTrigger;
bool flagCleanUpBasedOnMemory;
};
void cleanCache(const CacheCleanOptions& options);
} // namespace Cache
struct HttpOptions
{
// Basic data
const std::string& url;
bool externalRequest;
HttpCache::Policy cachePolicy;
// Connection handling information
long connectTimeoutMillis;
long performTimeoutMillis;
// Post data
std::istream* postData;
bool compressedPostData;
// Header data
std::string const* hdrContentType;
HttpAux::AdditionalHeaders const* addlHeaders;
HttpOptions(const std::string& url, bool externalRequest, HttpCache::Policy cachePolicy, long connectTimeoutMillis, long performTimeoutMillis)
:url(url)
,externalRequest(externalRequest)
,cachePolicy(cachePolicy)
,connectTimeoutMillis(connectTimeoutMillis)
,performTimeoutMillis(performTimeoutMillis)
,postData(NULL)
,hdrContentType(NULL)
,addlHeaders(NULL)
{}
void setPostData(std::istream* dataStream, bool compressed)
{
postData = dataStream;
compressedPostData = compressed;
}
void setHeaders(const std::string* contentType, const HttpAux::AdditionalHeaders* headers)
{
hdrContentType = contentType;
addlHeaders = headers;
}
}; // struct HttpOptions
void init(Http::CookieSharingPolicy cookieSharingPolicy); // NOTE: This call is not thread-safe.
void setCookiesForDomain(const std::string& domain, const std::string& cookies);
void getCookiesForDomain(const std::string& domain, std::string& cookies);
boost::filesystem::path getRobloxCookieJarPath();
void setProxy(const std::string& host, long port = 0);
void perform(HttpOptions& options, std::string& response);
} // namespace HttpPlatformImpl
} // namespace RBX
+24
View File
@@ -0,0 +1,24 @@
/* Copyright 2003-2006 ROBLOX Corporation, All Rights Reserved */
#pragma once
#include "Util/G3DCore.h"
#include "rbx/Declarations.h"
namespace RBX {
//
// http://www.parashift.com/c++-faq-lite/multiple-inheritance.html#faq-25.10
// This is a virtual base class - see note above. Any object that descends from it
// should use the "virtual" keyword, so only one is included.
//
class RBXInterface IHasLocation
{
public:
virtual const CoordinateFrame getLocation() = 0;
virtual ~IHasLocation() {}
};
} // namespace
+20
View File
@@ -0,0 +1,20 @@
/* Copyright 2003-2005 ROBLOX Corporation, All Rights Reserved */
#pragma once
#include "rbx/Debug.h"
// Simple class for returning metric values - used for graphics reporting
namespace RBX {
class RBXInterface IMetric
{
public:
IMetric() {}
virtual ~IMetric() {}
virtual std::string getMetric(const std::string& metric) const = 0;
virtual double getMetricValue(const std::string& metric) const = 0;
};
} // namespace
+154
View File
@@ -0,0 +1,154 @@
/* Copyright 2003-2005 ROBLOX Corporation, All Rights Reserved */
#pragma once
#include "boost/utility.hpp"
#include "util/utilities.h"
#include "Util/G3DCore.h"
#include "rbx/Debug.h"
#include "G3D/Array.h"
namespace RBX {
/* USAGE
class C
{
private:
int index;
public:
C() : index(-1) {}
~C() {RBXASSERT(index == -1);}
int& getIndex() {return index;}
};
main()
{
IndexArray<C, &C::getIndex> array;
C* c = new C();
C c2;
array.fastAppend(c);
array.fastAppend(&c2);
array.fastRemove(c)
array.fastRemove(&c2);
}
*/
template <class Item, int& (Item::*getIndex)()>
class IndexArray
: public boost::noncopyable // You can't copy elements from one array to another
// since the index values can't be shared.
{
private:
G3D::Array<Item*> array;
int& indexOf(Item* item) const {
return (item->*getIndex)();
}
public:
typedef Item** Iterator;
typedef const Item** ConstIterator;
inline void fastAppend(Item* item)
{
RBXASSERT(item);
RBXASSERT(indexOf(item) == -1);
RBXASSERT_IF_VALIDATING(array.find(item) == array.end());
indexOf(item) = array.size();
array.append(item);
}
inline void fastRemove(Item* item)
{
RBXASSERT_IF_VALIDATING(array.find(item) != array.end());
int removeIndex = indexOf(item);
RBXASSERT(removeIndex >= 0);
RBXASSERT(array[removeIndex] == item);
// Move last item to removal index
Item* oldLast = array.last(); // if array size == 1, this is redundant
array[removeIndex] = oldLast;
indexOf(oldLast) = removeIndex;
array.pop(false);
// Update indices
indexOf(item) = -1;
}
inline void remove(Item* item)
{
RBXASSERT_IF_VALIDATING(array.find(item) != array.end());
int removeIndex = indexOf(item);
RBXASSERT(removeIndex >= 0);
RBXASSERT(array[removeIndex] == item);
// Move all the items back in the array.
for (int i = removeIndex; i < array.size() - 1; i++)
{
Item* nextItem = array[i + 1];
array[i] = nextItem;
indexOf(nextItem) = i;
}
array.pop(false);
// Update indices
indexOf(item) = -1;
}
inline bool fastContains(Item* item) const
{
bool answer = (indexOf(item) >= 0);
RBXASSERT_IF_VALIDATING(answer == underlyingArray().contains(item));
return answer;
}
G3D::Array<Item*>& underlyingArray() {
return array;
}
const G3D::Array<Item*>& underlyingArray() const {
return array;
}
inline Item* operator[](int n) {
RBXASSERT(indexOf(array[n]) == n);
return array[n];
}
inline Item* operator[](unsigned int n) {
RBXASSERT(indexOf(array[n]) == n);
return array[n];
}
inline Item* const operator[](int n) const { // the pointer is const?
RBXASSERT(indexOf(array[n]) == n);
return array[n];
}
inline Item* const operator[](unsigned int n) const { // the pointer is const?...
RBXASSERT(indexOf(array[n]) == n);
return array[n];
}
inline int size() const {
return array.size();
}
};
}// namespace
+108
View File
@@ -0,0 +1,108 @@
/* Copyright 2003-2005 ROBLOX Corporation, All Rights Reserved */
#pragma once
#include "Util/G3DCore.h"
namespace RBX {
class IndexBox {
private:
/**
Looking from positive X back through to negative X, z is left, y is up
0 1 4 5
2 3 6 7
front back (seen through front)
*/
Vector3 corner[8];
public:
IndexBox();
IndexBox(
const Vector3& min,
const Vector3& max);
virtual ~IndexBox() {}
Vector3 getCenter() const;
Vector3 getCorner(int i) const {
return corner[i];
}
Vector3 getFaceNormal(int f) const {
return Vector3( INDEXBOX_FACE_TO_NORMAL[f][0],
INDEXBOX_FACE_TO_NORMAL[f][1],
INDEXBOX_FACE_TO_NORMAL[f][2]);
}
Vector3 getEdgeNormal(int f, int e) const {
return getFaceNormal(INDEXBOX_FACE_EDGE_TO_NORMAL[f][e]);
}
/**
Returns the four corners of a face (0 <= f < 6).
The corners are returned to form a counter clockwise quad facing outwards.
*/
void getFaceCorners(
int f,
Vector3& v0,
Vector3& v1,
Vector3& v2,
Vector3& v3) const;
/** The edge travels from v0 to v1. nR is to the right and nL is to the left.*/
void getEdge(
int e,
Vector3& v0,
Vector3& v1,
Vector3& nL,
Vector3& nR) const;
void getEdge(
int e,
Vector4& v0,
Vector4& v1,
Vector3& nL,
Vector3& nR) const;
static void getTextureCornersCentered(
int f,
const Vector3& halfSize,
Vector2& t0,
Vector2& t1,
Vector2& t2,
Vector2& t3);
static void getTextureCornersGrid(
int f,
const Vector3& halfSize,
Vector2& t0,
Vector2& t1,
Vector2& t2,
Vector2& t3);
/**
Returns true if this IndexBox is culled by the provided set of
planes. The IndexBox is culled if there exists at least one plane
whose halfspace the entire IndexBox is not in.
*/
bool culledBy(
const Plane* plane,
int numPlanes) const;
bool contains(
const Vector3& point) const;
static const int INDEXBOX_FACE_TO_VERTEX[6][4];
static const float INDEXBOX_FACE_TO_NORMAL[6][3];
static const int INDEXBOX_FACE_EDGE_TO_NORMAL[6][4];
/** normal indices are into INDEXBOX_FACE_TO_NORMAL array */
static const int INDEXBOX_EDGE_TO_VERTEX_AND_NORMALS[12][4];
};
} // namespace
+138
View File
@@ -0,0 +1,138 @@
/* Copyright 2003-2006 ROBLOX Corporation, All Rights Reserved */
#pragma once
#include "Util/IndexedTree.h"
/*
used ad the basis for the Primitive / Clump / Assembly / Mechanism / SimJob data structures
Up: Parent
Down: Child
Right: Upper
Left: Lower
Primitive <-> Clump <-> Assembly <-> Mechanism
A
|
Primitive
A A
| |
Primitive
A
|
Primitive <-> Clump A
A |
|
Primitive
A A
| |
Primitive
A
|
Primitive <-> Clump <-> Assembly
*/
namespace RBX {
class IndexedMesh : public IndexedTree
{
private:
IndexedMesh* upper; // could be null - only exists if direct connection to upper
IndexedMesh* lower; // could be null - only exists if direct connection to upper
IndexedMesh* computedUpper; // should == computeUpper;
protected:
// TODO: Make these protected
IndexedMesh* getUpper() {return upper;}
IndexedMesh* getLower() {return lower;}
const IndexedMesh* getConstUpper() const {return upper;}
const IndexedMesh* getConstLower() const {return lower;}
private:
const IndexedMesh* computeParentFromLower() const;
void setComputedUpper(IndexedMesh* newComputedUpper);
void setLower(IndexedMesh* newLower);
void severeChildren(IndexedMesh* lowerChild);
void attachChildren(IndexedMesh* lowerChild);
void lowersChanged() { // cycles up to the parent, calling onLowersChanged();
onLowersChanged();
if (getTypedParent<IndexedMesh>()) {
getTypedParent<IndexedMesh>()->lowersChanged();
}
if (getUpper()) {
getUpper()->lowersChanged();
}
}
static IndexedMesh* computeUpper(IndexedMesh* lower);
static const IndexedMesh* computeConstUpper(const IndexedMesh* lower);
void onLowerChildRemoved(IndexedMesh* lowerChild);
void onLowerChildAdded(IndexedMesh* lowerChild);
//////////////////////////////////////////////////
//
// Indexed Tree
/*override*/ void onParentChanged(IndexedTree* oldParent);
protected:
/*implement*/ virtual void onLowersChanged() {}
public:
IndexedMesh();
IndexedMesh(IndexedMesh* lower, IndexedMesh* parent);
~IndexedMesh();
IndexedMesh* getIndexedMeshParent(); // same as getTypedParent, but with bug checking
const IndexedMesh* getConstIndexedMeshParent() const; // same as getTypedParent, but with bug checking
void setUpper(IndexedMesh* newUpper);
template<class Type>
Type* getTypedLower() {
return rbx_static_cast<Type*>(getLower());
}
template<class Type>
const Type* getConstTypedLower() const {
return rbx_static_cast<const Type*>(getConstLower());
}
template<class Type>
Type* getTypedUpper() {
return rbx_static_cast<Type*>(getUpper());
}
template<class Type>
const Type* getConstTypedUpper() const {
return rbx_static_cast<const Type*>(getConstUpper());
}
IndexedMesh* getComputedUpper();
const IndexedMesh* getConstComputedUpper() const;
static bool isUpperRoot(const IndexedMesh* lower);
template<class Type, class Func>
inline void visitMeAndChildrenWhileNoUpper(Func func) // hack - for iterating all assemblies in a mechanism
{
Type* t = rbx_static_cast<Type*>(this);
func(t);
for (int i = 0; i < numChildren(); ++i) {
Type* child = getTypedChild<Type>(i);
IndexedMesh* childUpper = child->getUpper();
if (!childUpper)
{
child->visitMeAndChildrenWhileNoUpperUppers(func);
}
}
}
};
} // namespace
+132
View File
@@ -0,0 +1,132 @@
/* Copyright 2003-2006 ROBLOX Corporation, All Rights Reserved */
#pragma once
#include "rbx/Declarations.h"
#include "Util/IndexArray.h"
#include "rbx/Debug.h"
namespace RBX {
class RBXBaseClass IndexedTree
{
private:
IndexedTree* parent;
int index;
int& getIndex() {return index;}
IndexArray<IndexedTree, &IndexedTree::getIndex> children;
bool circularReference(IndexedTree* newAncestor, IndexedTree* child);
protected:
virtual void onParentChanging() {}
virtual void onParentChanged(IndexedTree* oldParent) {}
virtual void onChildAdding(IndexedTree* child) {}
virtual void onChildAdded(IndexedTree* child) {}
virtual void onChildRemoving(IndexedTree* child) {}
virtual void onChildRemoved(IndexedTree* child) {}
virtual void onAncestorChanged() {}
void setIndexedTreeParent(IndexedTree* newParent);
public:
IndexedTree();
virtual ~IndexedTree();
int numChildren() const {return children.size();}
template<class Type>
Type* getTypedChild(int i) {
return rbx_static_cast<Type*>(children[i]);
}
template<class Type>
const Type* getConstTypedChild(int i) const {
return rbx_static_cast<Type*>(children[i]);
}
template<class Type>
Type* getTypedParent() {
return rbx_static_cast<Type*>(parent);
}
template<class Type>
const Type* getConstTypedParent() const {
return rbx_static_cast<Type*>(parent);
}
template<class Type>
Type* getRoot() {
return (parent)
? parent->getRoot<Type>()
: rbx_static_cast<Type*>(this);
}
template<class Type>
const Type* getRoot() const {
return (parent)
? parent->getRoot<Type>()
: rbx_static_cast<const Type*>(this);
}
template<class Type>
Type* getOneBelowRoot() {
IndexedTree* above = parent;
RBXASSERT(above != NULL);
IndexedTree* answer = this;
while (above->parent) {
answer = above;
above = above->parent;
}
return rbx_static_cast<Type*>(answer);
}
int getDepth() const {
return parent ? (parent->getDepth() + 1) : 1;
}
template<class Type, class Func>
inline void visitMeAndChildren(Func func)
{
Type* t = rbx_static_cast<Type*>(this);
func(t);
for (int i = 0; i < children.size(); ++i) {
children[i]->visitMeAndChildren<Type, Func>(func);
}
}
template<class Type, class Func>
inline void visitConstMeAndChildren(Func func)
{
const Type* t = rbx_static_cast<const Type*>(this);
func(t);
for (int i = 0; i < children.size(); ++i) {
children[i]->visitConstMeAndChildren<Type, Func>(func);
}
}
template<class Type, class Func>
inline void visitDescendents(Func func)
{
for (int i = 0; i < children.size(); ++i) {
children[i]->visitMeAndChildren<Type, Func>(func);
}
}
template<class Type, class Func>
inline void visitConstDescendents(Func func) const
{
for (int i = 0; i < children.size(); ++i) {
children[i]->visitConstMeAndChildren<Type, Func>(func);
}
}
};
} // namespace
+14
View File
@@ -0,0 +1,14 @@
#pragma once
// A simple hash function from Robert Sedgwicks Algorithms in C book.
namespace RBX {
typedef enum {INSERT_RAW, INSERT_TO_TREE, INSERT_TO_3D_VIEW} InsertMode;
typedef enum {
PUT_TOOL_IN_STARTERPACK, // The user has been prompted about putting a tool into the starter pack
SUPPRESS_PROMPTS}
PromptMode;
} // namespace
+326
View File
@@ -0,0 +1,326 @@
#pragma once
// This code was adapted from SDL via GNU license below
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken@libsdl.org
*/
namespace RBX {
enum KeyCode {
SDLK_UNKNOWN = 0,
SDLK_BACKSPACE = 8,
SDLK_TAB = 9,
SDLK_CLEAR = 12,
SDLK_RETURN = 13,
SDLK_PAUSE = 19,
SDLK_ESCAPE = 27,
SDLK_SPACE = 32,
SDLK_EXCLAIM = 33,
SDLK_QUOTEDBL = 34,
SDLK_HASH = 35,
SDLK_DOLLAR = 36,
SDLK_PERCENT = 37,
SDLK_AMPERSAND = 38,
SDLK_QUOTE = 39,
SDLK_LEFTPAREN = 40,
SDLK_RIGHTPAREN = 41,
SDLK_ASTERISK = 42,
SDLK_PLUS = 43,
SDLK_COMMA = 44,
SDLK_MINUS = 45,
SDLK_PERIOD = 46,
SDLK_SLASH = 47,
SDLK_0 = 48,
SDLK_1 = 49,
SDLK_2 = 50,
SDLK_3 = 51,
SDLK_4 = 52,
SDLK_5 = 53,
SDLK_6 = 54,
SDLK_7 = 55,
SDLK_8 = 56,
SDLK_9 = 57,
SDLK_COLON = 58,
SDLK_SEMICOLON = 59,
SDLK_LESS = 60,
SDLK_EQUALS = 61,
SDLK_GREATER = 62,
SDLK_QUESTION = 63,
SDLK_AT = 64,
/*
Skip uppercase letters
*/
SDLK_LEFTBRACKET = 91,
SDLK_BACKSLASH = 92,
SDLK_RIGHTBRACKET = 93,
SDLK_CARET = 94,
SDLK_UNDERSCORE = 95,
SDLK_BACKQUOTE = 96,
SDLK_a = 97,
SDLK_b = 98,
SDLK_c = 99,
SDLK_d = 100,
SDLK_e = 101,
SDLK_f = 102,
SDLK_g = 103,
SDLK_h = 104,
SDLK_i = 105,
SDLK_j = 106,
SDLK_k = 107,
SDLK_l = 108,
SDLK_m = 109,
SDLK_n = 110,
SDLK_o = 111,
SDLK_p = 112,
SDLK_q = 113,
SDLK_r = 114,
SDLK_s = 115,
SDLK_t = 116,
SDLK_u = 117,
SDLK_v = 118,
SDLK_w = 119,
SDLK_x = 120,
SDLK_y = 121,
SDLK_z = 122,
SDLK_LEFTCURLY = 123,
SDLK_PIPE = 124,
SDLK_RIGHTCURLY = 125,
SDLK_TILDE = 126,
SDLK_DELETE = 127,
/* End of ASCII mapped keysyms */
/* International keyboard syms */
SDLK_WORLD_0 = 160, /* 0xA0 */
SDLK_WORLD_1 = 161,
SDLK_WORLD_2 = 162,
SDLK_WORLD_3 = 163,
SDLK_WORLD_4 = 164,
SDLK_WORLD_5 = 165,
SDLK_WORLD_6 = 166,
SDLK_WORLD_7 = 167,
SDLK_WORLD_8 = 168,
SDLK_WORLD_9 = 169,
SDLK_WORLD_10 = 170,
SDLK_WORLD_11 = 171,
SDLK_WORLD_12 = 172,
SDLK_WORLD_13 = 173,
SDLK_WORLD_14 = 174,
SDLK_WORLD_15 = 175,
SDLK_WORLD_16 = 176,
SDLK_WORLD_17 = 177,
SDLK_WORLD_18 = 178,
SDLK_WORLD_19 = 179,
SDLK_WORLD_20 = 180,
SDLK_WORLD_21 = 181,
SDLK_WORLD_22 = 182,
SDLK_WORLD_23 = 183,
SDLK_WORLD_24 = 184,
SDLK_WORLD_25 = 185,
SDLK_WORLD_26 = 186,
SDLK_WORLD_27 = 187,
SDLK_WORLD_28 = 188,
SDLK_WORLD_29 = 189,
SDLK_WORLD_30 = 190,
SDLK_WORLD_31 = 191,
SDLK_WORLD_32 = 192,
SDLK_WORLD_33 = 193,
SDLK_WORLD_34 = 194,
SDLK_WORLD_35 = 195,
SDLK_WORLD_36 = 196,
SDLK_WORLD_37 = 197,
SDLK_WORLD_38 = 198,
SDLK_WORLD_39 = 199,
SDLK_WORLD_40 = 200,
SDLK_WORLD_41 = 201,
SDLK_WORLD_42 = 202,
SDLK_WORLD_43 = 203,
SDLK_WORLD_44 = 204,
SDLK_WORLD_45 = 205,
SDLK_WORLD_46 = 206,
SDLK_WORLD_47 = 207,
SDLK_WORLD_48 = 208,
SDLK_WORLD_49 = 209,
SDLK_WORLD_50 = 210,
SDLK_WORLD_51 = 211,
SDLK_WORLD_52 = 212,
SDLK_WORLD_53 = 213,
SDLK_WORLD_54 = 214,
SDLK_WORLD_55 = 215,
SDLK_WORLD_56 = 216,
SDLK_WORLD_57 = 217,
SDLK_WORLD_58 = 218,
SDLK_WORLD_59 = 219,
SDLK_WORLD_60 = 220,
SDLK_WORLD_61 = 221,
SDLK_WORLD_62 = 222,
SDLK_WORLD_63 = 223,
SDLK_WORLD_64 = 224,
SDLK_WORLD_65 = 225,
SDLK_WORLD_66 = 226,
SDLK_WORLD_67 = 227,
SDLK_WORLD_68 = 228,
SDLK_WORLD_69 = 229,
SDLK_WORLD_70 = 230,
SDLK_WORLD_71 = 231,
SDLK_WORLD_72 = 232,
SDLK_WORLD_73 = 233,
SDLK_WORLD_74 = 234,
SDLK_WORLD_75 = 235,
SDLK_WORLD_76 = 236,
SDLK_WORLD_77 = 237,
SDLK_WORLD_78 = 238,
SDLK_WORLD_79 = 239,
SDLK_WORLD_80 = 240,
SDLK_WORLD_81 = 241,
SDLK_WORLD_82 = 242,
SDLK_WORLD_83 = 243,
SDLK_WORLD_84 = 244,
SDLK_WORLD_85 = 245,
SDLK_WORLD_86 = 246,
SDLK_WORLD_87 = 247,
SDLK_WORLD_88 = 248,
SDLK_WORLD_89 = 249,
SDLK_WORLD_90 = 250,
SDLK_WORLD_91 = 251,
SDLK_WORLD_92 = 252,
SDLK_WORLD_93 = 253,
SDLK_WORLD_94 = 254,
SDLK_WORLD_95 = 255, /* 0xFF */
/* Numeric keypad */
SDLK_KP0 = 256,
SDLK_KP1 = 257,
SDLK_KP2 = 258,
SDLK_KP3 = 259,
SDLK_KP4 = 260,
SDLK_KP5 = 261,
SDLK_KP6 = 262,
SDLK_KP7 = 263,
SDLK_KP8 = 264,
SDLK_KP9 = 265,
SDLK_KP_PERIOD = 266,
SDLK_KP_DIVIDE = 267,
SDLK_KP_MULTIPLY = 268,
SDLK_KP_MINUS = 269,
SDLK_KP_PLUS = 270,
SDLK_KP_ENTER = 271,
SDLK_KP_EQUALS = 272,
/* Arrows + Home/End pad */
SDLK_UP = 273,
SDLK_DOWN = 274,
SDLK_RIGHT = 275,
SDLK_LEFT = 276,
SDLK_INSERT = 277,
SDLK_HOME = 278,
SDLK_END = 279,
SDLK_PAGEUP = 280,
SDLK_PAGEDOWN = 281,
/* Function keys */
SDLK_F1 = 282,
SDLK_F2 = 283,
SDLK_F3 = 284,
SDLK_F4 = 285,
SDLK_F5 = 286,
SDLK_F6 = 287,
SDLK_F7 = 288,
SDLK_F8 = 289,
SDLK_F9 = 290,
SDLK_F10 = 291,
SDLK_F11 = 292,
SDLK_F12 = 293,
SDLK_F13 = 294,
SDLK_F14 = 295,
SDLK_F15 = 296,
/* Key state modifier keys */
SDLK_NUMLOCK = 300,
SDLK_CAPSLOCK = 301,
SDLK_SCROLLOCK = 302,
SDLK_RSHIFT = 303,
SDLK_LSHIFT = 304,
SDLK_RCTRL = 305,
SDLK_LCTRL = 306,
SDLK_RALT = 307,
SDLK_LALT = 308,
SDLK_RMETA = 309,
SDLK_LMETA = 310,
SDLK_LSUPER = 311, /* Left "Windows" key */
SDLK_RSUPER = 312, /* Right "Windows" key */
SDLK_MODE = 313, /* "Alt Gr" key */
SDLK_COMPOSE = 314, /* Multi-key compose key */
/* Miscellaneous function keys */
SDLK_HELP = 315,
SDLK_PRINT = 316,
SDLK_SYSREQ = 317,
SDLK_BREAK = 318,
SDLK_MENU = 319,
SDLK_POWER = 320, /* Power Macintosh power key */
SDLK_EURO = 321, /* Some european keyboards */
SDLK_UNDO = 322, /* Atari keyboard has Undo */
/* Add any other keys here */
// ROBLOX Gamepad stuff
SDLK_GAMEPAD_BUTTONX = 1000,
SDLK_GAMEPAD_BUTTONY = 1001,
SDLK_GAMEPAD_BUTTONA = 1002,
SDLK_GAMEPAD_BUTTONB = 1003,
SDLK_GAMEPAD_BUTTONR1 = 1004,
SDLK_GAMEPAD_BUTTONL1 = 1005,
SDLK_GAMEPAD_BUTTONR2 = 1006,
SDLK_GAMEPAD_BUTTONL2 = 1007,
SDLK_GAMEPAD_BUTTONR3 = 1008,
SDLK_GAMEPAD_BUTTONL3 = 1009,
SDLK_GAMEPAD_BUTTONSTART = 1010,
SDLK_GAMEPAD_BUTTONSELECT = 1011,
SDLK_GAMEPAD_DPADLEFT = 1012,
SDLK_GAMEPAD_DPADRIGHT = 1013,
SDLK_GAMEPAD_DPADUP = 1014,
SDLK_GAMEPAD_DPADDOWN = 1015,
SDLK_GAMEPAD_THUMBSTICK1 = 1016,
SDLK_GAMEPAD_THUMBSTICK2 = 1017,
SDLK_LAST
};
enum ModCode {
KMOD_NONE = 0x0000,
KMOD_LSHIFT= 0x0001,
KMOD_RSHIFT= 0x0002,
KMOD_LCTRL = 0x0040,
KMOD_RCTRL = 0x0080,
KMOD_LALT = 0x0100,
KMOD_RALT = 0x0200,
KMOD_LMETA = 0x0400,
KMOD_RMETA = 0x0800,
KMOD_NUM = 0x1000,
KMOD_CAPS = 0x2000,
KMOD_MODE = 0x4000,
KMOD_RESERVED = 0x8000
};
} // namespace
+9
View File
@@ -0,0 +1,9 @@
#pragma once
namespace RBX {
typedef enum KeywordFilterType { INCLUDE_KEYWORDS = 0,
EXCLUDE_KEYWORDS } KeywordFilterType;
} // namespace RBX
+267
View File
@@ -0,0 +1,267 @@
#pragma once
#include <list>
#include <vector>
#include <boost/unordered_map.hpp>
#include "Util/StandardOut.h"
namespace RBX
{
template<class Key, class Data>
class LRUCache
{
public:
typedef std::list< std::pair< Key, std::pair<unsigned long, Data> > > List; ///< Main cache storage typedef
typedef typename List::iterator List_Iter; ///< Main cache iterator
typedef typename List::const_iterator List_cIter; ///< Main cache iterator (const)
typedef boost::unordered_map<Key, List_Iter> Map; ///< Index typedef
typedef typename Map::iterator Map_Iter; ///< Index iterator
typedef typename Map::const_iterator Map_cIter; ///< Index iterator (const)
protected:
/// Main cache storage
List list;
/// Cache storage index
Map index;
unsigned long totalMemory;
public:
LRUCache() : totalMemory(0) {}
~LRUCache()
{
this->clear();
}
inline void printContentNames()
{
for(List_Iter iter = list.begin(); iter != list.end(); ++iter)
{
StandardOut::singleton()->printf(RBX::MESSAGE_INFO, "%s", iter->first.c_str());
}
}
inline unsigned long size()
{
return list.size();
}
inline unsigned long memSize()
{
return this->totalMemory;
}
inline void clear()
{
list.clear();
index.clear();
totalMemory = 0;
}
inline bool exists( const Key &key ) const
{
return index.find( key ) != index.end();
}
inline bool empty() const
{
return list.empty();
}
inline bool remove( const Key &key )
{
Map_Iter miter = index.find( key );
if( miter == index.end() ) return false;
remove( miter );
return true;
}
/*inline void touch( const Key &key )
{
internalTouch(key);
}*/
inline bool fetch( const Key &key, Data* result, unsigned long* size, bool touch = true )
{
Map_Iter miter = index.find( key );
if( miter == index.end() ) return false;
if(touch){
this->internalTouch( key );
}
if(result){
(*result) = miter->second->second.second; // map -> list -> pair -> value
}
if(size){
(*size) = miter->second->second.first;
}
return true;
}
inline bool fetch( const Key &key, Data* result, bool touch = true )
{
unsigned long size = 0;
return fetch(key, result, &size, touch);
}
inline virtual void resize( unsigned long newSize)
{
while( list.size() > newSize) {
// Remove the last element.
List_Iter liter = list.end();
--liter;
this->remove( liter->first );
}
}
// returns the size of last removed element
inline void removeLeastRecentlyUsed()
{
// Remove the last element.
List_Iter liter = list.end();
--liter;
this->remove( liter->first );
}
inline virtual void insert( const Key &key, const Data &data, const unsigned long dataSize = 0)
{
// Touch the key, if it exists, then replace the content.
Map_Iter miter = this->internalTouch( key );
if( miter != index.end() )
this->remove( miter );
// Ok, do the actual insert at the head of the list
list.push_front( std::make_pair( key, std::make_pair(dataSize, data) ) );
List_Iter liter = list.begin();
// Store the index
index.insert( std::make_pair( key, liter ) );
totalMemory += dataSize;
}
inline void insert(List_cIter iter, List_cIter iterEnd)
{
for(; iter != iterEnd; ++iter){
insert(iter->first, iter->second.second, iter->second.first);
}
}
inline List_Iter begin()
{
return list.begin();
}
inline List_Iter end()
{
return list.end();
}
private:
inline Map_Iter internalTouch( const Key &key )
{
Map_Iter miter = index.find( key );
if( miter == index.end() ) return miter;
// Move the found node to the head of the list.
list.splice( list.begin(), list, miter->second );
return miter;
}
inline void remove( const Map_Iter &miter )
{
totalMemory -= miter->second->second.first;
list.erase( miter->second );
index.erase( miter );
}
};
template<class Key,class Data>
class SizeEnforcedLRUCache : public LRUCache<Key, Data>
{
typedef LRUCache<Key, Data> Super;
/// Maximum size of the cache in elements
unsigned long maxSize;
public:
SizeEnforcedLRUCache(const unsigned long maxSize)
: maxSize(maxSize)
{}
~SizeEnforcedLRUCache() {}
inline void resize( unsigned long newSize)
{
maxSize = newSize;
Super::resize(maxSize);
}
inline void insert( const Key &key, const Data &data, const unsigned long dataSize = 0)
{
Super::insert(key, data, dataSize);
// Check to see if we need to remove an element due to exceeding max_size
if( this->list.size() > maxSize ) {
Super::removeLeastRecentlyUsed();
}
}
};
template<class Key, class Data>
class MemEnforcedLRUCache : public LRUCache<Key, Data>
{
typedef LRUCache<Key, Data> Super;
// Maximum memory size of all the elements in the cache
unsigned long maxMemSize;
public:
MemEnforcedLRUCache (const unsigned long maxSize) : maxMemSize(maxSize) {}
inline virtual void resize( unsigned long newSize)
{
maxMemSize = newSize;
while( this->totalMemory > maxMemSize )
{
Super::removeLeastRecentlyUsed();
RBXASSERT(this->totalMemory >= 0);
}
}
inline void insert( const Key &key, const Data &data, const unsigned long dataSize)
{
Super::insert(key, data, dataSize);
// Check to see if we need to remove an element due to exceeding max_size
while( this->totalMemory > maxMemSize ) {
Super::removeLeastRecentlyUsed();
RBXASSERT(this->totalMemory >= 0);
}
}
};
template<class Key,class Data>
class ConcurrentLRUCache
{
public:
RBX::LRUCache<Key, Data> cache;
boost::mutex mutex;
public:
ConcurrentLRUCache (int size)
: cache(size)
{}
bool fetch(const Key& id, Data* result)
{
boost::mutex::scoped_lock lock(mutex);
return cache.fetch(id, result);
}
void insert(const Key& id, const Data& data)
{
boost::mutex::scoped_lock lock(mutex);
cache.insert(id, data);
}
};
}
+24
View File
@@ -0,0 +1,24 @@
/* Copyright 2014 ROBLOX Corporation, All Rights Reserved */
#include "stdafx.h"
class LcmRand
{
public:
LcmRand() : seed(1337U) {}
uint32_t value()
{
const static uint32_t a = 214013U;
const static uint32_t c = 2531011U;
seed = seed * a + c;
return (seed >> 16) & 0x7FFF;
}
void setSeed(uint32_t newSeed)
{
seed = newSeed;
}
private:
uint32_t seed;
};
+22
View File
@@ -0,0 +1,22 @@
#pragma once
#include <string>
#include <boost/unordered_map.hpp>
namespace RBX {
class LegacyContentTable
{
private:
typedef boost::unordered_map<std::string, std::string> UrlMap;
UrlMap mMap;
std::string mEmpty;
public:
LegacyContentTable();
void AddEntry(const std::string& path, const std::string& contentId);
void AddEntryProd(const std::string& path, const std::string& contentId);
const std::string& FindEntry(const std::string& path);
};
}
+140
View File
@@ -0,0 +1,140 @@
#pragma once
#include "V8Tree/Service.h"
#include "Util/AsyncHttpCache.h"
namespace RBX {
extern const char* const sPages;
class Pages :
public DescribedNonCreatable<Pages, Instance, sPages, Reflection::ClassDescriptor::RUNTIME_LOCAL>
{
protected:
bool finished;
shared_ptr<const Reflection::ValueArray> currentPage;
public:
Pages();
virtual void fetchNextChunk(boost::function<void()> resumeFunction, boost::function<void(std::string)> errorFunction) {};
shared_ptr<const Reflection::ValueArray> getCurrentPage();
bool isFinished() const;
void advanceToNextPageAsync(boost::function<void()> resumeFunction, boost::function<void(std::string)> errorFunction);
};
extern const char* const sStandardPages;
class StandardPages :
public DescribedNonCreatable<StandardPages, Pages, sStandardPages, Reflection::ClassDescriptor::RUNTIME_LOCAL>
{
weak_ptr<DataModel> weakDM;
std::string fieldName;
std::string requestUrl;
int pageNumber;
void processFetchSuccess(std::string response, boost::function<void()> resumeFunction, boost::function<void(std::string)> errorFunction);
void processFetchError(std::string error, boost::function<void(std::string)> errorFunction);
void processFetch(std::string* response, std::exception* exception, boost::function<void()> resumeFunction, boost::function<void(std::string)> errorFunction);
public:
StandardPages(weak_ptr<DataModel> weakDM, const std::string& requestUrl, const std::string& fieldName);
virtual void fetchNextChunk(boost::function<void()> resumeFunction, boost::function<void(std::string)> errorFunction);
};
extern const char* const sFriendPages;
class FriendPages :
public DescribedNonCreatable<FriendPages, Pages, sFriendPages, Reflection::ClassDescriptor::RUNTIME_LOCAL>
{
weak_ptr<DataModel> weakDM;
std::string fieldName;
std::string requestUrl;
shared_ptr<const Reflection::ValueArray> nextPage;
int pageNumber;
bool firstTime;
void processFetchSuccess(std::string response, boost::function<void()> resumeFunction, boost::function<void(std::string)> errorFunction);
void processFetchError(std::string error, boost::function<void(std::string)> errorFunction);
void processFetch(std::string* response, std::exception* exception, boost::function<void()> resumeFunction, boost::function<void(std::string)> errorFunction);
public:
FriendPages(weak_ptr<DataModel> weakDM, const std::string& requestUrl);
virtual void fetchNextChunk(boost::function<void()> resumeFunction, boost::function<void(std::string)> errorFunction);
};
extern const char *const sLuaWebService;
#define LUA_WEB_SERVICE_STANDARD_PRIORITY 50
// This service is used to make web queries. It is frequently used by
// function calls originating in Lua, but is not restricted to use
// by Lua
class LuaWebService
: public DescribedNonCreatable<LuaWebService, Instance, sLuaWebService>
, public Service
{
private:
typedef DescribedNonCreatable<LuaWebService, Instance, sLuaWebService> Super;
struct CachedLuaWebServiceInfo
{
Reflection::Variant value;
CachedLuaWebServiceInfo() {}
CachedLuaWebServiceInfo(shared_ptr<const std::string> data, shared_ptr<const std::string> filename);
};
struct CachedRawLuaWebServiceInfo
{
std::string value;
CachedRawLuaWebServiceInfo() {}
CachedRawLuaWebServiceInfo(shared_ptr<const std::string> data, shared_ptr<const std::string> filename);
};
boost::shared_ptr<AsyncHttpCache<CachedLuaWebServiceInfo, true> > webCache;
boost::shared_ptr<AsyncHttpCache<CachedRawLuaWebServiceInfo, true> > webRawCache;
bool checkApiAccess;
Time timeToRecheckApiAccess;
boost::optional<bool > apiAccess;
template<typename Result>
bool checkCache(const std::string& url, boost::function<void(Result)> resumeFunction, boost::function<void(std::string)> errorFunction);
template<typename Result>
static bool TryDispatchRequest(AsyncHttpCache<LuaWebService::CachedLuaWebServiceInfo, true>* webCache, const std::string& url,
boost::function<void(Result)> resumeFunction, boost::function<void(std::string)> errorFunction);
template<typename Result>
static bool TryRawDispatchRequest(AsyncHttpCache<LuaWebService::CachedRawLuaWebServiceInfo, true>* webCache, const std::string& url,
boost::function<void(Result)> resumeFunction, boost::function<void(std::string)> errorFunction);
template<typename Result>
static void Callback(boost::weak_ptr<LuaWebService> weakLuaWebService, AsyncHttpQueue::RequestResult requestResult, std::string url,
boost::function<void(Result)> resumeFunction, boost::function<void(std::string)> errorFunction);
static void RawCallback(boost::weak_ptr<LuaWebService> weakLuaWebService, AsyncHttpQueue::RequestResult requestResult, std::string url,
boost::function<void(std::string)> resumeFunction, boost::function<void(std::string)> errorFunction);
public:
LuaWebService();
void asyncRequest(const std::string& url, float priority,
boost::function<void(shared_ptr<const Reflection::ValueArray>)> resumeFunction, boost::function<void(std::string)> errorFunction);
void asyncRequest(const std::string& url, float priority,
boost::function<void(shared_ptr<const Reflection::ValueMap>)> resumeFunction, boost::function<void(std::string)> errorFunction);
void asyncRequest(const std::string& url, float priority,
boost::function<void(bool)> resumeFunction, boost::function<void(std::string)> errorFunction);
void asyncRequest(const std::string& url, float priority,
boost::function<void(std::string)> resumeFunction, boost::function<void(std::string)> errorFunction);
void asyncRequest(const std::string& url, float priority,
boost::function<void(int)> resumeFunction, boost::function<void(std::string)> errorFunction);
//Skips the caches
void asyncRequestNoCache(const std::string& url, float priority, boost::function<void(shared_ptr<const Reflection::ValueMap>)> callback, AsyncHttpQueue::ResultJob resultJob);
// will block until api access request has returned
bool isApiAccessEnabled();
void setCheckApiAccessBecauseInStudio();
static bool parseWebJSONResponseHelper(std::string* response, std::exception* exception,
shared_ptr<const Reflection::ValueTable>& result, std::string& status);
};
}
+29
View File
@@ -0,0 +1,29 @@
#pragma once
#include "rbx/declarations.h"
#include <string>
#include <istream>
namespace RBX {
class RBXInterface MD5Hasher
{
public:
static MD5Hasher* create();
virtual ~MD5Hasher() {}
virtual void addData(std::istream& data) = 0;
virtual void addData(const std::string& data) = 0;
virtual void addData(const char* data, size_t nBytes) = 0;
virtual const std::string& toString() = 0;
virtual const char* c_str() = 0;
virtual void toBuffer(char (&result)[16]) = 0;
// Before 03-12-07 the hashing function didn't pad bytes with '0'
static std::string convertToLegacyHash(std::string hash);
};
std::string CollectMd5Hash(const std::string& fileName);
std::string ComputeMd5Hash(const std::string& data);
}//namespace
+16
View File
@@ -0,0 +1,16 @@
//
// MachOBaseAddr.h
// App
//
// Created by David Stahl on 11/10/14.
//
//
#ifndef App_MachOBaseAddr_h
#define App_MachOBaseAddr_h
uint32_t machODynamicBaseAddress(void);
uint32_t machOTextSize(void);
#endif
+39
View File
@@ -0,0 +1,39 @@
#pragma once
#include <string>
#include <vector>
namespace RBX {
// Helper class to gather identifying information about this machine and for
// communicating with the web banned machine database.
class MachineIdUploader {
public:
static const char* kBannedMachineMessage;
enum Result {
RESULT_MachineAccepted = 1,
RESULT_MachineBanned = 0
};
// Gather identifying info for this machine, send it out, and return
// weather this machine has been banned or not.
static Result uploadMachineId(const char* baseUrl);
static std::string getMachineId();
private:
struct MacAddress {
static const int kBytesInMacAddress = 6;
unsigned char address[kBytesInMacAddress];
std::string asString() const;
};
struct MachineId {
std::vector<MacAddress> macAddresses;
};
static bool fillMachineId(MachineId* out);
static bool buildMacAddressContent(bool needsLeadingAmp, const MachineId& id, std::stringstream& stream);
static void buildContent(const MachineId& id, std::stringstream& stream);
};
}
+387
View File
@@ -0,0 +1,387 @@
/* Copyright 2003-2007 ROBLOX Corporation, All Rights Reserved */
#pragma once
#include "Util/NormalId.h"
#include "Util/G3DCore.h"
#include "Util/PV.h"
#include "rbx/Debug.h"
#include "G3D/Array.h"
#include "RbxG3D/RbxRay.h"
#include <limits>
namespace RBX {
inline int fastFloorInt(float value)
{
return value < 0 ? static_cast<int>(value - 0.999f) : static_cast<int>(value);
}
inline int fastCeilInt(float value)
{
return value < 0 ? static_cast<int>(value) : static_cast<int>(value + 0.999f);
}
inline Vector3int16 fastFloorInt16(const Vector3& v)
{
return Vector3int16(fastFloorInt(v.x), fastFloorInt(v.y), fastFloorInt(v.z));
}
typedef enum {
AXIS_X = 0,
AXIS_Y = 1,
AXIS_Z = 2
} AxisIndex;
namespace Math
{
inline double pi() {return 3.14159265358979323846;}
inline double piHalf() {return pi() * 0.5f;}
inline double twoPi() {return pi() * 2.0f;}
inline float pif() {return static_cast<float>(pi());}
inline float piHalff() {return static_cast<float>(piHalf());}
inline float twoPif() {return static_cast<float>(twoPi());}
inline const float& inf() {
static const float i = std::numeric_limits<float>::infinity();
return i;
}
// Returns the 0-based most-significant bit (-1 if v is 0)
inline size_t computeMSB(size_t v)
{
size_t msb = -1;
while (v>0)
{
v >>= 1;
++msb;
}
return msb;
}
inline int iRound(float value) {
return G3D::iRound(value);
}
inline int iFloor(float value) {
return G3D::iRound(::floor(value));
}
inline float polarity(float value) {
return (value >= 0.0f) ? 1.0f : -1.0f;
}
inline float sign(float value) {
return (value > 0.0f)
? 1.0f
: (value < 0.0f ? -1.0f : 0.0f);
}
////////////////////////////////////////////////////////
//
// Denormalized detection
bool isDenormal(float f);
bool isNan(float f);
bool isNan(const Vector3& v);
bool isNanInf(float f);
bool isNanInfDenorm(float f);
bool isNanInfVector3(const Vector3& v);
bool isNanInfDenormVector3(const Vector3& v);
bool isNanInfDenormMatrix3(const Matrix3& m);
bool hasNanOrInf(const CoordinateFrame& c);
bool hasNanOrInf(const Matrix3& m);
// Sets denormalized values to 0.0
bool fixDenorm(float& f);
bool fixDenorm(Vector3& v);
////////////////////////////////////////////////////////
//
// fuzzyEq stuff
inline float epsilonf() { return 1.0e-6f; }
inline bool fuzzyEq(float a, float b, float epsilon) {
float aa = fabsf(a) + 1.0f;
return (a == b) || (fabsf(a - b) <= (aa * epsilon));
}
inline bool fuzzyEq(double a, double b, double epsilon) {
double aa = fabs(a) + 1.0f;
return (a == b) || (fabs(a - b) <= (aa * epsilon));
}
bool fuzzyEq(const Vector3& v0, const Vector3& v1, float epsilon = 1.0e-5f); // Note G3D::eps == 1e-6;
bool fuzzyEq(const Matrix3& m0, const Matrix3& m1, float epsilon = 1.0e-5f); // Note G3D::eps == 1e-6;
bool fuzzyEq(const Matrix4& m0, const Matrix4& m1, float epsilon = 1.0e-5f); // Note G3D::eps == 1e-6;
bool fuzzyEq(const CoordinateFrame& c0, const CoordinateFrame& c1, float epsT = 1.0e-5f, float epsRad = 1.0e-5f);
bool fuzzyAxisAligned(const Matrix3& m0, const Matrix3& m1, float radTolerance);
////////////////////////////////////////////////////////
//
// odd / even stuff
inline bool isEven(int value) {
return ((value % 2) == 0);
}
inline bool isOdd(int value) {
return ((value % 2) != 0);
}
inline int nextEven(int value) {
return (value + 1 + ((value + 1) % 2));
}
inline int nextOdd(int value) {
return (value + 1 + (value % 2));
}
////////////////////////////////////////////////////////
//
// Vector2 stuff
inline Vector2 expandVector2(const Vector2& v, int expand) {
Vector2 answer(v);
for (int i = 0; i < 2; ++i) {
answer[i] += expand * RBX::Math::sign(v[i]);
}
return answer;
}
inline Vector2 roundVector2(const Vector2& v) {
return Vector2(iRound(v.x), iRound(v.y));
}
////////////////////////////////////////////////////////
//
// Vector3 stuff
size_t hash(const Vector3& v);
bool isIntegerVector3(const Vector3& v);
Vector3 iRoundVector3(const Vector3& point);
float angle(const Vector3& v0, const Vector3& v1);
float smallAngle(const Vector3& v0, const Vector3& v1);
float elevationAngle(const Vector3& look);
Vector3 vector3Abs(const Vector3& v);
float volume(const Vector3& v);
float maxAxisLength(const Vector3& v);
Vector3 sortVector3(const Vector3& v);
Vector3 safeDirection(const Vector3& v); // handles case where V == vector3::zero();
Velocity calcTrajectory(const Vector3& launch, const Vector3& target, float speed);
Vector3 toGrid(const Vector3& v, const Vector3& grid);
Vector3 toGrid(const Vector3& v, float grid);
bool lessThan(const Vector3& min, const Vector3& max);
inline float longestVector3Component(const Vector3& v) {
return std::max(fabs(v.x), std::max(fabs(v.y), fabs(v.z)));
}
inline float planarSize(const Vector3& v) {
return (v.x < v.y)
? ((v.x < v.z) ? v.y * v.z : v.y * v.x)
: ((v.y < v.z) ? v.x * v.z : v.x * v.y);
}
inline float taxiCabMagnitude(const Vector3& v) {
return fabs(v.x) + fabs(v.y) + fabs(v.z);
}
float sumDeltaAxis(const Matrix3& r0, const Matrix3& r1);
inline const Plane& yPlane() {static Plane p(Vector3(0.0, 1.0, 0.0), Vector3::zero()); return p;}
Vector3 closestPointOnRay(const RBX::RbxRay& pointOnRay, const RBX::RbxRay& otherRay);
////////////////////////////////////////////////////////
//
// Manipulate/rotate Matrix3 and CoordinateFrame
Vector3 rotateAboutYGlobal(const Vector3& v, float radians);
Vector3 toSmallAngles(const Matrix3& matrix);
Matrix3 snapToAxes(const Matrix3& matrix);
bool isOrthonormal(const Matrix3& m);
bool orthonormalizeIfNecessary(Matrix3& m); // true if an orthonormalize was necessary
Vector3 toFocusSpace(const Vector3& goal, const CoordinateFrame& focus);
Vector3 fromFocusSpace(const Vector3& goal, const CoordinateFrame& focus);
Vector3 toDiagonal(const Matrix3& m);
inline Matrix3 fromDiagonal(const Vector3& v) {
return Matrix3( v[0], 0.0f, 0.0f,
0.0f, v[1], 0.0f,
0.0f, 0.0f, v[2] );
}
// Return the skew symmetric matrix for the the given vector.
// a.cross( b ) = A_* b where A_is the skew symmetric matrix for a.
//
inline Matrix3 toSkewSymmetric(const Vector3& v) {
return Matrix3( 0.0f, -v.z, v.y,
v.z, 0.0f, -v.x,
-v.y, v.x, 0.0f );
}
Matrix3 fromVectorToVectorRotation( const Vector3& fromVec, const Vector3& toVec );
Matrix3 fromRotationAxisAndAngle( const Vector3& axis, const float& angleRads );
Matrix3 fromShortestPlanarRotation( const Vector3& targetX, const Vector3& targetY );
Matrix3 fromDirectionCosines( const Vector3& fromX, const Vector3& fromY, const Vector3& fromZ,
const Vector3& toX, const Vector3& toY, const Vector3& toZ );
inline Vector3 getColumn(const Matrix3& m, int iCol) {
RBXASSERT_VERY_FAST((0 <= iCol) && (iCol < 3));
return Vector3(m[0][iCol], m[1][iCol], m[2][iCol]);
}
void mulMatrixDiagVector(const Matrix3& _mat, const Vector3& _vec, Matrix3& _answer);
void mulMatrixMatrixTranspose(const Matrix3& _m0, const Matrix3& _m1, Matrix3& _answer);
void mulMatrixTransposeMatrix(const Matrix3& _m0, const Matrix3& _m1, Matrix3& _answer);
// Byte Angles
unsigned char rotationToByte(float angle);
float rotationFromByte(unsigned char byteAngle);
// Axis Aligned Matrix / OrientId
static const int maxOrientationId = 36;
static const int minOrientationId = 0;
bool isAxisAligned(const Matrix3& matrix);
int getOrientId(const Matrix3& matrix);
void idToMatrix3(int orientId, Matrix3& matrix);
const Matrix3& matrixRotateX();
//static const Matrix3& matrixRotateNegativeX();
const Matrix3& matrixRotateY();
const Matrix3& matrixRotateNegativeY();
const Matrix3& matrixTiltZ();
const Matrix3& matrixTiltNegativeZ();
const Matrix3 matrixTiltQuadrant(int quadrant);
void rotateMatrixAboutX90(Matrix3& matrix, int times = 1);
void rotateMatrixAboutY90(Matrix3& matrix, int times = 1);
void rotateMatrixAboutZ90(Matrix3& matrix);
Matrix3 rotateAboutZ(const Matrix3& matrix, float radians);
Matrix3 getWellFormedRotForZVector(const Vector3& vec);
Matrix3 momentToObjectSpace(const Matrix3& iWorld, const Matrix3& bodyRotation);
Matrix3 momentToWorldSpace(const Matrix3& iBody, const Matrix3& bodyRotation);
Matrix3 getIWorldAtPoint(const Vector3& cofmPos,
const Vector3& worldPos,
const Matrix3& iWorldAtCofm,
float mass);
Matrix3 getIBodyAtPoint(const Vector3& pos,
const Matrix3& iBody,
float mass);
// CoordinateFrame
void rotateAboutYLocal(CoordinateFrame& c, float radians);
void rotateAboutYGlobal(CoordinateFrame& c, float radians);
CoordinateFrame snapToGrid(const CoordinateFrame& snap, float grid);
CoordinateFrame snapToGrid(const CoordinateFrame& snap, const Vector3& grid);
// http://www.vlfeat.org/api/mathop_8h-source.html#l00227
inline float atan2Fast(float y, float x) {
float angle, r;
float const c3 = 0.1821f;
float const c1 = 0.9675f;
float abs_y = fabsf(y) + 1.19209290e-07f;
if (x >= 0) {
r = (x - abs_y) / (x + abs_y) ;
angle = Math::pif() / 4.0f;
} else {
r = (x + abs_y) / (abs_y - x) ;
angle = 3.0f * Math::pif() / 4.0f ;
}
angle += (c3*r*r - c1) * r ;
return (y < 0) ? - angle : angle ;
}
inline float zAxisAngle(const Matrix3& matrix) {
Vector3 look = matrix.column(0);
float angle = (float) atan2(look.y, look.x);
// float angle = Math::atan2Fast(look.y, look.x);
return angle;
}
void pan(const Vector3& focusPosition, CoordinateFrame& camera, float radians);
// std::vector
void lerpArray(
const G3D::Array<float>& before,
const G3D::Array<float>& after,
G3D::Array<float>& answer,
float alpha);
// Pitch, Yaw stuff - replaces Euler Angles
int radiansToQuadrant(float radians);
int radiansToOctant(float radians);
inline float radiansToDegrees(float radians) {return radians * (180.0f / Math::pif());}
inline float degreesToRadians(float degrees) {return degrees * (Math::pif() / 180.0f);}
/**
Returns the heading as an angle in radians, where
north is 0 and west is PI/2
North == -z
Elevation is angle above (+) or below(-) horizon
*/
inline float getHeading(const Vector3& look) { return atan2( -look.x, -look.z); }
inline float getElevation(const Vector3& look) { return asin(look.y); }
void getHeadingElevation(const CoordinateFrame& c, float& heading, float& elevation);
void setHeadingElevation(CoordinateFrame& c, float heading, float elevation);
CoordinateFrame getFocusSpace(const CoordinateFrame& focus);
int toYAxisQuadrant(const CoordinateFrame& c); // 0..3
Matrix3 alignAxesClosest(const Matrix3& align, const Matrix3& target);
// NormalId stuff
NormalId getClosestObjectNormalId(const Vector3& worldV, const Matrix3& objectR);
inline Vector3 getWorldNormal(NormalId objId, const Matrix3& objectR) {
// return (objId < 3) ? getColumn(objectR, objId) : -getColumn(objectR, objId - 3);
int column = objId % 3;
int polarity = ((objId / 3) * (-2)) + 1;
return polarity * getColumn(objectR, column);
}
inline Vector3 getWorldNormal(NormalId objId, const CoordinateFrame& objectC) {
return getWorldNormal(objId, objectC.rotation);
}
// wraps from -pi to pi
float deltaRotationClose(float aRot, float bRot); // computes aRot - bRot, assuming angles are close. Undoes wrapping
float averageRotationClose(float aRot, float bRot); // computes average aRot, bRot, assuming angles are close. Undoes wrapping
double advanceWoundRotation(double currentRotationWound, double newRotationNotWound); // properly increments a wound up rotation - detects flips
float clampRotationClose(float rot, float limitLo, float limitHi);
// -3pi to -pi: -1
// -pi to pi: 0
// pi to 3pi: 1
inline double windingPart(double rad) {
return ::floor((rad + pi()) / twoPi()) ;
}
inline float radWrap(double rad) { // extra part
if ((rad >= -pi()) && (rad < pi())) {
return static_cast<float>(rad);
}
double answer = rad - (twoPi() * windingPart(rad));
RBXASSERT((answer >= -pi()) && (answer <= pi()));
return static_cast<float>(answer);
}
// Matrix operations
const Matrix3& getAxisRotationMatrix(int face);
// Vector to Object Space
// == mat.transpose() * vec
inline Vector3 vectorToObjectSpace(const Vector3& vec, const Matrix3& mat);
// Ray, Line
bool clipRay(Vector3& origin, Vector3& ray, Vector3 box[], Vector3& endPoint);
bool intersectLinePlane(const Line& line, const Plane& plane, Vector3& hit);
bool intersectRayPlane(const RbxRay& ray, const Plane& plane, Vector3& hit);
bool intersectRayConvexPolygon(const RBX::RbxRay& ray, const std::vector<Vector3>& poly, Vector3& hit, bool oneSided);
bool lineSegmentDistanceIfCrossing(const Vector3& line1Pt1, const Vector3& line1Pt2, const Vector3& line2Pt1, const Vector3& line2Pt2, float& distance, float adjustEdgeTol = 0.0f);
std::vector<Vector3> spatialPolygonIntersection(const std::vector<Vector3>& polyA, const std::vector<Vector3>& polyB);
std::vector<Vector2> planarPolygonIntersection(const std::vector<Vector2>& poly1, const std::vector<Vector2>& poly2);
// Misc.
float computeLaunchAngle(float v, float x, float y, float g);
Vector2 polygonStartingPoint(int numSides, float maxWidth);
bool evenWholeNumber( const float& rawInput );
bool evenWholeNumberFuzzy( const float& rawInput );
}
} // namespace
#include "Math.inl"
+18
View File
@@ -0,0 +1,18 @@
#pragma once
namespace RBX {
namespace Math{
// = mat.transpose() * vec
Vector3 vectorToObjectSpace(const Vector3& _vec, const Matrix3& _mat)
{
const float* vec = &_vec[0];
const float* mat = &_mat[0][0];
return Vector3 ( mat[0]*vec[0] + mat[3]*vec[1] + mat[6]*vec[2],
mat[1]*vec[0] + mat[4]*vec[1] + mat[7]*vec[2],
mat[2]*vec[0] + mat[5]*vec[1] + mat[8]*vec[2] );
}
} // namespace
} // namespace
+2
View File
@@ -0,0 +1,2 @@
#include "rbx/memory.h"
+34
View File
@@ -0,0 +1,34 @@
#pragma once
#include <stddef.h>
#include <boost/cstdint.hpp>
#include "standardout.h"
#include "FastLog.h"
namespace RBX {
// Utility functions for determining used/free/total memory.
namespace MemoryStats {
enum MemoryLevel
{
MEMORYLEVEL_ALL_CRITICAL_LOW,
MEMORYLEVEL_ONLY_PHYSICAL_CRITICAL_LOW,
MEMORYLEVEL_ALL_LOW,
MEMORYLEVEL_ONLY_PHYSICAL_LOW,
MEMORYLEVEL_LIMITED,
MEMORYLEVEL_OK
};
typedef boost::uint64_t memsize_t;
memsize_t usedMemoryBytes();
memsize_t freeMemoryBytes();
memsize_t totalMemoryBytes();
size_t slowGetMemoryPoolAllocation();
size_t slowGetMemoryPoolAvailability();
void releaseAllPoolMemory();
MemoryLevel slowCheckMemoryLevel(memsize_t extraMemoryUsed);
} // namespace MemoryStats
} // namespace RBX
+22
View File
@@ -0,0 +1,22 @@
/* Copyright 2003-2005 ROBLOX Corporation, All Rights Reserved */
#pragma once
#include "V8Tree/Service.h"
#include "Util/RunStateOwner.h"
#include "Reflection/Event.h"
namespace RBX {
class PartInstance;
class MeshId : public ContentId
{
public:
MeshId(const ContentId& id):ContentId(id) {}
MeshId(const char* id):ContentId(id) {}
MeshId(const std::string& id):ContentId(id) {}
MeshId() {}
};
} // namespace RBX
+123
View File
@@ -0,0 +1,123 @@
/* Copyright 2003-2005 ROBLOX Corporation, All Rights Reserved */
#pragma once
#include <boost/circular_buffer.hpp>
#include "G3DCore.h"
#include "rbx/rbxTime.h"
#include "boost/thread/mutex.hpp"
#include "Math.h"
namespace RBX {
#define MH_NUM_MAX_NODES 80
#define MH_MIN_PRECISION 0.01f
#define MH_TOLERABLE_COMPRESSION_ERROR 1.f
typedef unsigned char uint8_t;
typedef signed char int8_t;
class MovementHistory
{
public:
struct DeltaCompressedTranslation
{
// in terms of MIN_PRECISION
uint8_t precisionLevel;
int8_t dX;
int8_t dY;
int8_t dZ;
};
struct MovementNode
{
DeltaCompressedTranslation translation;
uint8_t delta2Ms;
MovementNode()
{
setZero();
}
MovementNode(const CoordinateFrame& newCFrame, const CoordinateFrame& oldCFrame, float deltaSecs)
{
Vector3 delta = newCFrame.translation - oldCFrame.translation;
compress(delta, *this);
if (deltaSecs < 0.f)
{
delta2Ms = 0;
}
else if (deltaSecs > 0.510f)
{
delta2Ms = 255; // overflow, use 255 to indicate the long gap
}
else
{
delta2Ms = (uint8_t)(deltaSecs*500.f);
}
}
bool isZero() const
{
return translation.dX == 0 && translation.dY == 0 && translation.dZ == 0;
}
void setZero()
{
translation.precisionLevel = 0;
translation.dX = 0;
translation.dY = 0;
translation.dZ = 0;
delta2Ms = 0;
}
// rotation will be estimated by interpolation
};
static const MovementHistory& getDefaultHistory()
{
static CoordinateFrame zeroCFrame;
static Velocity zeroVelocity;
static MovementHistory defaultMovementHistory(zeroCFrame, zeroVelocity, Time());
return defaultMovementHistory;
}
MovementHistory(const CoordinateFrame& cFrame, const Velocity& velocity, const Time& timeStamp);
~MovementHistory()
{}
void clearNodeHistory();
void addNode(const CoordinateFrame& cFrame, const Velocity& velocity, const Time& timeStamp);
size_t getNumNodes() const {return size;}
bool hasHistory(float accumulatedError) const;
void getMovementNodeList(const Time& lastCutOffTime, const Time& currentCutOffTime, std::deque<MovementNode>& result, bool crossPacketCompression, const CoordinateFrame& lastSentCFrame, CoordinateFrame& outCalculatedBaselineCFrame, Vector3& outCalculatedLinearVelocity) const;
const CoordinateFrame& getBaselineCFrame() const {return baselineCFrame;}
const Velocity& getBaselineVelocity() const {return baselineVelocity;}
static float decompress(int8_t v, uint8_t precisionLevel);
static void decompress(MovementNode node, Vector3& outTranslation);
const Time& getLastUpdateTime() const {return lastUpdateTime;}
float getTimeSpan() const {return timeSpanSec;}
static float getSecFrom2Ms(uint8_t delta2MS)
{
return ((float)delta2MS)/500.f;
}
private:
CoordinateFrame baselineCFrame;
Velocity baselineVelocity;
Time lastUpdateTime;
float timeSpanSec;
int checksum;
MovementNode movementNodes[MH_NUM_MAX_NODES];
size_t startIndex;
size_t size;
void popFront();
void pushBack(MovementNode node);
MovementNode concatNode(size_t lastIndex, size_t numNodesToConcat) const;
static int8_t compress(float v, uint8_t precisionLevel);
static void compress(Vector3 translation, MovementNode& outMovementNode);
};
} // namespace
+168
View File
@@ -0,0 +1,168 @@
#ifndef _E34E3E6DF0724eb493E138F10DF08D03
#define _E34E3E6DF0724eb493E138F10DF08D03
#include <string>
#include <map>
#include "boost/utility.hpp"
#include "rbx/Debug.h"
#include "rbx/boost.hpp"
#include "rbx/atomic.h"
#include <boost/unordered_map.hpp>
#include "rbx/threadsafe.h"
#include "security/ApiSecurity.h"
namespace RBX {
class Name : public boost::noncopyable
{
static RBX::mutex& mutex();
class NameMap;
static NameMap& map();
template<const char* const& sName>
static const Name& doDeclare()
{
static const Name& n = declare(sName);
return n;
}
template<const char* const& sName>
static void callDoDeclare()
{
doDeclare<sName>();
}
// sortIndex is atomic to avoid any chance of stale
// data when calling setOrderIndex
rbx::atomic<int> sortIndex;
public:
std::string const str; // the string that is the text name
static size_t size();
static size_t approximateMemoryUsage();
// Declaration and Query
static const Name& getNullName();
// Fast and thread-safe
NOINLINE static const Name& declare(const char* const& sName);
FORCEINLINE static const Name& declare(const std::string& sName)
{
return declare(sName.c_str());
}
template<const char* const& sName>
static const Name& declare()
{
if(sName == NULL)
return getNullName();
static boost::once_flag flag = BOOST_ONCE_INIT;
boost::call_once(&callDoDeclare<sName>, flag);
return doDeclare<sName>();
}
NOINLINE static const Name& lookup(const char* const& sName);
FORCEINLINE static const Name& lookup(const std::string& sName)
{
return lookup(sName.c_str());
}
bool empty() const { return getNullName()==*this; }
static bool empty(const Name* name) { return name==0 || *name==getNullName(); }
// Convert to string
const std::string& toString() const { return str; }
const char* c_str() const { return str.c_str(); }
// Comparison
#if 1
// Optimization - avoids string comparisons
static inline int compare(const Name& a, const Name& b) {
return a.sortIndex - b.sortIndex;
}
inline int compare(const Name& other) const {
return sortIndex - other.sortIndex;
}
inline bool operator < (const Name& other) const {
return sortIndex < other.sortIndex;
}
inline bool operator > (const Name& other) const {
return sortIndex > other.sortIndex;
}
#else
static inline int compare(const Name& a, const Name& b) {
return a.str.compare(b.str);
}
inline int compare(const Name& other) const {
return str.compare(other.str);
}
inline bool operator < (const Name& other) const {
return str < other.str;
}
inline bool operator > (const Name& other) const {
return str > other.str;
}
#endif
inline bool operator == (const Name& other) const {
return this==&other;
}
inline bool operator != (const Name& other) const {
return this!=&other;
}
inline bool operator == (const std::string& sName) const {
return this->str == sName;
}
inline bool operator != (const std::string& sName) const {
return this->str != sName;
}
inline bool operator == (const char* const &sName) const {
return this->str == sName;
}
inline bool operator != (const char* const &sName) const {
return this->str != sName;
}
private:
explicit Name(const char* const &sName);
void setOrderIndex();
};
std::ostream& operator<<(std::ostream& os, const RBX::Name& name);
// An object that has a Name
class RBXInterface INamed {
public:
virtual const Name& getName() const = 0;
};
// A template implementation of INamed
template <class BaseClass, const char* const& sName>
class Named : public BaseClass {
public:
// Constructors with different numbers of arguments
Named() : BaseClass() {}
template<typename Arg0>
Named(Arg0 arg0) : BaseClass(arg0) {}
template<typename Arg0, typename Arg1>
Named(Arg0 arg0, Arg1 arg1) : BaseClass(arg0, arg1) {}
template<typename Arg0, typename Arg1, typename Arg2>
Named(Arg0 arg0, Arg1 arg1, Arg2 arg2) : BaseClass(arg0, arg1, arg2) {}
template<typename Arg0, typename Arg1, typename Arg2, typename Arg3>
Named(Arg0 arg0, Arg1 arg1, Arg2 arg2, Arg3 arg3) : BaseClass(arg0, arg1, arg2, arg3) {}
static const Name& name() {
return Name::declare<sName>();
}
virtual const Name& getName() const {
return name();
}
};
}
#endif
+17
View File
@@ -0,0 +1,17 @@
#pragma once
#ifdef _WIN32
#include <windows.h>
namespace RBX
{
class ScopedNamedMutex
{
HANDLE hMutex;
public:
ScopedNamedMutex(const char* name);
~ScopedNamedMutex();
};
} // namespace RBX
#endif // #ifdef _WIN32
+86
View File
@@ -0,0 +1,86 @@
#pragma once
namespace RBX {
class NavKeys {
public:
bool forward_arrow;
bool backward_arrow;
bool left_arrow;
bool right_arrow;
bool forward_asdw;
bool backward_asdw;
bool left_asdw;
bool right_asdw;
bool strafe_left_q;
bool strafe_right_e;
bool space;
bool backspace;
bool shift;
NavKeys() : forward_arrow(false),
backward_arrow(false),
left_arrow(false),
right_arrow(false),
forward_asdw(false),
backward_asdw(false),
left_asdw(false),
right_asdw(false),
strafe_left_q(false),
strafe_right_e(false),
space(false),
backspace(false),
shift(false)
{}
bool forward() const {return (forward_arrow || forward_asdw);}
bool backward() const {return (backward_arrow || backward_asdw);}
bool left() const {return (left_arrow || left_asdw);}
bool right() const {return (right_arrow || right_asdw);}
bool up() const {return strafe_left_q;}
bool down() const {return strafe_right_e;}
bool backspaceDown() const {return backspace;}
bool arrowKeyDown() const {return (forward_arrow || backward_arrow || left_arrow || right_arrow);}
bool asdwKeyDown() const {return (forward_asdw || backward_asdw || left_asdw || right_asdw);}
bool qeKeyDown() const {return (strafe_left_q || strafe_right_e);}
bool navKeyDown() const {return (arrowKeyDown() || asdwKeyDown() || qeKeyDown() || space) || backspaceDown();}
int leftRightASDW() const {return left_asdw ? 1 : (right_asdw ? -1 : 0);}
int strafeQE() const {return strafe_left_q ? 1 : (strafe_right_e ? -1 : 0);}
int leftRightArrow() const {
return left_arrow ? 1 : (right_arrow ? -1 : 0);
}
int forwardBackwardArrow() const {
return forward_arrow ? 1 : (backward_arrow ? -1 : 0);
}
int forwardBackwardASDW() const {
return forward_asdw ? 1 : (backward_asdw ? -1 : 0);
}
int strafeLeftRightQE() const {
return strafe_left_q ? 1 : (strafe_right_e ? -1 : 0);
}
bool shiftKeyDown() const
{
return shift;
}
};
} // namespace
+69
View File
@@ -0,0 +1,69 @@
/* Copyright 2003-2006 ROBLOX Corporation, All Rights Reserved */
#pragma once
#include "Util/G3DCore.h"
namespace RBX {
enum NormalIdMask
{
NORM_NONE_MASK = 0x00,
NORM_X_MASK = 0x01,
NORM_Y_MASK = 0x02,
NORM_Z_MASK = 0x04,
NORM_X_NEG_MASK = 0x08,
NORM_Y_NEG_MASK = 0x10,
NORM_Z_NEG_MASK = 0x20,
NORM_ALL_MASK = 0x3f
};
enum NormalId { NORM_X = 0,
NORM_Y,
NORM_Z,
NORM_X_NEG,
NORM_Y_NEG,
NORM_Z_NEG,
NORM_UNDEFINED};
bool validNormalId(NormalId normalId);
NormalIdMask normalIdToMask(NormalId normal);
NormalId normalIdOpposite(NormalId normalId);
NormalId normalIdToU(NormalId normalId);
NormalId normalIdToV(NormalId normalId);
const Vector3& normalIdToVector3(NormalId normalId); // Vector pointing along the normal direction
const Matrix3& normalIdToMatrix3(NormalId normalId); // Z axis is away from face
NormalId Vector3ToNormalId(const Vector3& v);
NormalId Matrix3ToNormalId(const Matrix3& m);
NormalId intToNormalId(int i);
Vector3 uvwToObject(const Vector3& uvwPt, NormalId faceId);
Vector3 objectToUvw(const Vector3& objectPt, NormalId faceId);
template<NormalId faceId>
Vector3 uvwToObject(const Vector3& v);
template<NormalId faceId>
Vector3 objectToUvw(const Vector3& v);
// LEGACY - Deprecated
// old stuff - need to inspect and see if it is really objectToUvw or uvwToObject
Vector3 mapToUvw_Legacy(const Vector3& ptInObject, NormalId normalId);
template<NormalId normalId>
Vector3 faceMap_Legacy(const Vector3& v) {
return uvwToObject<normalId>(v);
}
template<NormalId normalId>
Vector3 faceMap_Legacy(float x, float y, float z) {
return faceMap_Legacy<normalId>(Vector3(x, y, z));
}
} // namespace
+375
View File
@@ -0,0 +1,375 @@
/* Copyright 2003-2007 ROBLOX Corporation, All Rights Reserved */
#pragma once
#include "rbx/Debug.h"
#include "Util/Name.h"
#include <string>
#include <map>
#include "Security/ApiSecurity.h"
#include "Security/FuzzyTokens.h"
#include "V8DataModel/HackDefines.h"
#include "rbx/boost.hpp"
#include "boost/weak_ptr.hpp"
#include "boost/shared_ptr.hpp"
#include "boost/scoped_ptr.hpp"
#include "boost/enable_shared_from_this.hpp"
using boost::shared_ptr;
using boost::scoped_ptr;
using boost::weak_ptr;
using boost::enable_shared_from_this;
namespace RBX
{
namespace Reflection
{
class DescribedBase;
}
enum CreatorRole
{
ReplicationCreator,
SerializationCreator,
ScriptingCreator,
EngineCreator
};
template<class T, class U> boost::shared_ptr<T> shared_polymorphic_downcast(const boost::shared_ptr<U>& r)
{
BOOST_ASSERT(dynamic_cast<T *>(r.get()) == r.get());
return boost::static_pointer_cast<T>(r);
}
template<class T, class U> boost::shared_ptr<T> shared_dynamic_cast(const boost::shared_ptr<U>& r)
{
return boost::dynamic_pointer_cast<T>(r);
}
template<class T, class U> boost::shared_ptr<T> shared_static_cast(const boost::shared_ptr<U>& r)
{
return boost::static_pointer_cast<T>(r);
}
// Use this to convert an object to its corresponding boost::shared_ptr
template<class T> boost::shared_ptr<T> shared_from(T* r)
{
return r ? boost::static_pointer_cast<T>(r->shared_from_this()) : boost::shared_ptr<T>();
}
template<class T> weak_ptr<T> weak_from(T* r)
{
return r ? boost::static_pointer_cast<T>(r->shared_from_this()) : boost::shared_ptr<T>();
}
// Use this to downcast an object to a shared_ptr
template<class T, class U> shared_ptr<T> shared_from_polymorphic_downcast(enable_shared_from_this<U>* r)
{
return r ? shared_polymorphic_downcast<T>(r->shared_from_this()) : shared_ptr<T>();
}
template<class T, class U> shared_ptr<T> shared_from_static_cast(enable_shared_from_this<U>* r)
{
return r ? shared_static_cast<T>(r->shared_from_this()) : shared_ptr<T>();
}
template<class T, class U> shared_ptr<T> shared_from_dynamic_cast(enable_shared_from_this<U>* r)
{
return r ? shared_dynamic_cast<T>(r->shared_from_this()) : shared_ptr<T>();
}
template <class T> inline bool weak_equal(const weak_ptr<T>& lhs, const weak_ptr<T>& rhs)
{
return !(lhs < rhs) && !(rhs < lhs);
}
class RBXInterface ICreator
{
public:
virtual shared_ptr<Reflection::DescribedBase> create() const = 0;
};
template<class Class>
class RBXBaseClass Creatable
{
public:
class Deleter
{
public:
void operator()(Class* instance)
{
Class::predelete(instance);
delete instance;
}
};
template<class T>
static shared_ptr<T> create()
{
shared_ptr<T> obj = shared_ptr<T>(new T(), Deleter());
shared_ptr<T> (*thisFunction)() = &create;
checkRbxCaller<kCallCheckCallersCode, callCheckSetBasicFlag<HATE_RETURN_CHECK> >(reinterpret_cast<void*>(thisFunction));
return obj;
}
template<class T, typename P1>
static shared_ptr<T> create(P1 p1)
{
shared_ptr<T> obj = shared_ptr<T>(new T(p1), Deleter());
shared_ptr<T> (*thisFunction)(P1) = &create;
checkRbxCaller<kCallCheckCallersCode, callCheckSetBasicFlag<HATE_RETURN_CHECK> >(reinterpret_cast<void*>(thisFunction));
return obj;
}
template<class T, typename P1, typename P2>
static shared_ptr<T> create(P1 p1, P2 p2)
{
shared_ptr<T> obj = shared_ptr<T>(new T(p1, p2), Deleter());
shared_ptr<T> (*thisFunction)(P1, P2) = &create;
checkRbxCaller<kCallCheckCallersCode, callCheckSetBasicFlag<HATE_RETURN_CHECK> >(reinterpret_cast<void*>(thisFunction));
return obj;
}
template<class T, typename P1, typename P2, typename P3>
static shared_ptr<T> create(P1 p1, P2 p2, P3 p3)
{
shared_ptr<T> obj = shared_ptr<T>(new T(p1, p2, p3), Deleter());
shared_ptr<T> (*thisFunction)(P1, P2, P3) = &create;
checkRbxCaller<kCallCheckCallersCode, callCheckSetBasicFlag<HATE_RETURN_CHECK> >(reinterpret_cast<void*>(thisFunction));
return obj;
}
template<class T, typename P1, typename P2, typename P3, typename P4>
static shared_ptr<T> create(P1 p1, P2 p2, P3 p3, P4 p4)
{
shared_ptr<T> obj = shared_ptr<T>(new T(p1, p2, p3, p4), Deleter());
shared_ptr<T> (*thisFunction)(P1, P2, P3, P4) = &create;
checkRbxCaller<kCallCheckCallersCode, callCheckSetBasicFlag<HATE_RETURN_CHECK> >(reinterpret_cast<void*>(thisFunction));
return obj;
}
template<class T, typename P1, typename P2, typename P3, typename P4, typename P5>
static shared_ptr<T> create(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
{
shared_ptr<T> obj = shared_ptr<T>(new T(p1, p2, p3, p4, p5), Deleter());
shared_ptr<T> (*thisFunction)(P1, P2, P3, P4, P5) = &create;
checkRbxCaller<kCallCheckCallersCode, callCheckSetBasicFlag<HATE_RETURN_CHECK> >(reinterpret_cast<void*>(thisFunction));
return obj;
}
template<class T, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
static shared_ptr<T> create(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)
{
shared_ptr<T> obj = shared_ptr<T>(new T(p1, p2, p3, p4, p5, p6), Deleter());
shared_ptr<T> (*thisFunction)(P1, P2, P3, P4, P5, P6) = &create;
checkRbxCaller<kCallCheckCallersCode, callCheckSetBasicFlag<HATE_RETURN_CHECK> >(reinterpret_cast<void*>(thisFunction));
return obj;
}
template<class T, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
static shared_ptr<T> create(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7)
{
shared_ptr<T> obj = shared_ptr<T>(new T(p1, p2, p3, p4, p5, p6, p7), Deleter());
shared_ptr<T> (*thisFunction)(P1, P2, P3, P4, P5, P6, P7) = &create;
checkRbxCaller<kCallCheckCallersCode, callCheckSetBasicFlag<HATE_RETURN_CHECK> >(reinterpret_cast<void*>(thisFunction));
return obj;
}
static std::map<const Name*, const ICreator*>& getCreators()
{
// TODO: replace with a faster lookup map, like the Loki AssocVector?
static std::map<const Name*, const ICreator*> creators;
return creators;
}
static shared_ptr<Class> createByName(const Name& name, CreatorRole creatorRole)
{
std::map<const Name*, const ICreator*>::iterator iter = getCreators().find(&name);
if (iter!=getCreators().end()){
if(shared_ptr<Class> result = shared_polymorphic_downcast<Class>(iter->second->create())){
switch(creatorRole)
{
case ReplicationCreator:
return result;
case SerializationCreator:
if(result->getDescriptor().isSerializable())
return result;
break;
case ScriptingCreator:
if(result->getDescriptor().isScriptCreatable())
return result;
break;
case EngineCreator:
return result;
}
}
}
return shared_ptr<Class>();
}
// Get object creator by className
static const ICreator* getCreator(const Name& name)
{
std::map<const Name*, const ICreator*>::iterator iter = getCreators().find(&name);
return (iter!=getCreators().end()) ? iter->second : NULL;
}
private:
Creatable(); // this is a utility class
};
template <class Class, class BaseClass, const char* const& sClassName, class FactoryClass>
class FactoryProduct : public BaseClass {
class Creator : public ICreator {
private:
static int isConstructedTrue() {return 666;}
static int isConstructed; // debugging - if constructed, == 666
const RBX::Name& getClassNameUnconstructed() const {
return RBX::Name::declare<sClassName>();
}
public:
static bool wasConstructed() {return isConstructed == isConstructedTrue();}
/* override */ shared_ptr<Reflection::DescribedBase> create() const {
RBXASSERT(wasConstructed());
return Creatable<FactoryClass>::template create<Class>();
}
const RBX::Name& getClassName() const {
RBXASSERT(wasConstructed());
return RBX::Name::declare<sClassName>();
}
Creator()
{
// Register this creator for create-by-className
const RBX::Name& name = getClassNameUnconstructed();
auto& creators = Creatable<FactoryClass>::getCreators();
RBXASSERT(creators.find(&name)==creators.end());
RBXASSERT(!wasConstructed());
creators[&name] = this;
isConstructed = isConstructedTrue();
RBXASSERT(creators.find(&name)!=creators.end());
RBXASSERT(wasConstructed());
}
~Creator() {
auto& creators = Creatable<FactoryClass>::getCreators();
RBXASSERT(wasConstructed());
creators.erase(&getClassName());
}
};
private:
#ifdef _WIN32
static const Creator creatorPrivate;
#else
static Creator creatorPrivate;
#endif
protected:
FactoryProduct()
{
}
template<class Arg0>
FactoryProduct(Arg0 arg0):BaseClass(arg0)
{
}
template<class Arg0, class Arg1>
FactoryProduct(Arg0 arg0, Arg1 arg1):BaseClass(arg0,arg1)
{
}
virtual ~FactoryProduct()
{
}
static const Creator& static_getCreator() {
RBXASSERT(Creator::wasConstructed());
return creatorPrivate;
}
public:
const ICreator& getCreator() {
return static_getCreator();
}
static const RBX::Name& className() { return static_getCreator().getClassName(); };
static bool isNullClassName() {
RBXASSERT(!className().empty());
return false;
};
const RBX::Name& getClassName() const { return static_getCreator().getClassName(); };
// Convenient static functions for creating an instance of this class:
// TODO: Refactor: rename createInstance --> create, but also need to rename AbstractFactoryProduct::create to something else
static shared_ptr<Class> createInstance() {
return Creatable<FactoryClass>::template create<Class>();
}
template<typename P1>
static shared_ptr<Class> createInstance(P1 p1)
{
return Creatable<FactoryClass>::template create<Class>(p1);
}
template<typename P1, typename P2>
static shared_ptr<Class> createInstance(P1 p1, P2 p2)
{
return Creatable<FactoryClass>::template create<Class>(p1, p2);
}
template<typename P1, typename P2, typename P3>
static shared_ptr<Class> createInstance(P1 p1, P2 p2, P3 p3)
{
return Creatable<FactoryClass>::template create<Class>(p1, p2, p3);
}
template<typename P1, typename P2, typename P3, typename P4>
static shared_ptr<Class> createInstance(P1 p1, P2 p2, P3 p3, P4 p4)
{
return Creatable<FactoryClass>::template create<Class>(p1, p2, p3, p4);
}
};
// Static Defination Go Here
// creatorPrivate was a const earlier, but that gives gcc error while trying to define the variable with const qualification.
// gcc error: expected nested-name-specifier before 'const'
// This is not a proper way to fix, but I do not have a choice right now. The variable is in a private section of a class so should be safe.
template <class Class, class BaseClass, const char* const& sClassName, class FactoryClass>
#ifdef _WIN32
typename const FactoryProduct<Class, BaseClass, sClassName, FactoryClass>::Creator FactoryProduct<Class, BaseClass, sClassName, FactoryClass>::creatorPrivate;
#else
typename FactoryProduct<Class, BaseClass, sClassName, FactoryClass>::Creator FactoryProduct<Class, BaseClass, sClassName, FactoryClass>::creatorPrivate;
#endif
template <class Class, class BaseClass, const char* const& sClassName, class FactoryClass>
int FactoryProduct<Class, BaseClass, sClassName, FactoryClass>::Creator::isConstructed;
// For objects that should NOT be creatable by a factory
template <class BaseClass, const char* const& sClassName>
class NonFactoryProduct : public BaseClass
{
public:
NonFactoryProduct():BaseClass() {}
template<class Arg0>
NonFactoryProduct(Arg0 arg0):BaseClass(arg0) {}
template<class Arg0, class Arg1>
NonFactoryProduct(Arg0 arg0, Arg1 arg1):BaseClass(arg0, arg1) {}
template<class Arg0, class Arg1, class Arg2>
NonFactoryProduct(Arg0 arg0, Arg1 arg1, Arg2 arg2):BaseClass(arg0, arg1, arg2) {}
template<class Arg0, class Arg1, class Arg2, class Arg3>
NonFactoryProduct(Arg0 arg0, Arg1 arg1, Arg2 arg2, Arg3 arg3):BaseClass(arg0, arg1, arg2, arg3) {}
static const RBX::Name& className()
{
return RBX::Name::declare<sClassName>();
};
static bool isNullClassName() {
RBXASSERT(className().empty() == (sClassName==NULL));
return sClassName==NULL;
};
const RBX::Name& getClassName() const {
return className();
}
};
} // namespace RBX
+58
View File
@@ -0,0 +1,58 @@
#pragma once
#include "FastLog.h"
namespace RBX {
// Wrapper around values that allows it to be used like
// a normal reference to the type (i.e. T& instead of T*).
// Also mildly obscures stored values so that they are harder to find
// with a memory scan.
template<typename T> class ObscureValue {
static const int kArraySize = (sizeof(T)/sizeof(long) < 1) ? 1 : sizeof(T)/sizeof(long);
union InternalStorage
{
long asRaw[kArraySize];
T asBase;
};
InternalStorage storage;
public:
explicit ObscureValue(const T& value){
InternalStorage tmp;
tmp.asBase = value;
for (int i = 0; i < kArraySize; ++i)
{
storage.asRaw[i] = tmp.asRaw[i] ^ reinterpret_cast<uintptr_t>(this) ;
}
}
operator const T() const {
InternalStorage tmp;
for (int i = 0; i < kArraySize; ++i)
{
tmp.asRaw[i] = storage.asRaw[i] ^ reinterpret_cast<uintptr_t>(this) ;
}
return tmp.asBase;
}
ObscureValue& operator=(const T& other) {
InternalStorage tmp;
tmp.asBase = other;
for (int i = 0; i < kArraySize; ++i)
{
storage.asRaw[i] = tmp.asRaw[i] ^ reinterpret_cast<uintptr_t>(this) ;
}
return *this;
}
private:
// Disable no-arg construction, copy, and regular assign.
// Some of these may be safe, but they are not needed yet,
// and the safety of this class is easier to understand without
// them.
ObscureValue();
ObscureValue(const ObscureValue&);
ObscureValue& operator=(const ObscureValue&);
};
}
+108
View File
@@ -0,0 +1,108 @@
#pragma once
#include "Util/Velocity.h"
namespace RBX {
class PV
{
public:
CoordinateFrame position;
Velocity velocity;
private:
/*
inline PV operator *(const PV& localPV) const {
CoordinateFrame worldPos(position * localPV.position);
Velocity otherVWorld = localPV.velocity.rotateBy(position.rotation);
Vector3 linearVel = linearVelocityAtPoint(worldPos.translation) + otherVWorld.linear;
Vector3 rotVel = velocity.rotational + otherVWorld.rotational;
Velocity worldVel(linearVel, rotVel);
return PV(worldPos, worldVel);
}
*/
public:
bool operator==(const PV& other) const {
return (position == other.position) && (velocity == other.velocity);
}
bool operator!=(const PV& other) const {
return !(*this == other);
}
// CoordinateFrame and Velocity both initialize to identity/0
inline PV()
{}
PV(const CoordinateFrame& _position, const Velocity& _velocity) :
position(_position), velocity(_velocity) {}
PV(const PV &other) :
position(other.position), velocity(other.velocity) {}
inline ~PV() {}
/**
Computes the inverse of this PV.
*/
/*
inline PV inverse() const {
PV out;
out.position = position.inverse();
out.velocity = -velocity.rotateBy(out.position.rotation);
return out;
}
inline PV toObjectSpace(const PV& g) const {
return this->inverse() * g;
}
inline PV toWorldSpace(const PV& localPV) const {
return *this * localPV;
}
*/
// Generate Local Linear Velocities
inline Vector3 linearVelocityAtPoint(const Vector3& worldPos) const {
return velocity.linearVelocityAtOffset(worldPos - position.translation);
}
// Generate Local Velocities
inline Velocity velocityAtPoint(const Vector3& worldPos) const {
return velocity.velocityAtOffset(worldPos - position.translation);
}
inline Velocity velocityAtLocalOffset(const Vector3& localOffset) const {
Vector3 worldPos = position.pointToWorldSpace(localOffset);
return velocityAtPoint(worldPos);
}
// Generate Local PVs
inline PV pvAtLocalOffset(const Vector3& localOffset) const {
return pvAtLocalCoord(CoordinateFrame(localOffset));
}
static inline void pvAtLocalCoord(const PV& base, const CoordinateFrame& localCoord, PV& answer) {
CoordinateFrame::mul(base.position, localCoord, answer.position);
answer.velocity = base.velocityAtPoint(answer.position.translation);
}
inline PV pvAtLocalCoord(const CoordinateFrame& localCoord) const {
PV answer;
pvAtLocalCoord(*this, localCoord, answer);
return answer;
}
inline PV lerp(const PV& other, float alpha) const {
return PV( position.lerp(other.position, alpha),
velocity.lerp(other.velocity, alpha) );
}
};
} // namespace RBX
+40
View File
@@ -0,0 +1,40 @@
#pragma once
namespace RBX {
enum PartMaterial
{
PLASTIC_MATERIAL = 0x0100,
SMOOTH_PLASTIC_MATERIAL = 0x0110,
NEON_MATERIAL = 0x0120,
WOOD_MATERIAL = 0x0200,
WOODPLANKS_MATERIAL = 0x0210,
MARBLE_MATERIAL = 0x0310,
SLATE_MATERIAL = 0x0320,
CONCRETE_MATERIAL = 0x0330,
GRANITE_MATERIAL = 0x0340,
BRICK_MATERIAL = 0x0350,
PEBBLE_MATERIAL = 0x0360,
COBBLESTONE_MATERIAL= 0x0370,
ROCK_MATERIAL = 0x0380,
SANDSTONE_MATERIAL = 0x0390,
BASALT_MATERIAL = 0x0314,
CRACKED_LAVA_MATERIAL = 0x0324,
RUST_MATERIAL = 0x0410,
DIAMONDPLATE_MATERIAL = 0x0420,
ALUMINUM_MATERIAL = 0x0430,
METAL_MATERIAL = 0x0440,
GRASS_MATERIAL = 0x0500,
SAND_MATERIAL = 0x0510,
FABRIC_MATERIAL = 0x0520,
SNOW_MATERIAL = 0x0530,
MUD_MATERIAL = 0x0540,
GROUND_MATERIAL = 0x0550,
ICE_MATERIAL = 0x0600,
GLACIER_MATERIAL = 0x0610,
AIR_MATERIAL = 0x0700,
WATER_MATERIAL = 0x0800,
LEGACY_MATERIAL = 0xFFFF, // should not be serialized
};
}
+101
View File
@@ -0,0 +1,101 @@
#pragma once
#include "Util/G3DCore.h"
#include "rbx/rbxTime.h"
#include <boost/circular_buffer.hpp>
#include "Util/Average.h"
#include "Util/Velocity.h"
#include "rbx/RunningAverage.h"
namespace RBX {
#define NUM_MAX_HISTORY 8
#define NUM_BUFFER_NODES 2
class PartInstance;
// This class keeps a list of frames and the time they were set.
class PathInterpolatedCFrame
{
private:
struct FrameInfo
{
CoordinateFrame coordinateFrame;
Velocity velocity;
RemoteTime remoteTime; // in sender's time scale
FrameInfo() {}
FrameInfo(const CoordinateFrame &cf, const Velocity& vel, const Time& local, const RemoteTime& remote) : coordinateFrame(cf), velocity(vel), remoteTime(remote) {}
};
FrameInfo prevFrame;
FrameInfo lastStartFrame;
bool beingMoved;
int uiStepId;
double localToRemoteTimeOffset; // subtract local time by this value to get remote time
RunningAverage<> avgInterval;
Time prevStepTime;
boost::circular_buffer_space_optimized<FrameInfo> frameInfos;
float targetDelayInSeconds;
int targetFrame;
// for analytics
double lastTargetDelayValue;
double targetDelayDeltaMax;
inline const CoordinateFrame& recordAndReturn(const CoordinateFrame& value, const Time& local, const RemoteTime& remote)
{
beingMoved = true;
prevFrame.coordinateFrame = value;
prevFrame.remoteTime = remote;
return prevFrame.coordinateFrame;
}
inline const CoordinateFrame& recordAndReturnHermite(const CoordinateFrame& value, const FrameInfo& startFrame, const Time& local, const RemoteTime& remote)
{
beingMoved = true;
lastStartFrame = startFrame;
prevFrame.coordinateFrame = value;
prevFrame.remoteTime = remote;
return prevFrame.coordinateFrame;
}
const CoordinateFrame& interpolate( const Time& now, const Time& targetTime, const unsigned int& upper, const PartInstance* part = NULL);
const CoordinateFrame& interpolateHermiteSpline( const Time& now, const Time& targetTime, const unsigned int& upper, const PartInstance* part = NULL);
RemoteTime computeSampleTargetTime( const Time& now);
public:
PathInterpolatedCFrame();
~PathInterpolatedCFrame() {}
void clearHistory();
// timeStamp is time this value was set. If coming from network, the value should be time it was send from the server
void setValue(PartInstance* part, const CoordinateFrame& value, const Velocity& vel, const RemoteTime& timeStamp, Time now, float localTimeOffest, int numNodesAhead);
void setTargetDelay(float value);
void setUiStepId(int id) {uiStepId = id;}
int getUiStepId() const {return uiStepId;}
double getLocalToRemoteTimeOffset() {return localToRemoteTimeOffset;}
void setRenderedFrame(const CoordinateFrame& value);
void setRenderedFrame(const CoordinateFrame& value, const RemoteTime& remoteTime);
CoordinateFrame computeValue(PartInstance* part, const Time& t);
CoordinateFrame getLastComputedValue() const { return prevFrame.coordinateFrame; }
bool isBeingMovedByInterpolator() const { return beingMoved; }
Color3 getSampleIntervalColor() const;
float getSampleInterval() const;
void renderPath(Adorn* adorn);
};
} // namespace
+117
View File
@@ -0,0 +1,117 @@
#pragma once
#include <boost/functional/hash.hpp>
#include "Util/Math.h"
namespace RBX {
enum PhysicalPropertiesMode
{
PhysicalPropertiesMode_Legacy,
PhysicalPropertiesMode_Default,
PhysicalPropertiesMode_NewPartProperties
};
class PhysicalProperties
{
private:
bool customEnabled;
float density;
float elasticity;
float friction;
float frictionWeight;
float elasticityWeight;
static float minDen() { return 0.01f; }
static float maxDen() { return 100.0f;}
static float minFri() { return 0.0f; } // Negative friction Generates energy
static float maxFri() { return 2.0f; }
static float minFrW() { return 0.0f; }
static float maxFrW() { return 100.0f;}
static float minEla() { return 0.0f; } // Negative Elasticity causes penetration
static float maxEla() { return 1.0f; } // Elasticity > 1 causes energy gain
static float minElW() { return 0.0f; }
static float maxElW() { return 100.0f;}
public:
// Default Constructor for initializing part instances
PhysicalProperties():
customEnabled(false),
density(0),
friction(0),
elasticity(0),
frictionWeight(0),
elasticityWeight(0)
{
}
// Constructor for enabling Custom
PhysicalProperties(float density_, float friction_, float elasticity_, float frictionWeight_ = 1.0f, float elasticityWeight_ = 1.0f):
customEnabled(true),
density (G3D::clamp(density_, minDen(), maxDen())),
friction (G3D::clamp(friction_, minFri(), maxFri())),
elasticity (G3D::clamp(elasticity_, minEla(), maxEla())),
frictionWeight (G3D::clamp(frictionWeight_, minFrW(), maxFrW())),
elasticityWeight(G3D::clamp(elasticityWeight_, minElW(), maxElW()))
{
}
size_t hashCode() const;
bool getCustomEnabled() const
{
return customEnabled;
}
void setCustomEnabled( bool value )
{
customEnabled = value;
}
float getDensity() const
{
return density;
}
float getFriction() const
{
return friction;
}
float getElasticity() const
{
return elasticity;
}
float getFrictionWeight() const
{
return frictionWeight;
}
float getElasticityWeight() const
{
return elasticityWeight;
}
//Operators
bool operator==(const PhysicalProperties& other) const
{
return ((customEnabled == other.customEnabled) &&
(density == other.density) &&
(friction == other.friction) &&
(elasticity == other.elasticity) &&
(frictionWeight == other.frictionWeight) &&
(elasticityWeight== other.elasticityWeight));
}
bool operator!=(const PhysicalProperties& other) const
{
return !(*this == other);
}
};
size_t hash_value(const PhysicalProperties& properties);
}; //Namespace RBX
+68
View File
@@ -0,0 +1,68 @@
#pragma once
#include "Util/G3DCore.h"
#include "Util/Quaternion.h"
namespace RBX {
class PhysicsCoord
{
public:
Vector3 translation;
Quaternion rotation;
bool operator==(const PhysicsCoord& other) const {
return (translation == other.translation) && (rotation == other.rotation);
}
bool operator!=(const PhysicsCoord& other) const {
return !(*this == other);
}
inline PhysicsCoord() :
translation(Vector3::zero()) {}
PhysicsCoord(const CoordinateFrame& cframe) :
translation(cframe.translation), rotation(cframe.rotation)
{}
PhysicsCoord(const Vector3& _translation) :
translation(_translation) {}
PhysicsCoord(const Vector3& _translation, const Quaternion& _rotation) :
translation(_translation), rotation(_rotation) {}
PhysicsCoord(const PhysicsCoord &other) :
translation(other.translation), rotation(other.rotation) {}
PhysicsCoord operator+ (const PhysicsCoord& rhs) const {
return PhysicsCoord(translation + rhs.translation, rotation + rhs.rotation);
}
PhysicsCoord operator- (const PhysicsCoord& rhs) const {
return PhysicsCoord(translation - rhs.translation, rotation - rhs.rotation);
}
float squaredMagnitude() const {
return translation.squaredMagnitude() + rotation.magnitude(); // note for quaternion magnitude == squared values?....
}
PhysicsCoord& operator+= (const PhysicsCoord& other) {
translation += other.translation;
rotation += other.rotation;
return *this;
}
PhysicsCoord operator*(float f) const {
return PhysicsCoord(translation * f, rotation * f);
}
PhysicsCoord operator/(float f) const {
float mul = 1.0f/f;
return *this * mul;
}
};
} // namespace RBX
+106
View File
@@ -0,0 +1,106 @@
#pragma once
#include "rbx/boost.hpp"
#include "rbx/rbxTime.h"
#include "boost/array.hpp"
#include <map>
#include <vector>
namespace RBX
{
namespace Profiling
{
void init(bool enabled);
void setEnabled(bool enabled);
bool isEnabled();
struct Bucket
{
float sampleTimeElapsed; // System time span that the bucket sampled for
float wallTimeSpan;
int frames; // The number of "frames" recorded in the bucket
double getActualFPS() const; // frames/sec
double getNominalFPS() const; // frames/sec
double getNominalFramePeriod() const; // secs/frame
double getSampleTime() const { return sampleTimeElapsed; }
double getWallTime() const { return wallTimeSpan; }
int getFrames() const { return frames; }
Bucket();
Bucket& operator+=(const Bucket& b);
};
class Profiler : public boost::noncopyable
{
protected:
const Time::Interval bucketTimeSpan; // The minimum amount of time per bucket
int currentBucket;
boost::array<Bucket, 512> buckets; // TODO: Use boost::circular_buffer
Time lastSampleTime;
public:
const std::string name;
Profiler(const char* name);
virtual ~Profiler() {};
Bucket getWindow(double window) const; // get last samples based on elapsed time
Bucket getFrames(int frames) const; // get n last frames.
static double profilingWindow;
};
// Profiles sections of code using the Mark class
class CodeProfiler : public Profiler
{
friend class Mark;
public:
CodeProfiler(const char* name);
private:
void log(bool frameTick, double wallTimeElapsed);
void unlog(double wallTimeElapsed);
};
// Mark a section of code as belonging to a CodeProfiler
// (Enclosing Mark will be disabled for the lifetime of this object)
class Mark
{
CodeProfiler& section;
Mark* enclosingMark;
bool frameTick;
Time startTime;
const bool enabled;
Time::Interval childrenElapsed; // sum of elapsed time (inclusive) in all Markers that have _this_ as a enclosingMark.
const bool logInclusive; // true if you want to log time including children. false will subtract time spent in children
public:
Mark(CodeProfiler& section, bool frameTick, bool logInclusive = false);
~Mark();
};
// BucketProfile
class BucketProfile
{
std::vector<int> data;
const int* bucketLimits;
unsigned int findBucket(int v);
int total;
public:
// WARNING: assumes pointer to bucketLimits is static and saves it directly
BucketProfile(const int* bucketLimits, int size);
BucketProfile(const BucketProfile& rhs);
BucketProfile();
const BucketProfile& operator = (const BucketProfile& rhs);
void addValue(int v);
void removeValue(int v);
void clear();
int getTotal() { return total; }
const std::vector<int>& getData() const { return data; };
const int* getLimits() const { return bucketLimits; };
};
}
};
+366
View File
@@ -0,0 +1,366 @@
#pragma once
#include <boost/scoped_ptr.hpp>
#include "rbx/rbxTime.h"
#include <vector>
#include "Security/RandomConstant.h"
#include "v8datamodel/HackDefines.h"
#include "util/HeapValue.h"
#include "Security/ApiSecurity.h"
namespace RBX {
namespace Hasher
{
// The PMC constructor assumes a specific ordering of these items.
enum HashSection
{
kGoldHashStart = 0,
kGoldHashEnd = 1,
kGoldHashRot = 2,
kRdataHash = 3,
kVmpPlainHash = 4,
kVmpMutantHash = 5,
kIatHash = 6,
kMiscHash = 7,
kMsvcHash = 8,
kVmp0MiscHash = 9,
kVmp1MiscHash = 10,
kNonGoldHashRot = 11,
kNumberOfSectionHashes = 12,
kGoldHashStruct = 12,
kAllHashStruct = 13,
kNumberOfHashes = 14
};
// These do not have a 1:1 relation with the indicies above.
enum HashFailures
{
// 0x?000
kVmp1MiscHashFail = 1<<15,
kVmp0MiscHashFail = 1<<14,
kVmpMutantHashFail = 1<<13,
kIatHashFail = 1<<12,
// 0x0?00
kGoldHashFail = 1<<11,
kNonceFail = 1<<10,
kAllHashStructFail = 1<<9,
kGoldHashStructFail = 1<<8,
// 0x00?0
kNonGoldHashRotFail = 1<<7,
kVmpPlainHashFail = 1<<6,
kMsvcHashFail = 1<<5,
kRdataHashFail = 1<<4,
// 0x000?
kMiscHashFail = 1<<3,
kGoldHashRotFail = 1<<2,
kGoldHashEndFail = 1<<1,
kGoldHashStartFail = 1<<0
};
static const unsigned int kGoldHashMask = kGoldHashFail;
static const unsigned int kDiffHashMask = kGoldHashStartFail | kGoldHashEndFail
| kMiscHashFail | kRdataHashFail | kMsvcHashFail | kGoldHashStructFail
| kAllHashStructFail | kVmpPlainHashFail | kVmpMutantHashFail | kVmp0MiscHashFail
| kVmp1MiscHashFail | kIatHashFail;
static const unsigned int kMovingHashMask = kNonceFail | kGoldHashRotFail
| kNonGoldHashRotFail;
static const int zeroPad[4] = {0,0,0,0};
static const unsigned int kPmcNonceGoodInc = 3692164867;
static const unsigned int kPmcNonceBadInc = 3692164869;
static const unsigned int kPmcNonceGoodIncInv = 2880154539; //0xABABABAB supplied by irc user. unimportant fact.
}
struct ScanRegion
{
char* startingAddress;
unsigned int size;
// ".text" and ".rdata" appear in several places in RAM, so it is safe to have them as literals.
// likewise, exploiters would quickly realize that .text and .rdata are scanned.
// if they change the value to something else, it would crash.
static ScanRegion getScanRegion(const char* moduleName, const char* RegionName);
ScanRegion() : startingAddress(NULL), size(0){}
ScanRegion(const ScanRegion &initValue) : startingAddress(initValue.startingAddress), size(initValue.size){}
ScanRegion(char* startingAddress, unsigned int size) : startingAddress(startingAddress), size(size) {}
};
struct ScanRegionTest : ScanRegion
{
void* hashState;
unsigned int lastHashValue;
bool closeHash;
bool useHashValueInStructHash;
bool useHashAddrSizeInStructHash;
ScanRegionTest() : ScanRegion(),
hashState(NULL),
lastHashValue(0),
closeHash(false),
useHashValueInStructHash(true),
useHashAddrSizeInStructHash(true) {}
ScanRegionTest(ScanRegion initValue) : ScanRegion(initValue),
hashState(NULL),
lastHashValue(0),
closeHash(false),
useHashValueInStructHash(true),
useHashAddrSizeInStructHash(true) {}
};
struct PmcHashContainer
{
typedef std::vector<unsigned int> HashVector;
unsigned int nonce;
HashVector hash;
PmcHashContainer(const PmcHashContainer& init);
PmcHashContainer() : nonce(0) {}
};
extern PmcHashContainer pmcHash;
#if defined(_WIN32) && !defined(RBX_PLATFORM_DURANGO)
class NtApiCaller
{
private:
static const uintptr_t kKey = 111777;
static const unsigned kNtQvmEndToken = 0x0018C204; // sub esp, 4; ret 0x18;
static const unsigned kNtGtxEndToken = 0x0008C204; // sub esp, 4; ret 0x08;
// on windows xp, this is 0x00?8C212FF // call dword ptr [edx]; ret 0x?8
static const unsigned kEndMask = 0xFFFFFF00;
typedef DWORD (NTAPI *NtQvmPfn)(HANDLE, PVOID, DWORD, PVOID, ULONG, PULONG);
typedef DWORD (NTAPI *NtGtxPfn)(HANDLE, PCONTEXT);
HANDLE thisProcess;
HeapValue<size_t> hashEndSize;
HeapValue<uintptr_t> ntQvmAsUint;
HeapValue<size_t> ntQvmCallHash;
HeapValue<uintptr_t> ntGtxAsUint;
HeapValue<size_t> ntGtxCallHash;
HeapValue<uintptr_t> ntdllTextBase;
HeapValue<size_t> ntdllSize;
static unsigned int hashFeed(unsigned int state, unsigned int value)
{
return state + _rotl((state+kKey)*(value-kKey), 7);
}
__forceinline void initApiFunction(uintptr_t pfn, HeapValue<uintptr_t>& pfnOut, uintptr_t callTemplate, HeapValue<uintptr_t>& callHashOut, HeapValue<uintptr_t>& hashEndSizeOut, unsigned int endToken)
{
if (!pfn || (pfn - ntdllTextBase > ntdllSize))
{
// couldn't find NtQueryVirtualMemory or it wasn't in the dll.
Tokens::apiToken.addFlagSafe(kNtApiNoApi);
}
pfnOut = pfn;
// ZwFilterToken isn't important, but it is called in a near identical way as NtQVM
// generate a hash of how ntdll will be called.
if (callTemplate && (callTemplate - ntdllTextBase < ntdllSize))
{
for (int i = 5; i < 32; ++i) // assume call takes < 32B on x86/WoW64
{
unsigned int value = *reinterpret_cast<unsigned int*>(callTemplate + i);
callHashOut = hashFeed(callHashOut, value);
if((kEndMask & value) == (kEndMask & endToken))
{
hashEndSizeOut = i;
break;
}
}
if (hashEndSizeOut == 0)
{
// didn't find the end token for some reason.
Tokens::apiToken.addFlagSafe(kNtApiNoSyscall);
}
}
else
{
// In this case, ZwFilterToken didn't exist for some reason, or wasn't in ntdll
Tokens::apiToken.addFlagSafe(kNtApiNoTemplate);
}
}
__forceinline bool checkCaller(uintptr_t pfn, const HeapValue<uintptr_t>& callHash)
{
const unsigned char* const& funcMem = reinterpret_cast<const unsigned char*>(pfn);
// probably should check to make sure this is within ntdll.
if (pfn && (pfn - ntdllTextBase < ntdllSize))
{
bool canCall = true;
// Check Early Hooking:
// mov eax, dword 0x0000???? <- B8 ?? ?? 00 00
if (funcMem[0] != 0xB8 || funcMem[3] != 0x00 || funcMem[4] != 0x00)
{
canCall = false;
Tokens::apiToken.addFlagSafe(kNtApiEarly);
}
// Check hash of function
unsigned int checkHash = 0;
int endIdx = hashEndSize;
for (int i = 5; i < 32; ++i) // assume call takes < 32B on x86 and WoW64
{
unsigned int value = *reinterpret_cast<volatile const unsigned int*>(funcMem + i);
checkHash = hashFeed(checkHash, value);
if(i == endIdx)
{
break;
}
}
if (checkHash != callHash)
{
canCall = false;
Tokens::apiToken.addFlagSafe(kNtApiHash);
}
// This decodes and calls the function pointer
return canCall;
}
else
{
// not defined or not within ntdll.
Tokens::apiToken.addFlagSafe(kNtApiNoCall);
}
return false;
}
public:
__forceinline DWORD virtualQuery(void* addr, MEMORY_BASIC_INFORMATION* info, size_t cb)
{
volatile DWORD result = 0;
uintptr_t pfn = ntQvmAsUint;
if (checkCaller(pfn, ntQvmCallHash))
{
result = reinterpret_cast<NtQvmPfn>(pfn)(thisProcess, addr, 0, info, cb, NULL);
}
pfn = 0;
return result;
}
__forceinline DWORD getThreadContext(HANDLE thread, CONTEXT* ctx)
{
volatile DWORD result = 0;
uintptr_t pfn = ntGtxAsUint;
if (checkCaller(pfn, ntGtxCallHash))
{
result = reinterpret_cast<NtGtxPfn>(pfn)(thread, ctx);
}
pfn = 0;
return result;
}
__forceinline bool isNtdllAddress(uintptr_t addr)
{
return (addr - ntdllTextBase) < ntdllSize;
}
NtApiCaller();
};
#endif
class ProgramMemoryChecker
{
protected:
unsigned int hsceHashOrReduced;
unsigned int hsceHashAndReduced;
public:
static const int kHASH_SEED_INIT = 42;
static const int kAllDone = 0xCCCCCCCC; // A number that is non-zero.
static const int kLuaLockOk = 0x1842783;
static const int kLuaLockBad = 0;
static const int kSteps = 30;
static const unsigned int kBlock = 16;
ProgramMemoryChecker();
unsigned int bytesPerStep;
unsigned int currentRegion;
const char* currentMemory;
std::vector<ScanRegionTest> scanningRegions;
unsigned int lastCompletedHash;
unsigned int lastGoldenHash;
Time lastCompletedTime;
unsigned int step();
unsigned int getLastCompletedHash() const;
unsigned int getLastGoldenHash() const;
Time getLastCompletedTime() const;
void getLastHashes(PmcHashContainer::HashVector& outHashes) const;
// This is a hash of the hashes, as well as a hash of the region information.
unsigned int hashScanningRegions(size_t regions = Hasher::kNumberOfHashes-2) const;
// return hash of HumanoidState::computeEvent, update hsceHashOrReduce.
unsigned int updateHsceHash();
unsigned int getHsceOrHash() const;
unsigned int getHsceAndHash() const;
// Should look at return code.
int isLuaLockOk() const;
// Check for stealthedit. Stealthedit sets some pages to non-executable
// and then catches the resulting exception, using the opportunity
// to redirect to a modified page without disturbing the hash mechanism.
// http://www.szemelyesintegracio.hu/cheats/41-game-hacking-articles/419-stealthedit
static bool areMemoryPagePermissionsSetupForHacking();
};
#ifdef _WIN32
_declspec(align(8)) extern const char* const maskAddr;
_declspec(align(8)) extern const char* const goldHash;
unsigned int protectVmpSections();
#else
__attribute__((__aligned__(8))) extern const char* const maskAddr;
__attribute__((__aligned__(8))) extern const char* const goldHash;
#endif
namespace Security{
// The storage for hash checker related security constants.
extern volatile const size_t rbxGoldHash;
// The lower part of .text
extern volatile const uintptr_t rbxLowerBase;
extern volatile const size_t rbxLowerSize;
// The upper part of .text
extern volatile const uintptr_t rbxUpperBase;
extern volatile const size_t rbxUpperSize;
// the .rdata section
extern volatile const uintptr_t rbxRdataBase;
extern volatile const size_t rbxRdataSize;
// the vmp sections
extern volatile const uintptr_t rbxVmpBase;
extern volatile const size_t rbxVmpSize;
// the Import Address (thunk) Table
extern volatile const uintptr_t rbxIatBase;
extern volatile const size_t rbxIatSize;
// the vmp sections (plain .text section)
extern volatile const uintptr_t rbxVmpPlainBase;
extern volatile const size_t rbxVmpPlainSize;
// the vmp sections (mutation .text section)
extern volatile const uintptr_t rbxVmpMutantBase;
extern volatile const size_t rbxVmpMutantSize;
// the vmp sections (don't know)
extern volatile const uintptr_t rbxVmp0MiscBase;
extern volatile const size_t rbxVmp0MiscSize;
// the vmp sections (don't know)
extern volatile const uintptr_t rbxVmp1MiscBase;
extern volatile const size_t rbxVmp1MiscSize;
// the .rdata section without IAT
extern volatile const uintptr_t rbxRdataNoIatBase;
extern volatile const size_t rbxRdataNoIatSize;
}
}
+12
View File
@@ -0,0 +1,12 @@
#pragma once
namespace RBX
{
class IProgressIndicator
{
public:
// returns true if cancel requested.
virtual bool setProgess(float percent) { return step(); }; // optional
virtual bool step() = 0;
};
}
+43
View File
@@ -0,0 +1,43 @@
#pragma once
#include <memory>
#include <string>
#include <boost/functional/hash/hash.hpp>
namespace RBX {
template<class Type>
class ProtectedGeneric
{
private:
Type value;
std::size_t hash;
public:
const Type& peekValue() const
{
return value;
}
bool getValue(Type& _value) const
{
_value = this->value;
boost::hash<Type> hasher;
std::size_t newHash = hasher(_value);
return (hash == newHash);
}
void setValue(Type _value)
{
this->value = _value;
boost::hash<Type> hasher;
hash = hasher(_value);
}
ProtectedGeneric(Type _value)
{
setValue(_value);
}
private:
ProtectedGeneric(const ProtectedGeneric& other)
{}
};
}
+53
View File
@@ -0,0 +1,53 @@
#pragma once
#include <string>
#include <boost/functional/hash.hpp>
#include <boost/scoped_ptr.hpp>
struct lua_State;
namespace RBX {
class ProtectedString
{
public:
static const ProtectedString emptyString;
static ProtectedString fromTrustedSource(const std::string& stringRef);
static ProtectedString fromBytecode(const std::string& stringRef);
// Only use in unit tests!
static ProtectedString fromTestSource(const std::string& stringRef);
ProtectedString();
ProtectedString(const ProtectedString& other);
const std::string& getSource() const { return source; }
const std::string& getBytecode() const { return bytecode; }
bool empty() const { return source.empty() && bytecode.empty(); }
const std::string& getOriginalHash() const;
void calculateHash(std::string* out) const;
bool operator==(const ProtectedString& other) const;
bool operator!=(const ProtectedString& other) const;
ProtectedString& operator=(const ProtectedString& other);
private:
std::string source;
std::string bytecode;
// Need to keep a pointer to hash to keep the size of this object in
// line with other lua-bridged types.
boost::scoped_ptr<std::string> hash;
// Hide this to force all changes in string to go through
// fromTrustedSource.
void setString(const std::string& newSource, const std::string& newBytecode);
};
size_t hash_value(const ProtectedString& str);
}
+112
View File
@@ -0,0 +1,112 @@
/* Copyright 2003-2005 ROBLOX Corporation, All Rights Reserved */
#pragma once
#include "Util/G3DCore.h"
namespace RBX {
class Quaternion {
public:
float x, y, z, w;
Quaternion(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {}
Quaternion(const G3D::Vector3& v, float _w = 0) : x((float)v.x), y((float)v.y), z((float)v.z), w(_w) {}
Quaternion() : x(0.0f), y(0.0f), z(0.0f), w(1.0f) {}
Quaternion(const G3D::Matrix3& rot);
Quaternion& operator= (const Quaternion& other);
inline const G3D::Vector3& imag() const {
return *(reinterpret_cast<const G3D::Vector3*>(this));
}
inline G3D::Vector3& imag() {
return *(reinterpret_cast<G3D::Vector3*>(this));
}
void toRotationMatrix(
Matrix3& rot) const;
inline float dot(const Quaternion& other) const {
return (x * other.x) + (y * other.y) + (z * other.z) + (w * other.w);
}
inline float magnitude() const {
return x*x + y*y + z*z + w*w;
}
float maxComponent() const {
return std::max( std::max(fabs(x), fabs(y)), std::max(fabs(z), fabs(w)));
}
// Return the angle of the axis-angle representation of the quaternion
inline float getAngle() const {
return 2.0f * acos(w);
}
// Return the axis of the axis-angle representation of the quaternion
inline Vector3 getAxis() const {
float sinSquared = 1.f - w * w;
if (sinSquared < 1e-6) //Check for divide by zero
return Vector3(1.0, 0.0, 0.0); // Arbitrary
float sinRecip = 1.f/ sqrtf(sinSquared);
return Vector3(x * sinRecip, y * sinRecip, z * sinRecip);
}
inline Quaternion conjugate() const {
return Quaternion(-x, -y, -z, w);
}
inline float& operator[] (int i) const {
return ((float*)this)[i];
}
inline operator float* () {
return (float*)this;
}
inline operator const float* () const {
return (float*)this;
}
inline Quaternion operator*(const Quaternion& other) const {
// Following Watt & Watt, page 360
const Vector3& v1 = imag();
const Vector3& v2 = other.imag();
float s1 = w;
float s2 = other.w;
return Quaternion(s1*v2 + s2*v1 + v1.cross(v2), s1*s2 - v1.dot(v2));
}
inline Quaternion operator+ (const Quaternion& other) const {
return Quaternion(x + other.x, y + other.y, z + other.z, w + other.w);
}
inline Quaternion operator- (const Quaternion& other) const {
return Quaternion(x - other.x, y - other.y, z - other.z, w - other.w);
}
inline Quaternion operator* (float s) const {
return Quaternion(s*x, s*y, s*z, s*w);
}
// inline
Quaternion& operator*=(float fScalar);
// inline
Quaternion& operator+=(const Quaternion& rkQuaternion);
void normalize() {
*this *= 1.0f / sqrtf(magnitude());
}
};
} // namespace
#include "Quaternion.inl"
+24
View File
@@ -0,0 +1,24 @@
/**
Quaternion.inl
*/
namespace RBX {
inline Quaternion& Quaternion::operator+= (const Quaternion& rkQuaternion) {
x += rkQuaternion.x;
y += rkQuaternion.y;
z += rkQuaternion.z;
w += rkQuaternion.w;
return *this;
}
inline Quaternion& Quaternion::operator*= (float fScalar) {
x *= fScalar;
y *= fScalar;
z *= fScalar;
w *= fScalar;
return *this;
}
} // namespace
+29
View File
@@ -0,0 +1,29 @@
#pragma once
#define STRING_BY_ID(id) (getStringById(id))
#ifdef _WIN32
__declspec(noinline) const char* getStringById(int id);
#elif __APPLE__ || __ANDROID__
__attribute__((noinline)) const char* getStringById(int id);
#else
#error Unsupported Platform.
#endif
enum StringIDs {
ArgStringID = 0,
LuaStringStringId = 1, //"lua"
CommandOutStringId = 2, //"> %s"
StudioASHXFmt = 3, //fmt
StudioASHX = 4, //ashx
RunningScript = 5, //Running script %s
ExecScriptNewThread = 6,//Execute script in new thread, name: %s, identity: %u
FullScriptCode = 7, //Full script code:\n %s
EnableToCreateSBThread = 8, //Unable to create trusted sandbox thread
EnableToCreateNewThread = 9, //Unable to create new thread
ScriptStr = 10, //Script
Rocky = 11,//rocky
HasGamePassLuaWarning = 12, //Game passes can only be queried by a Script running on a ROBLOX game server
NoTeleportInStudio = 13, //Teleporting while using ROBLOX Studio is not permitted
LoadingScreenScriptPath = 14, // The path to the script that creates the loading gui
};
+109
View File
@@ -0,0 +1,109 @@
/* Copyright 2003-2005 ROBLOX Corporation, All Rights Reserved */
#pragma once
#include "Util/G3DCore.h"
#include "G3D/Rect2D.h"
namespace RBX {
// TODO: Replace with G3D::Rect2D
class Rect {
public:
typedef enum {TOP, BOTTOM, LEFT, RIGHT, CENTER, NONE} Location;
static bool legalX(Location loc) {return ((loc != TOP) && (loc != BOTTOM));}
static bool legalY(Location loc) {return ((loc != LEFT) && (loc != RIGHT));}
Vector2 low; // top left
Vector2 high; // bottom right
Rect() : low(0,0), high(0,0) {}
Rect(Rect2D r) : low(r.x0y0()), high(r.x1y1()) {}
Rect2D toRect2D() const {return Rect2D::xyxy(low, high);}
Rect(float left, float top, float right, float bottom) :
low(left, top), high(right, bottom) {}
Rect(const Vector2& _high) :
low(Vector2::zero()), high(_high) {}
Rect(const Vector2& _low, const Vector2& _high) :
low(_low), high(_high) {}
static Rect fromLowSize(const Vector2& _low, const Vector2& _size) {
return Rect(_low, _low + _size);
}
static Rect xywh(float x, float y, float w, float h) {
return Rect(x,y,x+w,y+h);
}
static Rect fromCenterSize(const Vector2& _center, const Vector2& _size) {
Vector2 halfSize = _size * 0.5f;
return Rect(_center - halfSize, _center + halfSize);
}
static Rect fromCenterSize(const Vector2& _center, float _size) {
return fromCenterSize(_center, Vector2(_size, _size));
}
void unionWith(const Rect& other);
void unionWith(const Vector2& point) {
unionWith(Rect(point, point));
}
bool operator== (const Rect& other) const {
return ((low == other.low) && (high == other.high));
}
bool operator!= (const Rect& other) const {
return ((low != other.low) || (high != other.high));
}
bool contains(const Vector2& xz) const {
return ((xz.x >= low.x) && (xz.x <= high.x) && (xz.y >= low.y) && (xz.y <= high.y));
}
bool pointInRect(int x, int y) const {
return ((x >= low.x) && (x <= high.x) && (y >= low.y) && (y <= high.y));
}
bool pointInRect(Vector2int16 point) const {
return pointInRect(point.x, point.y);
}
Vector2 size() const {
return (high - low);
}
Vector2 center() const {
return (low + high) * 0.5;
}
Location pointInBorder(const Vector2& point, float borderRatio);
Vector2 positionPoint(Location xLoc, Location yLoc) const;
Vector2 positionPoint(const Vector2& point, Location xLoc, Location yLoc) const;
Rect positionChild(const Rect& child, Location xLoc, Location yLoc) const;
Rect inset(int dx) {
return Rect(low.x+dx, low.y+dx, high.x-dx, high.y-dx);
}
Rect inset(const Vector2int16& dd) {
return Rect(low.x+dd.x, low.y+dd.y, high.x-dd.x, high.y-dd.y);
}
Vector2 clamp(const Vector2& point) {
return point.clamp(low, high);
}
static const float BORDER_RATIO;
static const float BORDER_RATIO_DRAG;
static const float BORDER_RATIO_THIN;
};
}
+70
View File
@@ -0,0 +1,70 @@
/* Copyright 2003-2005 ROBLOX Corporation, All Rights Reserved */
#pragma once
#include "Util/Rect.h"
#include "rbx/Debug.h"
#include "Util/Math.h"
namespace RBX {
class Adorn;
class Region2 {
public:
class WeightedPoint {
public:
Vector2 point;
float radius;
WeightedPoint()
: point(Vector2::zero())
, radius(0.0f)
{}
WeightedPoint(const Vector2& point, const float radius)
: point(point)
, radius(radius)
{}
};
private:
WeightedPoint owner;
G3D::Array<WeightedPoint> others;
bool findCloserOther(const Vector2& point, const float slop) const;
public:
void clearEmpty() {
owner = WeightedPoint();
others.fastClear();
}
bool isEmpty() const {
return (owner.radius <= 0.0f);
}
Region2()
{}
~Region2() {}
void setOwner(const WeightedPoint& _owner) {
owner = _owner;
}
void appendOther(const WeightedPoint& _other) {
others.append(_other);
}
bool contains(const Vector2& pos2d, const float slop) const;
static float getRelativeError(const Vector2& pos2d, const WeightedPoint& owner); // go through all owner points - find best one
static bool pointInRange(const Vector2& pos2d, const WeightedPoint& owner, const float slop);
static bool closerToOtherPoint( const Vector2& pos2d,
const WeightedPoint& owner,
const WeightedPoint& other,
float slop);
};
}
+37
View File
@@ -0,0 +1,37 @@
/* Copyright 2003-2005 ROBLOX Corporation, All Rights Reserved */
#pragma once
#include "G3D/Vector3.h"
#include "G3D/CoordinateFrame.h"
namespace RBX {
class Extents;
class Region3 {
private:
G3D::CoordinateFrame cframe;
Vector3 size;
void init(const Extents &extents);
public:
Region3();
Region3(const Vector3& min, const Vector3& max);
explicit Region3(const Extents &extents);
~Region3() {}
const G3D::CoordinateFrame& getCFrame() const { return cframe; }
const Vector3& getSize() const { return size; }
Vector3 minPos() const;
Vector3 maxPos() const;
inline bool operator==(const Region3& other) const {
return (size == other.size) && (cframe == other.cframe);
}
inline bool operator!=(const Region3& other) const {
return !(*this == other);
}
};
}
+58
View File
@@ -0,0 +1,58 @@
/* Copyright 2003-2005 ROBLOX Corporation, All Rights Reserved */
#pragma once
#include "G3D/Vector3int16.h"
#include "G3DCore.h"
namespace RBX {
class Region3int16 {
private:
Vector3int16 minPos;
Vector3int16 maxPos;
public:
Region3int16()
{
}
Region3int16(const Vector3int16& min, const Vector3int16& max)
: minPos(min)
, maxPos(max)
{
}
const Vector3int16& getMinPos() const
{
return minPos;
}
const Vector3int16& getMaxPos() const
{
return maxPos;
}
bool operator==(const Region3int16& other) const
{
return (minPos == other.minPos) && (maxPos == other.maxPos);
}
bool operator!=(const Region3int16& other) const
{
return !(*this == other);
}
bool contains(const Vector3int16& p) const
{
return
static_cast<unsigned int>(p.x - minPos.x) <= static_cast<unsigned int>(maxPos.x - minPos.x) &&
static_cast<unsigned int>(p.y - minPos.y) <= static_cast<unsigned int>(maxPos.y - minPos.y) &&
static_cast<unsigned int>(p.z - minPos.z) <= static_cast<unsigned int>(maxPos.z - minPos.z);
}
bool empty() const
{
return minPos.x > maxPos.x || minPos.y > maxPos.y || minPos.z > maxPos.z;
}
};
}
+30
View File
@@ -0,0 +1,30 @@
/* Copyright 2003-2005 ROBLOX Corporation, All Rights Reserved */
#pragma once
#include "Util/Vector3int32.h"
namespace RBX {
class Region3int32 {
private:
Vector3int32 minPos;
Vector3int32 maxPos;
public:
Region3int32();
Region3int32(const Vector3int32& min, const Vector3int32& max);
~Region3int32() {}
Vector3int32 getMinPos() const;
Vector3int32 getMaxPos() const;
inline bool operator==(const Region3int32& other) const {
return (minPos == other.minPos) && (maxPos == other.maxPos);
}
inline bool operator!=(const Region3int32& other) const {
return !(*this == other);
}
};
}
+86
View File
@@ -0,0 +1,86 @@
/**
* RobloxGoogleAnalytics.h
* Copyright (c) 2013 ROBLOX Corp. All rights reserved.
*/
#pragma once
#include <string>
#include <sstream>
#include <rbx/signal.h>
namespace RBX {
// Singleton for tracking events across Studio using Google Analytics
// to process the data. Events are sent using the Measurement Protocol:
// https://developers.google.com/analytics/devguides/collection/protocol/v1
//
// All events are posted to the server asynchronously and any calls to
// track data should return immediately.
#define GA_CATEGORY_GAME "Game"
#define GA_CATEGORY_ACTION "Action"
#define GA_CATEGORY_ERROR "Error"
#define GA_CATEGORY_STUDIO "Studio"
#define GA_CATEGORY_COUNTERS "Counters"
#define GA_CATEGORY_RIBBONBAR "RibbonBar"
#define GA_CATEGORY_SECURITY "Security"
#define GA_CATEGORY_STUDIO_SETTINGS "StudioSettings"
// timing variables
#define GA_CLIENT_START "ClientStartTime"
namespace RobloxGoogleAnalytics
{
static const std::string kGoogleAnalyticsBaseURL = "http://www.google-analytics.com/collect";
// Allow for easy initialization based on a lottery number.
// Calls setCanUseAnalytics and init.
void lotteryInit(const std::string &accountPropertyID, size_t maxThreadScheduleSize, int lotteryThreshold, const char * productName = NULL, int robloxAnalyticsLottery = -1, const std::string &sessionKey = "sessionID=");
// Must be called before using the singleton.
void init(const std::string &accountPropertyID, size_t maxThreadScheduleSize, const char * productName = NULL);
bool isInitialized();
bool getCanUseAnalytics();
void setCanUseAnalytics();
void setUserID(int userID);
void setPlaceID(int placeID);
// Signal sent on each call to track an analytic.
rbx::signal<void()>& analyticTrackedSignal();
void setExperimentVariation(const std::string& name, int value);
void trackEvent(
const char *category,
const char *action = "custom",
const char *label = "none",
int value = 0,
bool sync = false);
void trackEventWithoutThrottling(
const char *category,
const char *action = "custom",
const char *label = "none",
int value = 0,
bool sync = false);
void trackUserTiming(
const char *category,
const char *variable,
int milliseconds,
const char *label = "none",
bool sync = false);
void sendEventRoblox(const char* category,
const char* action = "custom",
const char* label = "none",
int value = 0,
bool sync = false);
const std::string& getSessionId();
}
}
+146
View File
@@ -0,0 +1,146 @@
#pragma once
#include "Util/G3DCore.h"
namespace RBX {
// Represents rotations in angles
class RotationAngle
{
public:
RotationAngle()
: value(0)
, sin(0)
, cos(1)
{
}
explicit RotationAngle(float angle)
{
float angleRad = angle * (G3D::pi() / 180.f);
value = angle;
sin = sinf(angleRad);
cos = cosf(angleRad);
}
bool empty() const
{
return value == 0.f;
}
float getValue() const
{
return value;
}
float getSin() const
{
return sin;
}
float getCos() const
{
return cos;
}
bool operator==(const RotationAngle& other) const
{
return value == other.value;
}
bool operator!=(const RotationAngle& other) const
{
return value != other.value;
}
RotationAngle inverse() const
{
RotationAngle result;
result.value = -value;
result.sin = -sin;
result.cos = cos;
return result;
}
RotationAngle combine(const RotationAngle& other) const
{
RotationAngle result;
result.value = value + other.value;
result.sin = sin * other.cos + cos * other.sin;
result.cos = cos * other.cos - sin * other.sin;
return result;
}
private:
float value;
float sin;
float cos;
};
class Rotation2D
{
public:
Rotation2D()
{
}
Rotation2D(const RotationAngle& angle, const Vector2& center)
: angle(angle)
, center(center)
{
}
const RotationAngle& getAngle() const
{
return angle;
}
const Vector2& getCenter() const
{
return center;
}
bool empty() const
{
return angle.empty();
}
bool operator==(const Rotation2D& other) const
{
return angle == other.angle && center == other.center;
}
bool operator!=(const Rotation2D& other) const
{
return angle != other.angle || center != other.center;
}
Vector2 rotate(const Vector2& p) const
{
if (angle.empty())
return p;
Vector2 pl = p - center;
return center + Vector2(
pl.x * angle.getCos() - pl.y * angle.getSin(),
pl.y * angle.getCos() + pl.x * angle.getSin());
}
Rotation2D inverse() const
{
return Rotation2D(angle.inverse(), center);
}
private:
RotationAngle angle;
Vector2 center;
};
}

Some files were not shown because too many files have changed in this diff Show More