Publication of source code.

This commit is contained in:
XlXi 2023-04-16 13:03:43 -04:00
commit e7ad569246
767 changed files with 58342 additions and 0 deletions

20
SharedCode/Autoloader.php Normal file
View File

@ -0,0 +1,20 @@
<?php
/**
* Simple autoloader, so we don't need Composer just for this.
*/
class Autoloader
{
public static function register()
{
spl_autoload_register(function ($class) {
$file = $_SERVER['DOCUMENT_ROOT']."/../SharedCode/".str_replace('\\', DIRECTORY_SEPARATOR, $class).'.php';
if (file_exists($file)) {
require $file;
return true;
}
return false;
});
}
}
Autoloader::register();
?>

4
SharedCode/Global.php Normal file
View File

@ -0,0 +1,4 @@
<?php
require_once "Autoloader.php";
// EOF

1
SharedCode/README.txt Normal file
View File

@ -0,0 +1 @@
This is a ROBLOX backend reconstruction that's written PHP and was created by Brent Da Mage#5357 in September of 2020.

View File

@ -0,0 +1,27 @@
<?php
// This file defines the Roblox.Caching.CacheInfo class.
namespace Roblox\Caching;
class CacheInfo {
private /*CacheabilitySettings*/ $cacheSettings;
private /*String*/ $entityName;
private /*Bool*/ $boolValue;
function __construct($settings, $entityName, $boolValue = true) {
$this->cacheSettings = $settings;
$this->entityName = $entityName;
$this->boolValue = $boolValue;
}
function CacheSettings() {
return $cacheSettings;
}
function EntityName() {
return $entityName;
}
}
// EOF

View File

@ -0,0 +1,27 @@
<?php
// This file defines the Roblox.Caching.CacheabilitySettings class.
namespace Roblox\Caching;
class CacheabilitySettings {
public $collectionsAreCacheable = false;
public $countsAreCacheable = false;
public $entityIsCacheable = false;
public $idLookupsAreCacheable = false;
public $hasUnqualifiedCollections = false;
function __construct($settings = []) {
foreach ($settings as $name => $value) {
if (isset($this->$name)) {
// TODO: This makes potential private classes modifiable from outside the class
$this->$name = $value;
}else {
// One of the given cacheability settings doesn't exist
throw new \Exception("Invalid cacheability setting: \"$name\"");
}
}
}
}
// EOF

View File

@ -0,0 +1,20 @@
<?php
// This file defines the Roblox.Caching.LocalCache class. Originally housed in C:\teamcity-agent\work\a6371342c4f9b6ec\Assemblies\Caching\Roblox.Caching\RobloxCaches\LocalCache.cs.
namespace Roblox\Caching;
class LocalCache {
function __construct() {
}
function GetEntityFromCacheByIDLookup/*[TIndex,TEntity,TDal]*/(/*ICacheInfo*/ $cacheInfo, /*String*/ $entityIdLookup, /*Func`1*/ $getter) {
/*
at Roblox.Common.EntityHelper.DoGetOrCreate[TIndex,TDal,TEntity](GetOrCreateDAL`1 dalGetterOrCreater) in C:\teamcity-agent\work\a6371342c4f9b6ec\Assemblies\Data\Roblox.Data\Entities\EntityHelper.cs:line 316
at Roblox.Caching.LocalCache.GetEntityFromCacheByIDLookup[TIndex,TEntity,TDal](ICacheInfo cacheInfo, String entityIdLookup, Func`1 getter) in C:\teamcity-agent\work\a6371342c4f9b6ec\Assemblies\Caching\Roblox.Caching\RobloxCaches\LocalCache.cs:line 701
*/
}
}
// EOF

View File

@ -0,0 +1,38 @@
<?php
// This file defines the Roblox.Common.EntityHelper class. Originally housed in C:\teamcity-agent\work\a6371342c4f9b6ec\Assemblies\Data\Roblox.Data\Entities\EntityHelper.cs.
namespace Roblox\Common;
class EntityHelper {
static function GetOrCreateEntity/*[TIndex,TEntity,TDal]*/(/*ICacheInfo*/ $cacheInfo, /*String*/ $entityIdLookup, /*GetOrCreate`1*/ $getterOrCreator) {
/*
at Roblox.Caching.LocalCache.GetEntityFromCacheByIDLookup[TIndex,TEntity,TDal](ICacheInfo cacheInfo, String entityIdLookup, Func`1 getter) in C:\teamcity-agent\work\a6371342c4f9b6ec\Assemblies\Caching\Roblox.Caching\RobloxCaches\LocalCache.cs:line 701
at Roblox.Common.EntityHelper.GetOrCreateEntity[TIndex,TEntity,TDal](ICacheInfo cacheInfo, String entityIdLookup, GetOrCreate`1 getterOrCreator) in C:\teamcity-agent\work\a6371342c4f9b6ec\Assemblies\Data\Roblox.Data\Entities\EntityHelper.cs:line 0
*/
}
static function DoGetOrCreate/*[TIndex,TDal,TEntity]*/(/*GetOrCreateDAL`1*/ $dalGetterOrCreater) {
/*
at Roblox.Platform.Throttling.Entities.NamespaceDAL.GetOrCreateNamespace(String value)
at Roblox.Common.EntityHelper.DoGetOrCreate[TIndex,TDal,TEntity](GetOrCreateDAL`1 dalGetterOrCreater) in C:\teamcity-agent\work\a6371342c4f9b6ec\Assemblies\Data\Roblox.Data\Entities\EntityHelper.cs:line 316
*/
}
static function SaveEntity($entity, $createCode, $updateCode) {
}
/*
* Got rid of IDTYPE template. It can be retrieved from the $entityIdLookup parameter.
* CLASSNAME template can be passed via a parameter as a string.
* BIZCLASSNAME is unnecessary.
*/
static function GetEntity/*<<IDTYPE>, <CLASSNAME>, <BIZCLASSNAME>>*/(/*ICacheInfo*/ $cacheInfo, /*String*/ $entityIdLookup, /*Get`1*/ $getter) {
// Call the $getter function
call_user_func($getter, $entityIdLookup);
}
}
// EOF

View File

@ -0,0 +1,114 @@
using System;
using System.Collections.Generic;
using Roblox;
using Roblox.Caching;
using Roblox.Common;
using Roblox.Data.Interfaces;
namespace <NAMESPACE>
{
internal class <BIZCLASSNAME> : IRobloxEntity<<IDTYPE>, <CLASSNAME>> <BIZREMOTECACHEABLE>
{
private <CLASSNAME> _EntityDAL;
public <IDTYPE> ID
{
get { return _EntityDAL.ID; }
}
<BIZPROPERTIES>
public <BIZCLASSNAME>()
{
_EntityDAL = new <CLASSNAME>();
}
internal void Delete()
{
EntityHelper.DeleteEntity(
this,
_EntityDAL.Delete
);
}
internal void Save()
{
EntityHelper.SaveEntity(
this,
() =>
{
_EntityDAL.Created = DateTime.Now;
_EntityDAL.Updated = _EntityDAL.Created;
_EntityDAL.Insert();
},
() =>
{
_EntityDAL.Updated = DateTime.Now;
_EntityDAL.Update();
}
);
}
private static <BIZCLASSNAME> CreateNew(<CREATENEWPARAMS>)
{
var entity = new <BIZCLASSNAME>();
<CREATENEWPROPERTYSETTERS>
entity.Save();
return entity;
}
internal static <BIZCLASSNAME> Get(<IDTYPE> id)
{
return EntityHelper.GetEntity<<IDTYPE>, <CLASSNAME>, <BIZCLASSNAME>>(
EntityCacheInfo,
id,
() => <CLASSNAME>.Get(id)
);
}
#$@#@ - Unique ID used to find this section, don't change it. 599W#%2
internal static ICollection<<BIZCLASSNAME>> Get<BIZCLASSNAME>sBy<FKPROPERTYNAME>(<FKIDTYPE> <FKPROPERTYNAME>)
{
string collectionId = string.Format("Get<BIZCLASSNAME>sBy<FKPROPERTYNAME>_<FKPROPERTYNAME>:{0}", <FKPROPERTYNAME>);
return EntityHelper.GetEntityCollection<<BIZCLASSNAME>, <IDTYPE>>(
EntityCacheInfo,
new CacheManager.CachePolicy(
CacheManager.CacheScopeFilter.Qualified,
string.Format("<FKPROPERTYNAME>:{0}", <FKPROPERTYNAME>)
),
collectionId,
() => <BIZCLASSNAME>DAL.Get<BIZCLASSNAME>IDsBy<FKPROPERTYNAME>(<FKPROPERTYNAME>),
Get
);
}
#$@#@2 - Unique ID used to find this section, don't change it. 599W#%44
public void Construct(<CLASSNAME> dal)
{
_EntityDAL = dal;
}
public CacheInfo CacheInfo
{
get { return EntityCacheInfo; }
}
public static CacheInfo EntityCacheInfo = new CacheInfo(
new CacheabilitySettings(collectionsAreCacheable: true, countsAreCacheable: true, entityIsCacheable: true, idLookupsAreCacheable: true, hasUnqualifiedCollections: true),
typeof(<BIZCLASSNAME>).ToString(),
true
);
public IEnumerable<string> BuildEntityIDLookups()
{
yield break;
}
public IEnumerable<StateToken> BuildStateTokenCollection()
{
%^^^^yield return new StateToken(string.Format("<FKPROPERTYNAME>:{0}", <FKPROPERTYNAME>));^^^^%
yield break;
}
<BIZREMOTECACHEABLEREGION>
}
}

View File

@ -0,0 +1,133 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using Roblox.Common;
using Roblox.Common.Persistence;
namespace <NAMESPACE>
{
internal class <DALCLASSNAME>
{
private <IDTYPE> _ID = default(<IDTYPE>);
<DALFIELDS>
internal <IDTYPE> ID
{
get { return _ID; }
set { _ID = value; }
}
<DALPROPERTIES>
private static string <CONNECTIONSTRING>
{
get { return <CONNECTIONSTRINGVALUE>; }
}
internal <DALCLASSNAME>()
{
}
internal void Delete()
{
if (_ID == default(<IDTYPE>))
throw new ApplicationException("Required value not specified: ID.");
var queryParameters = new List<SqlParameter>
{
new SqlParameter("@ID", _ID)
};
var dbInfo = new dbInfo(
<CONNECTIONSTRING>,
"<DELETEPROCEDURE>",
queryParameters
);
EntityHelper.DoEntityDALDelete(dbInfo);
}
internal void Insert()
{
var queryParameters = new List<SqlParameter>
{
<QUERYPARAMETERS>
};
var dbInfo = new dbInfo(
<CONNECTIONSTRING>,
"<INSERTPROCEDURE>",
new SqlParameter("@ID", <IDSQLDBTYPE>),
queryParameters
);
_ID = EntityHelper.DoEntityDALInsert<<IDTYPE>>(dbInfo);
}
internal void Update()
{
var queryParameters = new List<SqlParameter>
{
new SqlParameter("@ID", _ID),
<QUERYPARAMETERS>
};
var dbInfo = new dbInfo(
<CONNECTIONSTRING>,
"<UPDATEPROCEDURE>",
queryParameters
);
EntityHelper.DoEntityDALUpdate(dbInfo);
}
private static <DALCLASSNAME> BuildDAL(SqlDataReader reader)
{
var dal = new <DALCLASSNAME>();
while (reader.Read())
{
dal.ID = (<IDTYPE>)reader["ID"];
<READERPARAMETERS>
}
if (dal.ID == default(<IDTYPE>))
return null;
return dal;
}
internal static <DALCLASSNAME> Get(<IDTYPE> id)
{
if (id == default(<IDTYPE>))
return null;
var queryParameters = new List<SqlParameter>
{
new SqlParameter("@ID", id)
};
var dbInfo = new dbInfo(
<CONNECTIONSTRING>,
"<GETPROCEDURE>",
queryParameters
);
return EntityHelper.GetEntityDAL(dbInfo, BuildDAL);
}
#$@#@ - Unique ID used to find this section, don't change it. 599W#%2
internal static ICollection<<IDTYPE>> Get<CLASSNAME>IDsBy<FKPROPERTYNAME>(<FKIDTYPE> <FKPROPERTYNAME>)
{
if (<FKPROPERTYNAME> == default(<FKIDTYPE>))
throw new ApplicationException("Required value not specified: <FKPROPERTYNAME>.");
var queryParameters = new List<SqlParameter>();
queryParameters.Add(new SqlParameter("@<FKPROPERTYNAME>", <FKPROPERTYNAME>));
return EntityHelper.GetDataEntityIDCollection<<IDTYPE>>(
new dbInfo(
<CONNECTIONSTRING>,
"<CLASSNAME>s_Get<CLASSNAME>IDsBy<FKPROPERTYNAME>",
queryParameters
)
);
}
#$@#@2 - Unique ID used to find this section, don't change it. 599W#%44
}
}

View File

@ -0,0 +1,169 @@
/* Standard Insertion */
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[<INSERTPROCEDURE>]') AND type in (N'P', N'PC'))
BEGIN
EXEC('CREATE PROCEDURE [dbo].[<INSERTPROCEDURE>] AS BEGIN SET NOCOUNT ON; END')
END
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER OFF
GO
ALTER PROCEDURE [dbo].[<INSERTPROCEDURE>]
(
@ID <SQLIDTYPE> OUTPUT
<SQLINPUTPARAMETERLIST>
)
AS
SET NOCOUNT ON
INSERT INTO
[<TABLENAME>]
(
<COLUMNLIST>
)
VALUES
(
<SQLPARAMETERLIST>
)
SET @ID = SCOPE_IDENTITY();
SET NOCOUNT OFF
RETURN
GO
/* Standard Update */
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[<UPDATEPROCEDURE>]') AND type in (N'P', N'PC'))
BEGIN
EXEC('CREATE PROCEDURE [dbo].[<UPDATEPROCEDURE>] AS BEGIN SET NOCOUNT ON; END')
END
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER OFF
GO
ALTER PROCEDURE [dbo].[<UPDATEPROCEDURE>]
(
@ID <SQLIDTYPE>
<SQLINPUTPARAMETERLIST>
)
AS
SET NOCOUNT ON
UPDATE
[<TABLENAME>]
SET
<SETVALUES>
WHERE
([ID] = @ID)
SET NOCOUNT OFF
RETURN
GO
/* Standard Get-By-ID */
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[<GETPROCEDURE>]') AND type in (N'P', N'PC'))
BEGIN
EXEC('CREATE PROCEDURE [dbo].[<GETPROCEDURE>] AS BEGIN SET NOCOUNT ON; END')
END
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[<GETPROCEDURE>]
(
@ID <SQLIDTYPE>
)
AS
SET NOCOUNT ON
SELECT
[ID]
,<COLUMNLIST>
FROM
[<TABLENAME>]
WHERE
([ID] = @ID)
SET NOCOUNT OFF
RETURN
GO
/* Standard Delete */
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[<DELETEPROCEDURE>]') AND type in (N'P', N'PC'))
BEGIN
EXEC('CREATE PROCEDURE [dbo].[<DELETEPROCEDURE>] AS BEGIN SET NOCOUNT ON; END')
END
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[<DELETEPROCEDURE>]
(
@ID <SQLIDTYPE>
)
AS
SET NOCOUNT ON
DELETE FROM
[<TABLENAME>]
WHERE
([ID] = @ID)
SET NOCOUNT OFF
RETURN
GO
#$@#@
/* FK Lookup */
/* Don't use this. It's garbage. */
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[<CLASSNAME>s_Get<CLASSNAME>IDsBy<FKPROPERTYNAME>]
(
@<FKPROPERTYNAME> <FKIDSQLTPE>
)
AS
SET NOCOUNT ON
SELECT
[ID]
FROM
[<CLASSNAME>s]
WHERE
([<FKPROPERTYNAME>] = @<FKPROPERTYNAME>)
SET NOCOUNT OFF
RETURN
599W#%44

View File

@ -0,0 +1,33 @@
<?php
namespace Roblox\Data\Entities;
// http://web.archive.org/web/20140610202425id_/http://broom.gametest1.robloxlabs.com/Legacy/DBWireup/SQL.txt
abstract class Entity {
public $ID;
function __construct() {
}
function CreateNew(...$params) {
// Set default properties here
// Modify properties based on params
// Call Insert function
throw new \Exception(__CLASS__ . "->CreateNew() not implemented");
}
function Delete() {
throw new \Exception(__CLASS__ . "->Delete() not implemented");
}
function Insert() {
throw new \Exception(__CLASS__ . "->Insert() not implemented");
}
function Update() {
throw new \Exception(__CLASS__ . "->Update() not implemented");
}
static function Get($id) {
throw new \Exception(__CLASS__ . "->Get() not implemented");
}
}
// EOF

View File

@ -0,0 +1,39 @@
<?php
namespace Roblox\Data\Entities;
// http://web.archive.org/web/20140610202425id_/http://broom.gametest1.robloxlabs.com/Legacy/DBWireup/DAL.txt
abstract class EntityDAL {
public $ID;
function __construct() {
}
function Delete() {
if (!isset($ID)) {
throw new \Exception("Required value not specified: ID.");
}
$queryParameters = [
new \Roblox\Mysql\SqlParameter("@ID", $ID)
];
$dbInfo = new dbInfo(
<CONNECTIONSTRING>, // the string used to connect to the DB
"<DELETEPROCEDURE>", // the name of the procedure
$queryParameters // the parameters used in the procedure defenition
);
\Roblox\Common\EntityHelper::DoEntityDALDelete($dbInfo);
}
function Insert() {
throw new \Exception(__CLASS__ . "->Insert() not implemented");
}
function Update() {
throw new \Exception(__CLASS__ . "->Update() not implemented");
}
static function Get($id) {
throw new \Exception(__CLASS__ . "->Get() not implemented");
}
}
// EOF

View File

@ -0,0 +1,16 @@
<?php
namespace Roblox\Data\Entities;
class EntityHelper {
// Applies the properties of one class to the other
static function SyncProperties(&$sender, &$receiver) {
// Grabs the sending class's variables as an array
$vars = get_object_vars($sender);
// Iterate through the sending class's variables and apply them to receiving class
do {
$receiver->{key($vars)} = current($vars);
}while (!(next($vars) === FALSE));
}
}
// EOF

View File

@ -0,0 +1,97 @@
<?php
namespace Roblox\Data\Entities;
// http://web.archive.org/web/20140610202436id_/http://broom.gametest1.robloxlabs.com/Legacy/DBWireup/BIZ.txt
// http://web.archive.org/web/20140610202432id_/http://broom.gametest1.robloxlabs.com/Legacy/DBWireup/DAL.txt
abstract class RobloxEntity {
private static $_entityBasePath = "\\Roblox\\Entities\\Mysql\\"; // TODO: add to site config
private $_EntityDAL;
public $ID; // ID isn't always an integer (JobIDs for example)
function __construct(int $id = null) {
$this->_EntityClassName = get_class($this)."Entity";
$this->Construct($this->Get($id));
if ($this->_EntityDAL !== null) {
// $this <-- $_EntityDAL
EntityHelper::SyncProperties($this->_EntityDAL, $this);
}else {
$this->Construct(new $this->_EntityClassName());
}
}
function Delete() {
$this->_EntityDAL->ID = $this->ID;
return $this->_EntityDAL->Delete();
}
function Save() {
// $this --> $this->_EntityDAL
EntityHelper::SyncProperties($this, $this->_EntityDAL);
// TODO: move this check to EntityHelper.SaveEntity
// The check for $this->ID here checks if we've loaded the entity from the database.
// If the entity doesn't already exist in the database, then create it.
$dateTime = new \DateTime();
if ($this->ID !== null) {
$this->_EntityDAL->Created = $dateTime->getTimestamp();
$this->_EntityDAL->Updated = $this->_EntityDAL->Created;
$this->_EntityDAL->Insert();
}else {
$this->_EntityDAL->Updated = $dateTime->getTimestamp();
$this->_EntityDAL->Update();
}
}
protected static function CreateNew(...$params){
// Generate the entity class path
$entityClassPath = self::$_entityBasePath . substr(get_called_class(), 7);
$entity = new $entityClassPath();
$entity->CreateNew(...$params);
return $entity;
}
static function Get(int $id) {
if ($id == null) {
return null;
}
// Generate the entity class path
$entityClassPath = self::$_entityBasePath . substr(get_called_class(), 7);
return \Roblox\Common\EntityHelper::GetEntity(
self::CacheInfo(), // EntityCacheInfo,
$id, // id,
$entityClassPath."::Get" // () => <CLASSNAME>.Get(id)
);
}
function Construct($dal) {
$this->_EntityDAL = $dal;
}
private static $_cacheSettings = [
"collectionsAreCacheable" => true,
"countsAreCacheable" => true,
"entityIsCacheable" => true,
"idLookupsAreCacheable" => true,
"hasUnqualifiedCollections" => true
];
public static function CacheInfo()
{
// Generate the entity cache info on the spot.
// We can't create it outside of this function.
$EntityCacheInfo = new \Roblox\Caching\CacheInfo(
new \Roblox\Caching\CacheabilitySettings(self::$_cacheSettings),
get_called_class(),
true // Not sure what this does
);
return $EntityCacheInfo;
}
}
// EOF

View File

@ -0,0 +1,20 @@
<?php
// This file defines the Roblox.Entities.Mssql.RobloxDataAccessPatternExtensions class. Originally housed in C:\teamcity-agent\work\a6371342c4f9b6ec\Assemblies\Entities\Roblox.Entities.Mssql\RobloxDataAccessPatternExtensions.cs.
namespace Roblox\Entities\Mssql;
class RobloxDataAccessPatternExtensions {
function __construct() {
}
function GetOrCreate/*[TDal]*/(/*RobloxDatabase*/ $database, /*String*/ $storedProcedureName, /*Func`2*/ $dalBuilder, /*Nullable`1*/ $commandTimeout, /*Boolean*/ $includeApplicationIntent, /*SqlParameter[]*/ $queryParameters) {
/*
at Roblox.Mssql.Database.ExecuteReader(String commandText, SqlParameter[] sqlParameters, CommandType commandType, Nullable`1 commandTimeout, Nullable`1 applicationIntent) in C:\teamcity-agent\work\a6371342c4f9b6ec\Assemblies\Mssql\Roblox.Mssql\Database.cs:line 226
at Roblox.Entities.Mssql.RobloxDataAccessPatternExtensions.GetOrCreate[TDal](RobloxDatabase database, String storedProcedureName, Func`2 dalBuilder, Nullable`1 commandTimeout, Boolean includeApplicationIntent, SqlParameter[] queryParameters) in C:\teamcity-agent\work\a6371342c4f9b6ec\Assemblies\Entities\Roblox.Entities.Mssql\RobloxDataAccessPatternExtensions.cs:line 51
*/
}
}
// EOF

View File

@ -0,0 +1,28 @@
<?php
namespace Roblox\Entities\Mysql\Platform\User;
class RobloxUser extends \Roblox\Data\Entities\Entity {
// Define properties here
function CreateNew(...$params) {
// Set default properties here
// Modify properties based on params
// Call Insert function
throw new \Exception(__CLASS__ . "->CreateNew() not implemented");
}
function Delete() {
throw new \Exception(__CLASS__ . "->Delete() not implemented");
}
function Insert() {
throw new \Exception(__CLASS__ . "->Insert() not implemented");
}
function Update() {
throw new \Exception(__CLASS__ . "->Update() not implemented");
}
static function Get($id) {
throw new \Exception(__CLASS__ . "->Get() not implemented");
}
}
// EOF

View File

@ -0,0 +1,20 @@
<?php
// This file defines the Job class.
namespace Roblox\Grid\Rcc;
class Job {
public $id;
public $expirationInSeconds;
public $category;
public $cores;
function __construct($id, $expirationInSeconds = 10, $category = 0, $cores = 1) {
$this->id = $id;
$this->expirationInSeconds = $expirationInSeconds;
$this->category = $category;
$this->cores = $cores;
}
}
// EOF

View File

@ -0,0 +1,29 @@
<?php
// This file defines the LuaType enum. Though this is a class, please treat it like an enum and **ONLY** reference it statically.
namespace Roblox\Grid\Rcc;
class LuaType {
public const LUA_TNIL = "LUA_TNIL";
public const LUA_TBOOLEAN = "LUA_TBOOLEAN";
public const LUA_TNUMBER = "LUA_TNUMBER";
public const LUA_TSTRING = "LUA_TSTRING";
public const LUA_TTABLE = "LUA_TTABLE";
// Casts a PHP value type to a LuaType enum.
static function castToLuaType($value) {
$luaTypeConversions = [
'NULL' => LuaType::LUA_TNIL,
'boolean' => LuaType::LUA_TBOOLEAN,
'integer' => LuaType::LUA_TNUMBER,
'double' => LuaType::LUA_TNUMBER,
'string' => LuaType::LUA_TSTRING,
'array' => LuaType::LUA_TTABLE,
'object' => LuaType::LUA_TNIL
];
return $luaTypeConversions[gettype($value)];
}
}
// EOF

View File

@ -0,0 +1,73 @@
<?php
// This file defines the LuaValue class.
namespace Roblox\Grid\Rcc;
class LuaValue {
public $value;
public $type;
public $table;
// Constructor
function __construct($baseValue) {
if (isset($baseValue)) {
$luaValue = LuaValue::serializeValue($baseValue);
foreach ($luaValue as $name => $child) {
$this->{$name} = $child;
}
}
}
// This function serializes the given PHP variable into a Lua value.
static function serializeValue($phpValue) {
$luaValue = new LuaValue(null); // A really dumb hack
$luaValue->type = LuaType::castToLuaType($phpValue);
if (is_array($phpValue)) {
// TODO: Make this an empty array by default to allow for easy table creation?
$luaValue->table = [];
foreach ($phpValue as $value) {
array_push($luaValue->table, new LuaValue($value));
}
}else {
$luaValue->value = $phpValue;
}
return $luaValue;
}
// This function deserializes the given Lua value into a normal PHP variable.
static function deserializeValue($luaValue) {
if (is_array($luaValue)) {
$phpValue = [];
foreach ($luaValue as $value) {
array_push($phpValue, LuaValue::deserializeValue($value));
}
}else {
if ($luaValue->type == LuaType::LUA_TTABLE && isset($luaValue->table->LuaValue)) {
$phpValue = [];
if (is_array($luaValue->table->LuaValue)) {
$value = $luaValue->table->LuaValue;
}else {
$value = $luaValue->table;
}
foreach ($value as $value) {
array_push($phpValue, $value->deserialize());
}
}elseif ($luaValue->type == LuaType::LUA_TNIL) {
// Null value
$phpValue = null;
}else {
// Direct read from LuaValue's value
$phpValue = $luaValue->value;
}
}
return $phpValue;
}
// This function deserializes the current Lua value into a normal PHP variable.
function deserialize() {
return LuaValue::deserializeValue($this);
}
}
// EOF

View File

@ -0,0 +1,800 @@
<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://roblox.com/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" targetNamespace="http://roblox.com/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<wsdl:types>
<s:schema elementFormDefault="qualified" targetNamespace="http://roblox.com/">
<s:element name="HelloWorld">
<s:complexType />
</s:element>
<s:element name="HelloWorldResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="HelloWorldResult" type="s:string" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="GetVersion">
<s:complexType />
</s:element>
<s:element name="GetVersionResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="GetVersionResult" type="s:string" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="GetStatus">
<s:complexType />
</s:element>
<s:element name="GetStatusResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="GetStatusResult" type="tns:Status" />
</s:sequence>
</s:complexType>
</s:element>
<s:complexType name="Status">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="version" type="s:string" />
<s:element minOccurs="1" maxOccurs="1" name="environmentCount" type="s:int" />
</s:sequence>
</s:complexType>
<s:element name="OpenJob">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="job" type="tns:Job" />
<s:element minOccurs="0" maxOccurs="1" name="script" type="tns:ScriptExecution" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="OpenJobEx">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="job" type="tns:Job" />
<s:element minOccurs="0" maxOccurs="1" name="script" type="tns:ScriptExecution" />
</s:sequence>
</s:complexType>
</s:element>
<s:complexType name="Job">
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="id" type="s:string" />
<s:element minOccurs="1" maxOccurs="1" name="expirationInSeconds" type="s:double" />
<s:element minOccurs="1" maxOccurs="1" name="category" type="s:int" />
<s:element minOccurs="1" maxOccurs="1" name="cores" type="s:double" />
</s:sequence>
</s:complexType>
<s:complexType name="ScriptExecution">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="name" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="script" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="arguments" type="tns:ArrayOfLuaValue" />
</s:sequence>
</s:complexType>
<s:complexType name="ArrayOfLuaValue">
<s:sequence>
<s:element minOccurs="0" maxOccurs="unbounded" name="LuaValue" nillable="true" type="tns:LuaValue" />
</s:sequence>
</s:complexType>
<s:complexType name="ArrayOfJob">
<s:sequence>
<s:element minOccurs="0" maxOccurs="unbounded" name="Job" nillable="true" type="tns:Job" />
</s:sequence>
</s:complexType>
<s:complexType name="LuaValue">
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="type" type="tns:LuaType" />
<s:element minOccurs="0" maxOccurs="1" name="value" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="table" type="tns:ArrayOfLuaValue" />
</s:sequence>
</s:complexType>
<s:simpleType name="LuaType">
<s:restriction base="s:string">
<s:enumeration value="LUA_TNIL" />
<s:enumeration value="LUA_TBOOLEAN" />
<s:enumeration value="LUA_TNUMBER" />
<s:enumeration value="LUA_TSTRING" />
<s:enumeration value="LUA_TTABLE" />
</s:restriction>
</s:simpleType>
<s:element name="OpenJobResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="unbounded" name="OpenJobResult" type="tns:LuaValue"/>
</s:sequence>
</s:complexType>
</s:element>
<s:element name="OpenJobExResponse">
<s:complexType>
<s:sequence>
<s:element name="OpenJobExResult" type="tns:ArrayOfLuaValue"/>
</s:sequence>
</s:complexType>
</s:element>
<s:element name="RenewLease">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="jobID" type="s:string" />
<s:element minOccurs="1" maxOccurs="1" name="expirationInSeconds" type="s:double" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="RenewLeaseResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="RenewLeaseResult" type="s:double" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="Execute">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="jobID" type="s:string" />
<s:element minOccurs="1" maxOccurs="1" name="script" type="tns:ScriptExecution" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="ExecuteResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="unbounded" name="ExecuteResult" nillable="true" type="tns:LuaValue" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="ExecuteEx">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="jobID" type="s:string" />
<s:element minOccurs="1" maxOccurs="1" name="script" type="tns:ScriptExecution" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="ExecuteExResponse">
<s:complexType>
<s:sequence>
<s:element name="ExecuteExResult" type="tns:ArrayOfLuaValue"/>
</s:sequence>
</s:complexType>
</s:element>
<s:element name="CloseJob">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="jobID" type="s:string" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="CloseJobResponse">
<s:complexType />
</s:element>
<s:element name="BatchJob">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="job" type="tns:Job" />
<s:element minOccurs="1" maxOccurs="1" name="script" type="tns:ScriptExecution" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="BatchJobResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="unbounded" name="BatchJobResult" nillable="true" type="tns:LuaValue" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="BatchJobEx">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="job" type="tns:Job" />
<s:element minOccurs="1" maxOccurs="1" name="script" type="tns:ScriptExecution" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="BatchJobExResponse">
<s:complexType>
<s:sequence>
<s:element name="BatchJobExResult" type="tns:ArrayOfLuaValue"/>
</s:sequence>
</s:complexType>
</s:element>
<s:element name="GetExpiration">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="jobID" type="s:string" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="GetExpirationResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="GetExpirationResult" type="s:double" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="GetAllJobs">
<s:complexType />
</s:element>
<s:element name="GetAllJobsResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="unbounded" name="GetAllJobsResult" nillable="true" type="tns:Job" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="GetAllJobsEx">
<s:complexType />
</s:element>
<s:element name="GetAllJobsExResponse">
<s:complexType>
<s:sequence>
<s:element name="GetAllJobsExResult" type="tns:ArrayOfJob" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="CloseExpiredJobs">
<s:complexType />
</s:element>
<s:element name="CloseExpiredJobsResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="CloseExpiredJobsResult" type="s:int" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="CloseAllJobs">
<s:complexType />
</s:element>
<s:element name="CloseAllJobsResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="CloseAllJobsResult" type="s:int" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="Diag">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="type" type="s:int" />
<s:element minOccurs="0" maxOccurs="1" name="jobID" type="s:string" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="DiagResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="unbounded" name="DiagResult" nillable="true" type="tns:LuaValue" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="DiagEx">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="type" type="s:int" />
<s:element minOccurs="0" maxOccurs="1" name="jobID" type="s:string" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="DiagExResponse">
<s:complexType>
<s:sequence>
<s:element name="DiagExResult" type="tns:ArrayOfLuaValue" />
</s:sequence>
</s:complexType>
</s:element>
</s:schema>
</wsdl:types>
<wsdl:message name="HelloWorldSoapIn">
<wsdl:part name="parameters" element="tns:HelloWorld" />
</wsdl:message>
<wsdl:message name="HelloWorldSoapOut">
<wsdl:part name="parameters" element="tns:HelloWorldResponse" />
</wsdl:message>
<wsdl:message name="GetVersionSoapIn">
<wsdl:part name="parameters" element="tns:GetVersion" />
</wsdl:message>
<wsdl:message name="GetVersionSoapOut">
<wsdl:part name="parameters" element="tns:GetVersionResponse" />
</wsdl:message>
<wsdl:message name="GetStatusSoapIn">
<wsdl:part name="parameters" element="tns:GetStatus" />
</wsdl:message>
<wsdl:message name="GetStatusSoapOut">
<wsdl:part name="parameters" element="tns:GetStatusResponse" />
</wsdl:message>
<wsdl:message name="OpenJobSoapIn">
<wsdl:part name="parameters" element="tns:OpenJob" />
</wsdl:message>
<wsdl:message name="OpenJobSoapOut">
<wsdl:part name="parameters" element="tns:OpenJobResponse" />
</wsdl:message>
<wsdl:message name="OpenJobExSoapIn">
<wsdl:part name="parameters" element="tns:OpenJobEx" />
</wsdl:message>
<wsdl:message name="OpenJobExSoapOut">
<wsdl:part name="parameters" element="tns:OpenJobExResponse" />
</wsdl:message>
<wsdl:message name="RenewLeaseSoapIn">
<wsdl:part name="parameters" element="tns:RenewLease" />
</wsdl:message>
<wsdl:message name="RenewLeaseSoapOut">
<wsdl:part name="parameters" element="tns:RenewLeaseResponse" />
</wsdl:message>
<wsdl:message name="ExecuteSoapIn">
<wsdl:part name="parameters" element="tns:Execute" />
</wsdl:message>
<wsdl:message name="ExecuteSoapOut">
<wsdl:part name="parameters" element="tns:ExecuteResponse" />
</wsdl:message>
<wsdl:message name="ExecuteExSoapIn">
<wsdl:part name="parameters" element="tns:ExecuteEx" />
</wsdl:message>
<wsdl:message name="ExecuteExSoapOut">
<wsdl:part name="parameters" element="tns:ExecuteExResponse" />
</wsdl:message>
<wsdl:message name="CloseJobSoapIn">
<wsdl:part name="parameters" element="tns:CloseJob" />
</wsdl:message>
<wsdl:message name="CloseJobSoapOut">
<wsdl:part name="parameters" element="tns:CloseJobResponse" />
</wsdl:message>
<wsdl:message name="BatchJobSoapIn">
<wsdl:part name="parameters" element="tns:BatchJob" />
</wsdl:message>
<wsdl:message name="BatchJobSoapOut">
<wsdl:part name="parameters" element="tns:BatchJobResponse" />
</wsdl:message>
<wsdl:message name="BatchJobExSoapIn">
<wsdl:part name="parameters" element="tns:BatchJobEx" />
</wsdl:message>
<wsdl:message name="BatchJobExSoapOut">
<wsdl:part name="parameters" element="tns:BatchJobExResponse" />
</wsdl:message>
<wsdl:message name="GetExpirationSoapIn">
<wsdl:part name="parameters" element="tns:GetExpiration" />
</wsdl:message>
<wsdl:message name="GetExpirationSoapOut">
<wsdl:part name="parameters" element="tns:GetExpirationResponse" />
</wsdl:message>
<wsdl:message name="GetAllJobsSoapIn">
<wsdl:part name="parameters" element="tns:GetAllJobs" />
</wsdl:message>
<wsdl:message name="GetAllJobsSoapOut">
<wsdl:part name="parameters" element="tns:GetAllJobsResponse" />
</wsdl:message>
<wsdl:message name="GetAllJobsExSoapIn">
<wsdl:part name="parameters" element="tns:GetAllJobsEx" />
</wsdl:message>
<wsdl:message name="GetAllJobsExSoapOut">
<wsdl:part name="parameters" element="tns:GetAllJobsExResponse" />
</wsdl:message>
<wsdl:message name="CloseExpiredJobsSoapIn">
<wsdl:part name="parameters" element="tns:CloseExpiredJobs" />
</wsdl:message>
<wsdl:message name="CloseExpiredJobsSoapOut">
<wsdl:part name="parameters" element="tns:CloseExpiredJobsResponse" />
</wsdl:message>
<wsdl:message name="CloseAllJobsSoapIn">
<wsdl:part name="parameters" element="tns:CloseAllJobs" />
</wsdl:message>
<wsdl:message name="CloseAllJobsSoapOut">
<wsdl:part name="parameters" element="tns:CloseAllJobsResponse" />
</wsdl:message>
<wsdl:message name="DiagSoapIn">
<wsdl:part name="parameters" element="tns:Diag" />
</wsdl:message>
<wsdl:message name="DiagSoapOut">
<wsdl:part name="parameters" element="tns:DiagResponse" />
</wsdl:message>
<wsdl:message name="DiagExSoapIn">
<wsdl:part name="parameters" element="tns:DiagEx" />
</wsdl:message>
<wsdl:message name="DiagExSoapOut">
<wsdl:part name="parameters" element="tns:DiagExResponse" />
</wsdl:message>
<wsdl:portType name="RCCServiceSoap">
<wsdl:operation name="HelloWorld">
<wsdl:input message="tns:HelloWorldSoapIn" />
<wsdl:output message="tns:HelloWorldSoapOut" />
</wsdl:operation>
<wsdl:operation name="GetVersion">
<wsdl:input message="tns:GetVersionSoapIn" />
<wsdl:output message="tns:GetVersionSoapOut" />
</wsdl:operation>
<wsdl:operation name="GetStatus">
<wsdl:input message="tns:GetStatusSoapIn" />
<wsdl:output message="tns:GetStatusSoapOut" />
</wsdl:operation>
<wsdl:operation name="OpenJob">
<wsdl:input message="tns:OpenJobSoapIn" />
<wsdl:output message="tns:OpenJobSoapOut" />
</wsdl:operation>
<wsdl:operation name="OpenJobEx">
<wsdl:input message="tns:OpenJobExSoapIn" />
<wsdl:output message="tns:OpenJobExSoapOut" />
</wsdl:operation>
<wsdl:operation name="RenewLease">
<wsdl:input message="tns:RenewLeaseSoapIn" />
<wsdl:output message="tns:RenewLeaseSoapOut" />
</wsdl:operation>
<wsdl:operation name="Execute">
<wsdl:input message="tns:ExecuteSoapIn" />
<wsdl:output message="tns:ExecuteSoapOut" />
</wsdl:operation>
<wsdl:operation name="ExecuteEx">
<wsdl:input message="tns:ExecuteExSoapIn" />
<wsdl:output message="tns:ExecuteExSoapOut" />
</wsdl:operation>
<wsdl:operation name="CloseJob">
<wsdl:input message="tns:CloseJobSoapIn" />
<wsdl:output message="tns:CloseJobSoapOut" />
</wsdl:operation>
<wsdl:operation name="BatchJob">
<wsdl:input message="tns:BatchJobSoapIn" />
<wsdl:output message="tns:BatchJobSoapOut" />
</wsdl:operation>
<wsdl:operation name="BatchJobEx">
<wsdl:input message="tns:BatchJobExSoapIn" />
<wsdl:output message="tns:BatchJobExSoapOut" />
</wsdl:operation>
<wsdl:operation name="GetExpiration">
<wsdl:input message="tns:GetExpirationSoapIn" />
<wsdl:output message="tns:GetExpirationSoapOut" />
</wsdl:operation>
<wsdl:operation name="GetAllJobs">
<wsdl:input message="tns:GetAllJobsSoapIn" />
<wsdl:output message="tns:GetAllJobsSoapOut" />
</wsdl:operation>
<wsdl:operation name="GetAllJobsEx">
<wsdl:input message="tns:GetAllJobsExSoapIn" />
<wsdl:output message="tns:GetAllJobsExSoapOut" />
</wsdl:operation>
<wsdl:operation name="CloseExpiredJobs">
<wsdl:input message="tns:CloseExpiredJobsSoapIn" />
<wsdl:output message="tns:CloseExpiredJobsSoapOut" />
</wsdl:operation>
<wsdl:operation name="CloseAllJobs">
<wsdl:input message="tns:CloseAllJobsSoapIn" />
<wsdl:output message="tns:CloseAllJobsSoapOut" />
</wsdl:operation>
<wsdl:operation name="Diag">
<wsdl:input message="tns:DiagSoapIn" />
<wsdl:output message="tns:DiagSoapOut" />
</wsdl:operation>
<wsdl:operation name="DiagEx">
<wsdl:input message="tns:DiagExSoapIn" />
<wsdl:output message="tns:DiagExSoapOut" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="RCCServiceSoap" type="tns:RCCServiceSoap">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="HelloWorld">
<soap:operation soapAction="http://roblox.com/HelloWorld" style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="GetVersion">
<soap:operation soapAction="http://roblox.com/GetVersion" style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="GetStatus">
<soap:operation soapAction="http://roblox.com/GetStatus" style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="OpenJob">
<soap:operation soapAction="http://roblox.com/OpenJob" style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="OpenJobEx">
<soap:operation soapAction="http://roblox.com/OpenJobEx" style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="RenewLease">
<soap:operation soapAction="http://roblox.com/RenewLease" style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="Execute">
<soap:operation soapAction="http://roblox.com/Execute" style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="ExecuteEx">
<soap:operation soapAction="http://roblox.com/ExecuteEx" style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="CloseJob">
<soap:operation soapAction="http://roblox.com/CloseJob" style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="BatchJob">
<soap:operation soapAction="http://roblox.com/BatchJob" style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="BatchJobEx">
<soap:operation soapAction="http://roblox.com/BatchJobEx" style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="GetExpiration">
<soap:operation soapAction="http://roblox.com/GetExpiration" style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="GetAllJobs">
<soap:operation soapAction="http://roblox.com/GetAllJobs" style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="GetAllJobsEx">
<soap:operation soapAction="http://roblox.com/GetAllJobsEx" style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="CloseExpiredJobs">
<soap:operation soapAction="http://roblox.com/CloseExpiredJobs" style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="CloseAllJobs">
<soap:operation soapAction="http://roblox.com/CloseAllJobs" style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="Diag">
<soap:operation soapAction="http://roblox.com/Diag" style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="DiagEx">
<soap:operation soapAction="http://roblox.com/DiagEx" style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:binding name="RCCServiceSoap12" type="tns:RCCServiceSoap">
<soap12:binding transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="HelloWorld">
<soap12:operation soapAction="http://roblox.com/HelloWorld" style="document" />
<wsdl:input>
<soap12:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap12:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="GetVersion">
<soap12:operation soapAction="http://roblox.com/GetVersion" style="document" />
<wsdl:input>
<soap12:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap12:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="GetStatus">
<soap12:operation soapAction="http://roblox.com/GetStatus" style="document" />
<wsdl:input>
<soap12:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap12:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="OpenJob">
<soap12:operation soapAction="http://roblox.com/OpenJob" style="document" />
<wsdl:input>
<soap12:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap12:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="OpenJobEx">
<soap12:operation soapAction="http://roblox.com/OpenJobEx" style="document" />
<wsdl:input>
<soap12:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap12:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="RenewLease">
<soap12:operation soapAction="http://roblox.com/RenewLease" style="document" />
<wsdl:input>
<soap12:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap12:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="Execute">
<soap12:operation soapAction="http://roblox.com/Execute" style="document" />
<wsdl:input>
<soap12:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap12:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="ExecuteEx">
<soap12:operation soapAction="http://roblox.com/ExecuteEx" style="document" />
<wsdl:input>
<soap12:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap12:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="CloseJob">
<soap12:operation soapAction="http://roblox.com/CloseJob" style="document" />
<wsdl:input>
<soap12:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap12:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="BatchJob">
<soap12:operation soapAction="http://roblox.com/BatchJob" style="document" />
<wsdl:input>
<soap12:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap12:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="BatchJobEx">
<soap12:operation soapAction="http://roblox.com/BatchJobEx" style="document" />
<wsdl:input>
<soap12:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap12:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="GetExpiration">
<soap12:operation soapAction="http://roblox.com/GetExpiration" style="document" />
<wsdl:input>
<soap12:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap12:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="GetAllJobs">
<soap12:operation soapAction="http://roblox.com/GetAllJobs" style="document" />
<wsdl:input>
<soap12:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap12:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="GetAllJobsEx">
<soap12:operation soapAction="http://roblox.com/GetAllJobsEx" style="document" />
<wsdl:input>
<soap12:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap12:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="CloseExpiredJobs">
<soap12:operation soapAction="http://roblox.com/CloseExpiredJobs" style="document" />
<wsdl:input>
<soap12:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap12:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="CloseAllJobs">
<soap12:operation soapAction="http://roblox.com/CloseAllJobs" style="document" />
<wsdl:input>
<soap12:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap12:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="Diag">
<soap12:operation soapAction="http://roblox.com/Diag" style="document" />
<wsdl:input>
<soap12:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap12:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="DiagEx">
<soap12:operation soapAction="http://roblox.com/DiagEx" style="document" />
<wsdl:input>
<soap12:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap12:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<service name="RCCServiceSoap">
<port name="RCCServiceSoapPort" binding="tns:RCCServiceSoap">
<soap:address location="127.0.0.1:64989"/>
</port>
</service>
</wsdl:definitions>

View File

@ -0,0 +1,264 @@
<?php
// This file defines the RCCServiceSoap class. The class inherits the properties of a standard SoapClient, but it can be used to call RCCService functions via SOAP requests.
namespace Roblox\Grid\Rcc;
class RCCServiceSoap {
private $SoapClient;
private $classmap = [
"Status" => "Roblox\Grid\Rcc\Status",
"Job" => "Roblox\Grid\Rcc\Job",
"ScriptExecution" => "Roblox\Grid\Rcc\ScriptExecution",
"LuaValue" => "Roblox\Grid\Rcc\LuaValue",
"LuaType" => "Roblox\Grid\Rcc\LuaType"
];
// The specification of a URL and port should always be done during production, though the defaults can be used when testing.
function __construct($url = "127.0.0.1", $port = 64989) {
$this->SoapClient = new \SoapClient(__DIR__."\RCCService.wsdl", ["location" => "http://".$url.":".$port, "uri" => "http://roblox.com/", "classmap" => $this->classmap, "exceptions" => false]);
}
// Begin function handlers
// Use the HelloWorld function as a template for all future functions.
// NOTE: Please use is_soap_fault() when checking if functions failed.
function callToService($name, $arguments = []) {
$result = $this->SoapClient->{$name}($arguments);
return (!is_soap_fault($result) ? (/*is_soap_fault($result) ||*/ !isset($result->{$name."Result"}) ? null : $result->{$name."Result"}) : $result);
}
private static function parseJobResult($value) {
if ($value !== new \stdClass() && isset($value->LuaValue)) {
// Our job result isn't empty, so let's deserialize it
$result = LuaValue::deserializeValue($value->LuaValue);
}else {
// Something went wrong :(
$result = null;
}
return $result;
}
/**
* Name: Hello World
* Description: This function calls a simple HelloWorld function from RCCService. The expected HelloWorldResponse is "Hello World".
* Parameters: []
*/
function HelloWorld() {
return $this->callToService(__FUNCTION__);
}
/**
* Name: Get Version
* Description: This function fetches the version of RCCService.
* Parameters: []
*/
function GetVersion() {
return $this->callToService(__FUNCTION__);
}
/**
* Name: Open Job
* Description: This function opens a job in accordance with the given arguments. Though this function is deprecated on ROBLOX's end, we'll still use it here and OpenJobEx will be called instead.
* Parameters: [
* "job" => "This function opens a job in accordance with the given arguments. It returns the value that's returned by the Lua script.",
* "script" => "The ScriptExecution class that's going to be executed in the job. This contains values such as name, script, and arguments."
* ]
*/
function OpenJob($job, $script = null) {
return $this->OpenJobEx($job, $script);
}
/**
* Name: Open Job Ex
* Description: This function opens a job in accordance with the given arguments. It returns the value that's returned by the Lua script. Feel free to use the other version of this function.
* Parameters: [
* "job" => "The Job class that's going to be serialized and pushed to the service.",
* "script" => "The ScriptExecution class that's going to be executed in the job. This contains values such as name, script, and arguments."
* ]
*/
function OpenJobEx($job, $script = null) {
$result = $this->callToService(__FUNCTION__, ["job" => $job, "script" => $script]);
return RCCServiceSoap::parseJobResult($result);
}
/**
* Name: Batch Job
* Description: This function runs a batch job in accordance with the given arguments. Though this function is deprecated on ROBLOX's end, we'll still use it here and BatchJobEx will be called instead.
* Parameters: [
* "job" => "The Job class that's going to be serialized and pushed to the service.",
* "script" => "The ScriptExecution class that's going to be executed in the job. This contains values such as name, script, and arguments."
* ]
*/
function BatchJob($job, $script) {
return $this->BatchJobEx($job, $script);
}
/**
* Name: Batch Job Ex
* Description: This function runs a batch job in accordance with the given arguments. Feel free to use the other version of this function.
* Parameters: [
* "job" => "The Job class that's going to be serialized and pushed to the service.",
* "script" => "The ScriptExecution class that's going to be executed in the job. This contains values such as name, script, and arguments."
* ]
*/
function BatchJobEx($job, $script) {
$result = $this->callToService(__FUNCTION__, ["job" => $job, "script" => $script]);
return RCCServiceSoap::parseJobResult($result);
}
/**
* Name: Renew Lease
* Description: This function changes the expirationInSeconds of a job based on the jobID. It essentially allows you to set the expiration time of a currently opened job.
* Parameters: [
* "jobID" => "The ID of the job who's expiration is going to be renewed.",
* "expirationInSeconds" => "The new expiration time for the job."
* ]
*/
function RenewLease($jobID, $expirationInSeconds) {
return $this->callToService(__FUNCTION__, ["jobID" => $jobID, "expirationInSeconds" => $expirationInSeconds]);
}
/**
* Name: Execute
* Description: This function uses the given arguments to execute a script inside an existing job. Though this function is deprecated on ROBLOX's end, we'll still use it here and ExecuteEx will be called instead.
* Parameters: [
* "jobID" => "The ID of the job in which the script is executed.",
* "script" => "The script that's going to be executed."
* ]
*/
function Execute($jobID, $script) {
return $this->ExecuteEx($jobID, $script);
}
/**
* Name: Execute Ex
* Description: This function uses the given arguments to execute a script inside an existing job.
* Parameters: [
* "jobID" => "The ID of the job in which the script is executed.",
* "script" => "The script that's going to be executed."
* ]
*/
function ExecuteEx($jobID, $script) {
return $this->callToService(__FUNCTION__, ["jobID" => $jobID, "script" => $script]);
}
/**
* Name: Close Job
* Description: This function closes an existing job using the given job ID.
* Parameters: [
* "jobID" => "The ID of the job that's going to be closed."
* ]
*/
function CloseJob($jobID) {
return $this->callToService(__FUNCTION__, ["jobID" => $jobID]);
}
/**
* Name: Get Expiration
* Description: This function fetches and returns the expirationInSeconds of a job using the given job ID.
* Parameters: [
* "jobID" => "The ID of the job."
* ]
*/
function GetExpiration($jobID) {
return $this->callToService(__FUNCTION__, ["jobID" => $jobID]);
}
/**
* Name: Diag
* Description: This function returns various types of diagnostic information from RCCService. Though this function is deprecated on ROBLOX's end, we'll still use it here and DiagEx will be called instead.
* Parameters: [
* "type" => "The diagnostic type to retrieve.",
* "jobID" => "The id of the job to retrieve the diagnostic from."
* ]
*/
function Diag($type, $jobID) {
return $this->DiagEx($type, $jobID);
}
/**
* Name: Diag Ex
* Description: This function returns various types of diagnostic information from RCCService.
* Parameters: [
* "type" => "The diagnostic type to retrieve.",
* "jobID" => "The id of the job to retrieve the diagnostic from."
* ]
*/
/* This is the format of the Diag data:
type == 0
DataModel Count in this process
PerfCounter data
Task Scheduler
(obsolete entry)
double threadAffinity
double numQueuedJobs
double numScheduledJobs
double numRunningJobs
long threadPoolSize
double messageRate
double messagePumpDutyCycle
DataModel Jobs Info
Machine configuration
Memory Leak Detection
type & 1
leak dump
type & 2
attempt to allocate 500k. if success, then true else false
type & 4
DataModel dutyCycles
*/
function DiagEx($type, $jobID) {
return $this->callToService(__FUNCTION__, ["type" => $type, "jobID" => $jobID]);
}
/**
* Name: Get Status
* Description: This function fetches the status information from RCCService. The returned Status class contains a version string and an environmentCount int.
* Parameters: []
*/
function GetStatus() {
return $this->callToService(__FUNCTION__);
}
/**
* Name: Get All Jobs
* Description: This function fetches an array of every job that's currently open on RCCService. Though this function is deprecated on ROBLOX's end, we'll still use it here and GetAllJobsEx will be called instead.
* Parameters: []
*/
function GetAllJobs() {
// GetAllJobs is deprecated.
return $this->GetAllJobsEx();
}
/**
* Name: Get All Jobs Ex
* Description: This function fetches an array of every job that's currently open on RCCService.
* Parameters: []
*/
function GetAllJobsEx() {
return $this->callToService(__FUNCTION__);
}
/**
* Name: Close Expired Jobs
* Description: This function closes all currently open and expired jobs on RCCService. This returns the amount of jobs that were closed.
* Parameters: []
*/
function CloseExpiredJobs() {
return $this->callToService(__FUNCTION__);
}
/**
* Name: Close All Jobs
* Description: This function closes all currently open jobs on RCCService. This returns the amount of jobs that were closed.
* Parameters: []
*/
function CloseAllJobs() {
return $this->callToService(__FUNCTION__);
}
}
// EOF

View File

@ -0,0 +1,20 @@
<?php
// This file defines the ScriptExecution class.
namespace Roblox\Grid\Rcc;
class ScriptExecution {
public $name;
public $script;
public $arguments = [];
function __construct($name, $script, $arguments = []) {
$this->name = $name;
$this->script = $script;
foreach ($arguments as $arg) {
array_push($this->arguments, new LuaValue($arg));
}
}
}
// EOF

View File

@ -0,0 +1,16 @@
<?php
// This file defines the Status class. This contains the version and environmentCount variables and it's used for gathering basic information from RCCService processes.
namespace Roblox\Grid\Rcc;
class Status {
public $version;
public $environmentCount;
function __construct($version, $environmentCount) {
$this->version = $version;
$this->environmentCount = $environmentCount;
}
}
// EOF

View File

@ -0,0 +1,45 @@
<?php
// This file defines the Gatherer class.
namespace Roblox\Logging;
class Gatherer {
//private const $logLocation = $_SERVER["DOCUMENT_ROOT"]."../Logging/Logs/";
/*public $machineIp;
public $timestamp = time();
public $date = \DateTime::format("Y-m-d H:i:s");*/
// Constructor
function __construct() {
}
private static function buildLogFileLocation($shardType) {
return $_SERVER["DOCUMENT_ROOT"]."../Logging/Logs/".$shardType."/";
}
private static function buildLogFileName($machineIp) {
$date = new \DateTime();
return $machineIp."_".$date->format("Y-m-d").".log";
}
private static function buildLogPath($machineIp, $shardType) {
return Gatherer::buildLogFileLocation($shardType).Gatherer::buildLogFileName($machineIp);
}
private static function buildLogEntry($text) {
$date = new \DateTime();
return $date->format("h:i:s")." \n";
}
static function logEntry($shardType, $machineIp, $entry) {
// ShardType check
if ($shardType !== ShardType::Server) {
$shardType = ShardType::Client;
}
$path = Gatherer::buildLogPath($machineIp, $shardType);
file_put_contents($path, Gatherer::buildLogEntry($entry), FILE_APPEND);
}
}
// EOF

View File

@ -0,0 +1,22 @@
<?php
// This file defines the LogEntry class.
//namespace Roblox\Logging\Gatherer;
class LogEntry {
// Shard types
private $shardClient = "Client";
private $shardServer = "Server";
public $shard;
public $entry;
// Constructor
function __construct($shard, $entry) {
$this->shard = $shard;
$this->entry = $entry;
}
}
// EOF

View File

@ -0,0 +1,12 @@
<?php
// This file defines the ShardType enum class.
namespace Roblox\Logging;
class ShardType {
public const Client = "Client";
public const Server = "Server";
}
// EOF

View File

@ -0,0 +1,32 @@
<?php
// This file defines the Roblox.Mssql.Database class. Originally housed in C:\teamcity-agent\work\a6371342c4f9b6ec\Assemblies\Mssql\Roblox.Mssql\Database.cs.
namespace Roblox\Mssql;
class Database {
function __construct() {
}
function ExecuteReader(/*String*/ $commandText, /*SqlParameter[]*/ $sqlParameters, /*CommandType*/ $commandType, /*Nullable`1*/ $commandTimeout, /*Nullable`1*/ $applicationIntent) {
/*
at Roblox.Mssql.GuardedDatabase.Execute(CommandType commandType, String commandText, SqlParameter[] sqlParameters, Action`1 action, Nullable`1 commandTimeout, Nullable`1 applicationIntent) in C:\teamcity-agent\work\a6371342c4f9b6ec\Assemblies\Mssql\Roblox.Mssql\GuardedDatabase.cs:line 22
at Roblox.Mssql.Database.ExecuteReader(String commandText, SqlParameter[] sqlParameters, CommandType commandType, Nullable`1 commandTimeout, Nullable`1 applicationIntent) in C:\teamcity-agent\work\a6371342c4f9b6ec\Assemblies\Mssql\Roblox.Mssql\Database.cs:line 226
*/
}
function Execute(/*CommandType*/ $commandType, /*String*/ $commandText, /*SqlParameter[]*/ $sqlParameters, /*Action`1*/ $action, /*Nullable`1*/ $commandTimeout, /*(Nullable`1*/ $applicationIntent) {
/*
at System.Data.SqlClient.SqlConnection.PermissionDemand()
at System.Data.SqlClient.SqlConnectionFactory.PermissionDemand(DbConnection outerConnection)
at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
at System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry)
at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry)
at System.Data.SqlClient.SqlConnection.Open()
at Roblox.Mssql.Database.Execute(CommandType commandType, String commandText, SqlParameter[] sqlParameters, Action`1 action, Nullable`1 commandTimeout, Nullable`1 applicationIntent) in C:\teamcity-agent\work\a6371342c4f9b6ec\Assemblies\Mssql\Roblox.Mssql\Database.cs:line 105
*/
}
}
// EOF

View File

@ -0,0 +1,21 @@
<?php
// This file defines the Roblox.Mssql.GuardedDatabase class. Originally housed in C:\teamcity-agent\work\a6371342c4f9b6ec\Assemblies\Mssql\Roblox.Mssql\GuardedDatabase.cs.
// Also has Roblox.Mssql.GuardedDatabase.<>c__DisplayClass2_0.<Execute>b__0() in C:\teamcity-agent\work\a6371342c4f9b6ec\Assemblies\Mssql\Roblox.Mssql\GuardedDatabase.cs:line 21.
namespace Roblox\Mssql;
class GuardedDatabase {
function __construct() {
}
function Execute(/*CommandType*/ $commandType, /*String*/ $commandText, /*SqlParameter[]*/ $sqlParameters, /*Action`1*/ $action, /*Nullable`1*/ $commandTimeout, /*Nullable`1*/ $applicationIntent) {
/*
at Roblox.Sentinels.ExecutionCircuitBreakerBase.Execute(Action action)
at Roblox.Mssql.GuardedDatabase.Execute(CommandType commandType, String commandText, SqlParameter[] sqlParameters, Action`1 action, Nullable`1 commandTimeout, Nullable`1 applicationIntent) in C:\teamcity-agent\work\a6371342c4f9b6ec\Assemblies\Mssql\Roblox.Mssql\GuardedDatabase.cs:line 22
*/
}
}
// EOF

View File

@ -0,0 +1,32 @@
<?php
// This file defines the ParameterHelper class.
namespace Roblox\Mysql\Helpers;
class ParameterHelper {
private static $phpToSqlType => [
"boolean" => "i",
"integer" => "i",
"double" => "d",
"string" => "s"
];
static function getSqlType($type) {
if (isset($phpToSqlType[$type])) {
return $phpToSqlType[$type];
} else {
throw new \Exception('Type "'.$type.'" not supported');
}
}
static function getSqlValue($value) {
if (gettype($value) == "boolean") {
// Cast bool to int for storage via SQL
$value = (int)$value
}
return $value;
}
}
// EOF

View File

@ -0,0 +1,20 @@
<?php
// This file defines the SqlParameter class.
namespace Roblox\Mysql;
class SqlParameter {
public $name;
public $value = null;
public $type = "NULL";
// Initializes a new instance of the SqlParameter class that uses the parameter name and a value of the new SqlParameter.
function __construct($name, $value) { // SqlParameter(String, Object)
$this->name = $name;
$this->type = Helpers\ParameterHelper::getSqlType(gettype($value));
$this->value = Helpers\ParameterHelper::getSqlValue($value);
}
}
// EOF

View File

@ -0,0 +1,21 @@
<?php
// This file defines the Roblox.Platform.AssetOwnership.UserAsset class.
namespace Roblox\Platform\AssetOwnership;
class UserAsset {
public /*int*/ $userAssetId;
public /*int*/ $assetId;
public /*int*/ $serialNumber;
public /*Roblox\Platform\Membership\IUser*/ $owner;
public /*\DateTime*/ $created;
public /*\DateTime*/ $updated;
function __construct($userAssetId) {
$this->userAssetId = $userAssetId;
// TODO: Load other values
}
}
// EOF

View File

@ -0,0 +1,65 @@
<?php
// This file defines the AssetType enum. Though this is a class, please treat it like an enum and **ONLY** reference it statically.
namespace Roblox\Platform\Assets;
class AssetType {
const Image = "Image";
const TShirt = "TShirt";
const Audio = "Audio";
const Mesh = "Mesh";
const Lua = "Lua";
const HTML = "HTML";
const Text = "Text";
const Hat = "Hat";
const Place = "Place";
const Model = "Model";
const Shirt = "Shirt";
const Pants = "Pants";
const Decal = "Decal";
const Avatar = "Avatar";
const Head = "Head";
const Face = "Face";
const Gear = "Gear";
const Badge = "Badge";
const GroupEmblem = "GroupEmblem";
const Animation = "Animation";
const Arms = "Arms";
const Legs = "Legs";
const Torso = "Torso";
const RightArm = "RightArm";
const LeftArm = "LeftArm";
const LeftLeg = "LeftLeg";
const RightLeg = "RightLeg";
const Package = "Package";
const YouTubeVideo = "YouTubeVideo";
const GamePass = "GamePass";
const App = "App";
const Code = "Code";
const Plugin = "Plugin";
const SolidModel = "SolidModel";
const MeshPart = "MeshPart";
const HairAccessory = "HairAccessory";
const FaceAccessory = "FaceAccessory";
const NeckAccessory = "NeckAccessory";
const ShoulderAccessory = "ShoulderAccessory";
const FrontAccessory = "FrontAccessory";
const BackAccessory = "BackAccessory";
const WaistAccessory = "WaistAccessory";
const ClimbAnimation = "ClimbAnimation";
const DeathAnimation = "DeathAnimation";
const FallAnimation = "FallAnimation";
const IdleAnimation = "IdleAnimation";
const JumpAnimation = "JumpAnimation";
const RunAnimation = "RunAnimation";
const SwimAnimation = "SwimAnimation";
const WalkAnimation = "WalkAnimation";
const PoseAnimation = "PoseAnimation";
const LocalizationTableManifest = "LocalizationTableManifest";
const LocalizationTableTranslation = "LocalizationTableTranslation";
const EmoteAnimation = "EmoteAnimation";
const Video = "Video";
}
// EOF

View File

@ -0,0 +1,12 @@
<?php
// This file defines the BundleType enum. Though this is a class, please treat it like an enum and **ONLY** reference it statically.
namespace Roblox\Platform\Bundles\Core;
class BundleType {
const BodyParts = "BodyParts";
const AvatarAnimations = "AvatarAnimations";
}
// EOF

View File

@ -0,0 +1,13 @@
<?php
// This file defines the Roblox.Platform.Membership.IUser interface.
namespace Roblox\Platform\Membership;
interface IUser {
public /*int*/ $userId;
public /*string*/ $username;
public /*UserModelBuildersClubMembershipTypeEnum*/ $buildersClubMembershipType;
}
// EOF

View File

@ -0,0 +1,14 @@
<?php
// This file defines the Roblox.Platform.Membership.User class. This class may or may not have existed.
namespace Roblox\Platform\Membership;
class User implements IUser {
function __construct($userId) {
$this->userId = $userId;
// TODO: Load other values
}
}
// EOF

View File

@ -0,0 +1,20 @@
<?php
// This file defines the Roblox.Platform.Throttling.Entities.NamespaceDAL class.
namespace Roblox\Platform\Throttling\Entities;
class NamespaceDAL {
function __construct() {
}
function GetOrCreateNamespace(/*String*/ $value) {
/*
at Roblox.Entities.Mssql.RobloxDataAccessPatternExtensions.GetOrCreate[TDal](RobloxDatabase database, String storedProcedureName, Func`2 dalBuilder, Nullable`1 commandTimeout, Boolean includeApplicationIntent, SqlParameter[] queryParameters) in C:\teamcity-agent\work\a6371342c4f9b6ec\Assemblies\Entities\Roblox.Entities.Mssql\RobloxDataAccessPatternExtensions.cs:line 51
at Roblox.Platform.Throttling.Entities.NamespaceDAL.GetOrCreateNamespace(String value)
*/
}
}
// EOF

View File

@ -0,0 +1,20 @@
<?php
// This file defines the Roblox.Platform.Throttling.IpRequest class.
namespace Roblox\Platform\Throttling;
class IpRequest {
function __construct() {
}
function IsEnabled() {
/*
at Roblox.Platform.Throttling.ThrottleRequestBase.GetRateLimitEntity()
at Roblox.Platform.Throttling.IpRequest.IsEnabled()
*/
}
}
// EOF

View File

@ -0,0 +1,20 @@
<?php
// This file defines the Roblox.Platform.Throttling.ThrottleRequestBase class.
namespace Roblox\Platform\Throttling;
class ThrottleRequestBase {
function __construct() {
}
function GetRateLimitEntity() {
/*
at Roblox.Common.EntityHelper.GetOrCreateEntity[TIndex,TEntity,TDal](ICacheInfo cacheInfo, String entityIdLookup, GetOrCreate`1 getterOrCreator) in C:\teamcity-agent\work\a6371342c4f9b6ec\Assemblies\Data\Roblox.Data\Entities\EntityHelper.cs:line 0
at Roblox.Platform.Throttling.ThrottleRequestBase.GetRateLimitEntity()
*/
}
}
// EOF

View File

@ -0,0 +1,10 @@
<?php
namespace Roblox\Platform\User;
class RobloxUser extends \Roblox\Data\Entities\RobloxEntity {
public string $UserName;
public int $Robux;
public int $Tickets;
}
// EOF

View File

@ -0,0 +1,12 @@
<?php
// This file defines the CatalogItemType enum. Though this is a class, please treat it like an enum and **ONLY** reference it statically.
namespace Roblox\Search\Client;
class CatalogItemType {
const Asset = "Asset";
const Bundle = "Bundle";
}
// EOF

View File

@ -0,0 +1,21 @@
<?php
// This file defines the Roblox.Sentinels.ExecutionCircuitBreakerBase class.
namespace Roblox\Sentinels;
class ExecutionCircuitBreakerBase {
function __construct() {
}
function Execute(/*Action*/ $action) {
/*
at Roblox.Mssql.Database.Execute(CommandType commandType, String commandText, SqlParameter[] sqlParameters, Action`1 action, Nullable`1 commandTimeout, Nullable`1 applicationIntent) in C:\teamcity-agent\work\a6371342c4f9b6ec\Assemblies\Mssql\Roblox.Mssql\Database.cs:line 105
at Roblox.Mssql.GuardedDatabase.&lt;&gt;c__DisplayClass2_0.&lt;Execute&gt;b__0() in C:\teamcity-agent\work\a6371342c4f9b6ec\Assemblies\Mssql\Roblox.Mssql\GuardedDatabase.cs:line 21
at Roblox.Sentinels.ExecutionCircuitBreakerBase.Execute(Action action)
*/
}
}
// EOF

View File

View File

@ -0,0 +1,200 @@
// AssetImage.js. Register the namespace for the control.
Type.registerNamespace('Roblox.Thumbs');
//
// Define the control properties.
//
Roblox.Thumbs.AssetImage = function (element) {
Roblox.Thumbs.AssetImage.initializeBase(this, [element]);
this._assetID = 0;
this._assetVersionID = null;
this._ov = false;
};
//
// Create the prototype for the control.
//
Roblox.Thumbs.AssetImage.prototype = {
initialize: function () {
Roblox.Thumbs.AssetImage.callBaseMethod(this, 'initialize');
this._webService = Roblox.Thumbs.Asset;
this._requestThumbnail = Function.createDelegate(this, this.requestThumbnail);
},
dispose: function () {
Roblox.Thumbs.AssetImage.callBaseMethod(this, 'dispose');
},
get_assetID: function () {
return this._assetID;
},
set_assetID: function (value) {
if (this._assetID !== value) {
this._assetID = value;
this.raisePropertyChanged('assetID');
}
},
get_assetVersionID: function () {
return this._assetVersionID;
},
set_assetVersionID: function (value) {
if (this._assetVersionID !== value) {
this._assetVersionID = value;
this.raisePropertyChanged('assetVersionID');
}
},
get_ov: function () {
return this._ov;
},
set_ov: function (value) {
if (this._ov !== value) {
this._ov = value;
this.raisePropertyChanged('ov');
}
},
requestThumbnail: function () {
var style = this.get_element().style;
var width = style.pixelWidth;
var height = style.pixelHeight;
var onSuccess = function (result, context) { context._onUrl(result); };
var onError = function (result, context) { context._onError(result); };
this._webService.RequestThumbnail_v2(this._assetID, this._assetVersionID, width, height, this._fileExtension, this._thumbnailFormatID, this._ov, onSuccess, onError, this);
}
};
// Optional descriptor for JSON serialization.
Roblox.Thumbs.AssetImage.descriptor = {
properties: []
};
// Register the class as a type that inherits from Sys.UI.Control.
Roblox.Thumbs.AssetImage.registerClass('Roblox.Thumbs.AssetImage', Roblox.Thumbs.Image);
Roblox.Thumbs.AssetImage.updateUrl = function(componentID) {
/// <summary>
/// This static function (that is intended to be called from script emitted
/// on the server)
/// </summary>
var a = $find(componentID);
if (a != null || a != undefined) {
a._onUpdate();
}
};
Roblox.Thumbs.AssetImage.mediaPlayer = null;
Roblox.Thumbs.AssetImage.isInitialized = false;
Roblox.Thumbs.AssetImage.currentlyPlayingAsset = null;
Roblox.Thumbs.AssetImage.InitMediaPlayer = function () {
if (typeof jQuery !== "undefined" && !Roblox.Thumbs.AssetImage.isInitialized) {
Roblox.Thumbs.AssetImage.isInitialized = true;
$(function () {
$(document).on("click", "div.MediaPlayerIcon", function (e) {
var assetButton = $(e.target);
assetButton.mediaUrl = assetButton.attr("data-mediathumb-url");
/// <summary>
/// Determines if the asset button and the given asset button are the same asset.
/// </summary>
assetButton.hasSameMediaAs = function (other) {
return assetButton.mediaUrl === other.mediaUrl;
};
/// <summary>
/// Plays or resumes the asset button's media and updates the button's visuals.
/// </summary>
assetButton.play = function () {
if (Roblox.Thumbs.AssetImage.currentlyPlayingAsset === null ||
!Roblox.Thumbs.AssetImage.currentlyPlayingAsset.hasSameMediaAs(assetButton)) {
// If another asset is playing then pause it first.
if (Roblox.Thumbs.AssetImage.currentlyPlayingAsset != null) {
Roblox.Thumbs.AssetImage.currentlyPlayingAsset.stop();
}
Roblox.Thumbs.AssetImage.mediaPlayer.jPlayer("setMedia", { mp3: assetButton.mediaUrl });
Roblox.Thumbs.AssetImage.currentlyPlayingAsset = assetButton;
Roblox.Thumbs.AssetImage.mediaPlayer.on($.jPlayer.event.ended, assetButton.onJPlayerEnded);
Roblox.Thumbs.AssetImage.mediaPlayer.on($.jPlayer.event.error, assetButton.onJPlayerError);
}
Roblox.Thumbs.AssetImage.mediaPlayer.jPlayer("play");
assetButton.removeClass("Play").addClass("Pause");
};
/// <summary>
/// Stops the asset button's media and resets the button.
/// </summary>
assetButton.stop = function () {
if (Roblox.Thumbs.AssetImage.currentlyPlayingAsset.hasSameMediaAs(assetButton)) {
Roblox.Thumbs.AssetImage.currentlyPlayingAsset = null;
Roblox.Thumbs.AssetImage.mediaPlayer.jPlayer("clearMedia");
Roblox.Thumbs.AssetImage.mediaPlayer.off($.jPlayer.event.ended);
Roblox.Thumbs.AssetImage.mediaPlayer.off($.jPlayer.event.error);
assetButton.removeClass("Pause").addClass("Play");
}
};
/// <summary>
/// Pauses the asset button's media and changes the button's visuals.
/// </summary>
assetButton.pause = function () {
if (Roblox.Thumbs.AssetImage.currentlyPlayingAsset.hasSameMediaAs(assetButton)) {
Roblox.Thumbs.AssetImage.mediaPlayer.jPlayer("pause");
assetButton.removeClass("Pause").addClass("Play");
}
}
/// <summary>
/// Handles the jPlayer error event.
/// </summary>
assetButton.onJPlayerError = function () {
assetButton.stop();
};
/// <summary>
/// Handles the jPlayer ended event.
/// </summary>
assetButton.onJPlayerEnded = function () {
assetButton.stop();
};
// If the media player isn't yet initialized then
// initialize it and begin playing when it's ready.
if (Roblox.Thumbs.AssetImage.mediaPlayer == null) {
Roblox.Thumbs.AssetImage.mediaPlayer = $("<div id='MediaPlayerSingleton'></div>").appendTo("body").jPlayer({
swfPath: '/js/jPlayer/2.9.2/jquery.jplayer.swf',
solution: "html, flash",
supplied: "mp3",
wmode: "transparent",
errorAlerts: false,
warningAlerts: false,
ready: function (event) {
assetButton.play();
}
});
}
else { // Otherwise, play or pause normally.
if (assetButton.hasClass("Pause")) {
assetButton.pause();
}
else {
assetButton.play();
}
}
});
});
}
}

View File

View File

View File

@ -0,0 +1,14 @@
// Register the namespace for the control.
Type.registerNamespace('Roblox.Thumbs');
//
// Definte the control properties.
//
Roblox.Thumbs.AvatarImage = function(element) {
Roblox.Thumbs.AvatarImage.initializeBase(this, [element]);
this._userID = 0;
}
//
// Create the prototype for the control.
//

View File

View File

View File

View File

View File

@ -0,0 +1,144 @@
// Image.Js. Register the namespace for the control.
Type.registerNamespace('Roblox.Thumbs');
//
// Define the control properties.
//
Roblox.Thumbs.Image = function (element) {
Roblox.Thumbs.Image.initializeBase(this, [element]);
this._fileExtension = null;
this._spinnerUrl = null;
this._pollTime = 3000;
this._waitTime = 0;
this._webService = null;
this._requestThumbnail = null;
this._updateTimeout = null;
this._spinner = null;
};
//
// Create the prototype for the control.
//
Roblox.Thumbs.Image.prototype = {
initialize: function () {
Roblox.Thumbs.Image.callBaseMethod(this, 'initialize');
},
dispose: function () {
if (typeof (this._updateTimeout) !== 'undefined')
window.clearTimeout(this._updateTimeout);
Roblox.Thumbs.Image.callBaseMethod(this, 'dispose');
},
_showSpinner: function () {
if (this._spinner !== null)
return;
this.get_element().style.position = "relative";
this._spinner = document.createElement("img");
this._spinner.style.position = "absolute";
this._spinner.style.left = "0px";
this._spinner.style.top = "0px";
this._spinner.style.height = "16px";
this._spinner.style.width = "16px";
this._spinner.style.border = 0;
this._spinner.src = this._spinnerUrl;
this.get_element().appendChild(this._spinner);
},
_hideSpinner: function () {
if (!this._spinner)
return;
var e = this.get_element();
if (e) {
e.removeChild(this._spinner);
}
this._spinner = null;
},
_onUpdate: function () {
if (!this._webService) {
this._hideSpinner();
return;
}
this._showSpinner();
this._requestThumbnail();
},
_onUrl: function (result) {
if (!this.get_element()) {
this._hideSpinner();
return;
}
Roblox.Controls.Image.SetImageSrc(this.get_element(), result.url);
if ((!result.final || result.url.indexOf("unavail") > 0) && this._waitTime <= 40) // Give up after 40 times.
{
// Try again later
this._waitTime = parseInt(this._waitTime) + parseInt(1);
this._updateTimeout = window.setTimeout(Function.createDelegate(this, this._onUpdate), this._pollTime);
}
else
this._hideSpinner();
},
_onError: function (result) {
this._hideSpinner();
},
get_thumbnailFormatID: function () {
return this._thumbnailFormatID;
},
set_thumbnailFormatID: function (value) {
if (this._thumbnailFormatID !== value) {
this._thumbnailFormatID = value;
this.raisePropertyChanged('thumbnailFormatID');
}
},
get_pollTime: function () {
return this._pollTime.value;
},
set_pollTime: function (value) {
if (this._pollTime !== value) {
this._pollTime = value;
this.raisePropertyChanged('pollTime');
}
},
get_fileExtension: function () {
return this._fileExtension;
},
set_fileExtension: function (value) {
if (this._fileExtension !== value) {
this._fileExtension = value;
this.raisePropertyChanged('fileExtension');
}
},
get_spinnerUrl: function () {
return this._spinnerUrl;
},
set_spinnerUrl: function (value) {
if (this._spinnerUrl !== value) {
this._spinnerUrl = value;
this.raisePropertyChanged('spinnerUrl');
}
}
};
// Optional descriptor for JSON serialization.
Roblox.Thumbs.Image.descriptor = {
properties: []
};
// Register the class as a type that inherits from Sys.UI.Control.
Roblox.Thumbs.Image.registerClass('Roblox.Thumbs.Image', Sys.UI.Control);

View File

View File

@ -0,0 +1,41 @@
<?php
// This file defines the TreeView class.
namespace Roblox\Web\AspNet;
class TreeView {
static function stampBulletTree(&$tree) {
foreach ($tree as &$item) {
if (isset($item['children']) && $item['children'] !== null && $item['children'] !== []) {
// Item has children (aka not empty!!!)
$item['icon'] = "jstree-bullet-black";
TreeView::stampBulletTree($item['children']);
}else {
$item['icon'] = "jstree-bullet-grey";
}
}
unset($item);
}
static function generateBulletTree(&$tree, $pageSelect = false) {
$buffer_tree = $tree;
$tree = [];
// Gets the current page's URL
$pageUrl = explode('?', $_SERVER['REQUEST_URI'], 2)[0];
foreach ($buffer_tree as $key => $item) {
$href = $item[0];
$selected = $href == $pageUrl;
if (isset($item[1]) && $item[1] !== null && $item[1] !== []) {
// If the element contains children, push them to the tree as well
TreeView::generateBulletTree($item[1]);
}
// Push the text and link to the element on the tree
array_push($tree, ["text" => $key, "a_attr" => ["href" => $href == "" ? "/Default.aspx" : $href], "children" => $item[1] ?? [], "state" => ["selected" => $selected]]);
}
unset($item);
TreeView::stampBulletTree($tree);
}
}
// EOF

View File

@ -0,0 +1,13 @@
<?php
// This file defines the Roblox.Web.Catalog.NoPriceStatus enum. Though this is a class, please treat it like an enum and **ONLY** reference it statically.
namespace Roblox\Web\Catalog;
class NoPriceStatus {
public const Free = "Free";
public const OffSale = "OffSale";
public const NoResellers = "NoResellers";
}
// EOF

View File

@ -0,0 +1,39 @@
<?php
// This file defines the Roblox.Web.Mvc.ThrottlingFilterAttribute class. Originally housed in C:\teamcity-agent\work\a6371342c4f9b6ec\Assemblies\Web\Roblox.Web.Mvc\FilterAttributes\ThrottlingFilterAttribute.cs.
namespace Roblox\Web\Mvc;
class ThrottlingFilterAttribute {
function __construct() {
}
function OnActionExecuting(/*ActionExecutingContext*/ $filterContext) {
/*
at Roblox.Web.Mvc.ThrottlingFilterAttribute.VerifyRequestThrottling(ActionExecutingContext filterContext) in C:\teamcity-agent\work\a6371342c4f9b6ec\Assemblies\Web\Roblox.Web.Mvc\FilterAttributes\ThrottlingFilterAttribute.cs:line 44
at Roblox.Web.Mvc.ThrottlingFilterAttribute.OnActionExecuting(ActionExecutingContext filterContext) in C:\teamcity-agent\work\a6371342c4f9b6ec\Assemblies\Web\Roblox.Web.Mvc\FilterAttributes\ThrottlingFilterAttribute.cs:line 31
*/
}
function VerifyRequestThrottling(/*ActionExecutingContext*/ $filterContext) {
/*
at Roblox.Web.WebThrottlingManager.IsRequestAllowed(List`1 requestsForCurrentContext, DateTime executionDateTime, RequesterType requester, String actionName) in C:\teamcity-agent\work\a6371342c4f9b6ec\Assemblies\Web\Roblox.Web\Throttling\WebThrottlingManager.cs:line 129
at Roblox.Web.Mvc.ThrottlingFilterAttribute.OnActionExecuting(ActionExecutingContext filterContext) in C:\teamcity-agent\work\a6371342c4f9b6ec\Assemblies\Web\Roblox.Web.Mvc\FilterAttributes\ThrottlingFilterAttribute.cs:line 31
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)
*/
}
}
// EOF

View File

@ -0,0 +1,20 @@
<?php
// This file defines the Roblox.Web.WebThrottlingManager class. Originally housed in C:\teamcity-agent\work\a6371342c4f9b6ec\Assemblies\Web\Roblox.Web\Throttling\WebThrottlingManager.cs.
namespace Roblox\Web;
class WebThrottlingManager {
function __construct() {
}
function IsRequestAllowed(/*List`1*/ $requestsForCurrentContext, /*DateTime*/ $executionDateTime, /*RequesterType*/ $requester, /*String*/ $actionName) {
/*
at Roblox.Platform.Throttling.IpRequest.IsEnabled()
at Roblox.Web.WebThrottlingManager.IsRequestAllowed(List`1 requestsForCurrentContext, DateTime executionDateTime, RequesterType requester, String actionName) in C:\teamcity-agent\work\a6371342c4f9b6ec\Assemblies\Web\Roblox.Web\Throttling\WebThrottlingManager.cs:line 129
*/
}
}
// EOF

View File

@ -0,0 +1,295 @@
<?php
/* This file is released under the GPL, any version you like
*
* PHP PSD reader class, v1.3
*
* By Tim de Koning
*
* Kingsquare Information Services, 22 jan 2007
*
* example use:
* ------------
* <?php
* include_once('classPhpPsdReader.php')
* header("Content-type: image/jpeg");
* print imagejpeg(imagecreatefrompsd('test.psd'));
* ?>
*
* More info, bugs or requests, contact info@kingsquare.nl
*
* Latest version and demo: http://www.kingsquare.nl/phppsdreader
*
* TODO
* ----
* - read color values for "multichannel data" PSD files
* - find and implement (hunter)lab to RGB algorithm
* - fix 32 bit colors... has something to do with gamma and exposure available since CS2, but dunno how to read them...
*/
class PhpPsdReader {
var $infoArray;
var $fp;
var $fileName;
var $tempFileName;
var $colorBytesLength;
function PhpPsdReader($fileName) {
set_time_limit(0);
$this->infoArray = array();
$this->fileName = $fileName;
$this->fp = fopen($this->fileName,'r');
if (fread($this->fp,4)=='8BPS') {
$this->infoArray['version id'] = $this->_getInteger(2);
fseek($this->fp,6,SEEK_CUR); // 6 bytes of 0's
$this->infoArray['channels'] = $this->_getInteger(2);
$this->infoArray['rows'] = $this->_getInteger(4);
$this->infoArray['columns'] = $this->_getInteger(4);
$this->infoArray['colorDepth'] = $this->_getInteger(2);
$this->infoArray['colorMode'] = $this->_getInteger(2);
/* COLOR MODE DATA SECTION */ //4bytes Length The length of the following color data.
$this->infoArray['colorModeDataSectionLength'] = $this->_getInteger(4);
fseek($this->fp,$this->infoArray['colorModeDataSectionLength'],SEEK_CUR); // ignore this snizzle
/* IMAGE RESOURCES */
$this->infoArray['imageResourcesSectionLength'] = $this->_getInteger(4);
fseek($this->fp,$this->infoArray['imageResourcesSectionLength'],SEEK_CUR); // ignore this snizzle
/* LAYER AND MASK */
$this->infoArray['layerMaskDataSectionLength'] = $this->_getInteger(4);
fseek($this->fp,$this->infoArray['layerMaskDataSectionLength'],SEEK_CUR); // ignore this snizzle
/* IMAGE DATA */
$this->infoArray['compressionType'] = $this->_getInteger(2);
$this->infoArray['oneColorChannelPixelBytes'] = $this->infoArray['colorDepth']/8;
$this->colorBytesLength = $this->infoArray['rows']*$this->infoArray['columns']*$this->infoArray['oneColorChannelPixelBytes'];
if ($this->infoArray['colorMode']==2) {
$this->infoArray['error'] = 'images with indexed colours are not supported yet';
return false;
}
} else {
$this->infoArray['error'] = 'invalid or unsupported psd';
return false;
}
}
function getImage() {
// decompress image data if required
switch($this->infoArray['compressionType']) {
// case 2:, case 3: zip not supported yet..
case 1:
// packed bits
$this->infoArray['scanLinesByteCounts'] = array();
for ($i=0; $i<($this->infoArray['rows']*$this->infoArray['channels']); $i++) $this->infoArray['scanLinesByteCounts'][] = $this->_getInteger(2);
$this->tempFileName = tempnam(realpath('/tmp'),'decompressedImageData');
$tfp = fopen($this->tempFileName,'wb');
foreach ($this->infoArray['scanLinesByteCounts'] as $scanLinesByteCount) {
fwrite($tfp,$this->_getPackedBitsDecoded(fread($this->fp,$scanLinesByteCount)));
}
fclose($tfp);
fclose($this->fp);
$this->fp = fopen($this->tempFileName,'r');
default:
// continue with current file handle;
break;
}
// let's write pixel by pixel....
$image = imagecreatetruecolor($this->infoArray['columns'],$this->infoArray['rows']);
for ($rowPointer = 0; ($rowPointer < $this->infoArray['rows']); $rowPointer++) {
for ($columnPointer = 0; ($columnPointer < $this->infoArray['columns']); $columnPointer++) {
/* The color mode of the file. Supported values are: Bitmap=0;
Grayscale=1; Indexed=2; RGB=3; CMYK=4; Multichannel=7;
Duotone=8; Lab=9.
*/
switch ($this->infoArray['colorMode']) {
case 2: // indexed... info should be able to extract from color mode data section. not implemented yet, so is grayscale
exit;
break;
case 0:
// bit by bit
if ($columnPointer == 0) $bitPointer = 0;
if ($bitPointer==0) $currentByteBits = str_pad(base_convert(bin2hex(fread($this->fp,1)), 16, 2),8,'0',STR_PAD_LEFT);
$r = $g = $b = (($currentByteBits[$bitPointer]=='1')?0:255);
$bitPointer++;
if ($bitPointer==8) $bitPointer = 0;
break;
case 1:
case 8: // 8 is indexed with 1 color..., so grayscale
$r = $g = $b = $this->_getInteger($this->infoArray['oneColorChannelPixelBytes']);
break;
case 4: // CMYK
$c = $this->_getInteger($this->infoArray['oneColorChannelPixelBytes']);
$currentPointerPos = ftell($this->fp);
fseek($this->fp,$this->colorBytesLength-1,SEEK_CUR);
$m = $this->_getInteger($this->infoArray['oneColorChannelPixelBytes']);
fseek($this->fp,$this->colorBytesLength-1,SEEK_CUR);
$y = $this->_getInteger($this->infoArray['oneColorChannelPixelBytes']);
fseek($this->fp,$this->colorBytesLength-1,SEEK_CUR);
$k = $this->_getInteger($this->infoArray['oneColorChannelPixelBytes']);
fseek($this->fp,$currentPointerPos);
$r = round(($c * $k) / (pow(2,$this->infoArray['colorDepth'])-1));
$g = round(($m * $k) / (pow(2,$this->infoArray['colorDepth'])-1));
$b = round(($y * $k) / (pow(2,$this->infoArray['colorDepth'])-1));
break;
case 9: // hunter Lab
// i still need an understandable lab2rgb convert algorithm... if you have one, please let me know!
$l = $this->_getInteger($this->infoArray['oneColorChannelPixelBytes']);
$currentPointerPos = ftell($this->fp);
fseek($this->fp,$this->colorBytesLength-1,SEEK_CUR);
$a = $this->_getInteger($this->infoArray['oneColorChannelPixelBytes']);
fseek($this->fp,$this->colorBytesLength-1,SEEK_CUR);
$b = $this->_getInteger($this->infoArray['oneColorChannelPixelBytes']);
fseek($this->fp,$currentPointerPos);
$r = $l;
$g = $a;
$b = $b;
break;
default:
$r = $this->_getInteger($this->infoArray['oneColorChannelPixelBytes']);
$currentPointerPos = ftell($this->fp);
fseek($this->fp,$this->colorBytesLength-1,SEEK_CUR);
$g = $this->_getInteger($this->infoArray['oneColorChannelPixelBytes']);
fseek($this->fp,$this->colorBytesLength-1,SEEK_CUR);
$b = $this->_getInteger($this->infoArray['oneColorChannelPixelBytes']);
fseek($this->fp,$currentPointerPos);
break;
}
if (($this->infoArray['oneColorChannelPixelBytes']==2)) {
$r = $r >> 8;
$g = $g >> 8;
$b = $b >> 8;
} elseif (($this->infoArray['oneColorChannelPixelBytes']==4)) {
$r = $r >> 24;
$g = $g >> 24;
$b = $b >> 24;
}
$pixelColor = imagecolorallocate($image,$r,$g,$b);
imagesetpixel($image,$columnPointer,$rowPointer,$pixelColor);
}
}
fclose($this->fp);
if (isset($this->tempFileName)) unlink($this->tempFileName);
return $image;
}
/**
*
* PRIVATE FUNCTIONS
*
*/
function _getPackedBitsDecoded($string) {
/*
The PackBits algorithm will precede a block of data with a one byte header n, where n is interpreted as follows:
n Meaning
0 to 127 Copy the next n + 1 symbols verbatim
-127 to -1 Repeat the next symbol 1 - n times
-128 Do nothing
Decoding:
Step 1. Read the block header (n).
Step 2. If the header is an EOF exit.
Step 3. If n is non-negative, copy the next n + 1 symbols to the output stream and go to step 1.
Step 4. If n is negative, write 1 - n copies of the next symbol to the output stream and go to step 1.
*/
$stringPointer = 0;
$returnString = '';
while (1) {
if (isset($string[$stringPointer])) $headerByteValue = $this->_unsignedToSigned(hexdec(bin2hex($string[$stringPointer])),1);
else return $returnString;
$stringPointer++;
if ($headerByteValue >= 0) {
for ($i=0; $i <= $headerByteValue; $i++) {
$returnString .= $string[$stringPointer];
$stringPointer++;
}
} else {
if ($headerByteValue != -128) {
$copyByte = $string[$stringPointer];
$stringPointer++;
for ($i=0; $i < (1-$headerByteValue); $i++) {
$returnString .= $copyByte;
}
}
}
}
}
function _unsignedToSigned($int,$byteSize=1) {
switch($byteSize) {
case 1:
if ($int<128) return $int;
else return -256+$int;
break;
case 2:
if ($int<32768) return $int;
else return -65536+$int;
case 4:
if ($int<2147483648) return $int;
else return -4294967296+$int;
default:
return $int;
}
}
function _hexReverse($hex) {
$output = '';
if (strlen($hex)%2) return false;
for ($pointer = strlen($hex);$pointer>=0;$pointer-=2) $output .= substr($hex,$pointer,2);
return $output;
}
function _getInteger($byteCount=1) {
switch ($byteCount) {
case 4:
// for some strange reason this is still broken...
return @reset(unpack('N',fread($this->fp,4)));
break;
case 2:
return @reset(unpack('n',fread($this->fp,2)));
break;
default:
return hexdec($this->_hexReverse(bin2hex(fread($this->fp,$byteCount))));
}
}
}
/**
* Returns an image identifier representing the image obtained from the given filename, using only GD, returns an empty string on failure
*
* @param string $fileName
* @return image identifier
*/
function imagecreatefrompsd($fileName) {
$psdReader = new PhpPsdReader($fileName);
if (isset($psdReader->infoArray['error'])) return '';
else return $psdReader->getImage();
}

File diff suppressed because it is too large Load Diff

6
api/.htaccess Normal file
View File

@ -0,0 +1,6 @@
ErrorDocument 404 "Access Denied"
ErrorDocument 403 "Access Denied"
ErrorDocument 401 "Access Denied"
RewriteEngine on
RewriteRule ^game/join/?$ /game/test.php [NC,L]

View File

@ -0,0 +1,110 @@
<?php
exit('disabled');
if (isset($_SERVER["HTTP_CF_CONNECTING_IP"])) {
$_SERVER['REMOTE_ADDR'] = $_SERVER["HTTP_CF_CONNECTING_IP"];
}
$IP = $_SERVER['REMOTE_ADDR'];
?>
<!DOCTYPE html>
<html>
<head>
<title>Report Abuse</title>
</head>
<body>
<div class="container">
<?php
if (isset($_POST['submitreport'])) {
$username = $_POST['username'];
$reason = $_POST['reason'];
$error = false;
if (strlen($username) == 0) {
$error = true;
echo '<h4>An error has occurred.</h4>';
echo 'You need to specifiy an username.<br><a href="http://api.xdiscuss.net/AbuseReport/InGameChat.php">Go back</a>';
}
if (strlen($username) > 20 and $error == false) {
$error = true;
echo '<h4>An error has occurred.</h4>';
echo 'The username you specified is too long.<br><a href="http://api.xdiscuss.net/AbuseReport/InGameChat.php">Go back</a>';
}
if (strlen($reason) == 0 and $error == false) {
$error = true;
echo '<h4>An error has occurred.</h4>';
echo 'You need to specifiy a reason.<br><a href="http://api.xdiscuss.net/AbuseReport/InGameChat.php">Go back</a>';
}
if (strlen($reason) > 256 and $error == false) {
$error = true;
echo '<h4>An error has occurred.</h4>';
echo 'The reason you specified is too long.<br><a href="http://api.xdiscuss.net/AbuseReport/InGameChat.php">Go back</a>';
}
if ($error == false) {
// Create database connection.
include_once $_SERVER['DOCUMENT_ROOT'].'/config.php';
try{
$dbcon = new PDO('mysql:host='.$db_host.';port='.$db_port.';dbname='.$db_name.'', $db_user, $db_passwd);
$dbcon->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
$dbcon->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}catch (PDOExpection $e){
exit;
}
$stmt = $dbcon->prepare("SELECT * FROM users WHERE username=:uid;");
$stmt->bindParam(':uid', $username, PDO::PARAM_INT);
$stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC);
$error = false;
if ($stmt->rowCount() == 0) {
$error = true;
echo '<h4>An error has occurred.</h4>';
echo 'The user you are reporting does not exist.<br><a href="http://api.xdiscuss.net/AbuseReport/InGameChat.php">Go back</a>';
}
if ($error == false) {
if ($result['banned'] == 1) {
$error = true;
echo '<h4>An error has occurred.</h4>';
echo 'The user you are reporting has been banned.<br><a href="http://api.xdiscuss.net/AbuseReport/InGameChat.php">Go back</a>';
}
}
if ($error == false) {
// Check if the same user has reported already.
$stmt = $dbcon->prepare("SELECT * FROM reports WHERE reportIP=:ip AND target=:username;");
$stmt->bindParam(':ip', $IP, PDO::PARAM_STR);
$stmt->bindParam(':username', $username, PDO::PARAM_STR);
$stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC);
if ($stmt->rowCount() > 0) {
echo '<h4>An error has occurred.</h4>';
echo 'You have already reported this user.<br><a href="http://api.xdiscuss.net/AbuseReport/InGameChat.php">Go back</a>';
}else{
$query = "INSERT INTO reports (`target`, `reason`, `date`, `reportIP`) VALUES (:username, :reason, NOW(), :ip);";
$stmt = $dbcon->prepare($query);
$stmt->bindParam(':username', $username, PDO::PARAM_STR);
$stmt->bindParam(':reason', $reason, PDO::PARAM_STR);
$stmt->bindParam(':ip', $IP, PDO::PARAM_STR);
$stmt->execute();
echo '<h4>Thank you!</h4>';
echo 'Your report has been saved. Thanks again!';
}
}
}
$dbcon = null;
exit;
}
?>
<h4>Report Abuse</h4>
<form method="post">
Username of rule breaker
<input style="width:100%;" name="username" maxlength="20" type="text" class="form-control"></input>
Say what this user did wrong
<textarea style="width:100%;" name="reason" maxlength="256" rows="3" class="form-control"></textarea>
<button type="submit" name="submitreport" style="width:100%;">Submit Report</button>
</form>
</div>
</body>
</html>

View File

View File

@ -0,0 +1 @@
OK

19
api/Asset/index.php Normal file
View File

@ -0,0 +1,19 @@
<?php
exit('disabled');
if (isset($_GET['id'])) {
$id = $_GET['id'];
if (!is_numeric($id)) die("Invalid Request");
if (is_array($id)) die("Invalid Request");
if (filter_var($id, FILTER_VALIDATE_INT) == true && $_SERVER['HTTP_USER_AGENT'] == "Graphictoria3") {
header("Content-Type: application/octet-stream");
header("Content-Transfer-Encoding: Binary");
header("Content-disposition: attachment; filename=".$id);
$url = 'http://api.xdiscuss.net/Asset/files/'.$id;
header("Location: ".$url);
}else{
echo 'Invalid Request';
}
}else{
echo 'Invalid Request';
}
?>

0
api/Error/Dmp.ashx Normal file
View File

138
api/Game/Help.php Normal file
View File

@ -0,0 +1,138 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>Help</title></head>
<body>
<form name="form1" method="post" id="form1">
<div>
</div>
<div>
<input type="hidden" name="__VIEWSTATEGENERATOR" id="__VIEWSTATEGENERATOR" value="081C9494" />
</div>
<p>
Besides using simple blocks, you can insert Things that other people have built into your Place. Use the Insert... menu in the game to browse.</p>
<table id="Table1" class="Help">
<tr style="font-weight: bold">
<td>
Action</td>
<td>
Primary</td>
<td>
Alternate</td>
</tr>
<tr>
<td>
Move Avatar</td>
<td>
Arrow keys</td>
<td>
ASDW keys</td>
</tr>
<tr>
<td>
Move Avatar (no tool selected)</td>
<td>
Click location with green disk</td>
<td>
</td>
</tr>
<tr>
<td>
Jump</td>
<td>
Space Bar</td>
<td>
</td>
</tr>
<tr>
<td>
Look up/down/left/right</td>
<td>
Right-click and drag mouse</td>
<td>
</td>
</tr>
<tr>
<td>
Look side to side</td>
<td>
Move mouse to the far right or far left
</td>
<td>
</td>
</tr>
<tr>
<td>
Zoom in/out and up/down</td>
<td>
Mouse wheel</td>
<td>
I (in) and O (out) keys</td>
</tr>
<tr>
<td>
Change Tool / Toggle tool on off</td>
<td>
Number keys 1, 2, 3, ...</td>
<td>
Click on the tool</td>
</tr>
<tr>
<td>
Drop Tool</td>
<td>
Backspace key</td>
<td>
</td>
</tr>
<tr>
<td>
Drop Hat</td>
<td>
Equal (=) key</td>
<td>
</td>
</tr>
<tr>
<td>
Regenerate dead or stuck avatar</td>
<td>
Avatar regenerates automatically</td>
<td>
Exit and then return to the Place</td>
</tr>
<tr>
<td>
First Person Mode</td>
<td>
Zoom all the way in</td>
<td>
</td>
</tr>
<tr>
<td>
</td>
<td>
</td>
<td>
</td>
</tr>
<tr>
<td>
</td>
<td>
</td>
<td>
</td>
</tr>
</table>
</form>
</body>
</html>

96
api/Game/Join.ashx Normal file
View File

@ -0,0 +1,96 @@
<?php
exit('disabled');
include_once $_SERVER['DOCUMENT_ROOT'].'/config.php';
try{
$dbcon = new PDO('mysql:host='.$db_host.';port='.$db_port.';dbname='.$db_name.';charset=utf8', $db_user, $db_passwd);
$dbcon->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
$dbcon->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}catch (PDOExpection $e){
exit;
}
$json = ["status"=>0, "authenticationUrl"=>null, "authenticationTicket"=>null, "joinScriptUrl"=>null];
header("Content-Type: text/plain");
if(!isset($_COOKIE["a_id"])){
http_response_code(401);
exit;
}
if(!isset($_GET["gID"]) || (int)$_GET["gID"] != $_GET["gID"]){
http_response_code(403);
exit;
}
$stmtUid = $dbcon->prepare("SELECT userId FROM sessions WHERE sessionId=:id;");
$stmtUid->bindParam(':id', $_COOKIE["a_id"], PDO::PARAM_STR);
$stmtUid->execute();
$rUserId = $stmtUid->fetch(PDO::FETCH_ASSOC);
// User row
$stmtU = $dbcon->prepare("SELECT * FROM users WHERE id=:id;");
$stmtU->bindParam(':id', $rUserId["userId"], PDO::PARAM_INT);
$stmtU->execute();
$rUser = $stmtU->fetch(PDO::FETCH_ASSOC);
// Game row
$stmtG = $dbcon->prepare("SELECT * FROM games WHERE id=:id;");
$stmtG->bindParam(':id', $_GET["gID"], PDO::PARAM_INT);
$stmtG->execute();
$rGame = $stmtG->fetch(PDO::FETCH_ASSOC);
if ($stmtU->rowCount() == 0 or $stmtG->rowCount() == 0){
http_response_code(403);
exit;
}
if ($rUser['publicBan'] == 1){
http_response_code(403);
exit;
}
if ($rGame['public'] == 0) {
if(!isset($_GET["key"])){
http_response_code(403);
exit;
}
$gameKey = $rGame['key'];
$stmtU = $dbcon->prepare("SELECT * FROM gameKeys WHERE userid=:id AND `key` = :key;");
$stmtU->bindParam(':id', $rUserId["userId"], PDO::PARAM_INT);
$stmtU->bindParam(':key', $_GET["key"], PDO::PARAM_STR);
$stmtU->execute();
if ($stmtU->rowCount() == 0 and $rGame['creator_uid'] != $rUserId["userId"] and $rUser['rank'] == 0){
http_response_code(403);
exit;
}
}
$stmt = $dbcon->prepare("DELETE FROM gameJoins WHERE uid=:uid");
$stmt->bindParam(':uid', $rUserId["userId"], PDO::PARAM_INT);
$stmt->execute();
$stmt = $dbcon->prepare("INSERT INTO `gameJoins` (`uid`, `gameId`) VALUES (:uid, :gameId);");
$stmt->bindParam(':uid', $rUserId["userId"], PDO::PARAM_INT);
$stmt->bindParam(':gameId', $_GET["gID"], PDO::PARAM_INT);
$stmt->execute();
// Badge awarding
$stmt = $dbcon->prepare("SELECT id FROM badges WHERE uid=:uid AND badgeId = 8;");
$stmt->bindParam(':uid', $rUserId["userId"], PDO::PARAM_INT);
$stmt->execute();
if ($stmt->rowCount() == 0) {
$stmt = $dbcon->prepare("INSERT INTO `badges` (`uid`, `badgeId`) VALUES (:uid, 8);");
$stmt->bindParam(':uid', $rUserId["userId"], PDO::PARAM_INT);
$stmt->execute();
}
// User row
$stmtC = $dbcon->prepare("SELECT * FROM users WHERE id=:id;");
$stmtC->bindParam(':id', $rGame['creator_uid'], PDO::PARAM_INT);
$stmtC->execute();
$creator = $stmtC->fetch(PDO::FETCH_ASSOC);
$script = "\r\n" . json_encode(["BaseUrl"=>"http://www.graphictoria.cf/", "SeleniumTestMode"=>false, "PlaceId"=>$_GET["gID"], "MachineAddress"=>$rGame["ip"], "VendorId"=>0, "DataCenterId"=>0, "PingUrl"=>"https://graphictoria.cf/core/func/api/auth/ping.php", "PingInterval"=>60, "GenerateTeleportJoin"=>false, "GameId"=>"00000000-0000-0000-0000-000000000000", "UserId"=>$rUserId["userId"], "ClientTicket"=>$rUser["gameKey"], "IsRobloxPlace"=>($creator['rank']==1), "CreatorTypeEnum"=>"User", "CreatorId"=>$rGame['creator_uid'], "ChatStyle"=>"ClassicAndBubble", "SessionId"=>sprintf('%04X%04X-%04X-%04X-%04X-%04X%04X%04X', mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(16384, 20479), mt_rand(32768, 49151), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535)), "ServerPort"=>$rGame['port'], "ClientPort"=>0, "SuperSafeChat"=>false, "IsUnknownOrUnder13"=>false, "MembershipType"=>($rUser["rank"]==1 ? "OutrageousBuildersClub" : "None"), "AccountAge"=>round((time()-strtotime($rUser["joinDate"])) / (60 * 60 * 24)), "UserName"=>$rUser["username"], "CharacterAppearance"=>"http://api.graphictoria.cf/user/getCharacter.php?uid=" . $rUserId["userId"] . "&key=D869593BF742A42F79915993EF1DB&tick=" . time(), "FollowUserId"=>0, "ScreenShotInfo"=>"", "VideoInfo"=>""], JSON_UNESCAPED_SLASHES | JSON_NUMERIC_CHECK);
$signature;
$key = file_get_contents($_SERVER["DOCUMENT_ROOT"] . "/../key.pem");
openssl_sign($script, $signature, $key, OPENSSL_ALGO_SHA1);
exit("--rbxsig%" . base64_encode($signature) . "%" . $script);
?>

View File

View File

View File

@ -0,0 +1,70 @@
<?php
exit('disabled');
include_once $_SERVER['DOCUMENT_ROOT'].'/config.php';
try{
$dbcon = new PDO('mysql:host='.$db_host.';port='.$db_port.';dbname='.$db_name.';charset=utf8', $db_user, $db_passwd);
$dbcon->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
$dbcon->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}catch (PDOExpection $e){
exit;
}
$json = ["status"=>0, "authenticationUrl"=>null, "authenticationTicket"=>null, "joinScriptUrl"=>null];
header("Content-Type: text/plain");
if(!isset($_COOKIE["a_id"])){
http_response_code(401);
exit(json_encode($json));
}
if(!isset($_GET["placeId"]) || (int)$_GET["placeId"] != $_GET["placeId"]){
http_response_code(403);
exit(json_encode($json));
}
$stmtUid = $dbcon->prepare("SELECT userId FROM sessions WHERE sessionId=:id;");
$stmtUid->bindParam(':id', $_COOKIE["a_id"], PDO::PARAM_STR);
$stmtUid->execute();
$rUserId = $stmtUid->fetch(PDO::FETCH_ASSOC);
// User row
$stmtU = $dbcon->prepare("SELECT * FROM users WHERE id=:id;");
$stmtU->bindParam(':id', $rUserId["userId"], PDO::PARAM_INT);
$stmtU->execute();
$rUser = $stmtU->fetch(PDO::FETCH_ASSOC);
// Game row
$stmtG = $dbcon->prepare("SELECT * FROM games WHERE id=:id;");
$stmtG->bindParam(':id', $_GET["placeId"], PDO::PARAM_INT);
$stmtG->execute();
$rGame = $stmtG->fetch(PDO::FETCH_ASSOC);
if ($stmtU->rowCount() == 0 or $stmtG->rowCount() == 0){
http_response_code(403);
exit(json_encode($json));
}
if ($rUser['publicBan'] == 1){
$json["status"]=6;
exit(json_encode($json));
}
if ($rGame['public'] == 0) {
if(!isset($_GET["key"])){
$json["status"]=6;
exit(json_encode($json));
}
$gameKey = $rGame['key'];
$stmtU = $dbcon->prepare("SELECT * FROM gameKeys WHERE userid=:id AND `key` = :key;");
$stmtU->bindParam(':id', $rUserId["userId"], PDO::PARAM_INT);
$stmtU->bindParam(':key', $_GET["key"], PDO::PARAM_STR);
$stmtU->execute();
if ($stmtU->rowCount() == 0 and $rGame['creator_uid'] != $rUserId["userId"] and $rUser['rank'] == 0){
$json["status"]=6;
exit(json_encode($json));
}
}
$json["status"] = 2;
$json["authenticationUrl"] = "http://api.graphictoria.cf/Login/Negotiate.ashx";
$json["authenticationTicket"] = $rUser["gameKey"];
$json["joinScriptUrl"] = "http://api.graphictoria.cf/Game/Join.ashx?gID=" . $_GET["placeId"];
exit(json_encode($json, JSON_UNESCAPED_SLASHES));
?>

4103
api/Game/Studio.ashx Normal file

File diff suppressed because it is too large Load Diff

0
api/Game/client.ashx Normal file
View File

437
api/Game/test.php Normal file
View File

@ -0,0 +1,437 @@
<?php
ob_start();
?>
-- functions --------------------------
function onPlayerAdded(player)
-- override
end
-- MultiplayerSharedScript.lua inserted here ------ Prepended to Join.lua --
-- log app init time
pcall(function()
local t = ElapsedTime()
local platform = settings().Diagnostics.OsPlatform
game:HttpGet("http://www.gtoria.net/Game/JoinRate.ashx?st=0&i=0&p=-1&c=GameAppInit&r=Success&d=" .. (math.floor(t*1000)) .. "&ip=192.168.0.3&errorType=&platform=" .. platform, false)
end)
pcall(function() game:SetPlaceID(1, false) end)
local startTime = tick()
local connectResolved = false
local loadResolved = false
local joinResolved = false
local playResolved = true
local playStartTime = 0
local cdnSuccess = 0
local cdnFailure = 0
-- if we are on a touch device, no blocking http calls allowed! This can cause a crash on iOS
-- In general we need a long term strategy to remove blocking http calls from all platforms
local isTouchDevice = Game:GetService("UserInputService").TouchEnabled
settings()["Game Options"].CollisionSoundEnabled = true
pcall(function() settings().Rendering.EnableFRM = true end)
pcall(function() settings().Physics.Is30FpsThrottleEnabled = true end)
pcall(function() settings()["Task Scheduler"].PriorityMethod = Enum.PriorityMethod.AccumulatedError end)
pcall(function() settings().Physics.PhysicsEnvironmentalThrottle = Enum.EnviromentalPhysicsThrottle.DefaultAuto end)
function reportContentProvider(time, queueLength, blocking)
pcall(function()
game:HttpGet("http://www.gtoria.net/Analytics/ContentProvider.ashx?t=" .. time .. "&ql=" .. queueLength, blocking and not isTouchDevice)
end)
end
function reportCdn(blocking)
pcall(function()
local newCdnSuccess = settings().Diagnostics.CdnSuccessCount
local newCdnFailure = settings().Diagnostics.CdnFailureCount
local successDelta = newCdnSuccess - cdnSuccess
local failureDelta = newCdnFailure - cdnFailure
cdnSuccess = newCdnSuccess
cdnFailure = newCdnFailure
if successDelta > 0 or failureDelta > 0 then
game:HttpGet("http://www.gtoria.net/Game/Cdn.ashx?source=client&success=" .. successDelta .. "&failure=" .. failureDelta, blocking and not isTouchDevice)
end
end)
end
function reportDuration(category, result, duration, blocking,errorType)
if not errorType then
errorType = ''
end
local platform = settings().Diagnostics.OsPlatform
local bytesReceived = -1
if stats().Network:getChildren()[2] ~= nil then
bytesReceived = stats().Network:getChildren()[2].Stats.totalBytesReceived:GetValue()
end
pcall(function() game:HttpGet("http://www.gtoria.net/Game/JoinRate.ashx?st=0&i=0&p=-1&c=" .. category .. "&r=" .. result .. "&d=" .. (math.floor(duration*1000)) .. "&b=" .. bytesReceived .. "&ip=192.168.0.3&errorType=" .. errorType .. "&platform=" .. platform, blocking and not isTouchDevice) end)
end
-- arguments ---------------------------------------
local threadSleepTime = ...
if threadSleepTime==nil then
threadSleepTime = 15
end
local test = true
print("! Joining game '' place -1 at 192.168.0.3")
local closeConnection = game.Close:connect(function()
if 0 then
reportCdn(true)
if not connectResolved then
local duration = tick() - startTime;
reportDuration("GameConnect", "Failure", duration, true)
elseif (not loadResolved) or (not joinResolved) then
local duration = tick() - startTime;
if not loadResolved then
loadResolved = true
reportDuration("GameLoad","Cancel", duration, true)
end
if not joinResolved then
joinResolved = true
reportDuration("GameJoin","Cancel", duration, true)
end
elseif not playResolved then
local duration = tick() - playStartTime;
playResolved = true
reportDuration("GameDuration","Success", duration, true)
end
if true then pcall(function() game:HttpPost("https://api.gtoria.net/auth/invalidate", "invalidate") end) end
end
end)
game:GetService("ChangeHistoryService"):SetEnabled(false)
game:GetService("ContentProvider"):SetThreadPool(16)
game:GetService("InsertService"):SetBaseSetsUrl("http://www.gtoria.net/Game/Tools/InsertAsset.ashx?nsets=10&type=base")
game:GetService("InsertService"):SetUserSetsUrl("http://www.gtoria.net/Game/Tools/InsertAsset.ashx?nsets=20&type=user&userid=%d")
game:GetService("InsertService"):SetCollectionUrl("http://www.gtoria.net/Game/Tools/InsertAsset.ashx?sid=%d")
game:GetService("InsertService"):SetAssetUrl("http://www.gtoria.net/Asset/?id=%d")
game:GetService("InsertService"):SetAssetVersionUrl("http://www.gtoria.net/Asset/?assetversionid=%d")
pcall(function() game:GetService("SocialService"):SetFriendUrl("http://www.gtoria.net/Game/LuaWebService/HandleSocialRequest.ashx?method=IsFriendsWith&playerid=%d&userid=%d") end)
pcall(function() game:GetService("SocialService"):SetBestFriendUrl("http://www.gtoria.net/Game/LuaWebService/HandleSocialRequest.ashx?method=IsBestFriendsWith&playerid=%d&userid=%d") end)
pcall(function() game:GetService("SocialService"):SetGroupUrl("http://www.gtoria.net/Game/LuaWebService/HandleSocialRequest.ashx?method=IsInGroup&playerid=%d&groupid=%d") end)
pcall(function() game:GetService("SocialService"):SetGroupRankUrl("http://www.gtoria.net/Game/LuaWebService/HandleSocialRequest.ashx?method=GetGroupRank&playerid=%d&groupid=%d") end)
pcall(function() game:GetService("SocialService"):SetGroupRoleUrl("http://www.gtoria.net/Game/LuaWebService/HandleSocialRequest.ashx?method=GetGroupRole&playerid=%d&groupid=%d") end)
pcall(function() game:GetService("GamePassService"):SetPlayerHasPassUrl("http://www.gtoria.net/Game/GamePass/GamePassHandler.ashx?Action=HasPass&UserID=%d&PassID=%d") end)
pcall(function() game:GetService("MarketplaceService"):SetProductInfoUrl("https://api.gtoria.net/marketplace/productinfo?assetId=%d") end)
pcall(function() game:GetService("MarketplaceService"):SetPlayerOwnsAssetUrl("https://api.gtoria.net/ownership/hasasset?userId=%d&assetId=%d") end)
pcall(function() game:SetCreatorID(0, Enum.CreatorType.User) end)
-- Bubble chat. This is all-encapsulated to allow us to turn it off with a config setting
pcall(function() game:GetService("Players"):SetChatStyle(Enum.ChatStyle.Classic) end)
local waitingForCharacter = false
local waitingForCharacterGuid = "86cadbcc-3b8b-493e-8d7b-4b103ae914e9";
pcall( function()
if settings().Network.MtuOverride == 0 then
settings().Network.MtuOverride = 1400
end
end)
-- globals -----------------------------------------
client = game:GetService("NetworkClient")
visit = game:GetService("Visit")
-- functions ---------------------------------------
function ifSeleniumThenSetCookie(key, value)
if false then
game:GetService("CookiesService"):SetCookieValue(key, value)
end
end
function setMessage(message)
-- todo: animated "..."
if not false then
game:SetMessage(message)
else
-- hack, good enought for now
game:SetMessage("Teleporting ...")
end
end
function showErrorWindow(message, errorType, errorCategory)
if 0 then
if (not loadResolved) or (not joinResolved) then
local duration = tick() - startTime;
if not loadResolved then
loadResolved = true
reportDuration("GameLoad","Failure", duration, false,errorType)
end
if not joinResolved then
joinResolved = true
reportDuration("GameJoin",errorCategory, duration, false,errorType)
end
pcall(function() game:HttpGet("?FilterName=Type&FilterValue=" .. errorType .. "&Type=JoinFailure", false) end)
elseif not playResolved then
local duration = tick() - playStartTime;
playResolved = true
reportDuration("GameDuration",errorCategory, duration, false,errorType)
pcall(function() game:HttpGet("?FilterName=Type&FilterValue=" .. errorType .. "&Type=GameDisconnect", false) end)
end
end
game:SetMessage(message)
end
function registerPlay(key)
if true and game:GetService("CookiesService"):GetCookieValue(key) == "" then
game:GetService("CookiesService"):SetCookieValue(key, "{ \"userId\" : 0, \"placeId\" : -1, \"os\" : \"" .. settings().Diagnostics.OsPlatform .. "\" }")
end
end
function analytics(name)
if not test and false then
pcall(function() game:HttpGet("?IPFilter=Primary&SecondaryFilterName=UserId&SecondaryFilterValue=0&Type=" .. name, false) end)
end
end
function analyticsGuid(name, guid)
if not test and false then
pcall(function() game:HttpGet("?IPFilter=Primary&SecondaryFilterName=guid&SecondaryFilterValue=" .. guid .. "&Type=" .. name, false) end)
end
end
function reportError(err, message)
print("***ERROR*** " .. err)
if not test then visit:SetUploadUrl("") end
client:Disconnect()
wait(4)
showErrorWindow("Error: " .. err, message, "Other")
end
-- called when the client connection closes
function onDisconnection(peer, lostConnection)
if lostConnection then
if waitingForCharacter then analyticsGuid("Waiting for Character Lost Connection",waitingForCharacterGuid) end
showErrorWindow("You have lost the connection to the game", "LostConnection", "LostConnection")
else
if waitingForCharacter then analyticsGuid("Waiting for Character Game Shutdown",waitingForCharacterGuid) end
showErrorWindow("This game has shut down", "Kick", "Kick")
end
pcall(function() game:HttpGet("&disconnect=true", true) end)
if true then pcall(function() game:HttpPost("https://api.gtoria.net/auth/invalidate", "invalidate") end) end
end
function requestCharacter(replicator)
-- prepare code for when the Character appears
local connection
connection = player.Changed:connect(function (property)
if property=="Character" then
game:ClearMessage()
waitingForCharacter = false
analyticsGuid("Waiting for Character Success", waitingForCharacterGuid)
connection:disconnect()
if 0 then
if not joinResolved then
local duration = tick() - startTime;
joinResolved = true
reportDuration("GameJoin","Success", duration, false)
playStartTime = tick()
playResolved = false
end
end
end
end)
setMessage("Requesting character")
if 0 and not loadResolved then
local duration = tick() - startTime;
loadResolved = true
reportDuration("GameLoad","Success", duration, false)
end
local success, err = pcall(function()
replicator:RequestCharacter()
setMessage("Waiting for character")
waitingForCharacter = true
analyticsGuid("Waiting for Character Begin",waitingForCharacterGuid);
end)
if not success then
reportError(err,"W4C")
return
end
end
-- called when the client connection is established
function onConnectionAccepted(url, replicator)
connectResolved = true
reportDuration("GameConnect", "Success", tick() - startTime, false)
local waitingForMarker = true
local success, err = pcall(function()
if not test then
visit:SetPing("", 300)
end
if not false then
game:SetMessageBrickCount()
else
setMessage("Teleporting ...")
end
replicator.Disconnection:connect(onDisconnection)
-- Wait for a marker to return before creating the Player
local marker = replicator:SendMarker()
marker.Received:connect(function()
waitingForMarker = false
requestCharacter(replicator)
end)
end)
if not success then
reportError(err,"ConnectionAccepted")
return
end
-- TODO: report marker progress
while waitingForMarker do
workspace:ZoomToExtents()
wait(0.5)
end
end
-- called when the client connection fails
function onConnectionFailed(_, error)
showErrorWindow("Failed to connect to the Game. (ID=" .. error .. ")", "ID" .. error, "Other")
end
-- called when the client connection is rejected
function onConnectionRejected()
connectionFailed:disconnect()
showErrorWindow("This game is not available. Please try another", "WrongVersion", "WrongVersion")
end
idled = false
function onPlayerIdled(time)
if time > 20*60 then
showErrorWindow(string.format("You were disconnected for being idle %d minutes", time/60), "Idle", "Idle")
client:Disconnect()
if not idled then
idled = true
end
end
end
-- main ------------------------------------------------------------
analytics("Start Join Script")
ifSeleniumThenSetCookie("SeleniumTest1", "Started join script")
pcall(function() settings().Diagnostics:LegacyScriptMode() end)
local success, err = pcall(function()
game:SetRemoteBuildMode(true)
setMessage("Connecting to Server")
client.ConnectionAccepted:connect(onConnectionAccepted)
client.ConnectionRejected:connect(onConnectionRejected)
connectionFailed = client.ConnectionFailed:connect(onConnectionFailed)
client.Ticket = ""
ifSeleniumThenSetCookie("SeleniumTest2", "Successfully connected to server")
playerConnectSucces, player = pcall(function() return client:PlayerConnect(1, "192.168.0.3", 53640, 0, threadSleepTime) end)
if not playerConnectSucces then
--Old player connection scheme
player = game:GetService("Players"):CreateLocalPlayer(1)
analytics("Created Player")
client:Connect("192.168.0.3", 53640, 0, threadSleepTime)
else
analytics("Created Player")
end
pcall(function()
registerPlay("rbx_evt_ftp")
delay(60*5, function() registerPlay("rbx_evt_fmp") end)
end)
-- negotiate an auth token
if true then
pcall(function() game:HttpPost("https://api.gtoria.net/auth/negotiate?ticket=", "negotiate") end)
delay(300, function()
while true do
pcall(function() game:HttpPost("https://api.gtoria.net/auth/renew", "renew") end)
wait(300)
end
end)
end
player:SetSuperSafeChat(true)
pcall(function() player:SetUnder13(true) end)
pcall(function() player:SetMembershipType(Enum.MembershipType.None) end)
pcall(function() player:SetAccountAge(0) end)
player.Idled:connect(onPlayerIdled)
-- Overriden
onPlayerAdded(player)
pcall(function() player.Name = [========[Player]========] end)
player.CharacterAppearance = ""
if not test then visit:SetUploadUrl("")end
analytics("Connect Client")
end)
if not success then
reportError(err,"CreatePlayer")
end
ifSeleniumThenSetCookie("SeleniumTest3", "Successfully created player")
if not test then
-- TODO: Async get?
loadfile("")("", -1, 0)
end
if 0 then
delay(60*5, function()
while true do
reportCdn(false)
wait(60*5)
end
end)
local cpTime = 30
delay(cpTime, function()
while cpTime <= 480 do
reportContentProvider(cpTime, game:GetService("ContentProvider").RequestQueueSize, false)
wait(cpTime)
cpTime = cpTime * 2
end
end)
end
pcall(function() game:SetScreenshotInfo("") end)
pcall(function() game:SetVideoInfo('<?xml version="1.0"?><entry xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:yt="http://gdata.youtube.com/schemas/2007"><media:group><media:title type="plain"><![CDATA[ROBLOX Place]]></media:title><media:description type="plain"><![CDATA[ For more games visit http://www.gtoria.net]]></media:description><media:category scheme="http://gdata.youtube.com/schemas/2007/categories.cat">Games</media:category><media:keywords>ROBLOX, video, free game, online virtual world</media:keywords></media:group></entry>') end)
-- use single quotes here because the video info string may have unescaped double quotes
analytics("Join Finished")
ifSeleniumThenSetCookie("SeleniumTest4", "Finished join")
<?php
$script = ob_get_clean();
$signature;
$key = file_get_contents($_SERVER["DOCUMENT_ROOT"] . "/../test.pem");
openssl_sign($script, $signature, $key, OPENSSL_ALGO_SHA1);
exit("--rbxsig%" . base64_encode($signature) . "%" . $script);
?>

1
api/Game/visit.php Normal file
View File

@ -0,0 +1 @@
%LruJmR3gQMo2oR+P7iDUdXBKjEVAKmCzZ8Hdk1ew8/fZGKyz9JMfk6DwuJgUdn10FJfpqXm3k0OEKv+ndf18QIVNZnR39guPB1B+2x0g0SR7sRJgZbtn4lDXJNk/rDDPgQmDZcLMpW24pJpsQIbDzmN63U6ihYlPWuDlU3r5Mzs=%game:GetService("RunService"):Run() local player = game.Players:CreateLocalPlayer(0) player:LoadCharacter() player.Character.Humanoid.Died:connect(function() wait(5) player:LoadCharacter() end)

11
api/Game/vsolo.php Normal file
View File

@ -0,0 +1,11 @@
game:GetService("Visit")
game:GetService("RunService"):Run()
local player = game.Players:CreateLocalPlayer(0)
player:LoadCharacter()
while (true) do
wait(0.1)
if (player.Character.Humanoid.Health == 0) then
wait(5)
player:LoadCharacter()
end
end

View File

@ -0,0 +1 @@
Coming soon.

16
api/IDE/Start.php Normal file
View File

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<title>Graphictoria</title>
<link rel="stylesheet" href="http://gtoria.net/html/css/bootstrap.min.css?v=45"/>
<link rel="stylesheet" href="http://gtoria.net/html/css/ripples.min.css?v=2">
<link rel="stylesheet" href="http://gtoria.net/html/css/style.css?v=51"/>
<link rel="stylesheet" href="http://gtoria.net/html/css/style3.css?v=40"/>
<script src="http://gtoria.net/html/js/jquery.js"></script>
</head>
<body class="container">
<h4 style="color:grey;">Welcome to Graphictoria!</h4>
<p><b>If you want to build</b>, create a new document and start building!<br>
<b>If you are here to host a server</b>, create a new document and run the command you've been given.</p>
</body>
</html>

24
api/Login/Negotiate.ashx Normal file
View File

@ -0,0 +1,24 @@
<?php
if(isset($_GET["suggest"])){
include_once $_SERVER['DOCUMENT_ROOT'].'/config.php';
try{
$dbcon = new PDO('mysql:host='.$db_host.';port='.$db_port.';dbname='.$db_name.';charset=utf8', $db_user, $db_passwd);
$dbcon->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
$dbcon->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}catch (PDOExpection $e){
exit;
}
$stmtU = $dbcon->prepare("SELECT id FROM users WHERE gameKey=:key;");
$stmtU->bindParam(':key', $_GET["suggest"], PDO::PARAM_STR);
$stmtU->execute();
$suggestion = $stmtU->fetch(PDO::FETCH_ASSOC);
if(isset($suggestion["id"])){
$stmtS = $dbcon->prepare("SELECT id,sessionId FROM sessions WHERE userId=:id ORDER BY id DESC;");
$stmtS->bindParam(':id', $suggestion["id"], PDO::PARAM_INT);
$stmtS->execute();
$session = $stmtS->fetch(PDO::FETCH_ASSOC);
setcookie("a_id", $session["sessionId"], time() + (86400 * 30), "/", ".gtoria.net", false, true);
}else{
http_response_code(403);
}
}

View File

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/html/css/bootstrap.min.css?v=15"/>
<title>Graphictoria</title>
<style>
body{
background:url("/html/img/background4.png") no-repeat center center fixed;background-size:cover;overflow-x:hidden;
}
</style>
</head>
<body>
<h2>Screenshot</h2>
<p>You have taken a screenshot.</p>
</body>
</html>

20
api/config.php Normal file
View File

@ -0,0 +1,20 @@
<?php
if (strpos($_SERVER['SCRIPT_NAME'], "config.php")) {
header("Location: /");
exit;
}
$db_host = "127.0.0.1";
$db_user = "";
$db_name = "";
$db_passwd = "";
$db_port = 3306;
try{
$dbcon = new PDO('mysql:host='.$db_host.';port='.$db_port.';dbname='.$db_name, $db_user, $db_passwd);
$dbcon->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
$dbcon->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}catch (PDOExpection $e){
exit;
}
?>

4
api/downloads/.htaccess Normal file
View File

@ -0,0 +1,4 @@
AuthType Basic
AuthName "Graphictoria Authentication Required"
AuthUserFile /var/www/api/downloads/.htpasswd
Require valid-user

1
api/downloads/.htpasswd Normal file
View File

@ -0,0 +1 @@
gtdownloadhandler:$apr1$RlcMELmY$b4ES1BCGe1HZTj/7nEnUL0

View File

@ -0,0 +1,17 @@
<?php
exit('disabled');
if (!isset($_GET['version']) || is_array($_GET['version'])) die("Invalid parameters");
if (!isset($_GET['key'])) die("no-key");
if (is_array($_GET['key'])) die("no-key");
if ($_GET['key'] != "SCwQKQk2UICh0BUoD7LGx2NNRZJBZ1dj") die("invalid-key");
if ($_GET['version'] == "2008") $filename = "Graphictoria08_1.exe";
if ($_GET['version'] == "2009") $filename = "Graphictoria2009_installer.exe";
if ($_GET['version'] == "2011") $filename = "Graphictoria2011_v2_3.exe";
if (!isset($filename) || strlen($filename) == 0) die("error");
$file = file_get_contents("/var/www/api/downloads/".$filename);
header("Content-disposition: attachment; filename=" . $filename);
header("Content-type: application/octet-stream");
echo $file;
?>

52
api/hooks/report.php Normal file
View File

@ -0,0 +1,52 @@
<?php
exit('disabled');
if (!isset($_GET['message'])) exit;
if (isset($_SERVER["HTTP_CF_CONNECTING_IP"]))
$_SERVER['REMOTE_ADDR'] = $_SERVER["HTTP_CF_CONNECTING_IP"];
if ($_SERVER['HTTP_USER_AGENT'] != "WEBHOOK GUY" || !isset($_GET['key']) || $_GET['key'] != "ZkfGU0SlOd4DZmquah0KAmywAS7rtqDL")
exit;
$message = $_GET['message'];
$message = str_replace("@here", "", $message);
$message = str_replace("@everyone", "", $message); // Seiko prevention
/*
* This is the file everyone claims logs your IP.
* Not really, as you can see.
*/
include_once $_SERVER['DOCUMENT_ROOT'].'/config.php';
try{
$dbcon = new PDO('mysql:host='.$db_host.';port='.$db_port.';dbname='.$db_name.'', $db_user, $db_passwd);
$dbcon->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbcon->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}catch (PDOExpection $e){
echo $e->getMessage();
}
$stmt = $dbcon->prepare("SELECT username FROM users WHERE `lastIP`=:ip ORDER BY id DESC LIMIT 1");
$stmt->bindParam(':ip', $_SERVER['REMOTE_ADDR'], PDO::PARAM_STR);
$stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC);
$url = "https://canary.discordapp.com/api/webhooks/x/x";
$dataArray = array('content' => "[Username (assumed): **".$result['username']."**] ".$message,
'username' => "Exploiter Alert");
$httpOptions = array(
'http' => array (
'header' => "Graphictoria-Server",
'content-type' => 'multipart/form-data',
'method' => "POST",
'content' => http_build_query($dataArray)
)
);
$context = stream_context_create($httpOptions);
$result = @file_get_contents($url, false, $context);
echo 'success';
$dbcon = null;
?>

View File

View File

View File

View File

View File

View File

View File

View File

View File

@ -0,0 +1 @@
Deny from all

View File

70
api/img/character.php Normal file
View File

@ -0,0 +1,70 @@
<?php
if (isset($_GET['id'])) {
$userid = $_GET['id'];
}else{
exit;
}
include_once $_SERVER['DOCUMENT_ROOT'].'/config.php';
try{
$dbcon = new PDO('mysql:host='.$db_host.';port='.$db_port.';dbname='.$db_name.'', $db_user, $db_passwd);
$dbcon->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbcon->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}catch (PDOExpection $e){
echo $e->getMessage();
}
$stmt = $dbcon->prepare("SELECT charap, id FROM users WHERE id=:id");
$stmt->bindParam(':id', $userid, PDO::PARAM_INT);
$stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC);
$userid = $result['id'];
$dbcon = null;
?>
game.Lighting.TimeOfDay = "12"
local player = game.Players:CreateLocalPlayer(0)
player.CharacterAppearance = "http://api.xdiscuss.net/user/getCharacter.php?uid=<?php echo $userid;?>&mode=ch&sid=1&key=D869593BF742A42F79915993EF1DB&tick=" .. tick()
local loadCharacter = coroutine.create(function()
wait(0.5)
player:LoadCharacter()
wait(0.5)
player:LoadCharacter()
wait(0.25)
local count = 0
local p = player.Backpack:GetChildren()
for i = 1, #p do
if p[i].className == "Tool" then
count = count + 1
if (count == 1) then
game.Workspace.Player.Torso:findFirstChild("Right Shoulder").DesiredAngle = 1.58
game.Workspace.Player.Torso:findFirstChild("Right Shoulder").CurrentAngle = 1.58
game.Workspace.Player.Torso.Anchored = true
wait(0.25)
p[i].Parent = player.Character
end
end
end
<?php
if ($result['charap'] == 1) {
echo 'player.Character.Torso.Anchored = true
game:GetService("RunService"):Run()
wait(0.5)
player.Character:findFirstChild("Left Leg").Anchored = true
wait(0.5)
player.Character:findFirstChild("Left Leg").Anchored = false
';
}elseif($result['charap'] == 2) {
echo 'player.Character.Humanoid.Sit = true
game:GetService("RunService"):Run()
wait(0.25)
player.Character.Torso.Anchored = true
';
}elseif($result['charap'] == 3) {
echo "player.Character.Torso['Left Shoulder'].C0=CFrame.new(-1, 0.5, 0, -4.37113883e-08, 0, -1, 0, 0.99999994, 0, 1, 0, -4.37113883e-08);
player.Character.Torso['Left Shoulder'].C1=CFrame.new(0.49999997, 0.49999997, 4.47034836e-08, 0.163175777, -0.229498923, -0.959533036, -0.33284384, 0.90274477, -0.272519022, 0.928756475, 0.363843203, 0.0709187835);
player.Character.Torso['Right Shoulder'].C0=CFrame.new(1, 0.5, 0, -4.37113883e-08, 0, 1, -0, 0.99999994, 0, -1, 0, -4.37113883e-08);
player.Character.Torso['Right Shoulder'].C1=CFrame.new(-0.5, 0.5, 0, 0.163175479, 0.229498848, 0.959533155, 0.332843512, 0.902745068, -0.272518843, -0.928756654, 0.363842756, 0.0709186569);";
}
?>
end)
coroutine.resume(loadCharacter)

78
api/img/character2008.php Normal file
View File

@ -0,0 +1,78 @@
<?php
if (isset($_GET['id'])) {
$userid = $_GET['id'];
}else{
exit;
}
include_once $_SERVER['DOCUMENT_ROOT'].'/config.php';
try{
$dbcon = new PDO('mysql:host='.$db_host.';port='.$db_port.';dbname='.$db_name.'', $db_user, $db_passwd);
$dbcon->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbcon->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}catch (PDOExpection $e){
echo $e->getMessage();
}
$stmt = $dbcon->prepare("SELECT charap, id FROM users WHERE id=:id");
$stmt->bindParam(':id', $userid, PDO::PARAM_INT);
$stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC);
$userid = $result['id'];
?>
game.Lighting.TimeOfDay = "12"
local player = game.Players:CreateLocalPlayer(0)
player.CharacterAppearance = "<?php
$stmt = $dbcon->prepare("SELECT * FROM wearing WHERE uid=:uid;");
$stmt->bindParam(':uid', $userid, PDO::PARAM_INT);
$stmt->execute();
if ($stmt->rowCount() == 0) {
echo 'http://api.xdiscuss.net/user/getcolors.php?uid='.$userid;
}else{
echo 'http://api.xdiscuss.net/user/getcolors.php?uid='.$userid.';';
}
$count = 0;
foreach($stmt as $result) {
if ($result['type'] == "gear") {
}else{
if ($count !== $stmt->rowCount()) {
if (isset($_GET['mode'])) {
echo $result['aprString'].';';
}else{
echo $result['aprString'].'?tick='.time().';';
}
}else{
echo $result['aprString'];
if (isset($_GET['mode'])) {
echo $result['aprString'];
}else{
echo $result['aprString'].'?tick='.time();
}
}
}
$count++;
}
$dbcon = null;
?>"
local loadCharacter = coroutine.create(function()
wait(0.5)
player:LoadCharacter()
wait(0.5)
player:LoadCharacter()
wait(0.25)
local count = 0
local p = player.Backpack:GetChildren()
for i = 1, #p do
if p[i].className == "Tool" then
count = count + 1
if (count == 1) then
game.Workspace.Player.Torso:findFirstChild("Right Shoulder").DesiredAngle = 1.58
game.Workspace.Player.Torso:findFirstChild("Right Shoulder").CurrentAngle = 1.58
game.Workspace.Player.Torso.Anchored = true
wait(0.25)
p[i].Parent = player.Character
end
end
end
end)
coroutine.resume(loadCharacter)

50
api/img/doFinish.php Normal file
View File

@ -0,0 +1,50 @@
<?php
include_once $_SERVER['DOCUMENT_ROOT'].'/config.php';
try{
$dbcon = new PDO('mysql:host='.$db_host.';port='.$db_port.';dbname='.$db_name.'', $db_user, $db_passwd);
$dbcon->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbcon->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}catch (PDOExpection $e){
echo $e->getMessage();
}
if (isset($_GET['renderid']) and isset($_GET['type']) and isset($_GET['apiKey']) and isset($_GET['version'])) {
$renderId = $_GET['renderid'];
$type = $_GET['type'];
$apiKey = $_GET['apiKey'];
$version = $_GET['version'];
if ($apiKey == "edrherhesrhserhserhrse") {
if ($type == "character") {
$time = time();
if ($version == 1) {
$stmt = $dbcon->prepare("UPDATE users SET imgTime = :time WHERE id=:id");
$stmt->bindParam(':id', $renderId, PDO::PARAM_INT);
$stmt->bindParam(':time', $time, PDO::PARAM_INT);
$stmt->execute();
}
if ($version == 2) {
$stmt = $dbcon->prepare("UPDATE users SET imgTime2008 = :time WHERE id=:id");
$stmt->bindParam(':id', $renderId, PDO::PARAM_INT);
$stmt->bindParam(':time', $time, PDO::PARAM_INT);
$stmt->execute();
}
}elseif ($type == "hats" || $type == "heads" || $type == "gear") {
$stmt = $dbcon->prepare("UPDATE catalog SET imgTime = NOW() WHERE datafile=:id");
$stmt->bindParam(':id', $renderId, PDO::PARAM_STR);
$stmt->execute();
}elseif ($type == "server") {
$stmt = $dbcon->prepare("UPDATE games SET imgTime = NOW() WHERE id=:id");
$stmt->bindParam(':id', $renderId, PDO::PARAM_STR);
$stmt->execute();
}
$stmt = $dbcon->prepare('DELETE FROM renders WHERE render_id = :rid AND type = :type AND version = :version;');
$stmt->bindParam(':rid', $renderId, PDO::PARAM_INT);
$stmt->bindParam(':version', $version, PDO::PARAM_INT);
$stmt->bindParam(':type', $type, PDO::PARAM_STR);
$stmt->execute();
}
}
$dbcon = null;
?>

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